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