4 # script to compare changes between translation files before merging them
6 # This file is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public
8 # License as published by the Free Software Foundation; either
9 # version 2 of the License, or (at your option) any later version.
11 # This software is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # General Public License for more details.
16 # You should have received a copy of the GNU General Public
17 # License along with this software; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 # author: Kornel Benko, kornel@lyx.org
22 # TODO: Search for good correlations of deleted and inserted string
23 # using Text::Levenshtein or Algorithm::Diff
26 use Term::ANSIColor qw(:constants);
28 my ($status, $foundline, $msgid, $msgstr, $fuzzy);
30 my %Messages = (); # Used for original po-file
31 my %newMessages = (); # new po-file
32 my %Untranslated = (); # inside new po-file
33 my %Fuzzy = (); # inside new po-file
34 my $result = 0; # exit value
39 while(defined($ARGV[0])) {
40 last if ($ARGV[0] !~ /^\-/);
41 my $param = shift(@ARGV);
43 my $name = shift(@ARGV);
47 if (! defined($names[0])) {
48 push(@names, "original");
50 if (! defined($names[1])) {
55 die('"', join('" "', @names, @ARGV) . "\" Expected exactly 2 parameters");
58 &check($names[0], $ARGV[0]);
59 &check($names[1], $ARGV[1]);
61 &parse_po_file($ARGV[0], \%Messages);
62 &parse_po_file($ARGV[1], \%newMessages);
64 my @MsgKeys = &getLineSortedKeys(\%newMessages);
66 print RED "<<< \"$names[0]\"\n", RESET;
67 print GREEN ">>> \"$names[1]\"\n", RESET;
68 for my $k (@MsgKeys) {
69 if ($newMessages{$k}->{msgstr} eq "") {
70 # this is still untranslated string
71 $Untranslated{$newMessages{$k}->{line}} = $k;
73 elsif ($newMessages{$k}->{fuzzy}) {
75 $Fuzzy{$newMessages{$k}->{line}} = $k;
77 if (exists($Messages{$k})) {
78 &printIfDiff($k, $Messages{$k}, $newMessages{$k});
79 delete($Messages{$k});
80 delete($newMessages{$k});
84 @MsgKeys = &getLineSortedKeys(\%Messages);
85 for my $k (@MsgKeys) {
87 print "deleted message\n";
88 print "< line = " . $Messages{$k}->{line} . "\n" if ($printlines);
89 print RED "< fuzzy = " . $Messages{$k}->{fuzzy} . "\n", RESET;
90 print RED "< msgid = \"$k\"\n", RESET;
91 print RED "< msgstr = \"" . $Messages{$k}->{msgstr} . "\"\n", RESET;
94 @MsgKeys = &getLineSortedKeys(\%newMessages);
95 for my $k (@MsgKeys) {
97 print "new message\n";
98 print "> line = " . $newMessages{$k}->{line} . "\n" if ($printlines);
99 print GREEN "> fuzzy = " . $newMessages{$k}->{fuzzy} . "\n", RESET;
100 print GREEN "> msgid = \"$k\"\n", RESET;
101 print GREEN "> msgstr = \"" . $newMessages{$k}->{msgstr} . "\"\n", RESET;
104 &printExtraMessages("fuzzy", \%Fuzzy);
105 &printExtraMessages("untranslated", \%Untranslated);
111 my ($spec, $filename) = @_;
113 if (! -e $filename ) {
114 die("$spec po file does not exist");
116 if ( ! -f $filename ) {
117 die("$spec po file is not regular");
119 if ( ! -r $filename ) {
120 die("$spec po file is not readable");
126 my ($k, $nk, $rM, $rnM) = @_;
127 print "diffline = " . $rM->{line} . "," . $rnM->{line} . "\n" if ($printlines);
128 print " msgid = \"$k\"\n";
129 if ($rM->{fuzzy} eq $rnM->{fuzzy}) {
130 print " fuzzy = " . $rM->{fuzzy} . "\n" if ($printlines);
133 print RED "< fuzzy = " . $rM->{fuzzy} . "\n", RESET;
135 print RED "< msgstr = " . $rM->{msgstr} . "\n", RESET;
137 print GREEN "> msgid = \"$nk\"\n", RESET;
139 if ($rM->{fuzzy} ne $rnM->{fuzzy}) {
140 print GREEN "> fuzzy = " . $rnM->{fuzzy} . "\n", RESET;
142 print GREEN "> msgstr = " . $rnM->{msgstr} . "\n", RESET;
148 my ($k, $rM, $rnM) = @_;
150 $doprint = 1 if ($rM->{fuzzy} != $rnM->{fuzzy});
151 $doprint = 1 if ($rM->{msgstr} ne $rnM->{msgstr});
154 &printDiff($k, $k, $rM, $rnM);
158 sub parse_po_file($$)
160 my ($file, $rMessages) = @_;
161 if (open(FI, '<', $file)) {
165 while (my $line = <FI>) {
167 &parse_po_line($line, $lineno, $rMessages);
169 &parse_po_line("", $lineno + 1, $rMessages);
174 sub parse_po_line($$$)
176 my ($line, $lineno, $rMessages) = @_;
179 if ($status eq "normal") {
180 if ($line =~ /^#, fuzzy/) {
183 elsif ($line =~ s/^msgid\s+//) {
184 $foundline = $lineno;
187 &parse_po_line($line);
190 elsif ($status eq "msgid") {
191 if ($line =~ /^\s*"(.*)"\s*/) {
194 elsif ($line =~ s/^msgstr\s+//) {
197 &parse_po_line($line);
200 elsif ($status eq "msgstr") {
201 if ($line =~ /^\s*"(.*)"\s*/) {
206 $rMessages->{$msgid}->{line} = $foundline;
207 $rMessages->{$msgid}->{fuzzy} = $fuzzy;
208 $rMessages->{$msgid}->{msgstr} = $msgstr;
215 die("invalid status");
219 sub getLineSortedKeys($)
221 my ($rMessages) = @_;
223 return sort {$rMessages->{$a}->{line} <=> $rMessages->{$b}->{line};} keys %{$rMessages};
226 sub printExtraMessages($$)
228 my ($type, $rExtra) = @_;
229 my @UntranslatedKeys = sort { $a <=> $b;} keys %{$rExtra};
231 if (@UntranslatedKeys > 0) {
232 print "Still " . 0 + @UntranslatedKeys . " $type messages found in $ARGV[1]\n";
233 for my $l (@UntranslatedKeys) {
234 print "> line $l: \"" . $rExtra->{$l} . "\"\n";