File Coverage

blib/lib/Locale/TextDomain/OO/Extract/Xslate.pm
Criterion Covered Total %
statement 86 114 75.4
branch 27 40 67.5
condition 37 96 38.5
subroutine 12 12 100.0
pod 1 1 100.0
total 163 263 61.9


line stmt bran cond sub pod time code
1             package Locale::TextDomain::OO::Extract::Xslate;
2             # vim:syntax=perl:tabstop=4:number:noexpandtab:
3             $Locale::TextDomain::OO::Extract::Xslate::VERSION = '0.01';
4             # ABSTRACT: Extract messages from Text::Xslate templates for translation with Locale::TextDomain::OO
5            
6 3     3   22811 use strict;
  3         5  
  3         85  
7 3     3   14 use warnings;
  3         6  
  3         84  
8 3     3   2431 use Moo;
  3         46137  
  3         18  
9 3     3   8411 use Path::Tiny;
  3         40157  
  3         244  
10 3     3   2491 use namespace::autoclean;
  3         48090  
  3         13  
11            
12             with qw(
13             Locale::TextDomain::OO::Extract::Role::File
14             );
15              
16             has 'debug' => (
17             is => 'rw',
18             default => 0,
19             );
20              
21             has 'syntax' => (
22             is => 'ro',
23             default => 'Kolon',
24             );
25              
26             has 'parser' => (
27             is => 'lazy',
28             init_arg => undef,
29             );
30              
31             sub _build_parser {
32 2     2   848 my $self = shift;
33 2         11 my $syntax = $self->syntax;
34 2     2   148 eval "use Text::Xslate::Syntax::${syntax};";
  2         1692  
  2         129951  
  2         54  
35 2 50       15 die $@ if $@;
36 2         38 "Text::Xslate::Syntax::${syntax}"->new();
37             }
38              
39             sub extract {
40 4     4 1 17287 my $self = shift;
41 4         11 my $messages = [];
42 4         14 my $filename = $self->filename;
43 4         122 $self->_scan_file( $messages, $filename );
44              
45 4         27 my ( $cat, $dom ) = ( $self->category, $self->domain );
46 4         293 foreach my $msg (@{ $messages }) {
  4         12  
47             $self->add_message({
48             category => ( $cat // '' ),
49             domain => ( $dom // '' ),
50             msgctxt => ( $msg->{'MSGCTXT'} // '' ),
51             msgid => ( $msg->{'MSGID'} // '' ),
52             msgid_plural => ( $msg->{'MSGID_PLURAL'} // '' ),
53 28   50     4919 reference => sprintf( '%s:%s', $msg->{'FILE'}, $msg->{'LINE'} ),
      50        
      100        
      50        
      100        
54             # automatic => 'my automatic comment',
55             });
56             }
57             }
58              
59             our $RESULT;
60             our $FILENAME;
61            
62             sub _scan {
63 4     4   11 my($self, $result, $filename, $data) = @_;
64 4         66 my $ast = $self->parser->parse($data);
65 4         84777 local $FILENAME = $filename;
66 4         10 local $RESULT = $result;
67 4         24 $self->_walker($ast);
68 4         774 return $result;
69             }
70            
71             sub _scan_file {
72 4     4   10 my ($self, $result, $filename) = @_;
73 4         17 my $data = path($filename)->slurp_utf8;
74 4         3734 return $self->_scan($result, $filename, $data);
75             }
76            
77             my $sp = '';
78             sub _walker {
79 1360     1360   1648 my($self, $ast) = @_;
80 1360 100 100     3559 $ast = [ $ast ] if $ast && ref($ast) eq 'Text::Xslate::Symbol';
81 1360 100 66     4107 return unless $ast && ref($ast) eq 'ARRAY';
82            
83 264         291 for my $sym (@{ $ast }) {
  264         467  
84              
85 452 100 66     2903 if ( $sym->arity eq 'methodcall' && $sym->value eq '.' ) {
    100 66        
86 20         46 my $second = $sym->second;
87 20 50 33     111 if ( $second && ref($second) eq 'Text::Xslate::Symbol' ) {
88 20 100 66     245 if ( $second->arity eq 'literal'
89             && $second->value =~ /\AN?(?:loc|_)_(x|n|nx|p|px|np|npx)?\Z/
90             ) {
91 14   100     53 my $flags = ( $1 || '' );
92 14         36 my $third = $sym->third;
93 14 50 33     144 if ( $third
      33        
      33        
94             && ref($third) eq 'ARRAY'
95             && $third->[0]
96             && ref( $third->[0] ) eq 'Text::Xslate::Symbol'
97             ) {
98 14         89 my %msg = ( FILE => $FILENAME, LINE => $second->line, FLAGS => $flags, );
99 14 50       33 if ( _parseMsg( \%msg, $flags, $third ) ) {
100 14         18 push @{$RESULT}, \%msg;
  14         40  
101             }
102             else {
103 0         0 warn "Invalid parameters for translation command at '$FILENAME', line " . $second->line;
104             }
105             }
106             else {
107 0         0 warn "Invalid parameters for translation command at '$FILENAME', line " . $second->line;
108             }
109             }
110             }
111             }
112             elsif ( $sym->arity eq 'call' && $sym->value eq '(' ) {
113 14         35 my $first = $sym->first;
114 14 50 33     89 if ( $first && ref($first) eq 'Text::Xslate::Symbol' ) {
115 14 50 33     189 if ( $first->arity eq 'name'
116             && $first->value =~ /\AN?(?:loc|_)_(x|n|nx|p|px|np|npx)?\Z/ ) {
117 14   100     58 my $flags = ( $1 || '' );
118 14         86 my $second = $sym->second;
119 14 50 33     149 if ( $second
      33        
      33        
120             && ref($second) eq 'ARRAY'
121             && $second->[0]
122             && ref( $second->[0] ) eq 'Text::Xslate::Symbol'
123             ) {
124 14         73 my %msg = ( FILE => $FILENAME, LINE => $first->line, FLAGS => $flags, );
125 14 50       47 if ( _parseMsg( \%msg, $flags, $second ) ) {
126 14         17 push @{$RESULT}, \%msg;
  14         51  
127             }
128             else {
129 0         0 warn "Invalid parameters for translation command at '$FILENAME', line " . $first->line;
130             }
131             }
132             else {
133 0         0 warn "Invalid parameters for translation command at '$FILENAME', line " . $first->line;
134             }
135             }
136             }
137             }
138            
139 452 50       1008 unless ( $self->debug ) {
140 452         1293 $self->_walker( $sym->first );
141 452         1227 $self->_walker( $sym->second );
142 452         1161 $self->_walker( $sym->third );
143             }
144             else {
145 0   0     0 warn $sp . "id: " . ( $sym->id // "undef()" ) . "\n";
146 0   0     0 warn $sp . "line: " . ( $sym->line // "undef()" ) . "\n";
147 0   0     0 warn $sp . "ldp: " . ( $sym->lbp // "undef()" ) . "\n";
148 0   0     0 warn $sp . "udp: " . ( $sym->ubp // "undef()" ) . "\n";
149 0   0     0 warn $sp . "type: " . ( $sym->type // "undef()" ) . "\n";
150 0   0     0 warn $sp . "arity: " . ( $sym->arity // "undef()" ) . "\n";
151 0   0     0 warn $sp . "assignment: " . ( $sym->assignment // "undef()" ) . "\n";
152 0   0     0 warn $sp . "value: " . ( $sym->value // "undef()" ) . "\n";
153            
154 0   0     0 warn $sp . "= first: " . ( $sym->first // "undef()" ) . "\n";
155 0         0 $sp .= ' ';
156 0         0 $self->_walker( $sym->first );
157 0         0 $sp =~ s/^..//;
158            
159 0   0     0 warn $sp . "= second: " . ( $sym->second // "undef()" ) . "\n";
160 0         0 $sp .= ' ';
161 0         0 $self->_walker( $sym->second );
162 0         0 $sp =~ s/^..//;
163            
164 0   0     0 warn $sp . "= third: " . ( $sym->third // "undef()" ) . "\n";
165 0         0 $sp .= ' ';
166 0         0 $self->_walker( $sym->third );
167 0         0 $sp =~ s/^..//;
168            
169 0         0 warn $sp . "----------\n";
170             }
171             }
172             }
173              
174             sub _parseMsg {
175 28     28   44 my ( $msg_r, $flags, $params ) = @_;
176              
177 28         35 my @p = @{ $params };
  28         67  
178 28         47 eval {
179 28 100       96 if ( index( $flags, 'p' ) >= 0 ) {
180 8 50 33     55 if ( defined $p[0] and $p[0]->arity eq 'literal' ) {
181 8         28 $msg_r->{'MSGCTXT'} = $p[0]->value;
182 8         11 shift @p;
183             }
184             else {
185 0         0 die;
186             }
187             }
188              
189 28 100       69 if ( index( $flags, 'n' ) >= 0 ) {
190 8 50 33     124 if ( defined $p[0] and $p[0]->arity eq 'literal'
      33        
      33        
      33        
191             and defined $p[1] and $p[1]->arity eq 'literal'
192             and defined $p[2]
193             ) {
194 8         28 $msg_r->{'MSGID'} = $p[0]->value;
195 8         28 $msg_r->{'MSGID_PLURAL'} = $p[1]->value;
196             }
197             else {
198 0         0 die;
199             }
200             }
201             else {
202 20 50 33     111 if ( defined $p[0] and $p[0]->arity eq 'literal' ) {
203 20         71 $msg_r->{'MSGID'} = $p[0]->value;
204             }
205             else {
206 0         0 die;
207             }
208             }
209             };
210              
211 28 50       64 return 0 if $@;
212 28         80 return 1;
213             }
214              
215             __PACKAGE__->meta->make_immutable;
216              
217             1;
218              
219             __END__