source: osm/applications/editors/josm/i18n/i18n.pl@ 19496

Last change on this file since 19496 was 19496, checked in by stoecker, 15 years ago

i18n update

  • Property svn:executable set to *
File size: 7.9 KB
Line 
1#! /usr/bin/perl -w
2
3use utf8;
4use encoding "utf8";
5use Term::ReadKey;
6use Encode;
7
8my $waswarn = 0;
9my $maxcount = 0;
10
11main();
12
13sub getdate
14{
15 my @t=gmtime();
16 return sprintf("%04d-%02d-%02d %02d:%02d+0000",
17 1900+$t[5],$t[4]+1,$t[3],$t[2],$t[1]);
18}
19
20sub loadfiles($@)
21{
22 my $desc;
23 my $all;
24 my ($lang,@files) = @_;
25 foreach my $file (@files)
26 {
27 die "Could not open file $file." if(!open FILE,"<:utf8",$file);
28 my $linenum = 0;
29
30 my $cnt = -1; # don't count translators info
31 if($file =~ /\/(.._..)\.po$/ || $file =~ /\/(..)\.po$/)
32 {
33 my $l = $1;
34 ++$lang->{$l};
35 my %postate = (last => "", type => "");
36 my $linenum = 0;
37 print "Reading file $file\n";
38 while(<FILE>)
39 {
40 ++$linenum;
41 my $fn = "$file:$linenum";
42 chomp;
43 if($_ =~ /^#/ || !$_)
44 {
45 checkpo(\%postate, \%all, $l, "line $linenum in $file", $keys, 1);
46 $postate{fuzzy} = 1 if ($_ =~ /fuzzy/);
47 }
48 elsif($_ =~ /^"(.*)"$/) {$postate{last} .= $1;}
49 elsif($_ =~ /^(msg.+) "(.*)"$/)
50 {
51 my ($n, $d) = ($1, $2);
52 ++$cnt if $n eq "msgid";
53 my $new = !${postate}{fuzzy} && (($n eq "msgid" && $postate{type} ne "msgctxt") || ($n eq "msgctxt"));
54 checkpo(\%postate, \%all, $l, "line $linenum in $file", $keys, $new);
55 $postate{last} = $d;
56 $postate{type} = $n;
57 $postate{src} = $fn if $new;
58 }
59 else
60 {
61 die "Strange line $linenum in $file: $_.";
62 }
63 }
64 checkpo(\%postate, \%all, $l, "line $linenum in $file", $keys, 1);
65 }
66 else
67 {
68 die "File format not supported for file $file.";
69 }
70 $maxcount = $cnt if $cnt > $maxcount;
71 close(FILE);
72 }
73 return %all;
74}
75
76my $alwayspo = 0;
77my $alwaysup = 0;
78my $noask = 0;
79my $conflicts;
80sub copystring($$$$$$$)
81{
82 my ($data, $en, $l, $str, $txt, $context, $ispo) = @_;
83
84 $en = "___${context}___$en" if $context;
85
86 if(exists($data->{$en}{$l}) && $data->{$en}{$l} ne $str)
87 {
88 return if !$str;
89 if($l =~ /^_/)
90 {
91 $data->{$en}{$l} .= ";$str" if !($data->{$en}{$l} =~ /$str/);
92 }
93 elsif(!$data->{$en}{$l})
94 {
95 $data->{$en}{$l} = $str;
96 }
97 else
98 {
99
100 my $f = $data->{$en}{_file} || "";
101 $f = ($f ? "$f;".$data->{$en}{"_src.$l"} : $data->{$en}{"_src.$l"}) if $data->{$en}{"_src.$l"};
102 my $isotherpo = ($f =~ /\.po\:/);
103 my $pomode = ($ispo && !$isotherpo) || (!$ispo && $isotherpo);
104
105 my $mis = "String mismatch for '$en' **$str** ($txt) != **$data->{$en}{$l}** ($f)\n";
106 my $replace = 0;
107
108 if(($conflicts{$l}{$str} || "") eq $data->{$en}{$l}) {}
109 elsif($pomode && $alwaysup) { $replace=$isotherpo; }
110 elsif($pomode && $alwayspo) { $replace=$ispo; }
111 elsif($noask) { print $mis; ++$waswarn; }
112 else
113 {
114 ReadMode 4; # Turn off controls keys
115 my $arg = "(l)eft, (r)ight";
116 $arg .= ", (p)o, (u)pstream[ts/mat], all p(o), all up(s)tream" if $pomode;
117 $arg .= ", e(x)it: ";
118 print "$mis$arg";
119 while((my $c = getc()))
120 {
121 if($c eq "l") { $replace=1; }
122 elsif($c eq "r") {}
123 elsif($c eq "p" && $pomode) { $replace=$ispo; }
124 elsif($c eq "u" && $pomode) { $replace=$isotherpo; }
125 elsif($c eq "o" && $pomode) { $alwayspo = 1; $replace=$ispo; }
126 elsif($c eq "s" && $pomode) { $alwaysup = 1; $replace=$isotherpo; }
127 elsif($c eq "x") { $noask = 1; ++$waswarn; }
128 else { print "\n$arg"; next; }
129 last;
130 }
131 print("\n");
132 ReadMode 0; # Turn on controls keys
133 }
134 if(!$noask)
135 {
136 if($replace)
137 {
138 $data->{$en}{$l} = $str;
139 $conflicts{$l}{$data->{$en}{$l}} = $str;
140 }
141 else
142 {
143 $conflicts{$l}{$str} = $data->{$en}{$l};
144 }
145 }
146 }
147 }
148 else
149 {
150 $data->{$en}{$l} = $str;
151 }
152}
153
154sub checkpo($$$$$$)
155{
156 my ($postate, $data, $l, $txt, $keys, $new) = @_;
157
158 if($postate->{type} eq "msgid") {$postate->{msgid} = $postate->{last};}
159 elsif($postate->{type} eq "msgid_plural") {$postate->{msgid_1} = $postate->{last};}
160 elsif($postate->{type} =~ /^msgstr(\[0\])?$/) {$postate->{msgstr} = $postate->{last};}
161 elsif($postate->{type} =~ /^msgstr\[(.+)\]$/) {$postate->{"msgstr_$1"} = $postate->{last};}
162 elsif($postate->{type} eq "msgctxt") {$postate->{context} = $postate->{last};}
163 elsif($postate->{type}) { die "Strange type $postate->{type} found\n" }
164
165 if($new)
166 {
167 if((!$postate->{fuzzy}) && $postate->{msgstr} && $postate->{msgid})
168 {
169 copystring($data, $postate->{msgid}, $l, $postate->{msgstr},$txt,$postate->{context}, 1);
170 for($i = 1; exists($postate->{"msgstr_$i"}); ++$i)
171 { copystring($data, $postate->{msgid}, "$l.$i", $postate->{"msgstr_$i"},$txt,$postate->{context}, 1); }
172 if($postate->{msgid_1})
173 { copystring($data, $postate->{msgid}, "en.1", $postate->{msgid_1},$txt,$postate->{context}, 1); }
174 copystring($data, $postate->{msgid}, "_src.$l", $postate->{src},$txt,$postate->{context}, 1);
175 }
176 elsif($postate->{msgstr} && !$postate->{msgid})
177 {
178 my %k = ($postate->{msgstr} =~ /(.+?): +(.+?)\\n/g);
179 # take the first one!
180 for $a (sort keys %k)
181 {
182 $keys->{$l}{$a} = $k{$a} if !$keys->{$l}{$a};
183 }
184 }
185 foreach my $k (keys %{$postate})
186 {
187 delete $postate->{$k};
188 }
189 $postate->{type} = $postate->{last} = "";
190 }
191}
192
193sub makestring($)
194{
195 my ($str) = @_;
196 $str =~ s/\\"/"/g;
197 $str =~ s/\\n/\n/g;
198 $str = encode("utf8", $str);
199 return pack("n",length($str)).$str;
200}
201
202sub createlang($@)
203{
204 my ($data, @files) = @_;
205 foreach my $file (@files)
206 {
207 my $la;
208 my $cnt = 0;
209 if($file =~ /[-_](.._..)\.lang$/ || $file =~ /^(?:.*\/)?(.._..)\.lang$/ ||
210 $file =~ /[-_](...?)\.lang$/ || $file =~ /^(?:.*\/)?(..)\.lang$/)
211 {
212 $la = $1;
213 }
214 else
215 {
216 die "Language for file $file unknown.";
217 }
218 die "Could not open outfile $file\n" if !open FILE,">:raw",$file;
219
220 foreach my $en (sort keys %{$data})
221 {
222 next if $data->{$en}{"en.1"};
223 my $val;
224 if($la eq "en")
225 {
226 ++$cnt;
227 $val = $en;
228 $val =~ s/^___(.*)___/_:$1\n/;
229 }
230 else
231 {
232 my $ennoctx = $en;
233 $ennoctx =~ s/^___(.*)___//;
234 $val = (exists($data->{$en}{$la})) ? $data->{$en}{$la} : "";
235 ++$cnt if $val;
236 $val = "" if($ennoctx eq $val);
237 }
238 print FILE makestring($val);
239 }
240 print FILE pack "n",0xFFFF;
241 foreach my $en (sort keys %{$data})
242 {
243 next if !$data->{$en}{"en.1"};
244 my $num;
245 for($num = 1; exists($data->{$en}{"$la.$num"}); ++$num)
246 { }
247 my $val;
248 if($la eq "en")
249 {
250 ++$cnt;
251 $val = $en;
252 $val =~ s/^___(.*)___/_:$1\n/;
253 }
254 else
255 {
256 $val = (exists($data->{$en}{$la})) ? $data->{$en}{$la} : "";
257 --$num if(!$val);
258 ++$cnt if $val;
259 if($num == 2)
260 {
261 my $ennoctx = $en;
262 $ennoctx =~ s/^___(.*)___//;
263 $num = 0 if $val eq $ennoctx && $data->{$en}{"$la.1"} eq $data->{$en}{"en.1"};
264 }
265 }
266
267 print FILE pack "C",$num;
268 if($num)
269 {
270 print FILE makestring($val);
271 for($num = 1; exists($data->{$en}{"$la.$num"}); ++$num)
272 {
273 print FILE makestring($data->{$en}{"$la.$num"});
274 }
275 }
276 }
277 close FILE;
278 print "Created file $file: Added $cnt strings out of $maxcount.\n";
279 }
280}
281
282sub main
283{
284 my %lang;
285 my @po;
286 my $basename = shift @ARGV;
287 foreach my $arg (@ARGV)
288 {
289 foreach my $f (glob $arg)
290 {
291 if($f =~ /\*/) { printf "Skipping $f\n"; }
292 elsif($f =~ /\.po$/) { push(@po, $f); }
293 else { die "unknown file extension."; }
294 }
295 }
296 my %data = loadfiles(\%lang,@po);
297 my @clang;
298 foreach my $la (sort keys %lang)
299 {
300 push(@clang, "${basename}$la.lang");
301 }
302 push(@clang, "${basename}en.lang");
303 die "There have been warning. No output.\n" if $waswarn;
304
305 createlang(\%data, @clang);
306}
Note: See TracBrowser for help on using the repository browser.