/usr/bin/msguntypot is in po4a 0.47-2.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 | #! /usr/bin/env perl
eval 'exec perl -S $0 ${1+"$@"}'
if $running_under_some_shell;
# msg untypo pot -- Update the PO files when you remove a typo in POT file not needing any translation update
#
# Copyright 2005 by Martin Quinson (mquinson#debian.fr)
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of GPL (see COPYING).
my $VERSION=$Locale::Po4a::TransTractor::VERSION;
=head1 NAME
msguntypot - update PO files when a typo is fixed in POT file
=head1 SYNOPSIS
B<msguntypot> B<-o> I<old_pot> B<-n> I<new_pot> I<pofiles> ...
=head1 DESCRIPTION
When you fix a trivial error which surely doesn't affect translations (e.g.
a typo) in a POT file, you should unfuzzy the corresponding msgstr in the
translated PO files to avoid so extra work to the translators.
This task is difficult and error prone when done manually, and this tool is
there to help doing so correctly. You just need to provide the two versions
of the POT file: before the edition and after as marked in the above
synopsis, and it all becomes automatic.
=head1 HOW TO USE IT
In short, when you discover a typo in one of your [english] message, do the
following:
=over
=item - Regenerate your POT and PO files.
make -C po/ update-po # for message program translations
debconf-updatepo # for debconf translations
po4a po4a.conf # for po4a based documentation translations
or something else, depending on your project's building settings. You know
how to make sure your POT an PO files are uptodate, don't you??
=item - Make a copy of your POT file.
cp myfile.pot myfile.pot.orig
=item - Make a copy of all your files.
mkdir po_fridge; cp *.po po_fridge
=item - Fix your typo.
$EDITOR the_file_in_which_there_is_a_typo
=item - Regenerate your POT and PO files.
See above.
=back
At this point, the typo fix fuzzied all the translations, and this
unfortunate change is the only one between the PO files of your main
directory and the one from the fridge. Here is how to solve this.
=over
=item - Discard fuzzy translation, restore the ones from the fridge.
cp po_fridge/*.po .
=item - Manually merge the PO files with the new POT file, but taking the useless fuzzy into account.
msguntypot -o myfile.pot.orig -n myfile.pot *.po
=item - Cleanups.
rm -rf myfile.pot.orig po_fridge
=back
You're done. The typo was eradicated from msgstr of both your POT and PO
files, and the PO files were not fuzzyied in the process. Your translators
love you already.
=head1 SEE ALSO
Despite its name, this tool is not part of the gettext tool suite. It is
instead part of po4a. More precisely, it's a random Perl script using the
fine po4a modules. For more information about po4a, please see:
L<po4a(7)>
=head1 AUTHORS
Martin Quinson (mquinson#debian,org)
=head1 COPYRIGHT AND LICENSE
Copyright 2005 by SPI, inc.
This program is free software; you may redistribute it and/or modify it
under the terms of GPL (see the COPYING file).
=cut
use 5.006;
use strict;
use warnings;
use Getopt::Long qw(GetOptions);
use Locale::Po4a::TransTractor;
use Locale::Po4a::Common;
use Pod::Usage qw(pod2usage);
use File::Temp;
Locale::Po4a::Common::textdomain('po4a');
sub show_version {
Locale::Po4a::Common::show_version("msguntypot");
exit 0;
}
my ($help,$debug,@verbose,$quiet,$noprevious);
@verbose = ();
$debug = 0;
my ($newfile,$oldfile)=("","");
Getopt::Long::config('bundling', 'no_getopt_compat', 'no_auto_abbrev');
GetOptions(
'help|h' => \$help,
'new|n=s' => \$newfile,
'old|o=s' => \$oldfile,
'verbose|v' => \@verbose,
'debug|d' => \$debug,
'quiet|q' => \$quiet,
'no-previous' => \$noprevious,
'version|V' => \&show_version
) or pod2usage();
# Argument check
$help && pod2usage (-verbose => 1, -exitval => 0);
my ($verbose) = (scalar @verbose);
$verbose = 1 if $debug;
$verbose = -1 if $quiet;
my %options = (
"verbose" => $verbose,
"debug" => $debug);
# Argument checking
defined($oldfile) && length($oldfile) || die wrap_msg(gettext("Mandatory argument '%s' missing."), "-o");
-e $oldfile || die wrap_msg(gettext("File %s does not exist."), $oldfile);
defined($newfile) && length($newfile) || die wrap_msg(gettext("Mandatory argument '%s' missing."), "-n");
-e $newfile || die wrap_msg(gettext("File %s does not exist."), $newfile);
# Parse files
my $newpot=Locale::Po4a::Po->new();
my $oldpot=Locale::Po4a::Po->new();
$newpot->read($newfile);
$oldpot->read($oldfile);
die wrap_msg(gettext("The new and old POT files have different amount of strings (%d != %d).".
" Something's seriously wrong here."),
$newpot->count_entries(), $oldpot->count_entries())
if ($newpot->count_entries() != $oldpot->count_entries());
# Compare them and find differences between them
my (%diff)=();
for (my ($o,$n)=(0,0) ;
$o<$oldpot->count_entries() && $n<$newpot->count_entries();
$o++,$n++) {
my ($oldstr,$newstr)=($oldpot->msgid($o),$newpot->msgid($n));
$diff{$oldstr} = $newstr
if ($oldstr ne $newstr);
}
print wrap_msg(gettext("Found %d modified entries."),scalar keys %diff) if $verbose;
my $msgmergeOpts = ($noprevious ? "" : "--previous");
# Get all po files and report differences in them
my ($pofile);
(undef,$pofile)=File::Temp::tempfile("po4aXXXX",
DIR => "/tmp",
SUFFIX => ".po",
OPEN => 0,
UNLINK => 0)
or die wrap_msg(gettext("Can't create a temporary PO file: %s"), $!);
my $pocount = 0;
while (my $poarg = shift) {
$pocount ++;
print wrap_msg(gettext("Handling %s"),$poarg) if $verbose;
if (system("msgmerge $msgmergeOpts -o $pofile $poarg $oldfile 2>/dev/null")) {
my $msg = $!;
unlink ($pofile);
die wrap_msg(gettext("Error while running msgmerge: %s"), $msg);
}
my $po=Locale::Po4a::Po->new();
$po->read($pofile);
for (my $n=0 ; $n<$po->count_entries(); $n++) {
my $str=$po->msgid($n);
my $newstr = $diff{$str};
if (defined $newstr) {
$po->{po}{ $newstr } = { %{ $po->{po}{ $str } } };
$po->{po}{ $str } = ();
delete $po->{po}{ $str };
print " Changed \"$str\" to \"$newstr\"\n" if ($verbose);
}
}
$po->write($poarg);
}
unlink($pofile);
print wrap_msg(gettext("Modified %d entries in %d files."),scalar keys %diff,$pocount);
exit 0;
__END__;
|