Browse Source

slurp_directory and pods

* implement ResourceGroup->slurp_directory
* add pods for most of the files

TODO: pods in Locale::Fluent

themage
theMage 8 months ago
parent
commit
a648c0e373
40 changed files with 871 additions and 32 deletions
  1. 0 2
      MANIFEST
  2. 12 0
      lib/Locale/Fluent.pm
  3. 14 0
      lib/Locale/Fluent/Elements.pm
  4. 20 0
      lib/Locale/Fluent/Elements/Argument.pm
  5. 16 0
      lib/Locale/Fluent/Elements/ArgumentList.pm
  6. 15 0
      lib/Locale/Fluent/Elements/Attribute.pm
  7. 9 0
      lib/Locale/Fluent/Elements/AttributeAccessor.pm
  8. 9 0
      lib/Locale/Fluent/Elements/Base.pm
  9. 14 0
      lib/Locale/Fluent/Elements/BlockPlaceable.pm
  10. 14 0
      lib/Locale/Fluent/Elements/BlockText.pm
  11. 14 0
      lib/Locale/Fluent/Elements/CallArguments.pm
  12. 10 0
      lib/Locale/Fluent/Elements/DefaultVariant.pm
  13. 9 0
      lib/Locale/Fluent/Elements/FunctionReference.pm
  14. 13 0
      lib/Locale/Fluent/Elements/InlineExpression.pm
  15. 14 0
      lib/Locale/Fluent/Elements/InlinePlaceable.pm
  16. 13 0
      lib/Locale/Fluent/Elements/InlineText.pm
  17. 17 0
      lib/Locale/Fluent/Elements/Message.pm
  18. 13 0
      lib/Locale/Fluent/Elements/MessageReference.pm
  19. 13 0
      lib/Locale/Fluent/Elements/NamedArgument.pm
  20. 13 0
      lib/Locale/Fluent/Elements/Pattern.pm
  21. 9 0
      lib/Locale/Fluent/Elements/PatternElement.pm
  22. 14 0
      lib/Locale/Fluent/Elements/SelectExpression.pm
  23. 13 0
      lib/Locale/Fluent/Elements/StringLiteral.pm
  24. 16 0
      lib/Locale/Fluent/Elements/Term.pm
  25. 13 0
      lib/Locale/Fluent/Elements/TermReference.pm
  26. 13 0
      lib/Locale/Fluent/Elements/Text.pm
  27. 13 0
      lib/Locale/Fluent/Elements/VariableReference.pm
  28. 15 0
      lib/Locale/Fluent/Elements/Variant.pm
  29. 44 0
      lib/Locale/Fluent/Parser.pm
  30. 267 30
      lib/Locale/Fluent/ResourceGroup.pm
  31. 64 0
      lib/Locale/Fluent/ResourceGroup/Context.pm
  32. 49 0
      lib/Locale/Fluent/ResourceSet.pm
  33. 57 0
      t/65-slurp.t
  34. 4 0
      test_files/slurp/base.en.flt
  35. 9 0
      test_files/slurp/base.flt
  36. 4 0
      test_files/slurp/base.it.flt
  37. 4 0
      test_files/slurp/base.nl.flt
  38. 4 0
      test_files/slurp/base.pt-br.flt
  39. 3 0
      test_files/slurp/base.pt-pt.flt
  40. 4 0
      test_files/slurp/base.pt.flt

+ 0 - 2
MANIFEST

@ -11,14 +11,12 @@ lib/Locale/Fluent/Elements/BlockText.pm
11 11
lib/Locale/Fluent/Elements/CallArguments.pm
12 12
lib/Locale/Fluent/Elements/DefaultVariant.pm
13 13
lib/Locale/Fluent/Elements/FunctionReference.pm
14
lib/Locale/Fluent/Elements/Identifier.pm
15 14
lib/Locale/Fluent/Elements/InlineExpression.pm
16 15
lib/Locale/Fluent/Elements/InlinePlaceable.pm
17 16
lib/Locale/Fluent/Elements/InlineText.pm
18 17
lib/Locale/Fluent/Elements/Message.pm
19 18
lib/Locale/Fluent/Elements/MessageReference.pm
20 19
lib/Locale/Fluent/Elements/NamedArgument.pm
21
lib/Locale/Fluent/Elements/NumberLiteral.pm
22 20
lib/Locale/Fluent/Elements/Pattern.pm
23 21
lib/Locale/Fluent/Elements/PatternElement.pm
24 22
lib/Locale/Fluent/Elements/SelectExpression.pm

