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
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
38 while(defined($ARGV[0])) {
39 last if ($ARGV[0] !~ /^\-/);
40 my $param = shift(@ARGV);
42 my $name = shift(@ARGV);
46 if (! defined($names[0])) {
47 push(@names, "original");
49 if (! defined($names[1])) {
54 die('"', join('" "', @names, @ARGV) . "\" Expected exactly 2 parameters");
57 &check($names[0], $ARGV[0]);
58 &check($names[1], $ARGV[1]);
60 &parse_po_file($ARGV[0], \%Messages);
61 &parse_po_file($ARGV[1], \%newMessages);
63 my @MsgKeys = &getLineSortedKeys(\%newMessages);
65 print "<<< \"$names[0]\"\n";
66 print ">>> \"$names[1]\"\n";
67 for my $k (@MsgKeys) {
68 if ($newMessages{$k}->{msgstr} eq "") {
69 # this is still untranslated string
70 $Untranslated{$newMessages{$k}->{line}} = $k;
72 elsif ($newMessages{$k}->{fuzzy}) {
74 $Fuzzy{$newMessages{$k}->{line}} = $k;
76 if (exists($Messages{$k})) {
77 &printIfDiff($k, $Messages{$k}, $newMessages{$k});
78 delete($Messages{$k});
79 delete($newMessages{$k});
83 @MsgKeys = &getLineSortedKeys(\%Messages);
84 for my $k (@MsgKeys) {
86 print "deleted message\n";
87 print "< line = " . $Messages{$k}->{line} . "\n";
89 print "< fuzzy = " . $Messages{$k}->{fuzzy} . "\n";
90 print "< msgid = \"$k\"\n";
91 print "< msgstr = \"" . $Messages{$k}->{msgstr} . "\"\n";
95 @MsgKeys = &getLineSortedKeys(\%newMessages);
96 for my $k (@MsgKeys) {
98 print "new message\n";
99 print "> line = " . $newMessages{$k}->{line} . "\n";
101 print "> fuzzy = " . $newMessages{$k}->{fuzzy} . "\n";
102 print "> msgid = \"$k\"\n";
103 print "> msgstr = \"" . $newMessages{$k}->{msgstr} . "\"\n";
107 &printExtraMessages("fuzzy", \%Fuzzy);
108 &printExtraMessages("untranslated", \%Untranslated);
114 my ($spec, $filename) = @_;
116 if (! -e $filename ) {
117 die("$spec po file does not exist");
119 if ( ! -f $filename ) {
120 die("$spec po file is not regular");
122 if ( ! -r $filename ) {
123 die("$spec po file is not readable");
129 my ($k, $nk, $rM, $rnM) = @_;
130 print "diffline = " . $rM->{line} . "," . $rnM->{line} . "\n";
131 print " msgid = \"$k\"\n";
132 if ($rM->{fuzzy} eq $rnM->{fuzzy}) {
133 print " fuzzy = " . $rM->{fuzzy} . "\n";
137 print "< fuzzy = " . $rM->{fuzzy} . "\n";
141 print "< msgstr = " . $rM->{msgstr} . "\n";
144 print "> msgid = \"$nk\"\n";
146 if ($rM->{fuzzy} ne $rnM->{fuzzy}) {
147 print "> fuzzy = " . $rnM->{fuzzy} . "\n";
149 print "> msgstr = " . $rnM->{msgstr} . "\n";
156 my ($k, $rM, $rnM) = @_;
158 $doprint = 1 if ($rM->{fuzzy} != $rnM->{fuzzy});
159 $doprint = 1 if ($rM->{msgstr} ne $rnM->{msgstr});
162 &printDiff($k, $k, $rM, $rnM);
166 sub parse_po_file($$)
168 my ($file, $rMessages) = @_;
169 if (open(FI, '<', $file)) {
173 while (my $line = <FI>) {
175 &parse_po_line($line, $lineno, $rMessages);
177 &parse_po_line("", $lineno + 1, $rMessages);
182 sub parse_po_line($$$)
184 my ($line, $lineno, $rMessages) = @_;
187 if ($status eq "normal") {
188 if ($line =~ /^#, fuzzy/) {
191 elsif ($line =~ s/^msgid\s+//) {
192 $foundline = $lineno;
195 &parse_po_line($line);
198 elsif ($status eq "msgid") {
199 if ($line =~ /^\s*"(.*)"\s*/) {
202 elsif ($line =~ s/^msgstr\s+//) {
205 &parse_po_line($line);
208 elsif ($status eq "msgstr") {
209 if ($line =~ /^\s*"(.*)"\s*/) {
214 $rMessages->{$msgid}->{line} = $foundline;
215 $rMessages->{$msgid}->{fuzzy} = $fuzzy;
216 $rMessages->{$msgid}->{msgstr} = $msgstr;
223 die("invalid status");
227 sub getLineSortedKeys($)
229 my ($rMessages) = @_;
231 return sort {$rMessages->{$a}->{line} <=> $rMessages->{$b}->{line};} keys %{$rMessages};
234 sub printExtraMessages($$)
236 my ($type, $rExtra) = @_;
237 my @UntranslatedKeys = sort { $a <=> $b;} keys %{$rExtra};
239 if (@UntranslatedKeys > 0) {
240 print "Still " . 0 + @UntranslatedKeys . " $type messages found in $ARGV[1]\n";
241 for my $l (@UntranslatedKeys) {
242 print "> line $l: \"" . $rExtra->{$l} . "\"\n";