File Coverage

blib/lib/Dancer2/Plugin/Locale.pm
Criterion Covered Total %
statement 21 21 100.0
branch n/a
condition n/a
subroutine 7 7 100.0
pod n/a
total 28 28 100.0


line stmt bran cond sub pod time code
1             package Dancer2::Plugin::Locale;
2              
3 1     1   306519 use strict;
  1         2  
  1         25  
4 1     1   3 use warnings;
  1         1  
  1         20  
5              
6 1     1   431 use Dancer2::Plugin;
  1         1608  
  1         5  
7             $Dancer2::Plugin::Locale::VERSION = '0.05';
8              
9             package Dancer2::Plugin::Locale::Obj;
10 1     1   1879 use Locales 0.33 unicode => 1;
  1         7029  
  1         4  
11 1     1   664 use Locale::Maketext::Utils;
  1         17065  
  1         30  
12 1     1   8 use base 'Locale::Maketext::Utils';
  1         2  
  1         108  
13             our %Lexicon;
14              
15             package Dancer2::Plugin::Locale;
16              
17 1     1   5 use File::Spec;
  1         1  
  1         148680  
18              
19             # use Tie::Hash::ReadonlyStack;
20              
21             plugin_keywords 'locale';
22              
23             sub locale {
24             my $dsl = shift;
25              
26             if (@_) {
27             return Dancer2::Plugin::Locale::Obj->get_handle( grep( { defined } (@_) ), 'en' ); # multiton already via Locale::Maketext::Utils
28             }
29              
30             my $app = $dsl->app;
31              
32             # TODO 2: request locale via browser/HTP req after session and before default?
33             return Dancer2::Plugin::Locale::Obj->get_handle( grep( { defined } ( eval { $app->session->read('locale') }, $dsl->config->{default_locale} ) ), 'en' ); # multiton already via Locale::Maketext::Utils
34             };
35              
36             sub BUILD {
37             my $dsl = shift;
38              
39             my @available_locales = ('en');
40              
41             # read locale/ dir for available locales (via config also? likley YAGNI/overly comlicated-why?)
42             my $locale_dir = File::Spec->catdir( $dsl->app->config->{'appdir'}, 'locale' ); # configurable? nah, why?
43             if ( -d $locale_dir ) {
44             if ( opendir my $dh, $locale_dir ) {
45             while ( my $file = readdir($dh) ) {
46             next if $file !~ m/\.json$/;
47             next if $file eq 'en.json';
48             $file =~ s/\.json//;
49             if ( Locales::normalize_tag($file) ne $file ) {
50             warn "Skipping un-normalized locale named lexicon ($file.json) …\n"; # just no apparent need to complicate things by trying to deal with this
51             next;
52             }
53             push @available_locales, $file;
54             }
55             closedir($dh);
56             }
57             else {
58             die "Could not read locale directory ($locale_dir): $!\n";
59             }
60             }
61             no strict 'refs'; ## no critic
62             no warnings 'redefine'; ## no critic
63             *Locale::Maketext::Utils::list_available_locales = sub {
64             return ( sort @available_locales );
65             };
66              
67             # create classes that Locale::Maketext uses
68             for my $tag (@available_locales) {
69             my $file = File::Spec->catfile( $locale_dir, "$tag.json" );
70              
71             # TODO 1: for en (and its alias) empty value means key *is* value …
72              
73             # TODO 1: support tieing to CDB_File hash (e.g. if -f locale_cdb/$tag.cdb) so as not to load all the data into memory (see use_external_lex_cache)?
74              
75             # TODO 2: POD app w/ charset !utf8 == ick
76             eval "package Dancer2::Plugin::Locale::Obj::$tag;use base 'Dancer2::Plugin::Locale::Obj';our \$Encoding='utf8';our \%Lexicon;package Dancer2::Plugin::Locale;"; ## no critic
77              
78             no strict 'refs'; ## no critic
79             %{"Dancer2::Plugin::Locale::Obj::$tag\::Lexicon"} = $tag eq 'en' && !-e $file ? () : ( %{ _from_json_file($file) } ); # TODO 1: instead: tie %{"Dancer2::Plugin::Locale::$tag\::Lexicon"}, 'Tie::Hash::ReadonlyStack', _from_json_file($file);
80             }
81              
82             # TODO 2: Is there a better way to add template keyword?
83             $dsl->app->add_hook(
84             Dancer2::Core::Hook->new(
85             name => 'before_template_render',
86             code => sub {
87             $_[0]->{locale} = sub { $dsl->locale(@_) };
88             },
89             )
90             );
91             };
92              
93             sub _from_json_file {
94             my ($file) = @_;
95             open( my $fh, '<', $file ) or die "Could not read “$file”: $!";
96             return from_json(
97             do { local $/; <$fh> }
98             );
99             }
100              
101             # TODO 2: localization tips
102             # TODO 2: extractor/checker tool
103              
104             1;
105              
106             __END__