File Coverage

lib/Dancer2/Plugin/Multilang.pm
Criterion Covered Total %
statement 3 17 17.6
branch 0 2 0.0
condition n/a
subroutine 1 3 33.3
pod 0 1 0.0
total 4 23 17.3


line stmt bran cond sub pod time code
1             package Dancer2::Plugin::Multilang;
2             {
3             $Dancer2::Plugin::Multilang::VERSION = '1.2.0';
4             }
5 1     1   584651 use Dancer2::Plugin 0.156000;
  1         13793  
  1         8  
6              
7             register 'language' => sub {
8 0     0     my $dsl = shift;
9 0           return $dsl->app->request->params->{'multilang.lang'};
10             };
11              
12             on_plugin_import {
13             my $dsl = shift;
14             my $conf = plugin_setting();
15             my @managed_languages = @{$conf->{'languages'}};
16             $dsl->app->add_hook(
17             Dancer2::Core::Hook->new(name => 'before', code => sub {
18             my $ignore = $conf->{'no_lang_prefix'} || 0;
19             my $default_language = $conf->{'default'};
20             my $match_string = "^\/(" . join('|', @managed_languages) . ")";
21             my $match_regexp = qr/$match_string/;
22             my $path = $dsl->app->request->path_info();
23             my $method = $dsl->app->request->method();
24             if(($ignore && $path !~ /^$ignore/) ||
25             ! $ignore )
26             {
27             my $lang = '';
28             if ($path =~ $match_regexp)
29             {
30             $lang = $1;
31             }
32             if($lang eq '')
33             {
34             if($dsl->app->request->params->{'multilang.lang'})
35             {
36             $dsl->cookie('multilang.lang' => $dsl->param('multilang.lang'));
37             }
38             else
39             {
40             my $accepted_language = $dsl->app->request->header('Accept-Language') ?
41             wanted_language($dsl, $dsl->app->request->header('Accept-Language'), @managed_languages) :
42             '';
43             if($dsl->cookie('multilang.lang'))
44             {
45             $dsl->redirect("/" . $dsl->cookie('multilang.lang') . $path, 307);
46             }
47             elsif($accepted_language ne '')
48             {
49             $dsl->redirect("/$accepted_language" . $path, 307);
50             }
51             else
52             {
53             $dsl->redirect("/$default_language" . $path, 307);
54             }
55             }
56             }
57             else
58             {
59             $path =~ s/$match_regexp//;
60             $dsl->forward($path, {'multilang.lang' => $lang}, { method => $method });
61             }
62             }
63             })
64             );
65             $dsl->app->add_hook(
66             Dancer2::Core::Hook->new(name => 'after', code => sub {
67             my $response = shift;
68             my $content = $response->{content};
69             my @managed_languages = @{$conf->{'languages'}};
70             if(my $selected_lan = $dsl->app->request->params->{'multilang.lang'})
71             {
72             for(@managed_languages)
73             {
74             my $lan = $_;
75             if($lan ne $selected_lan)
76             {
77             my $meta_for_lan = '\n";
78             $content =~ s/<\/head>/$meta_for_lan<\/head>/;
79             }
80             }
81             $response->{content} = $content;
82             }
83             })
84             );
85             for my $l( @managed_languages)
86             {
87             $dsl->any( ['get', 'post'] => "/" . $l . "/**", sub { $dsl->pass; });
88             $dsl->any( ['get', 'post'] => "/" . $l . "/", sub { $dsl->pass; });
89             }
90              
91             };
92              
93             sub wanted_language
94             {
95 0     0 0   my $dsl = shift;
96 0           my $header = shift;
97 0           my @managed_languages = @_;
98 0           my @lan_strings = split(',', $header);
99 0           for(@lan_strings)
100             {
101 0           my $str = $_;
102 0           $str =~ m/^(..?)(\-.+)?$/; #Only primary tag is considered
103 0           my $lan = $1;
104 0 0         if (grep {$_ eq $lan} @managed_languages) {
  0            
105 0           return $lan;
106             }
107             }
108 0           return '';
109             };
110              
111             register_plugin for_versions => [ 2 ];
112              
113             1;
114              
115             =encoding utf8
116              
117             =head1 NAME
118              
119             Dancer2::Plugin::Multilang - Dancer2 Plugin to create multilanguage sites
120              
121              
122             =head1 DESCRIPTION
123              
124             A plugin for Dancer2 to create multilanguage sites. In your app you can configure any route you want as /myroute/to/page.
125              
126             Plugin will make the app answer to /en/myroute/to/page or /it/myroute/to/page giving the language path to the route manager as a Dancer keyword.
127             It will also redirect navigation using information from the headers transmitted from the browser. Language change during navigation will be managed via cookie.
128              
129             Multilanguage SEO headers will be generated to give advice to the search engines about the language of the pages.
130              
131             =head1 SYNOPSIS
132              
133             # In your Dancer2 app,
134             use Dancer2::Plugin::Multilang
135              
136             #In your config.yml
137             plugins:
138             Multilang:
139             languages: ['it', 'en']
140             default: 'it'
141              
142             where languages is the array of all the languages managed and default is the response language if no information about language can be retrieved.
143              
144             #In the routes
145             get '/route/to/page' => sub {
146             if( language == 'en' )
147             {
148             /* english navigation */
149             }
150             elsif( language == 'it' )
151             {
152             /* italian navigation */
153             }
154             elsif...
155              
156             =head1 USAGE
157              
158             No language information has to be managed in route definition. Language path will be added transparently to your routes.
159              
160             language keyword can be used to retrieve language information inside the route manager.
161              
162             =head1 OPTIONS
163              
164             The options you can configure are:
165              
166             =over 4
167              
168             =item C (required)
169              
170             The array of the languages that will be managed.
171              
172             All the languages are two characters codes as in the primary tag defined by http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.10
173              
174             =item C (required)
175              
176             The default language that will be used when plugin can't guess desired one (or when desired one is not managed)
177              
178             =item C (optional)
179              
180             Do not add the language path to the route if it has this prefix. Useful for Google or Facebook authentication callbacks.
181              
182             no_lang_prefix: /auth
183              
184             =back
185              
186             =cut
187