File Coverage

blib/lib/Astro/App/Satpass2/Locale.pm
Criterion Covered Total %
statement 75 85 88.2
branch 32 42 76.1
condition 9 14 64.2
subroutine 12 12 100.0
pod n/a
total 128 153 83.6


line stmt bran cond sub pod time code
1             package Astro::App::Satpass2::Locale;
2              
3 22     22   2113 use 5.008;
  22         88  
4              
5 22     22   128 use strict;
  22         44  
  22         559  
6 22     22   131 use warnings;
  22         55  
  22         798  
7              
8 22         3217 use Astro::App::Satpass2::Utils qw{
9             expand_tilde instance
10             ARRAY_REF CODE_REF HASH_REF
11             @CARP_NOT
12 22     22   9582 };
  22         74  
13 22     22   167 use Exporter qw{ import };
  22         49  
  22         892  
14 22     22   12473 use I18N::LangTags ();
  22         64952  
  22         560  
15 22     22   10421 use I18N::LangTags::Detect ();
  22         41044  
  22         25371  
16              
17             our $VERSION = '0.051_01';
18              
19             our @EXPORT_OK = qw{ __localize __message __preferred };
20              
21             my @lang;
22             my $locale;
23              
24             {
25              
26             my %deref = (
27             ARRAY_REF() => sub {
28             my ( $data, $inx ) = @_;
29             defined $inx
30             and exists $data->[$inx]
31             and return $data->[$inx];
32             return;
33             },
34             CODE_REF() => sub {
35             my ( $code, $key, $arg ) = @_;
36             my $rslt = $code->( $key, $arg );
37             return $rslt;
38             },
39             HASH_REF() => sub {
40             my ( $data, $key ) = @_;
41             defined $key
42             and exists $data->{$key}
43             and return $data->{$key};
44             return;
45             },
46             '' => sub {
47             return;
48             },
49             );
50              
51             sub __localize {
52              
53             # Keys used:
54             # {argument} = argument for code reference
55             # {default} = the default value
56             # {text} = the text to localize, as scalar or array ref. REQUIRED.
57             # {locale} = fallback locales, as hash ref or ref to array of hash refs.
58              
59 17878     17878   53065 my %arg = @_;
60 17878 50       37994 unless ( $arg{text} ) {
61 0         0 require Carp;
62 0         0 Carp::confess( q );
63             }
64             ref $arg{text}
65 17878 100       35464 or $arg{text} = [ $arg{text} ];
66 17878   100     65497 $arg{locale} ||= [];
67             HASH_REF eq ref $arg{locale}
68 17878 100       37700 and $arg{locale} = [ $arg{locale} ];
69 17878   66     33145 $locale ||= _load();
70              
71 17878         25499 my @rslt;
72 17878         29258 foreach my $lc ( @lang ) {
73             SOURCE_LOOP:
74 17890         22815 foreach my $source ( @{ $locale }, @{ $arg{locale} } ) {
  17890         27755  
  17890         33719  
75 35778 50       65167 unless ( HASH_REF eq ref $source ) {
76 0         0 require Carp;
77 0         0 Carp::confess( "\$source is '$source'" );
78             }
79 35778 100       72988 my $data = $source->{$lc}
80             or next;
81 17885         24643 foreach my $key ( @{ $arg{text} } ) {
  17885         29944  
82             my $code = $deref{ ref $data }
83 33846 50       72228 or do {
84 0         0 require Carp;
85 0         0 Carp::confess(
86             'Programming error - Locale systen can ',
87             'not handle ', ref $data, ' as a container'
88             );
89             };
90             ( $data ) = $code->( $data, $key, $arg{argument} )
91 33846 100       77786 or next SOURCE_LOOP;
92             }
93             wantarray
94 3582 100       19581 or return $data;
95 26         119 push @rslt, $data;
96             }
97             }
98             wantarray
99 14322 100       58481 or return $arg{default};
100 25         136 return ( @rslt, $arg{default} );
101              
102             }
103              
104             }
105              
106             =begin comment
107              
108             {
109             my %stringify_ref = map { $_ => 1 } qw{ Template::Exception };
110              
111             sub __message {
112             # My OpenBSD 5.5 system seems not to stringify the arguments in
113             # the normal course of events, though my Mac OS 10.9 system
114             # does. The OpenBSD system gives instead a stringified hash
115             # reference (i.e. "HASH{0x....}").
116             my @raw_arg = @_;
117             my ( $msg, @arg ) =
118             map { $stringify_ref{ ref $_ } ? '' . $_ : $_ } @raw_arg;
119             my $lcl = __localize(
120             text => [ '+message', $msg ],
121             default => $msg,
122             );
123              
124             CODE_REF eq ref $lcl
125             and return $lcl->( $msg, @arg );
126              
127             $lcl =~ m/ \[ % /smx
128             or return join ' ', $lcl, @arg;
129              
130             grep { instance( $_, 'Template::Exception' ) } @raw_arg
131             and return join ' ', $lcl, @arg;
132              
133             my $tt = Template->new();
134              
135             my $output;
136             $tt->process( \$lcl, {
137             arg => \@arg,
138             }, \$output );
139              
140             return $output;
141             }
142             }
143              
144             =end comment
145              
146             =cut
147              
148             sub __message {
149 24     24   72 my ( $msg, @arg ) = @_;
150              
151 24 100       113 instance( $msg, 'Template::Exception' )
152             and return _message_template_exception( $msg, @arg );
153              
154 23         364 my $lcl = __localize(
155             text => [ '+message', $msg ],
156             default => $msg,
157             );
158              
159 23 50       97 CODE_REF eq ref $lcl
160             and return $lcl->( $msg, @arg );
161              
162 23 50       235 $lcl =~ m/ \[ % /smx
163             or return join ' ', $lcl, @arg;
164              
165 0         0 my $tt = Template->new();
166              
167 0         0 my $output;
168 0         0 $tt->process( \$lcl, {
169             arg => \@arg,
170             }, \$output );
171              
172 0         0 return $output;
173             }
174              
175             sub _message_template_exception {
176 1     1   7 my ( $ex, @arg ) = @_;
177 1         5 local $_ = $ex->info();
178             # NOTE we're assuming that if there is a return we caught a
179             # re-thrown exception that had already been munged.
180 1 50       10 m/ \n \z /smx
181             and return $ex;
182 1         5 $_ = join ' ', $_, @arg;
183 1 50       10 m/ [.?|] \z /smx
184             or $_ .= '.';
185 1         3 $_ .= "\n";
186 1         4 my $class = ref $ex;
187 1         5 return $class->new( $ex->type(), $_ );
188             }
189              
190             sub __preferred {
191 2   33 2   9 $locale ||= _load();
192 2 100       12 return wantarray ? @lang : $lang[0];
193             }
194              
195             sub _load {
196              
197             # Pick up the languages from the environment
198 6     6   47 @lang = I18N::LangTags::implicate_supers(
199             I18N::LangTags::Detect::detect() );
200              
201             # Normalize the language names.
202 6         2297 foreach ( @lang ) {
203 2 100       20 s/ ( [^_-]+ ) [_-] (.* ) /\L$1_\U$2/smx
204             or $_ = lc $_;
205 2 50       7 'c' eq $_
206             and $_ = uc $_;
207             }
208              
209             # Append the default locale name.
210 6 50       40 grep { 'C' eq $_ } @lang
  2         6  
211             or push @lang, 'C';
212              
213             # Accumulator for locale data.
214 6         17 my @locales;
215              
216             # Put all the user's data in a hash.
217 6         17 push @locales, {};
218 6         25 foreach my $lc ( @lang ) {
219 8         179 eval { ## no critic (ErrorHandling::RequireCheckingReturnValueOfEval)
220 8 50       58 defined( my $path = expand_tilde( "~~/locale/$lc.pm" ) )
221             or return;
222 3         5 my $data;
223             $data = do $path
224             and HASH_REF eq ref $data
225 3 100 66     436 and $locales[-1]{$lc} = $data;
226             };
227             }
228              
229             # Put the system-wide data in a hash.
230 6         356 push @locales, {};
231 6         22 foreach my $lc ( @lang ) {
232 8         31 my $mod_name = __PACKAGE__ . "::$lc";
233 8         16 my $data;
234             $data = eval "require $mod_name"
235             and HASH_REF eq ref $data
236 8 100 66     665 and $locales[-1]{$lc} = $data;
237             }
238              
239             # Return a reference to the names of locales.
240 6         44 return \@locales;
241             }
242              
243             1;
244              
245             __END__