source: subversion/applications/editors/josm/plugins/photoadjust/i18n/i18nlib.pm @ 33803

Last change on this file since 33803 was 31960, checked in by holgermappt, 4 years ago

Added scripts that read the JOSM *.lang language files.

File size: 6.4 KB
Line 
1### i18nlib.pm - Perl library based on i18n/i18n.pl.
2
3use utf8;
4binmode STDERR, ":encoding(utf8)";
5use Term::ReadKey;
6use Encode;
7
8my $waswarn = 0;
9my $maxcount = 0;
10
11sub loadfiles($@)
12{
13  my $desc;
14  my $all;
15  my ($lang,@files) = @_;
16  foreach my $file (@files)
17  {
18    die "Could not open file $file." if(!open FILE,"<:utf8",$file);
19    my $linenum = 0;
20
21    my $cnt = -1; # don't count translators info
22    if($file =~ /\/(.._..(@.+)?)\.po$/ || $file =~ /\/(...?(@.+)?)\.po$/)
23    {
24      my $l = $1;
25      ++$lang->{$l};
26      my %postate = (last => "", type => "");
27      my $linenum = 0;
28      print "Reading file $file\n";
29      while(<FILE>)
30      {
31        ++$linenum;
32        my $fn = "$file:$linenum";
33        chomp;
34        if($_ =~ /^#/ || !$_)
35        {
36          checkpo(\%postate, \%all, $l, "line $linenum in $file", $keys, 1);
37          $postate{fuzzy} = 1 if ($_ =~ /fuzzy/);
38        }
39        elsif($_ =~ /^"(.*)"$/) {$postate{last} .= $1;}
40        elsif($_ =~ /^(msg.+) "(.*)"$/)
41        {
42          my ($n, $d) = ($1, $2);
43          ++$cnt if $n eq "msgid";
44          my $new = !${postate}{fuzzy} && (($n eq "msgid" && $postate{type} ne "msgctxt") || ($n eq "msgctxt"));
45          checkpo(\%postate, \%all, $l, "line $linenum in $file", $keys, $new);
46          $postate{last} = $d;
47          $postate{type} = $n;
48          $postate{src} = $fn if $new;
49        }
50        else
51        {
52          die "Strange line $linenum in $file: $_.";
53        }
54      }
55      checkpo(\%postate, \%all, $l, "line $linenum in $file", $keys, 1);
56    }
57    else
58    {
59      die "File format not supported for file $file.";
60    }
61    $maxcount = $cnt if $cnt > $maxcount;
62    close(FILE);
63  }
64  return %all;
65}
66
67my $alwayspo = 0;
68my $alwaysup = 0;
69my $noask = 0;
70my $conflicts;
71sub copystring($$$$$$$)
72{
73  my ($data, $en, $l, $str, $txt, $context, $ispo) = @_;
74
75  $en = "___${context}___$en" if $context;
76
77  if(exists($data->{$en}{$l}) && $data->{$en}{$l} ne $str)
78  {
79    return if !$str;
80    if($l =~ /^_/)
81    {
82      $data->{$en}{$l} .= ";$str" if !($data->{$en}{$l} =~ /$str/);
83    }
84    elsif(!$data->{$en}{$l})
85    {
86      $data->{$en}{$l} = $str;
87    }
88    else
89    {
90
91      my $f = $data->{$en}{_file} || "";
92      $f = ($f ? "$f;".$data->{$en}{"_src.$l"} : $data->{$en}{"_src.$l"}) if $data->{$en}{"_src.$l"};
93      my $isotherpo = ($f =~ /\.po\:/);
94      my $pomode = ($ispo && !$isotherpo) || (!$ispo && $isotherpo);
95
96      my $mis = "String mismatch for '$en' **$str** ($txt) != **$data->{$en}{$l}** ($f)\n";
97      my $replace = 0;
98
99      if(($conflicts{$l}{$str} || "") eq $data->{$en}{$l}) {}
100      elsif($pomode && $alwaysup) { $replace=$isotherpo; }
101      elsif($pomode && $alwayspo) { $replace=$ispo; }
102      elsif($noask) { print $mis; ++$waswarn; }
103      else
104      {
105        ReadMode 4; # Turn off controls keys
106        my $arg = "(l)eft, (r)ight";
107        $arg .= ", (p)o, (u)pstream[ts/mat], all p(o), all up(s)tream" if $pomode;
108        $arg .= ", e(x)it: ";
109        print "$mis$arg";
110        while((my $c = getc()))
111        {
112          if($c eq "l") { $replace=1; }
113          elsif($c eq "r") {}
114          elsif($c eq "p" && $pomode) { $replace=$ispo; }
115          elsif($c eq "u" && $pomode) { $replace=$isotherpo; }
116          elsif($c eq "o" && $pomode) { $alwayspo = 1; $replace=$ispo; }
117          elsif($c eq "s" && $pomode) { $alwaysup = 1; $replace=$isotherpo; }
118          elsif($c eq "x") { $noask = 1; ++$waswarn; }
119          else { print "\n$arg"; next; }
120          last;
121        }
122        print("\n");
123        ReadMode 0; # Turn on controls keys
124      }
125      if(!$noask)
126      {
127        if($replace)
128        {
129          $data->{$en}{$l} = $str;
130          $conflicts{$l}{$data->{$en}{$l}} = $str;
131        }
132        else
133        {
134          $conflicts{$l}{$str} = $data->{$en}{$l};
135        }
136      }
137    }
138  }
139  else
140  {
141    $data->{$en}{$l} = $str;
142  }
143}
144
145sub checkpo($$$$$$)
146{
147  my ($postate, $data, $l, $txt, $keys, $new) = @_;
148
149  if($postate->{type} eq "msgid") {$postate->{msgid} = $postate->{last};}
150  elsif($postate->{type} eq "msgid_plural") {$postate->{msgid_1} = $postate->{last};}
151  elsif($postate->{type} =~ /^msgstr(\[0\])?$/) {$postate->{msgstr} = $postate->{last};}
152  elsif($postate->{type} =~ /^msgstr\[(.+)\]$/) {$postate->{"msgstr_$1"} = $postate->{last};}
153  elsif($postate->{type} eq "msgctxt") {$postate->{context} = $postate->{last};}
154  elsif($postate->{type}) { die "Strange type $postate->{type} found\n" }
155
156  if($new)
157  {
158    if((!$postate->{fuzzy}) && $postate->{msgstr} && $postate->{msgid})
159    {
160      copystring($data, $postate->{msgid}, $l, $postate->{msgstr},$txt,$postate->{context}, 1);
161      for($i = 1; exists($postate->{"msgstr_$i"}); ++$i)
162      { copystring($data, $postate->{msgid}, "$l.$i", $postate->{"msgstr_$i"},$txt,$postate->{context}, 1); }
163      if($postate->{msgid_1})
164      { copystring($data, $postate->{msgid}, "en.1", $postate->{msgid_1},$txt,$postate->{context}, 1); }
165      copystring($data, $postate->{msgid}, "_src.$l", $postate->{src},$txt,$postate->{context}, 1);
166    }
167    elsif($postate->{msgstr} && !$postate->{msgid})
168    {
169      my %k = ($postate->{msgstr} =~ /(.+?): +(.+?)\\n/g);
170      # take the first one!
171      for $a (sort keys %k)
172      {
173        $keys->{$l}{$a} = $k{$a} if !$keys->{$l}{$a};
174      }
175    }
176    foreach my $k (keys %{$postate})
177    {
178      delete $postate->{$k};
179    }
180    $postate->{type} = $postate->{last} = "";
181  }
182}
183
184### Load a JOSM language file.  The format is two byte string length, then the
185### string.  Length 0x0000 means the string was not in the PO file, i.e. there
186### is no translation (there are no empty strings).  Length 0xfffe (65534)
187### means the string is the same as the original string.  Length 0xffff ends
188### the string list.
189###
190### Args:
191###     filename (str): Path to language file.
192###
193### Returns:
194###     array: List of decoded strings.
195sub loadLangFile {
196  my ($filename) = @_;
197  my @strings;
198  open(my $langFd, $filename) or die "Cannot open file $filename: $!";
199  binmode($langFd);
200  my $buffer;
201  my $length;
202  while (1) {
203    read($langFd, $buffer, 2);
204    $length = unpack("n", $buffer);
205    die "Unable to read string length" unless ($buffer);
206    if ($length == 0) {
207      push(@strings, "");
208    }
209    elsif ($length == 0xfffe) {
210      push(@strings, "(see original string)");
211    }
212    elsif ($length == 0xffff) {
213      last;
214    }
215    else {
216      read($langFd, $buffer, $length);
217      push(@strings, $buffer);
218    }
219  }
220  close($langFd);
221  return @strings;
222}
223
2241;
Note: See TracBrowser for help on using the repository browser.