File Coverage

blib/lib/Getopt/EX/i18n.pm
Criterion Covered Total %
statement 23 94 24.4
branch 0 46 0.0
condition 0 9 0.0
subroutine 8 18 44.4
pod 0 10 0.0
total 31 177 17.5


line stmt bran cond sub pod time code
1             package Getopt::EX::i18n;
2 1     1   862 use 5.014;
  1         3  
3 1     1   5 use strict;
  1         1  
  1         22  
4 1     1   5 use warnings;
  1         2  
  1         30  
5 1     1   627 use Data::Dumper;
  1         6890  
  1         193  
6              
7             our $VERSION = "0.06";
8              
9             =encoding utf-8
10              
11             =head1 NAME
12              
13             Getopt::EX::i18n - General i18n module
14              
15             =head1 SYNOPSIS
16              
17             command -Mi18n [ options ]
18              
19             =head1 DESCRIPTION
20              
21             This module B provide an easy way to set locale environment
22             before executing arbitrary command. Locale list is taken from the
23             system by C command. Next list is a sample locales
24             available on macOS 10.15 (Catalina).
25              
26             af_ZA Afrikaans / South Africa
27             am_ET Amharic / Ethiopia
28             be_BY Belarusian / Belarus
29             bg_BG Bulgarian / Bulgaria
30             ca_ES Catalan; Valencian / Spain
31             cs_CZ Czech / Czech Republic
32             da_DK Danish / Denmark
33             de_AT German / Austria
34             de_CH German / Switzerland
35             de_DE German / Germany
36             el_GR Greek, Modern (1453-) / Greece
37             en_AU English / Australia
38             en_CA English / Canada
39             en_GB English / United Kingdom
40             en_IE English / Ireland
41             en_NZ English / New Zealand
42             en_US English / United States
43             es_ES Spanish / Spain
44             et_EE Estonian / Estonia
45             eu_ES Basque / Spain
46             fi_FI Finnish / Finland
47             fr_BE French / Belgium
48             fr_CA French / Canada
49             fr_CH French / Switzerland
50             fr_FR French / France
51             he_IL Hebrew / Israel
52             hr_HR Croatian / Croatia
53             hu_HU Hungarian / Hungary
54             hy_AM Armenian / Armenia
55             is_IS Icelandic / Iceland
56             it_CH Italian / Switzerland
57             it_IT Italian / Italy
58             ja_JP Japanese / Japan
59             kk_KZ Kazakh / Kazakhstan
60             ko_KR Korean / Korea, Republic of
61             lt_LT Lithuanian / Lithuania
62             nl_BE Dutch / Belgium
63             nl_NL Dutch / Netherlands
64             no_NO Norwegian / Norway
65             pl_PL Polish / Poland
66             pt_BR Portuguese / Brazil
67             pt_PT Portuguese / Portugal
68             ro_RO Romanian / Romania
69             ru_RU Russian / Russian Federation
70             sk_SK Slovak / Slovakia
71             sl_SI Slovenian / Slovenia
72             sr_YU Serbian / Yugoslavia
73             sv_SE Swedish / Sweden
74             tr_TR Turkish / Turkey
75             uk_UA Ukrainian / Ukraine
76             zh_CN Chinese / China
77             zh_HK Chinese / Hong Kong
78             zh_TW Chinese / Taiwan, Province of China
79              
80             As for Japanese locale C, following options are defined by
81             default, and set C environment as C.
82              
83             LOCALE: --ja_JP (raw)
84             --ja-JP (dash)
85             --jaJP (long)
86             --jajp (long_lc)
87             LANGUAGE: --ja (lang)
88             COUNTRY: --JP (country)
89             --jp (country_lc)
90              
91             Short language option (C<--ja>) is defined in the alphabetical order
92             of the country code, so the option C<--en> is assigned to C.
93             But if the same country name is found as language, it takes
94             precedence; German is used in three locales (C, C,
95             C) but option C<--de> is defined as C.
96              
97             Country options (C<--JP> and C<--jp>) are defined only when the same
98             language option is not defined by other entry, and only single entry
99             can be found for the country. Option for Switzerland is not defined
100             because there are three entries (C, C, C).
101             Country option C<--AM> is assigned to C, but language option
102             C<--am> is assigned to C.
103              
104             =head1 OPTION
105              
106             Option parameter can be given with B function called with
107             module declaration.
108              
109             command -Mi18n::setopt(name[=value])
110              
111             =over 7
112              
113             =item B
114              
115             =item B
116              
117             =item B
118              
119             =item B
120              
121             =item B
122              
123             =item B
124              
125             =item B
126              
127             These parameter tells which option is defined. All options are
128             enabled by default. You can disable country option like this:
129              
130             command -Mi18n::setopt(country=0,country_lc=0)
131              
132             command -Mi18n::setopt=country=0,country_lc=0
133              
134             =item B
135              
136             Show locale information.
137              
138             $ optex -Mi18n::setopt=verbose date --it
139             LANG=it_IT (Italian / Italy)
140             Gio 4 Giu 2020 16:47:33 JST
141              
142             =item B
143              
144             Show option list.
145              
146             =item B=I
147              
148             Set the option to display option list and exit. You can introduce a
149             new option B<-l> to show available option list:
150              
151             -Mi18n::setopt(listopt=-l)
152              
153             =item B=I
154              
155             Specify prefix string. Default is C<-->.
156              
157             =back
158              
159             =head1 SEE ALSO
160              
161             =over 7
162              
163             =item B
164              
165             You can execute arbitrary command on the system getting the benefit of
166             B using B.
167              
168             $ optex -Mi18n cal 2020 --am
169              
170             L
171              
172             L
173              
174             =back
175              
176             =head1 LICENSE
177              
178             Copyright (C) 2020 Kazumasa Utashiro.
179              
180             This library is free software; you can redistribute it and/or modify
181             it under the same terms as Perl itself.
182              
183             =head1 AUTHOR
184              
185             Kazumasa Utashiro Ekaz@utashiro.comE
186              
187             =cut
188              
189             my %opt = (
190             raw => 1,
191             dash => 1,
192             long => 1,
193             long_lc => 1,
194             lang => 1,
195             country => 1,
196             country_lc => 1,
197             verbose => 0,
198             list => 0,
199             prefix => '--',
200             listopt => undef,
201             );
202              
203             my $module;
204              
205             sub initialize {
206 0 0   0 0   return if state $called++;
207 0           my($obj, $argv) = @_;
208 0           $module = $obj;
209 0           setup();
210             }
211              
212             my @locale;
213             my %lang;
214             my %cc;
215             my %opthash;
216              
217             package LocaleObj {
218 1     1   600 use Moo;
  1         11935  
  1         6  
219             has [ qw(name lang cc) ] => (is => 'ro', required => 1);
220             sub create {
221 0     0 0   my $class = shift;
222 0 0         $_[0] =~ /^(([a-z][a-z])_([A-Z][A-Z]))$/ or die;
223 0           $class->new(name => $1, lang => $2, cc => $3);
224             }
225 1     1   2067 use Getopt::EX::i18n::iso639 qw(%iso639);
  1         3  
  1         131  
226 1     1   470 use Getopt::EX::i18n::iso3361 qw(%iso3361);
  1         2  
  1         266  
227 0 0   0 0   sub lang_name { $iso639 {+shift->lang} || 'UNKNOWN' }
228 0 0   0 0   sub cc_name { $iso3361{+shift->cc} || 'UNKNOWN' }
229             }
230              
231             sub finalize {
232 0     0 0   my($obj, $argv) = @_;
233 0           for my $locale (sort @locale) {
234 0 0         $locale =~ /^(?\w\w)_(?\w\w)$/ or next;
235 1     1   495 my($lang, $cc) = @+{qw(lang cc)};;
  1         437  
  1         922  
  0            
236 0           my @list;
237 0 0         push @list, "$locale" if $opt{raw};
238 0 0         push @list, "$lang-$cc" if $opt{dash};
239 0 0         push @list, "$lang$cc" if $opt{long};
240 0           $cc = lc $cc;
241 0 0         push @list, "$lang$cc" if $opt{long_lc};
242 0 0         if ($opt{lang}) {
243 0 0 0       if (!$opthash{$lang} or $lang eq $cc) {
244 0           push @list, $lang;
245             }
246             }
247 0 0 0       if ($lang eq $cc or @{$cc{$cc}} == 1) {
  0            
248 0 0         push @list, uc $cc if $opt{country};
249 0 0 0       push @list, $cc if $opt{country_lc} and !$lang{$cc};
250             }
251 0           for (@list) {
252 0           $opthash{$_} = LocaleObj->create($locale);
253             }
254             }
255              
256 0           $obj->mode(function => 1);
257 0 0         if (my $listopt = $opt{listopt}) {
258 0           $obj->setopt($listopt, "&options(show,exit)");
259             }
260 0           &options(set => 1, show => $opt{list});
261 0           return;
262             }
263              
264             sub options {
265 0     0 0   my %arg = (
266             set => 0, # set option
267             show => 0, # print option
268             exit => 0, # exit at the end
269             @_);
270 0           my @keys = do {
271 0           map { $_->[0] }
272 0 0         sort { $a->[1] cmp $b->[1] || $a->[0] cmp $b->[0] }
273 0           map { [ $_, $opthash{$_}->cc ] }
  0            
274             keys %opthash;
275             };
276 0           for my $opt (@keys) {
277 0           my $locale = $opthash{$opt};
278 0           my $option = $opt{prefix} . $opt;
279 0           my $name = $locale->name;
280 0           my $call = "&setenv(LANG=$name)";
281 0 0         $module->setopt($option, $call) if $arg{set};
282 0 0         if ($arg{show}) {
283             printf "option %-*s %s # %s / %s\n",
284 0           (state $optwidth = length($opt{prefix}) + length($name)),
285             $option, $call,
286             $locale->cc_name, $locale->lang_name;
287             }
288             }
289 0 0         exit if $arg{exit};
290 0           return ();
291             }
292              
293             sub setup {
294 0 0   0 0   return if state $called++;
295 0 0         grep { -x "$_/locale" } split /:/, $ENV{PATH} or return;
  0            
296 0           for (`locale -a`) {
297 0 0         /^((\w\w)_(\w\w))$/ or next;
298 0           my($name, $lang, $cc) = ($1, $2, lc $3);
299 0           push @locale, $name;
300 0           push @{ $lang{$lang} }, $name;
  0            
301 0           push @{ $cc{$cc} }, $name;
  0            
302             }
303             }
304              
305             sub locales {
306 0     0 0   chomp( my @locale = `locale -a` );
307 0           grep { /^\w\w_\w\w$/ } @locale;
  0            
308             }
309              
310             sub setopt {
311 0     0 0   %opt = (%opt, @_);
312             }
313              
314             sub setenv {
315 0     0 0   while (@_ >= 2) {
316 0           my($key, $value) = splice @_, 0, 2;
317 0 0         if ($opt{verbose}) {
318 0           my $l = LocaleObj->create($value);
319 0           warn sprintf("%s=%s (%s / %s)\n",
320             $key, $value, $l->lang_name, $l->cc_name);
321             }
322 0           $ENV{$key} = $value;
323             }
324 0           return ();
325             }
326              
327             1;
328              
329             __DATA__