File Coverage

blib/lib/Translate/Fluent/ResourceGroup.pm
Criterion Covered Total %
statement 109 129 84.5
branch 37 64 57.8
condition 19 34 55.8
subroutine 12 12 100.0
pod 5 6 83.3
total 182 245 74.2


line stmt bran cond sub pod time code
1             package Translate::Fluent::ResourceGroup;
2              
3 6     6   43 use Moo;
  6         13  
  6         54  
4              
5             has sets => (
6             is => 'rw',
7             default => sub { {} },
8             );
9              
10             has fallback_order => (
11             is => 'ro',
12             default => sub { ['language' ] },
13             );
14              
15             has default_language => (
16             is => 'ro',
17             default => sub { 'en' },
18             );
19              
20 6     6   4639 use Translate::Fluent::ResourceGroup::Context;
  6         19  
  6         184  
21 6     6   44 use Translate::Fluent::ResourceSet;
  6         11  
  6         10009  
22              
23             sub __build_self {
24 2     2   8 my ($class, $context) = @_;
25            
26 2         6 my %params = ();
27 2 50       9 if ($context->{default_language}) {
28 0         0 $params{default_language} = delete $context->{default_language};
29             }
30 2 50       8 if ($context->{fallback_order}) {
31 0         0 $params{fallback_order} = delete $context->{fallback_order};
32             }
33              
34 2         12 return $class->new( %params );
35             }
36              
37             sub slurp_file {
38 14     14 0 46 my ($self, $fname, $context) = @_;
39              
40 14 50       51 $self = $self->__build_self( $context )
41             unless ref $self;
42            
43 14         49 local $/ = undef;
44 14 50       774 open my $fh, $fname or do {
45 0         0 warn "Error opening file '$fname'";
46 0         0 next;
47             };
48              
49 14         523 my $fluent = <$fh>;
50 14 50       62 next unless $fluent; # is the file empty?
51              
52 14 100       121 if (my ($ctx) = $fluent =~ m{ \A\#\s*context:\s*([^\n]+)\n }x) {
53 12         27 my %fcontext;
54            
55 12         96 my @fcontext = map { split /\s*[:=]\s*/, $_, 2 } split /\s*[:=]\s/, $ctx;
  24         78  
56              
57 12 50       50 if ( !( scalar @fcontext % 2) ) {
58 12         39 %fcontext = @fcontext;
59              
60             $context->{ $_ } //= $fcontext{ $_ }
61 12   33     104 for keys %fcontext;
62             } else {
63 0         0 print STDERR "invalid context: '$ctx'\n";
64 0         0 warn "Invalid context in fluent file '$fname' - ignoring";
65             }
66             }
67              
68 14         56 my $resset = Translate::Fluent::Parser::parse_string( $fluent );
69 14 100       42 if ($resset) {
70 12         40 $self->add_resource_set( $resset, $context );
71             }
72              
73 14 50       36 return $self if defined wantarray;
74              
75 14         331 return;
76             }
77              
78             sub slurp_directory {
79 2     2 1 96 my ($self, $directory, $context) = @_;
80              
81 2 50       15 $self = $self->__build_self( $context )
82             unless ref $self;
83            
84 2         9 for my $k (qw(default_language fallback_order)) {
85             die "'$k' is invalid when adding resources to a resource group"
86 4 50       15 if $context->{$k};
87             }
88              
89 2   50     15 my $recursive = delete $context->{recursive} // 0;
90              
91 2 50       17 $directory .='/' unless substr($directory, -1) eq '/';
92              
93 2 50       127 opendir my $dh, $directory or die "Can't open $directory: $!";
94 2         108 my @all = readdir( $dh );
95 2         13 my @files = grep { m{ \.flt\z }xi } @all;
  18         56  
96 2         35 closedir( $dh );
97              
98             # first we slurp the subdirectories, so that the files
99             # on the top directories override the files in the sub directories
100             # I could go both ways, but I think it is more intuitive this way
101             # TODO: add directory priority to the docs of slurp_directory
102 2 50       11 if ($recursive) {
103 0 0       0 my @dirs = grep { !m{\A\.} and -d "$directory$_" } @all;
  0         0  
104              
105 0         0 for my $dir ( @dirs ) {
106 0         0 $self->slurp_directory( "$directory$dir", $context );
107             }
108             }
109              
110 2         8 for my $fname ( @files ) {
111 14         37 my %context = %{$context};
  14         41  
112            
113 14         75 my $fname = "$directory$fname";
114 14         56 $self->slurp_file( $fname, \%context );
115             }
116              
117 2         34 return $self;
118             }
119              
120             #TODO: add override priority to add_resource_set docs.
121             sub add_resource_set {
122 13     13 1 38 my ($self, $resource_set, $context ) = @_;
123              
124 13         29 my @kv = ();
125 13         20 for my $fbo (@{ $self->fallback_order }) {
  13         44  
126 13   66     68 my $fbok = $context->{ $fbo }
127             || ($fbo eq 'language' ? 'dev' : 'default');
128            
129 13         35 push @kv, $fbok;
130             }
131              
132 13         34 my $key = join '>', @kv;
133              
134 13         85 my $reset = $self->sets->{ $key };
135 13 50       30 if ( $reset ) {
136 0         0 for my $k (keys %{ $resource_set->resources }) {
  0         0  
137 0         0 $reset->add_resource( $resource_set->resources->{ $k } );
138             }
139              
140             } else {
141 13         46 $self->sets->{ $key } = $resource_set;
142              
143             }
144              
145 13         29 return;
146             }
147              
148             sub translate {
149 15     15 1 6454 my ($self, $res_id, $variables, $context) = @_;
150              
151             $context = $variables->{__context}
152 15 50 66     57 if !$context and $variables->{__context};
153              
154 15         20 my $_ctx;
155 15 50       38 if (ref $context eq 'Translate::Fluent::ResourceGroup::Context') {
156 0         0 $_ctx = $context;
157 0         0 $context = $_ctx->context;
158             }
159              
160 15         36 my $res = $self->_find_resource( $res_id, $context );
161              
162 15 100 100     83 return unless $res and $res->isa("Translate::Fluent::Elements::Message");
163              
164 13   33     276 $_ctx ||= Translate::Fluent::ResourceGroup::Context->new(
165             context => $context,
166             resgroup => $self,
167             );
168            
169 13   100     2241 return $res->translate({ %{$variables//{}}, __resourceset => $_ctx });
  13         67  
170             }
171              
172             sub get_term {
173 12     12 1 618 my ($self, $term_id, $context) = @_;
174              
175 12         23 my $term = $self->_find_resource( $term_id, $context );
176              
177 12 100       42 return unless $term->isa("Translate::Fluent::Elements::Term");
178              
179 11         24 return $term;
180             }
181              
182             sub get_message {
183 3     3 1 7 my ($self, $message_id, $context) = @_;
184              
185 3         5 my $res = $self->_find_resource( $message_id, $context );
186              
187 3 50       9 return unless $res->isa("Translate::Fluent::Elements::Message");
188              
189 3         7 return $res;
190             }
191              
192             sub _find_resource {
193 30     30   50 my ($self, $res_id, $context) = @_;
194              
195 30   66     84 my $lang = $context->{language} || $self->default_language;
196 30         45 my %ctx = ();
197 30         33 my @fborder = @{ $self->fallback_order };
  30         70  
198 30         53 for my $fb ( @fborder ) {
199 30   66     101 $ctx{ $fb } = $context->{ $fb }
200             || (($fb eq 'language') ? $lang : 'default');
201             }
202 30         71 my %fbnext = map { $fborder[$_-1] => $fborder[$_] } 1..$#fborder;
  0         0  
203 30         44 my $fbnext = ($fborder[0]);
204              
205 30         38 my $res;
206              
207             RESSET:
208 30         55 while (!$res) {
209 70         102 my $key = join '>', map { $ctx{$_} } @fborder;
  70         153  
210             # use Data::Dumper;
211             # print STDERR "checking '$key' => ", Dumper( \%ctx );
212            
213 70 100       279 if ( my $rset = $self->sets->{ $key }) {
214 31 100       100 last RESSET if $res = $rset->resources->{ $res_id };
215             }
216              
217 41 50       140 my $fbnext_default = $fbnext eq 'language' ? 'dev' : 'default';
218 41 100       74 if ($ctx{ $fbnext } eq $fbnext_default) {
219             do {
220             last RESSET
221 1 50       4 unless $fbnext{ $fbnext }; #no where else to look for
222              
223 0 0 0     0 $ctx{ $fbnext } = $context->{ $fbnext }
224             || $fbnext eq 'language' ? $lang : 'default';
225              
226 0         0 $fbnext = $fbnext{ $fbnext };
227              
228 1         2 } until $ctx{ $fbnext } ne $fbnext_default;
229              
230             $ctx{ $fbnext } = $fbnext eq 'language'
231 0 0       0 ? ( $self->__fallback_languages( $ctx{language} ) )[1]
232             : 'default';
233 0         0 $fbnext = $fborder[0];
234              
235             } else {
236             $ctx{ $fbnext } = $fbnext eq 'language'
237 40 50       99 ? ( $self->__fallback_languages( $ctx{language} ) )[1]
238             : 'default';
239             }
240             };
241              
242 30         65 return $res;
243             }
244              
245             sub __fallback_languages {
246 40     40   59 my ($self, $lang, $default_lang) = @_;
247              
248 40   33     177 $default_lang ||= $self->default_language;
249              
250 40 50       90 my @langs = ($lang) if $lang;
251              
252 40   66     143 while ($lang and $lang=~m{\-}) {
253 4         33 $lang =~ s{-\w+\z}{};
254 4         16 push @langs, $lang;
255             }
256 40 100       75 unless ($lang eq $default_lang) {
257 13         18 push @langs, $default_lang;
258             }
259              
260 40 50       76 push @langs, 'dev' unless $default_lang eq 'dev';
261              
262 40         113 return @langs;
263             }
264              
265             1;
266              
267             __END__