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   5458 use 5.008;
  22         89  
4              
5 22     22   118 use strict;
  22         40  
  22         609  
6 22     22   107 use warnings;
  22         57  
  22         1400  
7              
8 22         3923 use Astro::App::Satpass2::Utils qw{
9             expand_tilde instance
10             ARRAY_REF CODE_REF HASH_REF
11             @CARP_NOT
12 22     22   9434 };
  22         71  
13 22     22   175 use Exporter qw{ import };
  22         47  
  22         762  
14 22     22   13054 use I18N::LangTags ();
  22         83727  
  22         750  
15 22     22   11863 use I18N::LangTags::Detect ();
  22         53176  
  22         32287  
16              
17             our $VERSION = '0.057_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 17877     17877   506341 my %arg = @_;
60 17877 50       42954 unless ( $arg{text} ) {
61 0         0 require Carp;
62 0         0 Carp::confess( q );
63             }
64             ref $arg{text}
65 17877 100       51508 or $arg{text} = [ $arg{text} ];
66 17877   100     74607 $arg{locale} ||= [];
67             HASH_REF eq ref $arg{locale}
68 17877 100       44040 and $arg{locale} = [ $arg{locale} ];
69 17877   66     38855 $locale ||= _load();
70              
71 17877         27468 my @rslt;
72 17877         30851 foreach my $lc ( @lang ) {
73             SOURCE_LOOP:
74 17889         27163 foreach my $source ( @{ $locale }, @{ $arg{locale} } ) {
  17889         30765  
  17889         39131  
75 35776 50       74567 unless ( HASH_REF eq ref $source ) {
76 0         0 require Carp;
77 0         0 Carp::confess( "\$source is '$source'" );
78             }
79 35776 100       87426 my $data = $source->{$lc}
80             or next;
81 17884         27517 foreach my $key ( @{ $arg{text} } ) {
  17884         33377  
82             my $code = $deref{ ref $data }
83 33844 50       78974 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 33844 100       84347 or next SOURCE_LOOP;
92             }
93             wantarray
94 3582 100       27558 or return $data;
95 26         82 push @rslt, $data;
96             }
97             }
98             wantarray
99 14321 100       70019 or return $arg{default};
100 25         133 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 25     25   65 my ( $msg, @arg ) = @_;
150              
151 25 100       957 instance( $msg, 'Template::Exception' )
152             and return _message_template_exception( $msg, @arg );
153              
154 24         160 my $lcl = __localize(
155             text => [ '+message', $msg ],
156             default => $msg,
157             );
158              
159 24 50       83 CODE_REF eq ref $lcl
160             and return $lcl->( $msg, @arg );
161              
162 24 50       224 $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   2 my ( $ex, @arg ) = @_;
177 1         4 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       6 m/ \n \z /smx
181             and return $ex;
182 1         3 $_ = join ' ', $_, @arg;
183 1 50       4 m/ [.?|] \z /smx
184             or $_ .= '.';
185 1         3 $_ .= "\n";
186 1         2 my $class = ref $ex;
187 1         3 return $class->new( $ex->type(), $_ );
188             }
189              
190             sub __preferred {
191 2   33 2   7 $locale ||= _load();
192 2 100       10 return wantarray ? @lang : $lang[0];
193             }
194              
195             sub _load {
196              
197             # Pick up the languages from the environment
198 7     7   55 @lang = I18N::LangTags::implicate_supers(
199             I18N::LangTags::Detect::detect() );
200              
201             # Normalize the language names.
202 7         2839 foreach ( @lang ) {
203 2 100       14 s/ ( [^_-]+ ) [_-] (.* ) /\L$1_\U$2/smx
204             or $_ = lc $_;
205 2 50       5 'c' eq $_
206             and $_ = uc $_;
207             }
208              
209             # Append the default locale name.
210 7 50       57 grep { 'C' eq $_ } @lang
  2         6  
211             or push @lang, 'C';
212              
213             # Accumulator for locale data.
214 7         25 my @locales;
215              
216             # Put all the user's data in a hash.
217 7         24 push @locales, {};
218 7         22 foreach my $lc ( @lang ) {
219 9         260 eval { ## no critic (ErrorHandling::RequireCheckingReturnValueOfEval)
220 9 50       57 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     572 and $locales[-1]{$lc} = $data;
226             };
227             }
228              
229             # Put the system-wide data in a hash.
230 7         37 push @locales, {};
231 7         23 foreach my $lc ( @lang ) {
232 9         46 my $mod_name = __PACKAGE__ . "::$lc";
233 9         17 my $data;
234             $data = eval "require $mod_name"
235             and HASH_REF eq ref $data
236 9 100 66     709 and $locales[-1]{$lc} = $data;
237             }
238              
239             # Return a reference to the names of locales.
240 7         51 return \@locales;
241             }
242              
243             1;
244              
245             __END__