File Coverage

blib/lib/Plack/Middleware/I18N.pm
Criterion Covered Total %
statement 76 76 100.0
branch 33 38 86.8
condition 8 9 88.8
subroutine 17 17 100.0
pod 2 2 100.0
total 136 142 95.7


line stmt bran cond sub pod time code
1             package Plack::Middleware::I18N;
2              
3 1     1   341 use strict;
  1         1  
  1         30  
4 1     1   4 use warnings;
  1         2  
  1         21  
5              
6 1     1   5 use parent 'Plack::Middleware';
  1         2  
  1         5  
7              
8 1     1   2040 use Carp qw(croak);
  1         1  
  1         77  
9 1     1   6 use List::Util qw(first);
  1         1  
  1         87  
10 1     1   4 use I18N::AcceptLanguage;
  1         1  
  1         18  
11              
12 1     1   3 use Plack::Util::Accessor qw(i18n use_path use_session use_header custom_cb);
  1         1  
  1         4  
13              
14             sub prepare_app {
15 13     13 1 175 my $self = shift;
16              
17 13 100       279 croak 'i18n required' unless $self->{i18n};
18              
19 12 100       64 $self->{use_path} = 1 unless defined $self->{use_path};
20 12 100       24 $self->{use_session} = 1 unless defined $self->{use_session};
21 12 100       26 $self->{use_header} = 1 unless defined $self->{use_header};
22              
23 12         32 return $self;
24             }
25              
26             sub call {
27 12     12 1 12 my $self = shift;
28 12         8 my ($env) = @_;
29              
30 12         19 $self->_detect_language($env);
31              
32 12         29 return $self->app->($env);
33             }
34              
35             sub _detect_language {
36 12     12   13 my $self = shift;
37 12         9 my ($env) = @_;
38              
39 12         11 my $lang;
40 12 100       29 $lang = $self->_detect_from_path($env) if $self->use_path;
41 12 100 100     31 $lang ||= $self->_detect_from_session($env) if $self->use_session;
42 12 100 100     37 $lang ||= $self->_detect_from_header($env) if $self->use_header;
43 12 100       39 $lang = $self->_detect_from_custom_cb($env, $lang) if $self->custom_cb;
44              
45 12   66     54 $lang ||= $self->i18n->default_language;
46              
47 12         18 $env->{'plack.i18n'} = $self->i18n;
48 12         36 $env->{'plack.i18n.language'} = $lang;
49 12         19 $env->{'plack.i18n.handle'} = $self->i18n->handle($lang);
50              
51 12 100       28 if ($self->{use_session}) {
52 11         21 $env->{'psgix.session'}->{'plack.i18n.language'} = $lang;
53             }
54             }
55              
56             sub _detect_from_session {
57 7     7   41 my $self = shift;
58 7         7 my ($env) = @_;
59              
60 7 100       21 return unless my $session = $env->{'psgix.session'};
61              
62 2 50       6 return unless my $lang = $session->{'plack.i18n.language'};
63              
64 2 100       5 return unless $self->_is_allowed($lang);
65              
66 1         5 return $lang;
67             }
68              
69             sub _detect_from_path {
70 11     11   51 my $self = shift;
71 11         12 my ($env) = @_;
72              
73 11         13 my $path = $env->{PATH_INFO};
74              
75 11         21 my $languages_re = join '|', $self->i18n->languages;
76 11 100       82 if ($path =~ s{^/($languages_re)(?=/|$)}{}) {
77 4         5 $env->{PATH_INFO} = $path;
78 4 50       9 return $1 if $self->_is_allowed($1);
79             }
80              
81 7         8 return;
82             }
83              
84             sub _detect_from_header {
85 6     6   32 my $self = shift;
86 6         4 my ($env) = @_;
87              
88 6 100       17 return unless my $accept_header = $env->{HTTP_ACCEPT_LANGUAGE};
89              
90             return
91 1 50       3 unless my $lang =
92             $self->_build_acceptor->accepts($accept_header, [$self->i18n->languages]);
93              
94 1 50       74 return unless $self->_is_allowed($lang);
95              
96 1         5 return $lang;
97             }
98              
99             sub _detect_from_custom_cb {
100 2     2   9 my $self = shift;
101 2         2 my ($env, $detected_lang) = @_;
102              
103 2         5 my $lang = $self->custom_cb->($env, $detected_lang);
104              
105 2 100       14 return unless $lang;
106              
107 1 50       2 return unless $self->_is_allowed($lang);
108              
109 1         3 return $lang;
110             }
111              
112             sub _build_acceptor {
113 1     1   2 my $self = shift;
114              
115 1         7 return I18N::AcceptLanguage->new();
116             }
117              
118             sub _is_allowed {
119 8     8   6 my $self = shift;
120 8         17 my ($lang) = @_;
121              
122 8     22   61 return !!first { $lang eq $_ } $self->i18n->default_language,
  22         46  
123             $self->i18n->languages;
124             }
125              
126             1;
127             __END__