line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Locale::TextDomain::OO::Lexicon::Role::File; ## no critic (TidyCode)
|
2
|
|
|
|
|
|
|
|
3
|
22
|
|
|
22
|
|
22341
|
use strict;
|
|
22
|
|
|
|
|
65
|
|
|
22
|
|
|
|
|
729
|
|
4
|
22
|
|
|
22
|
|
145
|
use warnings;
|
|
22
|
|
|
|
|
48
|
|
|
22
|
|
|
|
|
750
|
|
5
|
22
|
|
|
22
|
|
152
|
use Carp qw(confess);
|
|
22
|
|
|
|
|
49
|
|
|
22
|
|
|
|
|
1263
|
|
6
|
22
|
|
|
22
|
|
1261
|
use Encode qw(decode FB_CROAK);
|
|
22
|
|
|
|
|
20017
|
|
|
22
|
|
|
|
|
1134
|
|
7
|
22
|
|
|
22
|
|
572
|
use English qw(-no_match_vars $OS_ERROR);
|
|
22
|
|
|
|
|
3579
|
|
|
22
|
|
|
|
|
170
|
|
8
|
22
|
|
|
22
|
|
3334
|
use Locale::TextDomain::OO::Singleton::Lexicon;
|
|
22
|
|
|
|
|
54
|
|
|
22
|
|
|
|
|
693
|
|
9
|
22
|
|
|
22
|
|
10573
|
use Locale::TextDomain::OO::Util::ExtractHeader;
|
|
22
|
|
|
|
|
31173
|
|
|
22
|
|
|
|
|
770
|
|
10
|
22
|
|
|
22
|
|
163
|
use Locale::TextDomain::OO::Util::JoinSplitLexiconKeys;
|
|
22
|
|
|
|
|
49
|
|
|
22
|
|
|
|
|
627
|
|
11
|
22
|
|
|
22
|
|
122
|
use Moo::Role;
|
|
22
|
|
|
|
|
48
|
|
|
22
|
|
|
|
|
178
|
|
12
|
22
|
|
|
22
|
|
8666
|
use MooX::Types::MooseLike::Base qw(CodeRef);
|
|
22
|
|
|
|
|
57
|
|
|
22
|
|
|
|
|
1095
|
|
13
|
22
|
|
|
22
|
|
17654
|
use Path::Tiny qw(path);
|
|
22
|
|
|
|
|
246981
|
|
|
22
|
|
|
|
|
1456
|
|
14
|
22
|
|
|
22
|
|
210
|
use namespace::autoclean;
|
|
22
|
|
|
|
|
54
|
|
|
22
|
|
|
|
|
176
|
|
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
our $VERSION = '1.034';
|
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
with qw(
|
19
|
|
|
|
|
|
|
Locale::TextDomain::OO::Lexicon::Role::GettextToMaketext
|
20
|
|
|
|
|
|
|
Locale::TextDomain::OO::Role::Logger
|
21
|
|
|
|
|
|
|
);
|
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
requires qw(
|
24
|
|
|
|
|
|
|
read_messages
|
25
|
|
|
|
|
|
|
);
|
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
has decode_code => (
|
28
|
|
|
|
|
|
|
is => 'ro',
|
29
|
|
|
|
|
|
|
isa => CodeRef,
|
30
|
|
|
|
|
|
|
lazy => 1,
|
31
|
|
|
|
|
|
|
default => sub {
|
32
|
|
|
|
|
|
|
sub {
|
33
|
|
|
|
|
|
|
my ($charset, $text) = @_;
|
34
|
|
|
|
|
|
|
defined $text
|
35
|
|
|
|
|
|
|
or return $text;
|
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
return decode( $charset, $text, FB_CROAK );
|
38
|
|
|
|
|
|
|
};
|
39
|
|
|
|
|
|
|
},
|
40
|
|
|
|
|
|
|
);
|
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
sub _decode_messages {
|
43
|
39
|
|
|
39
|
|
111
|
my ($self, $messages_ref) = @_;
|
44
|
|
|
|
|
|
|
|
45
|
39
|
|
|
|
|
143
|
my $charset = lc $messages_ref->[0]->{charset};
|
46
|
39
|
|
|
|
|
84
|
for my $value ( @{$messages_ref} ) {
|
|
39
|
|
|
|
|
109
|
|
47
|
296
|
|
|
|
|
3882
|
for my $key ( qw( msgid msgid_plural msgstr ) ) {
|
48
|
888
|
100
|
|
|
|
20730
|
if ( exists $value->{$key} ) {
|
49
|
553
|
|
|
|
|
1054
|
for my $text ( $value->{$key} ) {
|
50
|
553
|
|
|
|
|
10542
|
$text = $self->decode_code->($charset, $text);
|
51
|
|
|
|
|
|
|
}
|
52
|
|
|
|
|
|
|
}
|
53
|
|
|
|
|
|
|
}
|
54
|
296
|
100
|
|
|
|
7189
|
if ( exists $value->{msgstr_plural} ) {
|
55
|
92
|
|
|
|
|
156
|
my $got = @{ $value->{msgstr_plural} };
|
|
92
|
|
|
|
|
204
|
|
56
|
92
|
|
|
|
|
199
|
my $expected = $messages_ref->[0]->{nplurals};
|
57
|
|
|
|
|
|
|
$got <= $expected or confess sprintf
|
58
|
|
|
|
|
|
|
'Count of msgstr_plural=%s but nplurals=%s for msgid="%s" msgid_plural="%s"',
|
59
|
|
|
|
|
|
|
$got,
|
60
|
|
|
|
|
|
|
$expected,
|
61
|
|
|
|
|
|
|
( exists $value->{msgid} ? $value->{msgid} : q{} ),
|
62
|
92
|
50
|
|
|
|
263
|
( exists $value->{msgid_plural} ? $value->{msgid_plural} : q{} );
|
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
63
|
91
|
|
|
|
|
164
|
for my $text ( @{ $value->{msgstr_plural} } ) {
|
|
91
|
|
|
|
|
241
|
|
64
|
219
|
|
|
|
|
9463
|
$text = $self->decode_code->($charset, $text);
|
65
|
|
|
|
|
|
|
}
|
66
|
|
|
|
|
|
|
}
|
67
|
|
|
|
|
|
|
}
|
68
|
|
|
|
|
|
|
|
69
|
38
|
|
|
|
|
219
|
return;
|
70
|
|
|
|
|
|
|
}
|
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
sub _my_glob {
|
73
|
25
|
|
|
25
|
|
81
|
my ($self, $file) = @_;
|
74
|
|
|
|
|
|
|
|
75
|
25
|
|
|
|
|
127
|
my $dirname = $file->parent;
|
76
|
25
|
|
|
|
|
2733
|
my $filename = $file->basename;
|
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
# only one * allowed at all
|
79
|
25
|
|
|
|
|
354
|
my $dir_star_count = () = $dirname =~ m{ [*] }xmsg;
|
80
|
25
|
|
|
|
|
210
|
my $file_star_count = () = $filename =~ m{ [*] }xmsg;
|
81
|
25
|
|
|
|
|
63
|
my $count = $dir_star_count + $file_star_count;
|
82
|
25
|
100
|
|
|
|
177
|
$count
|
83
|
|
|
|
|
|
|
or return $file;
|
84
|
24
|
50
|
|
|
|
106
|
$count > 1
|
85
|
|
|
|
|
|
|
and confess 'Only one * in dirname/filename is allowd to reference the language';
|
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
# one * in filename
|
88
|
24
|
100
|
|
|
|
80
|
if ( $file_star_count ) {
|
89
|
2
|
|
|
|
|
12
|
( my $file_regex = quotemeta $filename ) =~ s{\\[*]}{.*?}xms;
|
90
|
|
|
|
|
|
|
return +(
|
91
|
2
|
|
|
|
|
53
|
sort $dirname->children( qr{\A $file_regex \z}xms )
|
92
|
|
|
|
|
|
|
);
|
93
|
|
|
|
|
|
|
}
|
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
# one * in dir
|
96
|
|
|
|
|
|
|
# split that dir into left, inner with * and right
|
97
|
22
|
|
|
|
|
234
|
my ( $left_dir, $inner_dir, $right_dir )
|
98
|
|
|
|
|
|
|
= split qr{( [^/*]* [*] [^/]* )}xms, $dirname;
|
99
|
22
|
|
|
|
|
402
|
( my $inner_dir_regex = quotemeta $inner_dir ) =~ s{\\[*]}{.*?}xms;
|
100
|
|
|
|
|
|
|
my @left_and_inner_dirs
|
101
|
22
|
|
|
|
|
97
|
= path($left_dir)->children( qr{$inner_dir_regex}xms );
|
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
return +(
|
104
|
|
|
|
|
|
|
sort
|
105
|
|
|
|
|
|
|
grep {
|
106
|
106
|
|
|
|
|
2886
|
$_->is_file;
|
107
|
|
|
|
|
|
|
}
|
108
|
|
|
|
|
|
|
map {
|
109
|
22
|
|
|
|
|
8145
|
path("$_$right_dir")->child($filename);
|
|
106
|
|
|
|
|
5690
|
|
110
|
|
|
|
|
|
|
}
|
111
|
|
|
|
|
|
|
@left_and_inner_dirs
|
112
|
|
|
|
|
|
|
);
|
113
|
|
|
|
|
|
|
}
|
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
sub _run_extra_commands {
|
116
|
28
|
|
|
28
|
|
107
|
my ($self, $identifier, $instance, $next_data_code) = @_;
|
117
|
|
|
|
|
|
|
|
118
|
28
|
100
|
|
|
|
106
|
if ( $identifier eq 'merge_lexicon' ) {
|
119
|
1
|
|
|
|
|
4
|
my ( $from1, $from2, $to ) = (
|
120
|
|
|
|
|
|
|
$next_data_code->(),
|
121
|
|
|
|
|
|
|
$next_data_code->(),
|
122
|
|
|
|
|
|
|
$next_data_code->(),
|
123
|
|
|
|
|
|
|
);
|
124
|
1
|
|
|
|
|
25
|
$instance->merge_lexicon( $from1, $from2, $to );
|
125
|
1
|
|
|
|
|
9
|
return 1;
|
126
|
|
|
|
|
|
|
}
|
127
|
27
|
50
|
|
|
|
124
|
if ( $identifier eq 'copy_lexicon' ) {
|
128
|
0
|
|
|
|
|
0
|
my ( $from, $to ) = ( $next_data_code->(), $next_data_code->() );
|
129
|
0
|
|
|
|
|
0
|
$instance->copy_lexicon( $from, $to );
|
130
|
0
|
|
|
|
|
0
|
return 1;
|
131
|
|
|
|
|
|
|
}
|
132
|
27
|
100
|
|
|
|
94
|
if ( $identifier eq 'move_lexicon' ) {
|
133
|
1
|
|
|
|
|
4
|
my ( $from, $to ) = ( $next_data_code->(), $next_data_code->() );
|
134
|
1
|
|
|
|
|
7
|
$instance->move_lexicon( $from, $to );
|
135
|
1
|
|
|
|
|
10
|
return 1;
|
136
|
|
|
|
|
|
|
}
|
137
|
26
|
100
|
|
|
|
111
|
if ( $identifier eq 'delete_lexicon' ) {
|
138
|
1
|
|
|
|
|
4
|
my $name = $next_data_code->();
|
139
|
1
|
|
|
|
|
6
|
$instance->delete_lexicon($name);
|
140
|
1
|
|
|
|
|
8
|
return 1;
|
141
|
|
|
|
|
|
|
}
|
142
|
|
|
|
|
|
|
|
143
|
25
|
|
|
|
|
90
|
return;
|
144
|
|
|
|
|
|
|
}
|
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
sub lexicon_ref {
|
147
|
21
|
|
|
21
|
1
|
52488
|
my ($self, $file_lexicon_ref) = @_;
|
148
|
|
|
|
|
|
|
|
149
|
21
|
|
|
|
|
229
|
my $instance = Locale::TextDomain::OO::Singleton::Lexicon->instance;
|
150
|
21
|
100
|
|
|
|
508
|
$self->logger and $instance->logger( $self->logger );
|
151
|
|
|
|
|
|
|
my $search_dirs = $file_lexicon_ref->{search_dirs}
|
152
|
21
|
50
|
|
|
|
960
|
or confess 'Hash key "search_dirs" expected';
|
153
|
21
|
|
|
|
|
208
|
my $header_util = Locale::TextDomain::OO::Util::ExtractHeader->instance;
|
154
|
21
|
|
|
|
|
232
|
my $key_util = Locale::TextDomain::OO::Util::JoinSplitLexiconKeys->instance;
|
155
|
21
|
|
|
|
|
107
|
my $data = $file_lexicon_ref->{data};
|
156
|
21
|
|
|
|
|
52
|
my $index = 0;
|
157
|
|
|
|
|
|
|
DATA:
|
158
|
21
|
|
|
|
|
49
|
while ( $index < @{ $file_lexicon_ref->{data} } ) {
|
|
48
|
|
|
|
|
11848
|
|
159
|
28
|
|
|
|
|
85
|
my $identifier = $data->[ $index++ ];
|
160
|
|
|
|
|
|
|
$self->_run_extra_commands(
|
161
|
|
|
|
|
|
|
$identifier,
|
162
|
|
|
|
|
|
|
$instance,
|
163
|
6
|
|
|
6
|
|
17
|
sub { return $data->[ $index++ ] },
|
164
|
28
|
100
|
|
|
|
212
|
) and next DATA;
|
165
|
25
|
|
|
|
|
517
|
my ( $lexicon_key, $lexicon_value )
|
166
|
|
|
|
|
|
|
= ( $identifier, $data->[ $index++ ] );
|
167
|
25
|
|
|
|
|
74
|
for my $dir ( @{ $search_dirs } ) {
|
|
25
|
|
|
|
|
88
|
|
168
|
25
|
|
|
|
|
125
|
my $file = path( $dir, $lexicon_value );
|
169
|
25
|
|
|
|
|
1421
|
my @files = $self->_my_glob($file);
|
170
|
25
|
|
|
|
|
1142
|
for ( @files ) {
|
171
|
40
|
|
|
|
|
7984
|
my $filename = $_->canonpath;
|
172
|
40
|
|
|
|
|
239
|
my $lexicon_language_key = $lexicon_key;
|
173
|
40
|
|
|
|
|
107
|
my $language = $filename;
|
174
|
40
|
|
|
|
|
165
|
my @parts = split m{[*]}xms, $file;
|
175
|
40
|
100
|
|
|
|
353
|
if ( @parts == 2 ) {
|
176
|
39
|
|
|
|
|
156
|
substr $language, 0, length $parts[0], q{};
|
177
|
39
|
|
|
|
|
182
|
substr $language, - length $parts[1], length $parts[1], q{};
|
178
|
39
|
|
|
|
|
224
|
$lexicon_language_key =~ s{[*]}{$language}xms;
|
179
|
|
|
|
|
|
|
}
|
180
|
40
|
|
|
|
|
230
|
my $messages_ref = $self->read_messages($filename);
|
181
|
|
|
|
|
|
|
my $header_msgstr = $messages_ref->[0]->{msgstr}
|
182
|
40
|
50
|
|
|
|
101726
|
or confess 'msgstr of header not found';
|
183
|
40
|
|
|
|
|
127
|
my $header_ref = $messages_ref->[0];
|
184
|
40
|
|
|
|
|
9862
|
%{$header_ref} = (
|
185
|
|
|
|
|
|
|
msgid => $header_ref->{msgid},
|
186
|
40
|
|
|
|
|
97
|
%{ $header_util->extract_header_msgstr( $header_ref->{msgstr} ) },
|
|
40
|
|
|
|
|
368
|
|
187
|
|
|
|
|
|
|
);
|
188
|
|
|
|
|
|
|
$file_lexicon_ref->{gettext_to_maketext}
|
189
|
40
|
100
|
|
|
|
308
|
and $self->gettext_to_maketext($messages_ref);
|
190
|
|
|
|
|
|
|
$file_lexicon_ref->{decode}
|
191
|
40
|
100
|
|
|
|
257
|
and $self->_decode_messages($messages_ref);
|
192
|
|
|
|
|
|
|
$instance->data->{$lexicon_language_key} = {
|
193
|
|
|
|
|
|
|
map { ## no critic (ComplexMappings)
|
194
|
303
|
|
|
|
|
507
|
my $message_ref = $_;
|
195
|
|
|
|
|
|
|
my $msg_key = $key_util->join_message_key({(
|
196
|
|
|
|
|
|
|
map {
|
197
|
303
|
|
|
|
|
549
|
$_ => delete $message_ref->{$_};
|
|
909
|
|
|
|
|
3202
|
|
198
|
|
|
|
|
|
|
}
|
199
|
|
|
|
|
|
|
qw( msgctxt msgid msgid_plural )
|
200
|
|
|
|
|
|
|
)});
|
201
|
303
|
|
|
|
|
11319
|
( $msg_key => $message_ref );
|
202
|
39
|
|
|
|
|
84
|
} @{$messages_ref}
|
|
39
|
|
|
|
|
118
|
|
203
|
|
|
|
|
|
|
};
|
204
|
39
|
100
|
|
|
|
973
|
$self->logger and $self->logger->(
|
205
|
|
|
|
|
|
|
qq{Lexicon "$lexicon_language_key" loaded from file "$filename".},
|
206
|
|
|
|
|
|
|
{
|
207
|
|
|
|
|
|
|
object => $self,
|
208
|
|
|
|
|
|
|
type => 'debug',
|
209
|
|
|
|
|
|
|
event => 'lexicon,load',
|
210
|
|
|
|
|
|
|
},
|
211
|
|
|
|
|
|
|
);
|
212
|
|
|
|
|
|
|
}
|
213
|
|
|
|
|
|
|
}
|
214
|
|
|
|
|
|
|
}
|
215
|
|
|
|
|
|
|
|
216
|
20
|
|
|
|
|
99
|
return $self;
|
217
|
|
|
|
|
|
|
}
|
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
1;
|
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
__END__
|