+ 12 - 0
lib/Locale/Fluent.pm

@ -12,6 +12,18 @@ use Locale::Fluent::ResourceGroup;
12 12
#TODO: add methods for the most common locale::fluent operations
13 13
14 14
15
sub parse_file {
16
  my $class = shift;
17
18
  return Locale::Fluent::Parser::parse_file( @_ );
19
}
20
21
sub slurp_directory {
22
  my $class = shift;
23
24
  return Locale::Fluent::ResourceGroup->slurp_directory( @_ );
25
}
26
15 27
1; # End of Locale::Fluent
16 28
17 29

+ 14 - 0
lib/Locale/Fluent/Elements.pm

@ -50,3 +50,17 @@ sub create {
50 50
}
51 51
52 52
1;
53
54
__END__
55
56
=head1 NOTHING TO SEE HERE
57
58
this file is part of L<Locale::Fluent>. See its documentation for more information
59
60
=head2 create
61
62
this package implements a create method, but is not that interesting
63
64
65
=cut
66

+ 20 - 0
lib/Locale/Fluent/Elements/Argument.pm

@ -44,3 +44,23 @@ sub translate {
44 44
45 45
46 46
1;
47
48
__END__
49
50
=head1 NOTHING TO SEE HERE
51
52
This file is part of L<Locale::Fluent>. See its documentation for more
53
information.
54
55
=head2 identifier
56
57
this file implements an identifier method to allow to get the name of
58
an named_argument
59
60
=head2 translate
61
62
This file implements the translate method for choice variants, but it is not
63
that interesting.
64
65
=cut
66

+ 16 - 0
lib/Locale/Fluent/Elements/ArgumentList.pm

@ -41,3 +41,19 @@ sub to_variables {
41 41
42 42
43 43
1;
44
45
__END__
46
47
=head1 NOTHING TO SEE HERE
48
49
This file is part of L<Locale::Fluent>. See its documentation for more
50
information.
51
52
=head2 to_variables
53
54
This file implements the to_variables, to facilitate reusage of normal
55
translation  code when calling attributes with parameters, but it is not
56
that interesting.
57
58
=cut
59

+ 15 - 0
lib/Locale/Fluent/Elements/Attribute.pm

@ -25,3 +25,18 @@ sub translate {
25 25
26 26
27 27
1;
28
29
__END__
30
31
=head1 NOTHING TO SEE HERE
32
33
This file is part of L<Locale::Fluent>. See its documentation for more
34
information.
35
36
=head2 translate
37
38
this package implements a translate method for Attributes, but is not that
39
interesting
40
41
=cut
42

+ 9 - 0
lib/Locale/Fluent/Elements/AttributeAccessor.pm

@ -17,3 +17,12 @@ around BUILDARGS => sub {
17 17
};
18 18
19 19
1;
20
__END__
21
22
=head1 NOTHING TO SEE HERE
23
24
This file is part of L<Locale::Fluent>. See its documentation for more
25
information.
26
27
=cut
28

+ 9 - 0
lib/Locale/Fluent/Elements/Base.pm

@ -43,3 +43,12 @@ around BUILDARGS => sub {
43 43
44 44
1;
45 45
46
__END__
47
48
=head1 NOTHING TO SEE HERE
49
50
This file is part of L<Locale::Fluent>. See its documentation for more
51
information.
52
53
=cut
54

+ 14 - 0
lib/Locale/Fluent/Elements/BlockPlaceable.pm

@ -19,3 +19,17 @@ sub translate {
19 19
}
20 20
21 21
1;
22
23
__END__
24
25
=head1 NOTHING TO SEE HERE
26
27
This file is part of L<Locale::Fluent>. See its documentation for more
28
information.
29
30
=head2 translate
31
32
this package implements a translate method, but is not that interesting.
33
34
=cut
35

+ 14 - 0
lib/Locale/Fluent/Elements/BlockText.pm

@ -22,3 +22,17 @@ sub translate {
22 22
}
23 23
24 24
1;
25
26
__END__
27
28
=head1 NOTHING TO SEE HERE
29
30
This file is part of L<Locale::Fluent>. See its documentation for more
31
information.
32
33
=head2 translate
34
35
This package implements a translate method, but is not that interesting;
36
37
=cut
38

+ 14 - 0
lib/Locale/Fluent/Elements/CallArguments.pm

@ -18,3 +18,17 @@ sub to_variables {
18 18
}
19 19
20 20
1;
21
22
__END__
23
24
=head1 NOTHING TO SEE HERE
25
26
This file is part of L<Locale::Fluent>. See its documentation for more
27
information.
28
29
=head2 to_variables
30
31
this package implements a to_variables method, but is not that interesting
32
33
=cut
34

+ 10 - 0
lib/Locale/Fluent/Elements/DefaultVariant.pm

@ -4,3 +4,13 @@ use Moo;
4 4
extends 'Locale::Fluent::Elements::Variant';
5 5
6 6
1;
7
8
__END__
9
10
=head1 NOTHING TO SEE HERE
11
12
This file is part of L<Locale::Fluent>. See its documentation for more
13
information.
14
15
=cut
16

+ 9 - 0
lib/Locale/Fluent/Elements/FunctionReference.pm

@ -20,3 +20,12 @@ around BUILDARGS => sub {
20 20
};
21 21
22 22
1;
23
__END__
24
25
=head1 NOTHING TO SEE HERE
26
27
This file is part of L<Locale::Fluent>. See its documentation for more
28
information.
29
30
=cut
31

+ 13 - 0
lib/Locale/Fluent/Elements/InlineExpression.pm

@ -47,3 +47,16 @@ sub translate {
47 47
}
48 48
49 49
1;
50
__END__
51
52
=head1 NOTHING TO SEE HERE
53
54
This file is part of L<Locale::Fluent>. See its documentation for more
55
information.
56
57
=head2 translate
58
59
this package implements a translate method, but it is not that interesting
60
61
=cut
62

+ 14 - 0
lib/Locale/Fluent/Elements/InlinePlaceable.pm

@ -35,3 +35,17 @@ sub translate {
35 35
36 36
37 37
1;
38
39
__END__
40
41
=head1 NOTHING TO SEE HERE
42
43
This file is part of L<Locale::Fluent>. See its documentation for more
44
information.
45
46
=head2 translate
47
48
this package implements a translate method, but is not that interesting
49
50
=cut
51

+ 13 - 0
lib/Locale/Fluent/Elements/InlineText.pm

@ -15,3 +15,16 @@ sub translate {
15 15
}
16 16
17 17
1;
18
__END__
19
20
=head1 NOTHING TO SEE HERE
21
22
This file is part of L<Locale::Fluent>. See its documentation for more
23
information.
24
25
=head2 translate
26
27
this package implements a translate method, but is not that interesting
28
29
=cut
30

+ 17 - 0
lib/Locale/Fluent/Elements/Message.pm

@ -44,3 +44,20 @@ sub get_attribute_resource {
44 44
45 45
46 46
1;
47
48
__END__
49
50
=head1 NOTHING TO SEE HERE
51
52
This file is part of L<Locale::Fluent>. See its documentation for more
53
information.
54
55
=head2 translate
56
57
=head2 get_attribute_resource
58
59
this package implements the methods translate and get_attribute_resource, but
60
it is not that interesting
61
62
=cut
63

+ 13 - 0
lib/Locale/Fluent/Elements/MessageReference.pm

@ -41,3 +41,16 @@ sub translate {
41 41
}
42 42
43 43
1;
44
__END__
45
46
=head1 NOTHING TO SEE HERE
47
48
This file is part of L<Locale::Fluent>. See its documentation for more
49
information.
50
51
=head2 translate
52
53
this package implements a translate method, but it is not that interesting
54
55
=cut
56

+ 13 - 0
lib/Locale/Fluent/Elements/NamedArgument.pm

@ -32,3 +32,16 @@ sub translate {
32 32
}
33 33
34 34
1;
35
__END__
36
37
=head1 NOTHING TO SEE HERE
38
39
This file is part of L<Locale::Fluent>. See its documentation for more
40
information.
41
42
=head2 translate
43
44
this package implements a translate method, but it is not that interesting
45
46
=cut
47

+ 13 - 0
lib/Locale/Fluent/Elements/Pattern.pm

@ -30,3 +30,16 @@ sub translate {
30 30
}
31 31
32 32
1;
33
__END__
34
35
=head1 NOTHING TO SEE HERE
36
37
This file is part of L<Locale::Fluent>. See its documentation for more
38
information.
39
40
=head2 translate
41
42
this package implements a translate method, but it is not that interesting
43
44
=cut
45

+ 9 - 0
lib/Locale/Fluent/Elements/PatternElement.pm

@ -10,3 +10,12 @@ has [qw(inline_text block_text inline_placeable block_placeable)] => (
10 10
11 11
12 12
1;
13
__END__
14
15
=head1 NOTHING TO SEE HERE
16
17
This file is part of L<Locale::Fluent>. See its documentation for more
18
information.
19
20
=cut
21

+ 14 - 0
lib/Locale/Fluent/Elements/SelectExpression.pm

@ -61,3 +61,17 @@ sub translate {
61 61
package Locale::Fluent::Elements::_variantlist;
62 62
63 63
1;
64
65
__END__
66
67
=head1 NOTHING TO SEE HERE
68
69
This file is part of L<Locale::Fluent>. See its documentation for more
70
information.
71
72
=head2 translate
73
74
this package implements a translate method, but it is not that interesting
75
76
=cut
77

+ 13 - 0
lib/Locale/Fluent/Elements/StringLiteral.pm

@ -16,3 +16,16 @@ sub translate {
16 16
}
17 17
18 18
1;
19
__END__
20
21
=head1 NOTHING TO SEE HERE
22
23
This file is part of L<Locale::Fluent>. See its documentation for more
24
information.
25
26
=head2 translate
27
28
this package implements a translate method, but it is not that interesting
29
30
=cut
31

+ 16 - 0
lib/Locale/Fluent/Elements/Term.pm

@ -44,3 +44,19 @@ sub get_attribute_resource {
44 44
45 45
46 46
1;
47
__END__
48
49
=head1 NOTHING TO SEE HERE
50
51
This file is part of L<Locale::Fluent>. See its documentation for more
52
information.
53
54
=head2 translate
55
56
=head2 get_attribute_resource
57
58
this package implements the methods translate and get_attribute_resource, but
59
it is not that interesting
60
61
=cut
62

+ 13 - 0
lib/Locale/Fluent/Elements/TermReference.pm

@ -46,3 +46,16 @@ sub translate {
46 46
}
47 47
48 48
1;
49
__END__
50
51
=head1 NOTHING TO SEE HERE
52
53
This file is part of L<Locale::Fluent>. See its documentation for more
54
information.
55
56
=head2 translate
57
58
this package implements a translate method, but it is not that interesting
59
60
=cut
61

+ 13 - 0
lib/Locale/Fluent/Elements/Text.pm

@ -16,3 +16,16 @@ sub translate {
16 16
}
17 17
18 18
1;
19
__END__
20
21
=head1 NOTHING TO SEE HERE
22
23
This file is part of L<Locale::Fluent>. See its documentation for more
24
information.
25
26
=head2 translate
27
28
this package implements a translate package, but it is not that interesting
29
30
=cut
31

+ 13 - 0
lib/Locale/Fluent/Elements/VariableReference.pm

@ -18,3 +18,16 @@ sub translate {
18 18
}
19 19
20 20
1;
21
__END__
22
23
=head1 NOTHING TO SEE HERE
24
25
This file is part of L<Locale::Fluent>. See its documentation for more
26
information.
27
28
=head2 translate
29
30
this package implements a translate method, but it is not that interesting
31
32
=cut
33

+ 15 - 0
lib/Locale/Fluent/Elements/Variant.pm

@ -27,3 +27,18 @@ sub translate {
27 27
}
28 28
29 29
1;
30
31
__END__
32
33
=head1 NOTHING TO SEE HERE
34
35
This file is part of L<Locale::Fluent>. See its documentation for more
36
information.
37
38
=head2 translate
39
40
This file implements the translate method for choice variants, but it is not
41
that interesting.
42
43
=cut
44

+ 44 - 0
lib/Locale/Fluent/Parser.pm

@ -208,3 +208,47 @@ sub parse_string {
208 208
209 209
  return $reset;
210 210
}
211
212
1;
213
214
__END__
215
216
=head1 NAME
217
218
Locale::Fluent::Parser - Load fluent files and tranform them into objects
219
220
=head1 SYNOPSIS
221
222
  use Locale::Fluent::Parser qw(parse_file);
223
224
  my $resource_set = parse_file( "some_project.en.flt" );
225
226
  print $resource_set->translate("some_tag" );
227
228
=head1 EXPORTS
229
230
=head2 parse_file( $filename )
231
232
parse_file takes a filename and parse it into a L<Locale::Fluent::ResourceSet>
233
object that can be used to translate translation tags.
234
235
See L<#SYNOPSIS> for example.
236
237
If the file does not contain any valid resources, parse_file will
238
C<return undef>. 
239
240
=head2 parse_string( $string )
241
242
parse_string takes a string and parses it into a L<Locale::Fluent::ResourceSet>
243
object.
244
245
If the string does not contain any valid resources, parse_string will
246
C<return undef>.
247
248
=head1 SEE MORE
249
250
This file is part of L<Locale::Fluent> - version, license and more general
251
information can be found in its documentation
252
253
=cut
254

+ 267 - 30
lib/Locale/Fluent/ResourceGroup.pm

@ -17,33 +17,94 @@ has default_language => (
17 17
  default => sub { 'en' },
18 18
);
19 19
20
sub __fallback_languages {
21
  my ($self, $lang, $default_lang) = @_;
20
use Locale::Fluent::ResourceGroup::Context;
21
use Locale::Fluent::ResourceSet;
22 22
23
  $default_lang ||= $self->default_language;
23
sub slurp_directory {
24
  my ($self, $directory, $context) = @_;
24 25
25
  my @langs = ($lang) if $lang;
26
  unless (ref $self and $self->isa("Locale::Fluent::ResourceGroup")) {
27
    my %params = ();
28
    if ($context->{default_language}) {
29
      $params{default_language} = delete $context->{default_language};
30
    }
31
    if ($context->{fallback_order}) {
32
      $params{fallback_order} = delete $context->{fallback_order};
33
    }
34
    $self = $self->new( %params );
35
  }
26 36
27
  while ($lang and $lang=~m{\-}) {
28
    $lang =~ s{-\w+\z}{};
29
    push @langs, $lang;
37
  for my $k (qw(default_language fallback_order)) {
38
    die "'$k' is invalid when adding resources to a resource group"
39
      if $context->{$k};
30 40
  }
31
  unless ($lang eq $default_lang) {
32
    push @langs, $default_lang;
41
42
  my $recursive = delete $context->{recursive} // 0;
43
44
  $directory .='/' unless substr($directory, -1) eq '/';
45
46
  opendir my $dh, $directory or die "Can't open $directory: $!";
47
  my @all = readdir( $dh );
48
  my @files = grep { m{ \.flt\z }xi } @all;
49
  closedir( $dh );
50
51
  # first we slurp the subdirectories, so that the files
52
  # on the top directories override the files in the sub directories
53
  # I could go both ways, but I think it is more intuitive this way
54
  # TODO: add directory priority to the docs of slurp_directory
55
  if ($recursive) {
56
    my @dirs = grep { !m{\A\.} and -d "$directory$_" } @all;
57
58
    for my $dir ( @dirs ) {
59
      $self->slurp_directory( "$directory$dir", $context );
60
    }
33 61
  }
34 62
35
  push @langs, 'dev' unless $default_lang eq 'dev';
63
  local $/ = undef;
64
  for my $fname ( @files ) {
65
    my %context = %{$context};
36 66
37
  return @langs;
67
    open my $fh, "$directory$fname" or do {
68
        warn "Error opening file '$directory$fname'";
69
        next;
70
      };
71
72
    my $fluent = <$fh>;
73
    next unless $fluent; # is the file empty?
74
75
    if (my ($ctx) = $fluent =~ m{ \A\#\s*context:\s*([^\n]+)\n }x) {
76
      my %fcontext;
77
      
78
      my @fcontext = map { split /\s*[:=]\s*/, $_, 2 } split /\s*[:=]\s/, $ctx;
79
80
      if ( !( scalar @fcontext % 2) ) {
81
        %fcontext = @fcontext;
82
83
        $context{ $_ } //= $fcontext{ $_ }
84
          for keys %fcontext;
85
      } else {
86
        print STDERR "invalid context: '$ctx'\n";
87
        warn "Invalid context in fluent file '$directory$fname' - ignoring";
88
      }
89
    }
90
91
    my $resset =  Locale::Fluent::Parser::parse_string( $fluent );
92
    if ($resset) {
93
      $self->add_resource_set( $resset, \%context );
94
    }
95
  }
96
97
  return $self;
38 98
}
39 99
100
#TODO: add override priority to add_resource_set docs.
40 101
sub add_resource_set {
41 102
  my ($self, $resource_set, $context ) = @_;
42 103
43 104
  my @kv  = ();
44 105
  for my $fbo (@{ $self->fallback_order }) {
45 106
    my $fbok = $context->{ $fbo }
46
      || $fbo eq 'language' ? 'dev' : 'default';
107
      || ($fbo eq 'language' ? 'dev' : 'default');
47 108
    
48 109
    push @kv, $fbok;
49 110
  }
@ -53,7 +114,7 @@ sub add_resource_set {
53 114
  my $reset = $self->sets->{ $key };
54 115
  if ( $reset ) {
55 116
    for my $k (keys %{ $resource_set->resources }) {
56
      $reset->add_resource( $resource_set->resource->{ $k } );
117
      $reset->add_resource( $resource_set->resources->{ $k } );
57 118
    }
58 119
59 120
  } else {
@ -161,29 +222,205 @@ sub _find_resource {
161 222
  return $res;
162 223
}
163 224
164
package Locale::Fluent::ResourceGroup::Context;
225
sub __fallback_languages {
226
  my ($self, $lang, $default_lang) = @_;
165 227
166
use Moo;
228
  $default_lang ||= $self->default_language;
167 229
168
has context => (
169
  is => 'ro',
170
  default => sub { {} },
171
);
230
  my @langs = ($lang) if $lang;
172 231
173
has resgroup => (
174
  is => 'ro',
175
);
232
  while ($lang and $lang=~m{\-}) {
233
    $lang =~ s{-\w+\z}{};
234
    push @langs, $lang;
235
  }
236
  unless ($lang eq $default_lang) {
237
    push @langs, $default_lang;
238
  }
176 239
177
sub get_term {
178
  my ($self, $term_id) = @_;
240
  push @langs, 'dev' unless $default_lang eq 'dev';
179 241
180
  return $self->resgroup->get_term( $term_id, $self->context );
242
  return @langs;
181 243
}
182 244
183
sub get_message {
184
  my ($self, $message_id) = @_;
245
1;
185 246
186
  return $self->resgroup->get_message( $message_id, $self->context );
187
}
247
__END__
248
249
=head1 NAME
250
251
Locale::Fluent::ResourceGroup - a group of contextualized L<ResourceSet>s.
252
253
=head1 SYNOPSIS
254
255
  my $group = Locale::Fluent::ResourceGroup->slurp_directory( "somedir" );
256
  my $variables = {};
257
258
  print $group->translate("some-resource", $variables, { language => "en" });
259
260
=head1 DESCRIPTION
261
262
Where L<Locale::Fluent::ResourceSet> allow you to get translations from a
263
single set of resources, C<Locale::Fluent::ResourceGroup> provides the
264
mechanisms to use multiple resource sets with basic rules to find the needed
265
resource across multiple resource set.
266
267
This main idea behind this is that often we don't have perfect translations
268
for our software, and that it is better to provide the text in the wrong
269
language than not being able to provide a translation at all.
270
271
=head2 FALLBACK_ORDER
272
273
while creating a resource group you can define a list of context parameters to
274
fall back through when looking for a resource (message or term). The order
275
in which they are listed is the order in which they are released.
276
277
When one context paramater is released, the next possible value for that
278
parameter is tested. For this purpose, language is special. The remaining
279
parameters, when released, the value 'default' is used.
280
281
For language, the fallback path is a bit longer. If the language used in the
282
translate context is a variant of a main language, then the main language is
283
used. After the main language, then the default_language of the ResourceGroup
284
is used (default is 'en'), and then 'dev' is used.
285
286
When a resource set is added to a group, all the context paramaters that are
287
not defined when adding the resource set default to 'default' or 'dev' (dev
288
for the language parameter).
289
290
Consider the following fallback order:
291
292
  [qw( site plugin language )]
293
294
And now consider the following translate context:
295
296
  { site      => "google.com",
297
    plugin    => "footer",
298
    language  => "pt-br",
299
  }
300
301
For this request, a given resource is going to be search is the ResourceSets
302
that have the following contexts:
303
304
  google.com > footer > pt-br
305
  default    > footer > pt-br
306
  google.com > default> pt-br
307
  default    > default> pt-br
308
  google.com > footer > pt
309
  default    > footer > pt
310
  google.com > default> pt
311
  default    > default> pt
312
  google.com > footer > en
313
  default    > footer > en
314
  google.com > default> en
315
  default    > default> en
316
  google.com > footer > dev
317
  default    > footer > dev
318
  google.com > default> dev
319
  default    > default> dev
320
321
=head1 METHODS
322
323
=head2 new([...])
324
325
Creates a new ResourceGroup. possible parameters are:
326
327
=over 4
328
329
=item * fallback_order => [qw<...>]
330
331
the fallback order defines the order with which context parameters of a
332
translation request are relaxed to find a translation resource.
333
334
context parameters that are not listed in the fallback_order are - at the
335
moment - ignored, as having an arbitrary list of context parameters may make
336
it very difficult to find any translation resources at all.
337
338
This behavior may change in the future, so try to avoid using context
339
parameters anywhere that are not listed in the fallback_order of the
340
ResourceGroup.
341
342
See L<#FALLBACK_ORDER> above for details on the fallback mechanism.
343
344
=item * default_language => '...'
345
346
The default language is the language used when a translation request is made
347
without a language context, or when the resource is not found in the given
348
language.
349
350
If a resource is still not found in the default_language, the default is to
351
look for it using 'dev' for the language. 
352
353
=back
354
355
=head2 slurp_directory( $directory, $context )
356
357
slurp_directory load all the files fluent in a directory (and, optionally,
358
sub-directories) and add all the resources found to the current ResourceGroup.
359
360
For convinience, if called as a static method, it created a new ResourceGroup
361
and returns it.
362
363
When called as a static method, slurp_directory supports a few extra
364
parameters in the $context, which are passed to C<new>:
365
366
=over 4
367
368
=item * fallback_order
369
370
=item * default_language
371
372
=back
373
374
Additionally, $context can also include a value for C<recursive>, which
375
will define if files existing in sub-directories are also loaded or not.
376
377
All the remaining values in $context are used as values for the contexts
378
of all the resources loaded.
379
380
381
=head3 context from files
382
383
Additionally, C<slurp_directory> checks the first line of each file
384
loaded to see if it matches:
385
386
  #context: \w+[:=]\w+([,;]\w+[:=]\w+)*
387
388
(meaning, "$key: $value" pais separated by , or ;)
389
390
If the first line of the files match that, those values are added to the
391
$context passed to slurp_directory.
392
393
To notice, values passed to slurp_directory have priority over those
394
defined in the translation files.
395
396
=head2 add_resource_set( $resource_set, $context )
397
398
add_resource_set adds a pre-existing ResourceSet to a ResourceGroup with
399
the context provided.
400
401
=head2 translate( $res_id, $variables, $context )
402
403
Search for a Message with the id $res_id using the $context provided and
404
translates it.
405
406
=head2 get_term( $term_id, $context )
407
408
Search for a Term with the id $term_id using the $context provided and returns
409
it. While this may be useful, it is intended for internal use.
410
411
=head2 get_message( $message_id, $context )
412
413
Search for a Message with the id $message_id using the $context provided and
414
returns it. While this may be useful, it is intended for internal use.
415
416
While you could use the returned $message to perform a translation, this would
417
fail when such translation needs a term or a message - which may not always
418
happen. Do not do that.
419
420
=head1 SEE MORE
421
422
This file is part of L<Locale::Fluent> - version, license and more general
423
information can be found in its documentation.
424
425
=cut
188 426
189
1;

+ 64 - 0
lib/Locale/Fluent/ResourceGroup/Context.pm

@ -0,0 +1,64 @@
1
package Locale::Fluent::ResourceGroup::Context;
2
3
use Moo;
4
5
has context => (
6
  is => 'ro',
7
  default => sub { {} },
8
);
9
10
has resgroup => (
11
  is => 'ro',
12
);
13
14
sub get_term {
15
  my ($self, $term_id) = @_;
16
17
  return $self->resgroup->get_term( $term_id, $self->context );
18
}
19
20
sub get_message {
21
  my ($self, $message_id) = @_;
22
23
  return $self->resgroup->get_message( $message_id, $self->context );
24
}
25
26
1;
27
28
__END__
29
30
=head1 NAME
31
32
Locale::Fluent::ResourceGroup::Context - ResourceSet emulation
33
34
=head1 SYNOPSIS
35
36
DO NOT USE DIRECTLY
37
38
=head1 DESCRIPTION
39
40
This package is used internally by L<Locale::Fluent::ResourceGroup> to
41
provide the functionality of L<Locale::Fluent::ResourceSet> and keep track
42
of what is the context of the original translation request.
43
44
This is needed so that all sub-translations needed to finish a translation
45
request are done in a consistent way. This object, unlike the ResourceSet,
46
does not keep any translation objects, it only delegates getting this objects
47
from L<Locale::Fluent::ResourceGroup> with the right context.
48
49
=head1 METHODS IMPLEMENTED
50
51
This package only implements the methods of L<Locale::Fluent:ResourceSet>
52
needed during translation calls. See that class for details on those methods.
53
54
=head2 get_term( $term_id )
55
56
=head2 get_message( $message_id )
57
58
=head1 SEE MORE
59
60
This file is part of L<Locale::Fluent> - version, license and more general
61
information can be found in its documentation
62
63
=cut
64

+ 49 - 0
lib/Locale/Fluent/ResourceSet.pm

@ -44,4 +44,53 @@ sub get_message {
44 44
45 45
1;
46 46
47
__END__
48
49
=head1 NAME
50
51
Locale::Fluent::ResourceSet - a set of translation resources 
52
53
=head1 SYNOPSIS
54
55
  my $resource_set = Locale::Fluent->parse_file( "filename.flt" );
56
  my $variables = {};
57
58
  print $resource_set->translate('some-string', $variables );
59
60
=head1 DESCRIPTION
61
62
C<Locale::Fluent::ResourceSet> groups multiple translation resources,
63
often from a single file, and allow you to get translations from them,
64
even when they need other resources in the resource set.
65
66
=head1 METHODS
67
68
=head2 add_resource( $resource )
69
70
C<add_resource> can be used to add one resource to an existing ResourceSet.
71
72
while this can be used externally, it is intended for internal use.
73
74
=head2 translate( $res_id, $variables )
75
76
Translate a message.
77
78
  my $text = $resource_set->translate( 'some-message-id', $variables );
79
80
=head2 get_term( $term_id )
81
82
Returns a Term object with the id $term_id. This can be useful, but is
83
intended for internal use.
84
85
=head2 get_message( $message_id )
86
87
Returns a Message object with the id $message_id. This can be useful, but is
88
intended for internal use.
89
90
=head1 SEE MORE
91
92
This file is part of L<Locale::Fluent> - version, license and more general
93
information can be found in its documentation.
94
95
=cut
47 96

+ 57 - 0
t/65-slurp.t

@ -0,0 +1,57 @@
1
#!perl -T
2
use 5.006;
3
use strict;
4
use warnings;
5
use Test::More;
6
7
8
BEGIN {
9
    use_ok( 'Locale::Fluent' ) || print "Bail out!\n";
10
}
11
12
my $path = $0;
13
$path =~ s{t/.*.t}{test_files/slurp};
14
15
16
my $resource_group = Locale::Fluent::ResourceGroup->slurp_directory( $path );
17
isa_ok($resource_group, "Locale::Fluent::ResourceGroup");
18
19
my $ptbr = $resource_group->translate(
20
                  'my-language',
21
                  {},
22
                  { language => 'pt-br' }
23
              );
24
is( $ptbr, 'Português do Brasil', 'pt-br');
25
26
my $ptpt = $resource_group->translate(
27
                  'my-language',
28
                  {},
29
                  { language => 'pt-pt' }
30
              );
31
is( $ptpt, 'Português', 'pt-pt');
32
33
my $enus = $resource_group->translate(
34
                  'my-language',
35
                  {},
36
                  { language => 'en-us' }
37
              );
38
is( $enus, 'English', 'en-us');
39
40
# Random language that doesn't exist/have translation
41
# should default to default_language = 'en'
42
my $exfi = $resource_group->translate(
43
                  'my-language',
44
                  {},
45
                  { language => 'ex-fi' } 
46
              );
47
is( $exfi, 'English', 'ex-fi');
48
49
my $exfi2 = $resource_group->translate(
50
                  'my-unfound-language',
51
                  {},
52
                  { language => 'ex-fi' } 
53
              );
54
is( $exfi2, 'Just a Dev String', 'unfound-language');
55
56
57
done_testing();

+ 4 - 0
test_files/slurp/base.en.flt

@ -0,0 +1,4 @@
1
#context: language = en
2
3
my-language = English
4

+ 9 - 0
test_files/slurp/base.flt

@ -0,0 +1,9 @@
1
2
# Name of the language, in the language
3
my-language = Dev Strings
4
5
# used in tests to test default to dev language
6
# do not translate to other languages
7
my-unfound-language = Just a Dev String
8
9

+ 4 - 0
test_files/slurp/base.it.flt

@ -0,0 +1,4 @@
1
# context: language: it
2
3
my-language = Italiano
4

+ 4 - 0
test_files/slurp/base.nl.flt

@ -0,0 +1,4 @@
1
# context: language: nl
2
3
my-language=Nederlands
4

+ 4 - 0
test_files/slurp/base.pt-br.flt

@ -0,0 +1,4 @@
1
# context: language: pt-br
2
3
my-language = Português do Brasil
4

+ 3 - 0
test_files/slurp/base.pt-pt.flt

@ -0,0 +1,3 @@
1
# context: language: pt-pt
2
3

+ 4 - 0
test_files/slurp/base.pt.flt

@ -0,0 +1,4 @@
1
#context: language: pt
2
3
my-language = Português
4