File Coverage

blib/lib/Mojolicious/Plugin/LocaleTextDomainOO.pm
Criterion Covered Total %
statement 49 78 62.8
branch 1 18 5.5
condition 8 29 27.5
subroutine 11 18 61.1
pod 1 1 100.0
total 70 144 48.6


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