File Coverage

blib/lib/Catalyst/Plugin/I18N.pm
Criterion Covered Total %
statement 24 76 31.5
branch 0 16 0.0
condition 0 10 0.0
subroutine 8 14 57.1
pod 6 6 100.0
total 38 122 31.1


line stmt bran cond sub pod time code
1             package Catalyst::Plugin::I18N;
2              
3 1     1   45347 use strict;
  1         3  
  1         42  
4 1     1   5 use warnings;
  1         2  
  1         31  
5              
6 1     1   3106 use MRO::Compat;
  1         29490  
  1         44  
7 1     1   4026 use I18N::LangTags ();
  1         4784  
  1         33  
8 1     1   2746 use I18N::LangTags::Detect;
  1         3695  
  1         29  
9 1     1   4975 use I18N::LangTags::List;
  1         30092  
  1         867  
10              
11             require Locale::Maketext::Simple;
12              
13             our $VERSION = '0.10';
14             our %options = ( Export => '_loc', Decode => 1 );
15              
16             =head1 NAME
17              
18             Catalyst::Plugin::I18N - I18N for Catalyst
19              
20             =head1 SYNOPSIS
21              
22             use Catalyst 'I18N';
23              
24             print join ' ', @{ $c->languages };
25             $c->languages( ['de'] );
26             print $c->localize('Hello Catalyst');
27              
28             Use a macro if you're lazy:
29              
30             [% MACRO l(text, args) BLOCK;
31             c.localize(text, args);
32             END; %]
33              
34             [% l('Hello Catalyst') %]
35             [% l('Hello [_1]', 'Catalyst') %]
36             [% l('lalala[_1]lalala[_2]', ['test', 'foo']) %]
37             [% l('messages.hello.catalyst') %]
38              
39             =head1 DESCRIPTION
40              
41             Supports mo/po files and Maketext classes under your application's I18N
42             namespace.
43              
44             # MyApp/I18N/de.po
45             msgid "Hello Catalyst"
46             msgstr "Hallo Katalysator"
47              
48             # MyApp/I18N/i_default.po
49             msgid "messages.hello.catalyst"
50             msgstr "Hello Catalyst - fallback translation"
51              
52             # MyApp/I18N/de.pm
53             package MyApp::I18N::de;
54             use base 'MyApp::I18N';
55             our %Lexicon = ( 'Hello Catalyst' => 'Hallo Katalysator' );
56             1;
57              
58             =head2 CONFIGURATION
59              
60             You can override any parameter sent to L<Locale::Maketext::Simple> by specifying
61             a C<maketext_options> hashref to the C<Plugin::I18N> config section. For
62             example, the following configuration will override the C<Decode> parameter which
63             normally defaults to C<1>:
64              
65             __PACKAGE__->config(
66             'Plugin::I18N' =>
67             maketext_options => {
68             Decode => 0
69             }
70             );
71              
72             All languages fallback to MyApp::I18N which is mapped onto the i-default
73             language tag. If you use arbitrary message keys, use i_default.po to translate
74             into English, otherwise the message key itself is returned.
75              
76             =head2 EXTENDED METHODS
77              
78             =head3 setup
79              
80             =cut
81              
82             sub setup {
83 0     0 1   my $self = shift;
84 0           $self->next::method(@_);
85 0           my $calldir = $self;
86 0           $calldir =~ s{::}{/}g;
87 0           my $file = "$calldir.pm";
88 0           my $path = $INC{$file};
89 0           $path =~ s{\.pm$}{/I18N};
90              
91 0   0       my $user_opts = $self->config->{ 'Plugin::I18N' }->{ maketext_options } || {};
92 0           local %options = ( %options, Path => $path, %$user_opts );
93              
94 0           eval <<"";
95             package $self;
96             Locale::Maketext::Simple->import( \%Catalyst\::Plugin\::I18N\::options );
97              
98              
99 0 0         if ($@) {
100 0           $self->log->error(qq/Couldn't initialize i18n "$self\::I18N", "$@"/);
101             }
102             else {
103 0 0         $self->log->debug(qq/Initialized i18n "$self\::I18N"/) if $self->debug;
104             }
105              
106 0 0         if (! $self->config->{ 'Plugin::I18N' }->{installed_languages}) {
107 0           my $languages_list = {};
108             # We re-read the list of files in $path
109             # Originally tried to detect via namespaces, but this lists the currently set LANG envvar, which may not
110             # be a supported language. Also misses out .pm files
111             # Is acceptable to re-read this directory once on setup
112 0 0         if (opendir my $langdir, $path) {
113 0           foreach my $entry (readdir $langdir) {
114 0 0         next unless $entry =~ m/\A (\w+)\.(?:pm|po|mo) \z/xms;
115 0           my $langtag = $1;
116 0 0         next if $langtag eq "i_default";
117 0           my $language_tag = $langtag;
118             #my $language_tag = "$class\::I18N"->get_handle( $langtag )->language_tag;
119             # Did use the get_handle, but that caused problems because en became "Default (Fallthru) Language"
120             # Just do a simple convert instead
121 0           $language_tag =~ s/_/-/g;
122 0           $languages_list->{ $langtag } = I18N::LangTags::List::name( $language_tag );
123             }
124 0           closedir $langdir;
125             }
126 0           $self->config->{ 'Plugin::I18N' }->{installed_languages} = $languages_list;
127             }
128             }
129              
130             =head2 METHODS
131              
132             =head3 languages
133              
134             Contains languages.
135              
136             $c->languages(['de_DE']);
137             print join '', @{ $c->languages };
138              
139             =cut
140              
141             sub languages {
142 0     0 1   my ( $c, $languages ) = @_;
143 0 0         if ($languages) { $c->{languages} = $languages }
  0            
144             else {
145 0   0       $c->{languages} ||= [
146             I18N::LangTags::implicate_supers(
147             I18N::LangTags::Detect->http_accept_langs(
148             $c->request->header('Accept-Language')
149             )
150             ),
151             'i-default'
152             ];
153             }
154 1     1   15 no strict 'refs';
  1         2  
  1         340  
155 0           &{ ref($c) . '::_loc_lang' }( @{ $c->{languages} } );
  0            
  0            
156 0           return $c->{languages};
157             }
158              
159             =head3 language
160              
161             return selected locale in your locales list.
162              
163             =cut
164              
165             sub language {
166 0     0 1   my $c = shift;
167 0   0       my $class = ref $c || $c;
168              
169 0           my $lang = ref "$class\::I18N"->get_handle( @{ $c->languages } );
  0            
170 0           $lang =~ s/.*:://;
171              
172 0           return $lang;
173             }
174              
175             =head3 language_tag
176              
177             return language tag for current locale. The most notable difference from this
178             method in comparison to C<language()> is typically that languages and regions
179             are joined with a dash and not an underscore.
180              
181             $c->language(); # en_us
182             $c->language_tag(); # en-us
183              
184             =cut
185              
186             sub language_tag {
187 0     0 1   my $c = shift;
188 0   0       my $class = ref $c || $c;
189              
190 0           return "$class\::I18N"->get_handle( @{ $c->languages } )->language_tag;
  0            
191             }
192              
193             =head3 installed_languages
194              
195             Returns a hash of { langtag => "descriptive name for language" } based on language files
196             in your application's I18N directory. The descriptive name is based on I18N::LangTags::List information.
197             If the descriptive name is not available, will be undef.
198              
199             =cut
200              
201             sub installed_languages {
202 0     0 1   my $c = shift;
203 0           return $c->config->{ 'Plugin::I18N' }->{installed_languages};
204             }
205              
206             =head3 loc
207              
208             =head3 localize
209              
210             Localize text.
211              
212             print $c->localize( 'Welcome to Catalyst, [_1]', 'sri' );
213              
214             =cut
215              
216             *loc = \&localize;
217              
218             sub localize {
219 0     0 1   my $c = shift;
220 0           $c->languages;
221 1     1   7 no strict 'refs';
  1         3  
  1         139  
222 0 0         return &{ ref($c) . '::_loc' }( $_[0], @{ $_[1] } )
  0            
  0            
223             if ( ref $_[1] eq 'ARRAY' );
224 0           return &{ ref($c) . '::_loc' }(@_);
  0            
225             }
226              
227             =head1 SEE ALSO
228              
229             L<Catalyst>
230              
231             =head1 AUTHORS
232              
233             Sebastian Riedel E<lt>sri@cpan.orgE<gt>
234              
235             Brian Cassidy E<lt>bricas@cpan.orgE<gt>
236              
237             Christian Hansen E<lt>chansen@cpan.orgE<gt>
238              
239             =head1 COPYRIGHT AND LICENSE
240              
241             Copyright (c) 2005 - 2009
242             the Catalyst::Plugin::I18N L</AUTHORS>
243             as listed above.
244              
245             This program is free software, you can redistribute it and/or modify it under
246             the same terms as Perl itself.
247              
248             =cut
249              
250             1;