File Coverage

blib/lib/YATT/Lite/Partial/Gettext.pm
Criterion Covered Total %
statement 58 86 67.4
branch 16 28 57.1
condition 9 18 50.0
subroutine 12 15 80.0
pod 0 9 0.0
total 95 156 60.9


line stmt bran cond sub pod time code
1             package YATT::Lite::Partial::Gettext; sub MY () {__PACKAGE__}
2 13     13   68 use strict;
  13         24  
  13         428  
3 13     13   134 use warnings qw(FATAL all NONFATAL misc);
  13         24  
  13         680  
4             use YATT::Lite::Partial
5 13         108 (fields => [qw/locale_cache/]
6 13     13   66 , requires => [qw/error use_encoded_config/]);
  13         22  
7              
8 13     13   77 use YATT::Lite::Util qw/ckeval/;
  13         21  
  13         806  
9              
10             #========================================
11             # Locale support.
12             #========================================
13              
14 13         124 use YATT::Lite::Util::Enum (_E_ => [qw/MTIME DICT LIST
15 13     13   70 FORMULA NPLURALS HEADER/]);
  13         23  
16              
17             sub configure_locale {
18 5     5 0 9 (my MY $self, my $spec) = @_;
19              
20 5         31 require Locale::PO;
21              
22 5 50       19 if (ref $spec eq 'ARRAY') {
23 5         10 my ($type, @args) = @$spec;
24 5 50       32 my $sub = $self->can("configure_locale_$type")
25             or $self->error("Unknown locale spec: %s", $type);
26 5         16 $sub->($self, @args);
27             } else {
28 0         0 die "NIMPL";
29             }
30             }
31              
32             sub configure_locale_data {
33 5     5 0 6 (my MY $self, my $value) = @_;
34 5   100     20 my $cache = $self->{locale_cache} ||= {};
35 5         16 foreach my $lang (keys %$value) {
36 8         15 my $entry = [];
37 8         19 $entry->[_E_LIST] = my $list = $value->{$lang};
38 8         13 $entry->[_E_DICT] = my $hash = {};
39 8         18 foreach my $po (@$list) {
40 10         102 $hash->{$po->dequote($po->msgid)} = $po;
41             }
42 8         143 $self->lang_parse_header($entry);
43 8         59 $cache->{$lang} = $entry;
44             }
45             }
46              
47             sub lang_parse_header {
48 8     8 0 14 (my MY $self, my $entry) = @_;
49 8 100       29 my $header = $entry->[_E_DICT]->{''}
50             or return;
51 3         11 my $xhf = YATT::Lite::XHF::parse_xhf
52             ($header->dequote($header->msgstr));
53 3         31 my ($sub, $nplurals);
54 3 50       9 if (my $form = $xhf->{'Plural-Forms'}) {
55 3 50       27 if (($nplurals, my $formula) = $form =~ m{^\s*nplurals\s*=\s*(\d+)\s*;
56             \s*plural\s*=\s*([^;]+)}x) {
57 3         6 $formula =~ s/\bn\b/\$n/g;
58 3         17 $sub = ckeval(sprintf q|sub {my ($n) = @_; %s}|, $formula);
59             }
60             } else {
61 0         0 $sub = \&lang_plural_formula_en;
62 0         0 $nplurals = 2;
63             }
64 3         10 @{$entry}[_E_FORMULA, _E_NPLURALS, _E_HEADER] = ($sub, $nplurals, $xhf);
  3         14  
65              
66             }
67              
68             sub lang_load_msgcat {
69 0     0 0 0 (my MY $self, my ($lang, $fn)) = @_;
70 0         0 require Locale::PO;
71 0         0 my $entry = [];
72 0         0 $entry->[_E_DICT] = my $hash = {};
73 0         0 $entry->[_E_LIST] = my $res = Locale::PO->load_file_asarray($fn);
74              
75 0         0 my $use_encoding = $self->use_encoded_config;
76              
77 0         0 foreach my $loc (@$res) {
78 0 0       0 if ($use_encoding) {
79 0         0 $loc->msgid(Encode::decode("utf-8", $loc->dequote($loc->msgid)));
80 0         0 $loc->msgstr(Encode::decode("utf-8", $loc->dequote($loc->msgstr)));
81             }
82 0         0 my $id = $loc->dequote($loc->msgid);
83 0         0 $hash->{$id} = $loc;
84             }
85 0         0 $self->lang_parse_header($entry);
86 0         0 $self->{locale_cache}{$lang} = $entry;
87             }
88              
89             sub _lang_dequote {
90 0     0   0 shift;
91 0         0 my $string = shift;
92 0         0 $string =~ s/^"(.*)"/$1/s; # XXX: Locale::PO::dequote is not enough.
93 0         0 $string =~ s/\\"/"/g;
94 0         0 return $string;
95             }
96              
97 4     4 0 7 sub lang_plural_formula_en { my ($n) = @_; $n != 1 }
  4         25  
98              
99             sub lang_gettext {
100 7     7 0 339 (my MY $self, my ($lang, $msgid)) = @_;
101 7 100       30 my $entry = $self->lang_getmsg($lang, $msgid)
102             or return $msgid;
103 2 50       9 $entry->dequote($entry->msgstr) || $msgid;
104             }
105              
106             sub lang_ngettext {
107 6     6 0 450 (my MY $self, my ($lang, $msgid, $msg_plural, $num)) = @_;
108 6 100       18 if (my ($locale, $entry) = $self->lang_getmsg($lang, $msgid)) {
109 2         58 my $ix = $locale->[_E_FORMULA]->($num);
110 2         8 my $hash = $entry->msgstr_n;
111 2 50       20 if (defined (my $hit = $hash->{$ix})) {
112 2         7 return $entry->dequote($hit);
113             }
114             }
115 4         12 return ($msgid, $msg_plural)[lang_plural_formula_en($num)];
116             }
117              
118             sub lang_msgcat {
119 0     0 0 0 (my MY $self, my $lang) = @_;
120 0         0 my ($catalog);
121             return unless defined $lang
122 0 0 0     0 and $catalog = $self->{locale_cache}{$lang};
123 0 0       0 if (wantarray) {
124             # For later use in lang_extract_lcmsg
125 0   0     0 ($catalog->[_E_LIST] //= [], $catalog->[_E_DICT] //= {});
      0        
126             } else {
127 0         0 $catalog;
128             }
129             }
130              
131             sub lang_getmsg {
132 13     13 0 25 (my MY $self, my ($lang, $msgid)) = @_;
133 13         24 my ($catalog, $msg);
134 13 100 66     110 if (defined $msgid and defined $lang
      100        
      66        
135             and $catalog = $self->{locale_cache}{$lang}
136             and $msg = $catalog->[_E_DICT]{$msgid}) {
137 4 100       21 wantarray ? ($catalog, $msg) : $msg;
138             } else {
139 9         57 return;
140             }
141             }
142              
143             1;