File Coverage

blib/lib/Mojolicious/Plugin/LocaleTextDomainOO.pm
Criterion Covered Total %
statement 51 82 62.2
branch 1 18 5.5
condition 8 29 27.5
subroutine 11 19 57.8
pod 1 1 100.0
total 72 149 48.3


line stmt bran cond sub pod time code
1             package Mojolicious::Plugin::LocaleTextDomainOO;
2 5     5   2492 use Mojo::Base 'Mojolicious::Plugin';
  5         7  
  5         28  
3              
4 5     5   2866 use Locale::TextDomain::OO;
  5         445851  
  5         192  
5 5     5   2193 use Locale::TextDomain::OO::Lexicon::File::PO;
  5         168404  
  5         151  
6 5     5   2360 use Locale::TextDomain::OO::Lexicon::File::MO;
  5         56663  
  5         142  
7 5     5   2433 use I18N::LangTags;
  5         10225  
  5         199  
8 5     5   2020 use I18N::LangTags::Detect;
  5         4711  
  5         178  
9              
10 5   50 5   23 use constant DEBUG => $ENV{MOJO_I18N_DEBUG} || 0;
  5         6  
  5         5518  
11              
12             our $VERSION = '0.04';
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 191 my ( $plugin, $app, $plugin_config ) = @_;
26              
27             # Initialize
28 5   100     22 my $file_type = $plugin_config->{file_type} || 'po';
29 5   100     23 my $default = $plugin_config->{default} || 'en';
30 5         10 $default =~ tr/-A-Z/_a-z/;
31 5         8 $default =~ tr/_a-z0-9//cd;
32 5   50     30 my $languages = $plugin_config->{languages} // [$default];
33              
34 5         7 my $plugins = $plugins_default;
35 0         0 push @$plugins, @{ $plugin_config->{plugins} }
36 5 50       15 if ( ref $plugin_config->{plugins} eq 'ARRAY' );
37              
38 5     0   14 my $logger = sub { };
39             $logger = sub {
40 0     0     my ( $message, $arg_ref ) = @_;
41 0   0       my $type = $arg_ref->{type} || 'debug';
42 0           $app->log->$type($message);
43 0           return;
44             }
45 5         8 if DEBUG;
46              
47             # Default Handler
48             my $loc = sub {
49 0     0   0 Locale::TextDomain::OO->instance(
50             plugins => $plugins,
51             languages => $languages,
52             logger => $logger,
53             );
54 5         14 };
55              
56             # Add hook and replace url_for helper
57 5         11 $Mojolicious::Plugin::LocaleTextDomainOO::I18N::code->(
58             $app, $plugin_config
59             );
60              
61             # Add "locale" helper
62 5         22 $app->helper( locale => $loc );
63              
64             # Add "lexicon" helper
65             $app->helper(
66             lexicon => sub {
67 5     5   1010 my ( $app, $conf ) = @_;
68 5   100     19 $conf->{decode} = $conf->{decode} // 1; # Default: utf8 flaged
69 5         16 $plugin->$file_type->lexicon_ref($conf);
70             }
71 5         136 );
72              
73             # Add "languages" helper
74             $app->helper(
75             languages => sub {
76 0     0   0 my ( $self, @languages ) = @_;
77 0 0       0 unless (@languages) { $self->locale->languages }
  0         0  
78 0         0 else { $self->locale->languages( \@languages ) }
79             }
80 5         86 );
81              
82             # Add "language" helper
83             $app->helper(
84             language => sub {
85 0     0   0 my ( $self, $language ) = @_;
86 0 0       0 unless ($language) { $self->locale->language }
  0         0  
87 0         0 else { $self->locale->language($language) }
88             }
89 5         133 );
90              
91             # Add helper from gettext methods
92 5         67 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         8 foreach my $method (@methods) {
101 160     0   1426 $app->helper( $method => sub { shift->app->locale->$method(@_) } );
  0         0  
102             }
103              
104 5         42 foreach my $method (qw /__begin_d __end_d/) {
105 0     0     $app->helper( $method => sub { shift->app->locale->$method(@_); undef; }
  0            
106 10         72 );
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 0     0     my $self = shift;
188 0           my $url = $self->$mojo_url_for(@_);
189              
190             # Absolute URL
191 0 0         return $url if $url->is_abs;
192              
193             # Discard target if present
194 0 0 0       shift if ( @_ % 2 && !ref $_[0] ) || ( @_ > 1 && ref $_[-1] );
      0        
      0        
195              
196             # Unveil params
197 0 0         my %params = @_ == 1 ? %{ $_[0] } : @_;
  0            
198              
199             # Detect lang
200 0 0 0       if ( my $lang = $params{lang} || $self->stash('lang') ) {
201 0   0       my $path = $url->path || [];
202              
203             # Root
204 0 0 0       if ( !$path->[0] ) {
    0          
205 0           $path->parts( [$lang] );
206             }
207              
208             # No language detected
209             elsif ( ref $langs ne 'ARRAY'
210 0           or not scalar grep { $path->contains("/$_") } @$langs )
211             {
212 0           unshift @{ $path->parts }, $lang;
  0            
213             }
214             }
215              
216 0           $url;
217             };
218              
219             {
220 5     5   27 no strict 'refs';
  5         5  
  5         125  
221 5     5   16 no warnings 'redefine';
  5         5  
  5         318  
222              
223             *Mojolicious::Controller::url_for = $i18n_url_for;
224             }
225             };
226              
227             1;
228             __END__