File Coverage

blib/lib/Mojolicious/Plugin/I18NUtils.pm
Criterion Covered Total %
statement 106 106 100.0
branch 10 16 62.5
condition 38 56 67.8
subroutine 19 19 100.0
pod 1 1 100.0
total 174 198 87.8


line stmt bran cond sub pod time code
1             package Mojolicious::Plugin::I18NUtils;
2              
3             # ABSTRACT: provide some helper functions for I18N
4 27     27   20651 use Mojo::Base 'Mojolicious::Plugin';
  27         48  
  27         289  
5 27     27   29721 use Time::Piece;
  27         225165  
  27         132  
6 27     27   21909 use CLDR::Number;
  27         3871757  
  27         909  
7 27     27   21200 use HTTP::AcceptLanguage;
  27         85539  
  27         930  
8              
9 27     27   18085 use Mojolicious::Plugin::I18NUtils::Locale;
  27         85  
  27         283  
10              
11             our $VERSION = '0.19';
12              
13             sub register {
14 27     27 1 20492 my ($self, $app, $config) = @_;
15              
16 27   50     152 $config //= {};
17 27   100     913 my $parse_format = $config->{format} // '%Y-%m-%d %H:%M:%S';
18              
19 27         61 my %objects;
20              
21             $app->helper( browser_languages => sub {
22 129     129   43875 my $c = shift;
23              
24 129         447 my $lang = HTTP::AcceptLanguage->new( $c->req->headers->accept_language );
25 129         10828 return $lang->languages;
26 27         275 });
27              
28             $app->helper( datetime_loc => sub {
29 50     50   419607 my $c = shift;
30 50         111 my ($date, $lang) = @_;
31              
32 50   66     306 $lang //= ($c->browser_languages)[0];
33              
34 50 50       760 return '' if !defined $date;
35              
36 50         185 my $output_format = $self->_date_long( $lang );
37 50         167 my $formatted_date = $self->_translate( $date, $parse_format, $output_format );
38              
39 50         269 return $formatted_date;
40 27         1235 } );
41              
42             $app->helper( date_loc => sub {
43 60     60   495505 my $c = shift;
44 60         121 my ($date, $lang) = @_;
45              
46 60   66     344 $lang //= ($c->browser_languages)[0];
47              
48 60 50       869 return '' if !defined $date;
49              
50 60         212 my $output_format = $self->_date_short( $lang );
51 60         202 my $formatted_date = $self->_translate( $date, $parse_format, $output_format );
52              
53 60         332 return $formatted_date;
54 27         920 } );
55              
56             $app->helper( date_from_to => sub {
57 11     11   88441 my $c = shift;
58 11         24 my ($date, $from, $to) = @_;
59              
60 11         37 my $in_format = $self->_date_short( $from );
61 11         26 my $out_format = $self->_date_short( $to );
62              
63 11 50       44 $out_format = '%Y-%m-%d' if lc $to eq 'iso';
64              
65 11         34 my $formatted_date = $self->_translate( $date, $in_format, $out_format );
66              
67 11         89 return $formatted_date;
68 27         682 } );
69              
70             $app->helper( currency => sub {
71 30     30   268001 my ($c, $number, $locale, $currency, $opts) = @_;
72              
73 30   66     217 $locale //= ($c->browser_languages)[0];
74              
75 30   66     1139 $objects{cldr}->{$locale} ||= CLDR::Number->new( locale => $locale );
76 30   66     40683 $objects{cur}->{$locale} ||= $objects{cldr}->{$locale}->currency_formatter( currency_code => $currency );
77              
78 30         1311781 my $cur_object = $objects{cur}->{$locale};
79              
80 30 50 66     150 if ( $opts && $opts->{cash} ) {
81 16         362 $cur_object->cash(1);
82             }
83              
84 30         8355 my $formatted = $cur_object->format( $number );
85 30         19815 $cur_object->cash(0);
86              
87 30         14512 return $formatted;
88 27         691 } );
89              
90             $app->helper( decimal => sub {
91 18     18   154987 my ($c, $number, $locale) = @_;
92              
93 18   66     214 $locale //= ($c->browser_languages)[0];
94              
95 18   66     658 $objects{cldr}->{$locale} ||= CLDR::Number->new( locale => $locale );
96 18   66     21754 $objects{dec}->{$locale} ||= $objects{cldr}->{$locale}->decimal_formatter;
97              
98 18         201876 my $formatted = $objects{dec}->{$locale}->format( $number );
99 18         13657 return $formatted;
100 27         682 } );
101              
102             $app->helper( range => sub {
103 27     27   246767 my ($c, $lower, $upper, $locale) = @_;
104              
105 27   66     168 $locale //= ($c->browser_languages)[0];
106              
107 27   66     1011 $objects{cldr}->{$locale} ||= CLDR::Number->new( locale => $locale );
108 27   66     33093 $objects{dec}->{$locale} ||= $objects{cldr}->{$locale}->decimal_formatter;
109              
110 27         305430 my $formatted = $objects{dec}->{$locale}->range( $lower, $upper );
111 27         31240 return $formatted;
112 27         658 } );
113              
114             $app->helper( at_least => sub {
115 54     54   469009 my ($c, $number, $locale) = @_;
116              
117 54   66     317 $locale //= ($c->browser_languages)[0];
118              
119 54   66     1131 $objects{cldr}->{$locale} ||= CLDR::Number->new( locale => $locale );
120 54   66     36840 $objects{dec}->{$locale} ||= $objects{cldr}->{$locale}->decimal_formatter;
121              
122 54         212541 my $formatted = $objects{dec}->{$locale}->at_least( $number );
123 54         34420 return $formatted;
124 27         707 } );
125              
126             $app->helper( locale_obj => sub {
127 26     26   205050 my ( $c, $locale) = @_;
128              
129 26   66     152 $locale //= ($c->browser_languages)[0];
130              
131 26         354 return Mojolicious::Plugin::I18NUtils::Locale->new( locale => $locale );
132 27         670 });
133             }
134              
135             sub _translate {
136 121     121   263 my ($self, $date, $in, $out) = @_;
137              
138 121 100       391 if ( length $date < 11 ) {
139 45         139 $date .= ' 00:00:00';
140             }
141              
142 121         254 my $out_date;
143              
144             {
145 121     11   182 local $SIG{__WARN__} = sub {};
  121         831  
146              
147 121 100       308 eval {
148 121         647 my $date_obj = Time::Piece->strptime( $date, $in );
149 113         3456 $out_date = $date_obj->strftime( $out );
150 113         7023 1;
151             } or $out_date = '';
152             }
153              
154 121         12333 return $out_date;
155             }
156              
157             sub _date_long {
158 50     50   102 my ($self, $lang) = @_;
159              
160 50 50       111 return "%d/%m/%Y %H:%M:%S" if !$lang;
161              
162 50         104 $lang = lc $lang;
163 50         114 $lang =~ s/-/_/g;
164              
165 50         298 state $formats = {
166             ar_sa => '%d.%m.%Y %H:%M:%S',
167             bg => '%d.%m.%Y %H:%M:%S',
168             ca => '%d.%m.%Y %H:%M:%S',
169             cs => '%d/%m/%Y %H:%M:%S',
170             da => '%d.%m.%Y %H:%M:%S',
171             de => '%d.%m.%Y %H:%M:%S',
172             el => '%d.%m.%Y %H:%M:%S',
173             en_ca => '%Y-%m-%d %H:%M:%S',
174             en_gb => '%d/%m/%Y %H:%M:%S',
175             en => '%m/%d/%Y %H:%M:%S',
176             es_co => '%d/%m/%Y - %H:%M:%S',
177             es_mx => '%d/%m/%Y - %H:%M:%S',
178             es => '%d/%m/%Y - %H:%M:%S',
179             et => '%d.%m.%Y %H:%M:%S',
180             fa => '%d.%m.%Y %H:%M:%S',
181             fi => '%d.%m.%Y %H:%M:%S',
182             fr_ca => '%d.%m.%Y %H:%M:%S',
183             fr => '%d.%m.%Y %H:%M:%S',
184             he => '%d/%m/%Y %H:%M:%S',
185             hi => '%d/%m/%Y - %H:%M:%S',
186             hr => '%d.%m.%Y %H:%M:%S',
187             hu => '%Y.%m.%d %H:%M:%S',
188             it => '%d/%m/%Y %H:%M:%S',
189             ja => '%Y/%m/%d %H:%M:%S',
190             lt => '%Y-%m-%d %H:%M:%S',
191             lv => '%d.%m.%Y %H:%M:%S',
192             ms => '%d.%m.%Y %H:%M:%S',
193             nb_no => '%d/%m %Y %H:%M:%S',
194             nl => '%d-%m-%Y %H:%M:%S',
195             pl => '%Y-%m-%d %H:%M:%S',
196             pt_br => '%d/%m/%Y %H:%M:%S',
197             pt => '%Y-%m-%d %H:%M:%S',
198             ru => '%d.%m.%Y %H:%M:%S',
199             sk_sk => '%d.%m.%Y %H:%M:%S',
200             sl => '%d.%m.%Y %H:%M:%S',
201             sr_cyrl => '%d.%m.%Y %H:%M:%S',
202             sr_latn => '%d.%m.%Y %H:%M:%S',
203             sv => '%d/%m %Y %H:%M:%S',
204             sw => '%m/%d/%Y %H:%M:%S',
205             tr => '%d.%m.%Y %H:%M:%S',
206             uk => '%m/%d/%Y %H:%M:%S',
207             vi_vn => '%d.%m.%Y %H:%M:%S',
208             zh_cn => '%Y.%m.%d %H:%M:%S',
209             zh_tw => '%Y.%m.%d %H:%M:%S',
210             };
211              
212 50   50     237 return $formats->{$lang} // '%d/%m/%Y %H:%M:%S';
213             }
214              
215             sub _date_short {
216 82     82   142 my ($self, $lang) = @_;
217              
218 82 50       192 return "%d/%m/%Y" if !$lang;
219              
220 82         160 $lang = lc $lang;
221 82         176 $lang =~ s/-/_/g;
222              
223 82         362 state $formats = {
224             ar_sa => '%d.%m.%Y',
225             bg => '%d.%m.%Y',
226             ca => '%d.%m.%Y',
227             cs => '%d/%m/%Y',
228             da => '%d.%m.%Y',
229             de => '%d.%m.%Y',
230             el => '%d.%m.%Y',
231             en_ca => '%Y-%m-%d',
232             en_gb => '%d/%m/%Y',
233             en => '%m/%d/%Y',
234             es_co => '%d/%m/%Y',
235             es_mx => '%d/%m/%Y',
236             es => '%d/%m/%Y',
237             et => '%d.%m.%Y',
238             fa => '%d.%m.%Y',
239             fi => '%d.%m.%Y',
240             fr_ca => '%d.%m.%Y',
241             fr => '%d.%m.%Y',
242             he => '%d/%m/%Y',
243             hi => '%d/%m/%Y',
244             hr => '%d.%m.%Y',
245             hu => '%Y.%m.%d',
246             it => '%d/%m/%Y',
247             ja => '%Y/%m/%d',
248             lt => '%Y-%m-%d',
249             lv => '%d.%m.%Y',
250             ms => '%d.%m.%Y',
251             nb_no => '%d.%m.%Y',
252             nl => '%d-%m-%Y',
253             pl => '%Y-%m-%d',
254             pt_br => '%d/%m/%Y',
255             pt => '%Y-%m-%d',
256             ru => '%d.%m.%Y',
257             sk_sk => '%d.%m.%Y',
258             sl => '%d.%m.%Y',
259             sr_cyrl => '%d.%m.%Y',
260             sr_latn => '%d.%m.%Y',
261             sv => '%Y.%m.%d',
262             sw => '%m/%d/%Y',
263             tr => '%d.%m.%Y',
264             uk => '%m/%d/%Y',
265             vi_vn => '%d.%m.%Y',
266             zh_cn => '%Y.%m.%d',
267             zh_tw => '%Y.%m.%d',
268             };
269              
270 82   100     363 return $formats->{$lang} // '%d/%m/%Y';
271             }
272              
273             1;
274              
275             __END__