File Coverage

blib/lib/Mojolicious/Plugin/LocaleTextDomainOO.pm
Criterion Covered Total %
statement 76 82 92.6
branch 15 18 83.3
condition 22 29 75.8
subroutine 18 19 94.7
pod 1 1 100.0
total 132 149 88.5


line stmt bran cond sub pod time code
1             package Mojolicious::Plugin::LocaleTextDomainOO;
2 5     5   3502 use Mojo::Base 'Mojolicious::Plugin';
  5         11  
  5         36  
3              
4 5     5   3358 use Locale::TextDomain::OO;
  5         546049  
  5         196  
5 5     5   2740 use Locale::TextDomain::OO::Lexicon::File::PO;
  5         253598  
  5         171  
6 5     5   2452 use Locale::TextDomain::OO::Lexicon::File::MO;
  5         105018  
  5         177  
7 5     5   2810 use I18N::LangTags;
  5         12614  
  5         256  
8 5     5   2179 use I18N::LangTags::Detect;
  5         5899  
  5         195  
9              
10 5   50 5   35 use constant DEBUG => $ENV{MOJO_I18N_DEBUG} || 0;
  5         11  
  5         6854  
11              
12             our $VERSION = '0.05';
13              
14             has 'po' => sub { Locale::TextDomain::OO::Lexicon::File::PO->new };
15             has 'mo' => sub { Locale::TextDomain::OO::Lexicon::File::MO->new };
16              
17             my $plugins_default = [
18             qw/
19             Expand::Gettext::DomainAndCategory
20             Language::LanguageOfLanguages
21             /
22             ];
23              
24             sub register {
25 5     5 1 285 my ( $plugin, $app, $plugin_config ) = @_;
26              
27             # Initialize
28 5   100     32 my $file_type = $plugin_config->{file_type} || 'po';
29 5   100     26 my $default = $plugin_config->{default} || 'en';
30 5         14 $default =~ tr/-A-Z/_a-z/;
31 5         63 $default =~ tr/_a-z0-9//cd;
32 5   50     33 my $languages = $plugin_config->{languages} // [$default];
33              
34 5         9 my $plugins = $plugins_default;
35 0         0 push @$plugins, @{ $plugin_config->{plugins} }
36 5 50       19 if ( ref $plugin_config->{plugins} eq 'ARRAY' );
37              
38 5     1   21 my $logger = sub { };
39             $logger = sub {
40 0     0   0 my ( $message, $arg_ref ) = @_;
41 0   0     0 my $type = $arg_ref->{type} || 'debug';
42 0         0 $app->log->$type($message);
43 0         0 return;
44             }
45 5         11 if DEBUG;
46              
47             # Default Handler
48             my $loc = sub {
49 84     84   26144 Locale::TextDomain::OO->instance(
50             plugins => $plugins,
51             languages => $languages,
52             logger => $logger,
53             );
54 5         19 };
55              
56             # Add hook and replace url_for helper
57 5         20 $Mojolicious::Plugin::LocaleTextDomainOO::I18N::code->(
58             $app, $plugin_config
59             );
60              
61             # Add "locale" helper
62 5         32 $app->helper( locale => $loc );
63              
64             # Add "lexicon" helper
65             $app->helper(
66             lexicon => sub {
67 5     5   1466 my ( $app, $conf ) = @_;
68 5   100     31 $conf->{decode} = $conf->{decode} // 1; # Default: utf8 flaged
69 5         35 $plugin->$file_type->lexicon_ref($conf);
70             }
71 5         174 );
72              
73             # Add "languages" helper
74             $app->helper(
75             languages => sub {
76 23     23   1318 my ( $self, @languages ) = @_;
77 23 50       103 unless (@languages) { $self->locale->languages }
  0         0  
78 23         175 else { $self->locale->languages( \@languages ) }
79             }
80 5         76 );
81              
82             # Add "language" helper
83             $app->helper(
84             language => sub {
85 18     18   62808 my ( $self, $language ) = @_;
86 18 100       69 unless ($language) { $self->locale->language }
  12         101  
87 6         42 else { $self->locale->language($language) }
88             }
89 5         74 );
90              
91             # Add helper from gettext methods
92 5         77 my @methods = (
93             qw/
94             __ __x __n __nx __p __px __np __npx
95             N__ N__x N__n N__nx N__p N__px N__np N__npx
96             __d __dn __dp __dnp __dx __dnx __dpx __dnpx
97             N__d N__dn N__dp N__dnp N__dx N__dnx N__dpx N__dnpx
98             /
99             );
100 5         13 foreach my $method (@methods) {
101 160     34   2166 $app->helper( $method => sub { shift->app->locale->$method(@_) } );
  34         217928  
102             }
103              
104 5         62 foreach my $method (qw /__begin_d __end_d/) {
105 8     8   8702 $app->helper( $method => sub { shift->app->locale->$method(@_); undef; }
  8         733  
106 10         111 );
107             }
108             }
109              
110             #######################################################################
111             ### This code is Mojolicious::Plugin::I18N
112             #######################################################################
113             package Mojolicious::Plugin::LocaleTextDomainOO::I18N;
114              
115             our $code = sub {
116             my ( $app, $conf ) = @_;
117              
118             my $langs = $conf->{support_url_langs};
119             my $hosts = $conf->{support_hosts};
120             my $default = $conf->{default} || 'en';
121             $default =~ tr/-A-Z/_a-z/;
122             $default =~ tr/_a-z0-9//cd;
123              
124             # Add hook
125             $app->hook(
126             before_dispatch => sub {
127             my $self = shift;
128              
129             # Header detection
130             my @languages =
131             $conf->{no_header_detect}
132             ? ()
133             : I18N::LangTags::implicate_supers(
134             I18N::LangTags::Detect->http_accept_langs(
135             $self->req->headers->accept_language
136             )
137             );
138              
139             # Host detection
140             my $host = $self->req->headers->header('X-Host')
141             || $self->req->headers->host;
142             if ( $conf->{support_hosts} && $host ) {
143             warn $host;
144             $host =~ s/^www\.//; # hack
145             if ( my $lang = $conf->{support_hosts}->{$host} ) {
146             $self->app->log->debug(
147             "Found language $lang, Host header is $host");
148              
149             unshift @languages, $lang;
150             }
151             }
152              
153             # Set default language
154             $self->stash( lang_default => $languages[0] ) if $languages[0];
155              
156             # URL detection
157             if ( my $path = $self->req->url->path ) {
158             my $part = $path->parts->[0];
159              
160             if ( $part && $langs && grep { $part eq $_ } @$langs ) {
161              
162             # Ignore static files
163             return if $self->res->code;
164              
165             $self->app->log->debug("Found language $part in URL $path");
166              
167             unshift @languages, $part;
168              
169             # Save lang in stash
170             $self->stash( lang => $part );
171              
172             # Clean path
173             shift @{ $path->parts };
174             $path->trailing_slash(0);
175             }
176             }
177              
178             # Languages
179             $self->languages( @languages, $default );
180             }
181             );
182              
183             # Reimplement "url_for" helper
184             my $mojo_url_for = *Mojolicious::Controller::url_for{CODE};
185              
186             my $i18n_url_for = sub {
187 68     68   143288 my $self = shift;
188 68         240 my $url = $self->$mojo_url_for(@_);
189              
190             # Absolute URL
191 68 100       17385 return $url if $url->is_abs;
192              
193             # Discard target if present
194 47 100 100     620 shift if ( @_ % 2 && !ref $_[0] ) || ( @_ > 1 && ref $_[-1] );
      100        
      100        
195              
196             # Unveil params
197 47 100       180 my %params = @_ == 1 ? %{ $_[0] } : @_;
  2         8  
198              
199             # Detect lang
200 47 100 100     504 if ( my $lang = $params{lang} || $self->stash('lang') ) {
201 16   50     172 my $path = $url->path || [];
202              
203             # Root
204 16 100 33     264 if ( !$path->[0] ) {
    50          
205 6         107 $path->parts( [$lang] );
206             }
207              
208             # No language detected
209             elsif ( ref $langs ne 'ARRAY'
210 30         1114 or not scalar grep { $path->contains("/$_") } @$langs )
211             {
212 10         411 unshift @{ $path->parts }, $lang;
  10         24  
213             }
214             }
215              
216 47         682 $url;
217             };
218              
219             {
220 5     5   39 no strict 'refs';
  5         23  
  5         213  
221 5     5   32 no warnings 'redefine';
  5         11  
  5         444  
222              
223             *Mojolicious::Controller::url_for = $i18n_url_for;
224             }
225             };
226              
227             1;
228             __END__