File Coverage

blib/lib/XML/TMX/FromPO.pm
Criterion Covered Total %
statement 14 159 8.8
branch 0 88 0.0
condition 0 30 0.0
subroutine 5 16 31.2
pod 5 5 100.0
total 24 298 8.0


line stmt bran cond sub pod time code
1             package XML::TMX::FromPO;
2             $XML::TMX::FromPO::VERSION = '0.39';
3             # ABSTRACT: Generates a TMX file from a group of PO files
4              
5 1     1   88897 use 5.010;
  1         14  
6 1     1   5 use warnings;
  1         2  
  1         78  
7 1     1   6 use strict;
  1         1  
  1         22  
8 1     1   355 use XML::TMX::Writer;
  1         4  
  1         55  
9 1     1   7 use Exporter ();
  1         2  
  1         1772  
10              
11              
12             our @ISA = 'Exporter';
13             our @EXPORT_OK = qw(&new &parse_dir &create_tmx &clean_tmx);
14              
15              
16             sub new {
17 0     0 1   my $proto = shift;
18 0   0       my $class = ref($proto) || $proto;
19 0           my $self = {};
20              
21 0           $self->{LANG} = undef;
22 0           $self->{OUTPUT} = undef;
23 0           $self->{DEBUG} = 0;
24              
25 0           __common_conf($self, @_);
26              
27 0 0         unless(defined($self->{CONVER})) {
28 0 0         if(system('recode >/dev/null 2>&1')) {
29 0           $self->{CONVERT} = 'iconv -f %t -t utf8 < %f';
30             } else {
31 0           $self->{CONVERT} = 'recode %t..utf8 < %f';
32             }
33             }
34              
35 0           $self->{TMX} = {};
36 0           bless($self, $class);
37 0           return($self);
38             }
39              
40              
41              
42             sub rec_get_po {
43 0     0 1   my $self = shift;
44 0           my $dir = shift;
45 0           my $lan1 = shift;
46 0           __common_conf($self, @_);
47              
48             # check if directory is readable
49 0 0         if(-f $dir) {
50 0           my $file=$dir;
51 0           my $lang = lc($lan1);
52              
53 0 0 0       if(!defined($self->{LANG}) || __check_lang($self, $lang)) {
54 0           __processa($self, $file, $lang);
55             }
56             }
57             else {
58 0 0         die("$dir is not a readable directory\n") unless(-d $dir);
59 0           for my $file (<$dir/*>) {
60              
61 0 0         if($file =~ /(.*)\.(po|messages)$/) {
    0          
    0          
62 0           my $lang = lc($lan1);
63              
64 0 0 0       if(!defined($self->{LANG}) || __check_lang($self, $lang)) {
65 0           __processa($self, $file, $lang);
66             }
67             }
68             elsif($file =~ /(.*)\.(\w+)\.(po|messages)$/) {
69 0           my $lang = lc($lan1);
70             ## ??? my $lang = "\L$2";
71              
72 0 0 0       if(!defined($self->{LANG}) || __check_lang($self, $lang)) {
73 0           __processa($self, $file, $lang);
74             }
75             }
76             elsif(-d $file) {
77 0           rec_get_po($self,$file,$lan1)
78             }
79             else {
80             ## warn ("$file ... não tem lingua\n") if($self->{DEBUG});
81             }
82             }
83             }
84              
85 0 0         __add_en($self) if(__check_lang($self, 'en'));
86 0           __limpa($self);
87             }
88              
89              
90              
91             sub parse_dir {
92 0     0 1   my $self = shift;
93 0           my $dir = shift;
94              
95 0           __common_conf($self, @_);
96              
97             # check if directory is readable
98 0 0         die("$dir is not a readable directory\n") unless(-d $dir);
99              
100 0           for my $file ((<$dir/*.po>),(<$dir/*.messages>)) {
101 0 0         if($file =~ /(\w+)\.(po|messages)$/) {
    0          
102 0           my $lang = "\L$1";
103              
104 0 0 0       if(!defined($self->{LANG}) || __check_lang($self, $lang)) {
105 0           __processa($self, $file, $lang);
106             }
107             } elsif($file =~ /(.*)\.(\w+)\.(po|messages)$/) {
108 0           my $lang = "\L$2";
109              
110 0 0 0       if(!defined($self->{LANG}) || __check_lang($self, $lang)) {
111 0           __processa($self, $file, $lang);
112             }
113             } else {
114 0 0         warn ("$file ... não tem lingua\n") if($self->{DEBUG});
115             }
116             }
117              
118 0 0         __add_en($self) if(__check_lang($self, 'en'));
119 0           __limpa($self);
120             }
121              
122             # return value:
123             # * 0 -> lang does not exist
124             # * 1 -> lang exists
125             sub __check_lang {
126 0     0     my $self = shift;
127 0           my $lang = shift;
128 0           my @regex = @{$self->{LANG}};
  0            
129              
130 0           while(my $regex = shift(@regex)) {
131 0 0         last if($regex gt $lang);
132 0 0         if($lang =~ /^$regex$/i) {
133 0           return(1);
134             }
135             }
136 0           return(0);
137             }
138              
139             sub __add_en {
140 0     0     my $self = shift;
141              
142 0           for my $str (keys %{$self->{TMX}}) {
  0            
143 0           $self->{TMX}{$str}{'en'} = $str;
144             }
145             }
146              
147              
148             sub create_tmx {
149 0     0 1   my $self = shift;
150 0           my $tmx = new XML::TMX::Writer();
151              
152 0           __common_conf($self, @_);
153              
154 0           my $n_langs = @{$self->{LANG}};
  0            
155              
156 0 0         if(defined($self->{OUTPUT})) {
157 0           $tmx->start_tmx(ID => 'XML::TMX::FromPO', OUTPUT => $self->{OUTPUT});
158             } else {
159 0           $tmx->start_tmx(ID => 'XML::TMX::FromPO');
160             }
161              
162 0           for my $chave (keys %{$self->{TMX}}) {
  0            
163 0           my $reg = __make_tu($self, $self->{TMX}{$chave});
164             # only write to file if all languages are defined
165 0 0         $tmx->add_tu(%{$reg}) if(keys(%{$reg}) >= $n_langs);
  0            
  0            
166             }
167 0           $tmx->end_tmx();
168             }
169              
170              
171             sub clean_tmx {
172 0     0 1   my $self = shift;
173 0           $self->{TMX} = {};
174             }
175              
176             sub __make_tu {
177 0     0     my $self = shift;
178 0           my $block = shift;
179 0           my $reg = {};
180              
181 0 0         if(!defined($self->{LANG})) {
182 0           return($block);
183             }
184              
185 0           for my $lang (keys %$block) {
186 0 0         $reg->{$lang} = $block->{$lang} if(__check_lang($self, $lang));
187             }
188 0           return($reg);
189             }
190              
191             sub __processa {
192 0     0     my $self = shift;
193 0           my $a = shift;
194 0           my $l = shift;
195              
196 0           local $/ = "\nmsgid";
197             #local $/ = "\nmsgid ";
198 0 0         print STDERR "$a\n" if($self->{DEBUG});
199              
200 0           my $codeline = `grep -i Content-Type $a | grep -i charset`;
201 0           my $code = "?";
202              
203 0 0         if($codeline =~ /charset=([\w-]+)/) { $code = $1; }
  0            
204              
205 0           my $convert = $self->{CONVERT};
206              
207 0           $convert =~ s/\%t/$code/i;
208 0           $convert =~ s/\%f/$a/i;
209              
210 0 0 0       if($code eq "?" || $code =~ /utf-?8/i ) { open(F,$a) or die;}
  0 0          
211 0 0         else { open(F,"$convert|") or die;}
212              
213 0           my $mi = 0;
214              
215 0           while() {
216 0           chomp;
217 0 0 0       next if($mi == 0 && /^msgid\s+""/);
218 0 0 0       if(/"Content-Type:/ && /charset=([\w-]+)/) { $code = $1; next }
  0            
  0            
219 0           s/(^|\n)\s*#.*//g;
220              
221             # s/_//g unless $under;
222              
223 0 0         next unless(/\n\s*msgstr/);
224 0           my ($m1,$m2) = ($`,$');
225              
226 0           $m1 =~ s/(^\s*"|"\s*$)//g;
227 0           $m1 =~ s/("\s*\n\s*")/ /g;
228 0           $m2 =~ s/(^\s*"|"\s*$)//g;
229 0           $m2 =~ s/("\s*\n\s*")/ /g;
230              
231 0 0         unless($m1) {
232 0           warn "\n====M1 vazio... \n$m1\n=$m2\n";
233 0           next;
234             }
235              
236 0 0         if($m2) {
237 0           $self->{TMX}{$m1}{$l} = $m2;
238             } # || "????? $m1";
239              
240             #$self->{TMX}{$m1}{'en'} = $m1;
241             # print "\n====\n$m1\n=$m2\n";
242              
243 0           $mi++;
244             }
245 0 0         print STDERR "Charset: $code\n" if($self->{DEGUB});
246 0           close F;
247             }
248              
249             sub __limpa {
250 0     0     my $self = shift;
251              
252             # possíveis limpezas
253             # (1) eliminar traduções que sejam igual ao original
254             # (2) eliminar strings que não contenham pelo menos 2 letras
255             # consecutivas
256             # (3) eliminar frases que fiquem sem traduções
257             #
258             # um teste realizado com os po's do evolution mostrou uma redução do
259             # ficheiro final de 12M para 8,6M, uma análise com o diff aos dumps
260             # permitiu ver que grande parte do ''lixo'' eram de (1)
261              
262 0           for my $h1 (keys %{$self->{TMX}}) {
  0            
263 0 0         if($h1 =~ /[a-z][a-z]/i) {
264 0           for my $h2 (keys %{$self->{TMX}{$h1}}) {
  0            
265             # optimização (1)
266 0 0 0       delete($self->{TMX}{$h1}{$h2}) if($h2 !~ /^en/i && $h1 eq $self->{TMX}{$h1}{$h2});
267             }
268             # optimização (3)
269 0 0         delete($self->{TMX}{$h1}) unless(keys %{$self->{TMX}{$h1}});
  0            
270             } else {
271             # optimização (2)
272 0           delete($self->{TMX}{$h1});
273             }
274             }
275             }
276              
277              
278              
279             sub __common_conf {
280 0     0     my $self = shift;
281 0           my %opt = @_;
282              
283 0 0         if(defined($opt{LANG})) {
284 0           my @list;
285 0           for my $l (sort(split(/\s+/, $opt{LANG}))) {
286 0 0         push(@list, $l) if($l =~ /^[a-z0-9_]+$/i);
287             }
288 0 0         $self->{LANG} = \@list if(@list);
289             }
290              
291 0 0         $self->{CONVERT} = $opt{CONVERT} if defined($opt{CONVERT});
292 0 0         $self->{OUTPUT} = $opt{OUTPUT} if defined($opt{OUTPUT});
293 0 0         $self->{DEBUG} = $opt{DEBUG} if defined($opt{DEBUG});
294             }
295              
296              
297             1;
298              
299             __END__