line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# Locale::Maketext::Gettext - Joins the gettext and Maketext frameworks |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
# Copyright (c) 2003-2019 imacat. All rights reserved. This program is free |
4
|
|
|
|
|
|
|
# software; you can redistribute it and/or modify it under the same terms |
5
|
|
|
|
|
|
|
# as Perl itself. |
6
|
|
|
|
|
|
|
# First written: 2003-04-23 |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
package Locale::Maketext::Gettext; |
9
|
11
|
|
|
11
|
|
34887
|
use 5.008; |
|
11
|
|
|
|
|
1699
|
|
10
|
11
|
|
|
11
|
|
52
|
use strict; |
|
11
|
|
|
|
|
20
|
|
|
11
|
|
|
|
|
1843
|
|
11
|
11
|
|
|
11
|
|
48
|
use warnings; |
|
11
|
|
|
|
|
26
|
|
|
11
|
|
|
|
|
343
|
|
12
|
11
|
|
|
11
|
|
50
|
use base qw(Locale::Maketext Exporter); |
|
11
|
|
|
|
|
16
|
|
|
11
|
|
|
|
|
5775
|
|
13
|
11
|
|
|
11
|
|
115890
|
use vars qw($VERSION @ISA %Lexicon @EXPORT @EXPORT_OK); |
|
11
|
|
|
|
|
28
|
|
|
11
|
|
|
|
|
999
|
|
14
|
|
|
|
|
|
|
$VERSION = 1.29; |
15
|
|
|
|
|
|
|
@EXPORT = qw(read_mo); |
16
|
|
|
|
|
|
|
@EXPORT_OK = @EXPORT; |
17
|
|
|
|
|
|
|
# Prototype declaration |
18
|
|
|
|
|
|
|
sub read_mo($); |
19
|
|
|
|
|
|
|
|
20
|
11
|
|
|
11
|
|
2161
|
use Encode qw(encode decode FB_DEFAULT); |
|
11
|
|
|
|
|
37241
|
|
|
11
|
|
|
|
|
715
|
|
21
|
11
|
|
|
11
|
|
68
|
use File::Spec::Functions qw(catfile); |
|
11
|
|
|
|
|
22
|
|
|
11
|
|
|
|
|
416
|
|
22
|
11
|
|
|
11
|
|
55
|
no strict qw(refs); |
|
11
|
|
|
|
|
24
|
|
|
11
|
|
|
|
|
271
|
|
23
|
|
|
|
|
|
|
|
24
|
11
|
|
|
11
|
|
51
|
use vars qw(%CACHE $REREAD_MO $MO_FILE); |
|
11
|
|
|
|
|
18
|
|
|
11
|
|
|
|
|
696
|
|
25
|
|
|
|
|
|
|
%CACHE = qw(); |
26
|
|
|
|
|
|
|
$REREAD_MO = 0; |
27
|
|
|
|
|
|
|
$MO_FILE = ""; |
28
|
11
|
|
|
11
|
|
55
|
use vars qw(@SYSTEM_LOCALEDIRS); |
|
11
|
|
|
|
|
21
|
|
|
11
|
|
|
|
|
25403
|
|
29
|
|
|
|
|
|
|
@SYSTEM_LOCALEDIRS = qw(/usr/share/locale /usr/lib/locale |
30
|
|
|
|
|
|
|
/usr/local/share/locale /usr/local/lib/locale); |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
# encoding: Set or retrieve the output encoding |
33
|
|
|
|
|
|
|
sub encoding : method { |
34
|
52
|
|
|
52
|
1
|
219
|
local ($_, %_); |
35
|
52
|
|
|
|
|
69
|
my $self; |
36
|
52
|
|
|
|
|
103
|
($self, $_) = @_; |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
# This is not a static method |
39
|
52
|
50
|
|
|
|
122
|
return if ref($self) eq ""; |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
# Set the output encoding |
42
|
52
|
100
|
|
|
|
121
|
if (@_ > 1) { |
43
|
48
|
100
|
|
|
|
92
|
if (defined $_) { |
44
|
19
|
|
|
|
|
34
|
$self->{"ENCODING"} = $_; |
45
|
|
|
|
|
|
|
} else { |
46
|
29
|
|
|
|
|
48
|
delete $self->{"ENCODING"}; |
47
|
|
|
|
|
|
|
} |
48
|
48
|
|
|
|
|
82
|
$self->{"USERSET_ENCODING"} = $_; |
49
|
|
|
|
|
|
|
} |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
# Return the encoding |
52
|
52
|
100
|
|
|
|
180
|
return exists $self->{"ENCODING"}? $self->{"ENCODING"}: undef; |
53
|
|
|
|
|
|
|
} |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
# key_encoding: Specify the encoding used in the keys |
56
|
|
|
|
|
|
|
sub key_encoding : method { |
57
|
29
|
|
|
29
|
1
|
63
|
local ($_, %_); |
58
|
29
|
|
|
|
|
40
|
my $self; |
59
|
29
|
|
|
|
|
61
|
($self, $_) = @_; |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
# This is not a static method |
62
|
29
|
50
|
|
|
|
88
|
return if ref($self) eq ""; |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
# Set the encoding used in the keys |
65
|
29
|
50
|
|
|
|
77
|
if (@_ > 1) { |
66
|
29
|
100
|
|
|
|
55
|
if (defined $_) { |
67
|
2
|
|
|
|
|
5
|
$self->{"KEY_ENCODING"} = $_; |
68
|
|
|
|
|
|
|
} else { |
69
|
27
|
|
|
|
|
49
|
delete $self->{"KEY_ENCODING"}; |
70
|
|
|
|
|
|
|
} |
71
|
|
|
|
|
|
|
} |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
# Return the encoding |
74
|
29
|
100
|
|
|
|
84
|
return exists $self->{"KEY_ENCODING"}? $self->{"KEY_ENCODING"}: undef; |
75
|
|
|
|
|
|
|
} |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
# new: Initialize the language handler |
78
|
|
|
|
|
|
|
sub new : method { |
79
|
155
|
|
|
155
|
0
|
60969
|
local ($_, %_); |
80
|
155
|
|
|
|
|
249
|
my ($self, $class); |
81
|
155
|
|
33
|
|
|
522
|
$class = ref($_[0]) || $_[0]; |
82
|
155
|
|
|
|
|
293
|
$self = bless {}, $class; |
83
|
155
|
|
|
|
|
443
|
$self->subclass_init; |
84
|
155
|
|
|
|
|
492
|
$self->init; |
85
|
155
|
|
|
|
|
740
|
return $self; |
86
|
|
|
|
|
|
|
} |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
# subclass_init: Initialize at the subclass level, so that it can be |
89
|
|
|
|
|
|
|
# inherited by calling $self->SUPER:subclass_init |
90
|
|
|
|
|
|
|
sub subclass_init : method { |
91
|
155
|
|
|
155
|
0
|
210
|
local ($_, %_); |
92
|
155
|
|
|
|
|
248
|
my ($self, $class); |
93
|
155
|
|
|
|
|
203
|
$self = $_[0]; |
94
|
155
|
|
|
|
|
228
|
$class = ref($self); |
95
|
|
|
|
|
|
|
# Initialize the instance lexicon |
96
|
155
|
|
|
|
|
442
|
$self->{"Lexicon"} = {}; |
97
|
|
|
|
|
|
|
# Initialize the LOCALEDIRS registry |
98
|
155
|
|
|
|
|
281
|
$self->{"LOCALEDIRS"} = {}; |
99
|
|
|
|
|
|
|
# Initialize the MO timestamp |
100
|
155
|
|
|
|
|
253
|
$self->{"REREAD_MO"} = $REREAD_MO; |
101
|
|
|
|
|
|
|
# Initialize the DIE_FOR_LOOKUP_FAILURES setting |
102
|
155
|
|
|
|
|
211
|
$self->{"DIE_FOR_LOOKUP_FAILURES"} = 0; |
103
|
155
|
|
|
|
|
876
|
$self->SUPER::fail_with($self->can("failure_handler_auto")); |
104
|
|
|
|
|
|
|
# Initialize the ENCODE_FAILURE setting |
105
|
155
|
|
|
|
|
1111
|
$self->{"ENCODE_FAILURE"} = FB_DEFAULT; |
106
|
|
|
|
|
|
|
# Initialize the MO_FILE value of this instance |
107
|
155
|
|
|
|
|
248
|
$self->{"MO_FILE"} = ""; |
108
|
155
|
100
|
|
|
|
201
|
${"$class\::MO_FILE"} = "" if !defined ${"$class\::MO_FILE"}; |
|
43
|
|
|
|
|
160
|
|
|
155
|
|
|
|
|
622
|
|
109
|
|
|
|
|
|
|
# Find the locale name, for this subclass |
110
|
155
|
|
|
|
|
392
|
$self->{"LOCALE"} = $class; |
111
|
155
|
|
|
|
|
696
|
$self->{"LOCALE"} =~ s/^.*:://; |
112
|
155
|
|
|
|
|
513
|
$self->{"LOCALE"} =~ s/(_)(.*)$/$1 . uc $2/e; |
|
63
|
|
|
|
|
354
|
|
113
|
|
|
|
|
|
|
# Map i_default to C |
114
|
155
|
50
|
|
|
|
341
|
$self->{"LOCALE"} = "C" if $self->{"LOCALE"} eq "i_default"; |
115
|
|
|
|
|
|
|
# Set the category. Currently this is always LC_MESSAGES |
116
|
155
|
|
|
|
|
255
|
$self->{"CATEGORY"} = "LC_MESSAGES"; |
117
|
|
|
|
|
|
|
# Default key encoding is US-ASCII |
118
|
155
|
|
|
|
|
208
|
$self->{"KEY_ENCODING"} = "US-ASCII"; |
119
|
155
|
|
|
|
|
300
|
return; |
120
|
|
|
|
|
|
|
} |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
# bindtextdomain: Bind a text domain to a locale directory |
123
|
|
|
|
|
|
|
sub bindtextdomain : method { |
124
|
71
|
|
|
71
|
1
|
323
|
local ($_, %_); |
125
|
71
|
|
|
|
|
101
|
my ($self, $DOMAIN, $LOCALEDIR); |
126
|
71
|
|
|
|
|
145
|
($self, $DOMAIN, $LOCALEDIR) = @_; |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
# This is not a static method |
129
|
71
|
50
|
|
|
|
167
|
return if ref($self) eq ""; |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
# Return null for this rare case |
132
|
|
|
|
|
|
|
return if !defined $LOCALEDIR |
133
|
71
|
100
|
100
|
|
|
144
|
&& !exists ${$self->{"LOCALEDIRS"}}{$DOMAIN}; |
|
2
|
|
|
|
|
16
|
|
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
# Register the DOMAIN and its LOCALEDIR |
136
|
70
|
100
|
|
|
|
143
|
${$self->{"LOCALEDIRS"}}{$DOMAIN} = $LOCALEDIR if defined $LOCALEDIR; |
|
69
|
|
|
|
|
167
|
|
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
# Return the registry |
139
|
70
|
|
|
|
|
94
|
return ${$self->{"LOCALEDIRS"}}{$DOMAIN}; |
|
70
|
|
|
|
|
165
|
|
140
|
|
|
|
|
|
|
} |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
# textdomain: Set the current text domain |
143
|
|
|
|
|
|
|
sub textdomain : method { |
144
|
82
|
|
|
82
|
1
|
644
|
local ($_, %_); |
145
|
82
|
|
|
|
|
128
|
my ($self, $class, $DOMAIN, $LOCALEDIR, $mo_file); |
146
|
82
|
|
|
|
|
240
|
($self, $DOMAIN) = @_; |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
# This is not a static method |
149
|
82
|
50
|
|
|
|
204
|
return if ref($self) eq ""; |
150
|
|
|
|
|
|
|
# Find the class name |
151
|
82
|
|
|
|
|
130
|
$class = ref($self); |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
# Return the current domain |
154
|
82
|
100
|
|
|
|
160
|
return $self->{"DOMAIN"} if !defined $DOMAIN; |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
# Set the timestamp of this read in this instance |
157
|
78
|
|
|
|
|
123
|
$self->{"REREAD_MO"} = $REREAD_MO; |
158
|
|
|
|
|
|
|
# Set the current domain |
159
|
78
|
|
|
|
|
131
|
$self->{"DOMAIN"} = $DOMAIN; |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
# Clear it |
162
|
78
|
|
|
|
|
132
|
$self->{"Lexicon"} = {}; |
163
|
78
|
|
|
|
|
110
|
%{"$class\::Lexicon"} = qw(); |
|
78
|
|
|
|
|
239
|
|
164
|
78
|
|
|
|
|
144
|
$self->{"MO_FILE"} = ""; |
165
|
78
|
|
|
|
|
97
|
${"$class\::MO_FILE"} = ""; |
|
78
|
|
|
|
|
170
|
|
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
# The format is "{LOCALEDIR}/{LOCALE}/{CATEGORY}/{DOMAIN}.mo" |
168
|
|
|
|
|
|
|
# Search the system locale directories if the domain was not |
169
|
|
|
|
|
|
|
# registered yet |
170
|
78
|
100
|
|
|
|
215
|
if (!exists ${$self->{"LOCALEDIRS"}}{$DOMAIN}) { |
|
78
|
|
|
|
|
303
|
|
171
|
4
|
|
|
|
|
8
|
undef $mo_file; |
172
|
4
|
|
|
|
|
12
|
foreach $LOCALEDIR (@SYSTEM_LOCALEDIRS) { |
173
|
|
|
|
|
|
|
$_ = catfile($LOCALEDIR, $self->{"LOCALE"}, |
174
|
13
|
|
|
|
|
131
|
$self->{"CATEGORY"}, "$DOMAIN.mo"); |
175
|
13
|
100
|
66
|
|
|
330
|
if (-f $_ && -r $_) { |
176
|
1
|
|
|
|
|
4
|
$mo_file = $_; |
177
|
1
|
|
|
|
|
3
|
last; |
178
|
|
|
|
|
|
|
} |
179
|
|
|
|
|
|
|
} |
180
|
|
|
|
|
|
|
# Not found at last |
181
|
4
|
100
|
|
|
|
20
|
return $DOMAIN if !defined $mo_file; |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
# This domain was registered |
184
|
|
|
|
|
|
|
} else { |
185
|
74
|
|
|
|
|
466
|
$mo_file = catfile(${$self->{"LOCALEDIRS"}}{$DOMAIN}, |
186
|
74
|
|
|
|
|
87
|
$self->{"LOCALE"}, $self->{"CATEGORY"}, "$DOMAIN.mo"); |
187
|
|
|
|
|
|
|
} |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
# Record it |
190
|
75
|
|
|
|
|
148
|
${"$class\::MO_FILE"} = $mo_file; |
|
75
|
|
|
|
|
209
|
|
191
|
75
|
|
|
|
|
122
|
$self->{"MO_FILE"} = $mo_file; |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
# Read the MO file |
194
|
|
|
|
|
|
|
# Cached |
195
|
75
|
100
|
|
|
|
274
|
if (!$self->_is_using_cache($mo_file)) { |
196
|
51
|
|
|
|
|
89
|
my ($enc, @stats, $mtime, $size); |
197
|
|
|
|
|
|
|
# Read it |
198
|
51
|
|
|
|
|
116
|
%_ = read_mo($mo_file); |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
# Successfully read |
201
|
51
|
100
|
|
|
|
177
|
if (scalar(keys %_) > 0) { |
202
|
|
|
|
|
|
|
# Decode it |
203
|
|
|
|
|
|
|
# Find the encoding of that MO file |
204
|
46
|
50
|
|
|
|
340
|
if ($_{""} =~ /^Content-Type: text\/plain; charset=(.*)$/im) { |
205
|
46
|
|
|
|
|
128
|
$enc = $1; |
206
|
|
|
|
|
|
|
# Default to US-ASCII |
207
|
|
|
|
|
|
|
} else { |
208
|
0
|
|
|
|
|
0
|
$enc = "US-ASCII"; |
209
|
|
|
|
|
|
|
} |
210
|
|
|
|
|
|
|
# Set the current encoding to the encoding of the MO file |
211
|
46
|
|
|
|
|
267
|
$_{$_} = decode($enc, $_{$_}) foreach keys %_; |
212
|
|
|
|
|
|
|
} |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
# Cache them |
215
|
51
|
|
|
|
|
74980
|
@stats = stat $mo_file; |
216
|
51
|
100
|
|
|
|
204
|
if (@stats > 0) { |
217
|
48
|
|
|
|
|
133
|
($mtime, $size) = @stats[9,7]; |
218
|
|
|
|
|
|
|
} else { |
219
|
3
|
|
|
|
|
7
|
($mtime, $size) = (undef, undef); |
220
|
|
|
|
|
|
|
} |
221
|
51
|
|
|
|
|
657
|
$CACHE{$mo_file} = { |
222
|
|
|
|
|
|
|
"Lexicon" => {%_}, |
223
|
|
|
|
|
|
|
"encoding" => $enc, |
224
|
|
|
|
|
|
|
"mtime" => $mtime, |
225
|
|
|
|
|
|
|
"size" => $size, |
226
|
|
|
|
|
|
|
}; |
227
|
|
|
|
|
|
|
} |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
# Respect the existing output encoding |
230
|
75
|
100
|
|
|
|
223
|
if (defined $CACHE{$mo_file}->{"encoding"}) { |
231
|
70
|
|
|
|
|
223
|
$self->{"MO_ENCODING"} = $CACHE{$mo_file}->{"encoding"}; |
232
|
|
|
|
|
|
|
} else { |
233
|
5
|
|
|
|
|
9
|
delete $self->{"MO_ENCODING"}; |
234
|
|
|
|
|
|
|
} |
235
|
|
|
|
|
|
|
# Respect the MO file encoding unless there is a user preferrence |
236
|
75
|
100
|
|
|
|
167
|
if (!exists $self->{"USERSET_ENCODING"}) { |
237
|
70
|
100
|
|
|
|
124
|
if (exists $self->{"MO_ENCODING"}) { |
238
|
65
|
|
|
|
|
114
|
$self->{"ENCODING"} = $self->{"MO_ENCODING"}; |
239
|
|
|
|
|
|
|
} else { |
240
|
5
|
|
|
|
|
8
|
delete $self->{"ENCODING"}; |
241
|
|
|
|
|
|
|
} |
242
|
|
|
|
|
|
|
} |
243
|
75
|
|
|
|
|
164
|
$self->{"Lexicon"} = $CACHE{$mo_file}->{"Lexicon"}; |
244
|
75
|
|
|
|
|
102
|
%{"$class\::Lexicon"} = %{$CACHE{$mo_file}->{"Lexicon"}}; |
|
75
|
|
|
|
|
510
|
|
|
75
|
|
|
|
|
226
|
|
245
|
75
|
|
|
|
|
546
|
$self->clear_isa_scan; |
246
|
|
|
|
|
|
|
|
247
|
75
|
|
|
|
|
514
|
return $DOMAIN; |
248
|
|
|
|
|
|
|
} |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
# _is_using_cache: Return whether we are using our cache. |
251
|
|
|
|
|
|
|
sub _is_using_cache : method { |
252
|
75
|
|
|
75
|
|
115
|
local ($_, %_); |
253
|
75
|
|
|
|
|
108
|
my ($self, $mo_file, @stats, $mtime, $size); |
254
|
75
|
|
|
|
|
119
|
($self, $mo_file) = @_; |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
# NO if we do not have such a cache. |
257
|
75
|
100
|
|
|
|
307
|
return undef unless exists $CACHE{$mo_file}; |
258
|
|
|
|
|
|
|
|
259
|
25
|
|
|
|
|
497
|
@stats = stat $mo_file; |
260
|
|
|
|
|
|
|
# The MO file does not exist previously. |
261
|
25
|
50
|
33
|
|
|
167
|
if (!defined $CACHE{$mo_file}->{"mtime"} |
262
|
|
|
|
|
|
|
|| !defined $CACHE{$mo_file}->{"size"}) { |
263
|
|
|
|
|
|
|
# Use the cache if the MO file still does not exist. |
264
|
0
|
|
|
|
|
0
|
return (@stats == 0); |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
# The MO file exists previously. |
267
|
|
|
|
|
|
|
} else { |
268
|
|
|
|
|
|
|
# Use the cache if the MO file did not change. |
269
|
25
|
|
|
|
|
60
|
($mtime, $size) = @stats[9,7]; |
270
|
|
|
|
|
|
|
return $mtime == $CACHE{$mo_file}->{"mtime"} |
271
|
25
|
|
66
|
|
|
157
|
&& $size == $CACHE{$mo_file}->{"size"}; |
272
|
|
|
|
|
|
|
} |
273
|
|
|
|
|
|
|
} |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
# maketext: Encode after maketext |
276
|
|
|
|
|
|
|
sub maketext : method { |
277
|
194
|
|
|
194
|
1
|
3896
|
local ($_, %_); |
278
|
194
|
|
|
|
|
298
|
my ($self, $key, @param, $class, $keyd); |
279
|
194
|
|
|
|
|
334
|
($self, $key, @param) = @_; |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
# This is not a static method - NOW |
282
|
194
|
50
|
|
|
|
404
|
return if ref($self) eq ""; |
283
|
|
|
|
|
|
|
# Find the class name |
284
|
194
|
|
|
|
|
268
|
$class = ref($self); |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
# MO file should be re-read |
287
|
194
|
100
|
|
|
|
449
|
if ($self->{"REREAD_MO"} < $REREAD_MO) { |
288
|
2
|
|
|
|
|
3
|
$self->{"REREAD_MO"} = $REREAD_MO; |
289
|
2
|
50
|
|
|
|
7
|
defined($_ = $self->textdomain) and $self->textdomain($_); |
290
|
|
|
|
|
|
|
} |
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
# If the instance lexicon is changed. |
293
|
|
|
|
|
|
|
# Maketext uses a class lexicon. We have to copy the instance |
294
|
|
|
|
|
|
|
# lexicon into the class lexicon. This is slow. Mass memory |
295
|
|
|
|
|
|
|
# copy sucks. Avoid create several language handles for a |
296
|
|
|
|
|
|
|
# single localization subclass whenever possible. |
297
|
|
|
|
|
|
|
# Maketext uses class lexicon in order to track the inheritance. |
298
|
|
|
|
|
|
|
# It is hard to change it. |
299
|
194
|
100
|
|
|
|
266
|
if (${"$class\::MO_FILE"} ne $self->{"MO_FILE"}) { |
|
194
|
|
|
|
|
704
|
|
300
|
16
|
|
|
|
|
22
|
${"$class\::MO_FILE"} = $self->{"MO_FILE"}; |
|
16
|
|
|
|
|
33
|
|
301
|
16
|
|
|
|
|
19
|
%{"$class\::Lexicon"} = %{$self->{"Lexicon"}}; |
|
16
|
|
|
|
|
62
|
|
|
16
|
|
|
|
|
38
|
|
302
|
|
|
|
|
|
|
} |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
# Decode the source text |
305
|
194
|
|
|
|
|
289
|
$keyd = $key; |
306
|
|
|
|
|
|
|
$keyd = decode($self->{"KEY_ENCODING"}, $keyd, $self->{"ENCODE_FAILURE"}) |
307
|
194
|
100
|
66
|
|
|
818
|
if exists $self->{"KEY_ENCODING"} && !Encode::is_utf8($key); |
308
|
|
|
|
|
|
|
# Maketext |
309
|
194
|
|
|
|
|
4708
|
$_ = $self->SUPER::maketext($keyd, @param); |
310
|
|
|
|
|
|
|
# Output to the requested encoding |
311
|
185
|
100
|
100
|
|
|
7541
|
if (exists $self->{"ENCODING"}) { |
|
|
100
|
66
|
|
|
|
|
312
|
74
|
|
|
|
|
176
|
$_ = encode($self->{"ENCODING"}, $_, $self->{"ENCODE_FAILURE"}); |
313
|
|
|
|
|
|
|
# Pass through the empty/invalid lexicon |
314
|
111
|
|
|
|
|
395
|
} elsif ( scalar(keys %{$self->{"Lexicon"}}) == 0 |
315
|
|
|
|
|
|
|
&& exists $self->{"KEY_ENCODING"} |
316
|
|
|
|
|
|
|
&& !Encode::is_utf8($key)) { |
317
|
7
|
|
|
|
|
20
|
$_ = encode($self->{"KEY_ENCODING"}, $_, $self->{"ENCODE_FAILURE"}); |
318
|
|
|
|
|
|
|
} |
319
|
|
|
|
|
|
|
|
320
|
184
|
|
|
|
|
11507
|
return $_; |
321
|
|
|
|
|
|
|
} |
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
# pmaketext: Maketext with context |
324
|
|
|
|
|
|
|
sub pmaketext : method { |
325
|
9
|
|
|
9
|
1
|
47
|
local ($_, %_); |
326
|
9
|
|
|
|
|
11
|
my ($self, $ctxt, $key, @param); |
327
|
9
|
|
|
|
|
20
|
($self, $ctxt, $key, @param) = @_; |
328
|
|
|
|
|
|
|
# This is not a static method - NOW |
329
|
9
|
50
|
|
|
|
19
|
return if ref($self) eq ""; |
330
|
|
|
|
|
|
|
# This is actually a wrapper to the maketext() method |
331
|
9
|
|
|
|
|
36
|
return $self->maketext("$ctxt\x04$key", @param); |
332
|
|
|
|
|
|
|
} |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
# read_mo: Subroutine to read and parse the MO file |
335
|
|
|
|
|
|
|
# Refer to gettext documentation section 8.3 |
336
|
|
|
|
|
|
|
sub read_mo($) { |
337
|
52
|
|
|
52
|
1
|
221
|
local ($_, %_); |
338
|
52
|
|
|
|
|
88
|
my ($mo_file, $len, $FH, $content, $tmpl); |
339
|
52
|
|
|
|
|
87
|
$mo_file = $_[0]; |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
# Avild being stupid |
342
|
52
|
100
|
66
|
|
|
1574
|
return unless -f $mo_file && -r $mo_file; |
343
|
|
|
|
|
|
|
# Read the MO file |
344
|
49
|
|
|
|
|
593
|
$len = (stat $mo_file)[7]; |
345
|
49
|
50
|
|
|
|
1688
|
open $FH, $mo_file or return; # GNU gettext never fails! |
346
|
49
|
|
|
|
|
203
|
binmode $FH; |
347
|
49
|
50
|
|
|
|
1031
|
defined($_ = read $FH, $content, $len) |
348
|
|
|
|
|
|
|
or return; |
349
|
49
|
50
|
|
|
|
470
|
close $FH or return; |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
# Find the byte order of the MO file creator |
352
|
49
|
|
|
|
|
173
|
$_ = substr($content, 0, 4); |
353
|
|
|
|
|
|
|
# Little endian |
354
|
49
|
100
|
|
|
|
199
|
if ($_ eq "\xde\x12\x04\x95") { |
|
|
100
|
|
|
|
|
|
355
|
44
|
|
|
|
|
75
|
$tmpl = "V"; |
356
|
|
|
|
|
|
|
# Big endian |
357
|
|
|
|
|
|
|
} elsif ($_ eq "\x95\x04\x12\xde") { |
358
|
3
|
|
|
|
|
4
|
$tmpl = "N"; |
359
|
|
|
|
|
|
|
# Wrong magic number. Not a valid MO file. |
360
|
|
|
|
|
|
|
} else { |
361
|
2
|
|
|
|
|
13
|
return; |
362
|
|
|
|
|
|
|
} |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
# Check the MO format revision number |
365
|
47
|
|
|
|
|
174
|
$_ = unpack $tmpl, substr($content, 4, 4); |
366
|
|
|
|
|
|
|
# There is only one revision now: revision 0. |
367
|
47
|
50
|
|
|
|
127
|
return if $_ > 0; |
368
|
|
|
|
|
|
|
|
369
|
47
|
|
|
|
|
76
|
my ($num, $offo, $offt); |
370
|
|
|
|
|
|
|
# Number of messages |
371
|
47
|
|
|
|
|
92
|
$num = unpack $tmpl, substr($content, 8, 4); |
372
|
|
|
|
|
|
|
# Offset to the beginning of the original messages |
373
|
47
|
|
|
|
|
85
|
$offo = unpack $tmpl, substr($content, 12, 4); |
374
|
|
|
|
|
|
|
# Offset to the beginning of the translated messages |
375
|
47
|
|
|
|
|
85
|
$offt = unpack $tmpl, substr($content, 16, 4); |
376
|
47
|
|
|
|
|
85
|
%_ = qw(); |
377
|
47
|
|
|
|
|
119
|
for ($_ = 0; $_ < $num; $_++) { |
378
|
639
|
|
|
|
|
787
|
my ($len, $off, $stro, $strt); |
379
|
|
|
|
|
|
|
# The first word is the length of the message |
380
|
639
|
|
|
|
|
985
|
$len = unpack $tmpl, substr($content, $offo+$_*8, 4); |
381
|
|
|
|
|
|
|
# The second word is the offset of the message |
382
|
639
|
|
|
|
|
965
|
$off = unpack $tmpl, substr($content, $offo+$_*8+4, 4); |
383
|
|
|
|
|
|
|
# Original message |
384
|
639
|
|
|
|
|
909
|
$stro = substr($content, $off, $len); |
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
# The first word is the length of the message |
387
|
639
|
|
|
|
|
957
|
$len = unpack $tmpl, substr($content, $offt+$_*8, 4); |
388
|
|
|
|
|
|
|
# The second word is the offset of the message |
389
|
639
|
|
|
|
|
924
|
$off = unpack $tmpl, substr($content, $offt+$_*8+4, 4); |
390
|
|
|
|
|
|
|
# Translated message |
391
|
639
|
|
|
|
|
943
|
$strt = substr($content, $off, $len); |
392
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
# Hash it |
394
|
639
|
|
|
|
|
1487
|
$_{$stro} = $strt; |
395
|
|
|
|
|
|
|
} |
396
|
|
|
|
|
|
|
|
397
|
47
|
|
|
|
|
534
|
return %_; |
398
|
|
|
|
|
|
|
} |
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
# reload_text: Method to purge the lexicon cache |
401
|
|
|
|
|
|
|
sub reload_text : method { |
402
|
2
|
|
|
2
|
1
|
10
|
local ($_, %_); |
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
# Purge the text cache |
405
|
2
|
|
|
|
|
23
|
%CACHE = qw(); |
406
|
2
|
|
|
|
|
4
|
$REREAD_MO = time; |
407
|
|
|
|
|
|
|
|
408
|
2
|
|
|
|
|
5
|
return; |
409
|
|
|
|
|
|
|
} |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
# fail_with: A wrapper to the fail_with() of Locale::Maketext, in order |
412
|
|
|
|
|
|
|
# to record the preferred failure handler of the user, so that |
413
|
|
|
|
|
|
|
# die_for_lookup_failures() knows where to return to. |
414
|
|
|
|
|
|
|
sub fail_with : method { |
415
|
2
|
|
|
2
|
1
|
17
|
local ($_, %_); |
416
|
2
|
|
|
|
|
2
|
my $self; |
417
|
2
|
|
|
|
|
4
|
($self, $_) = @_; |
418
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
# This is not a static method |
420
|
2
|
50
|
|
|
|
5
|
return if ref($self) eq ""; |
421
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
# Set the current setting |
423
|
2
|
50
|
|
|
|
6
|
if (@_ > 1) { |
424
|
2
|
50
|
|
|
|
13
|
if (defined $_) { |
425
|
2
|
|
|
|
|
5
|
$self->{"USERSET_FAIL"} = $_; |
426
|
2
|
50
|
|
|
|
5
|
$self->SUPER::fail_with($_) if $self->{"DIE_FOR_LOOKUP_FAILURES"}; |
427
|
|
|
|
|
|
|
} else { |
428
|
0
|
|
|
|
|
0
|
delete $self->{"USERSET_FAIL"}; |
429
|
0
|
0
|
|
|
|
0
|
delete $self->{"fail"} if $self->{"DIE_FOR_LOOKUP_FAILURES"}; |
430
|
|
|
|
|
|
|
} |
431
|
|
|
|
|
|
|
} |
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
# Return the current setting |
434
|
2
|
50
|
|
|
|
6
|
return exists $self->{"USERSET_FAIL"}? $self->{"USERSET_FAIL"}: undef; |
435
|
|
|
|
|
|
|
} |
436
|
|
|
|
|
|
|
|
437
|
|
|
|
|
|
|
# die_for_lookup_failures: Whether we should die for lookup failure |
438
|
|
|
|
|
|
|
# The default is no. GNU gettext never fails. |
439
|
|
|
|
|
|
|
sub die_for_lookup_failures : method { |
440
|
41
|
|
|
41
|
1
|
427
|
local ($_, %_); |
441
|
41
|
|
|
|
|
52
|
my $self; |
442
|
41
|
|
|
|
|
77
|
($self, $_) = @_; |
443
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
# This is not a static method |
445
|
41
|
50
|
|
|
|
110
|
return if ref($self) eq ""; |
446
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
# Set the current setting |
448
|
41
|
50
|
|
|
|
87
|
if (@_ > 1) { |
449
|
41
|
100
|
|
|
|
76
|
if ($_) { |
450
|
4
|
|
|
|
|
9
|
$self->{"DIE_FOR_LOOKUP_FAILURES"} = 1; |
451
|
4
|
100
|
|
|
|
8
|
if (exists $self->{"USERSET_FAIL"}) { |
452
|
3
|
|
|
|
|
6
|
$self->{"fail"} = $self->{"USERSET_FAIL"}; |
453
|
|
|
|
|
|
|
} else { |
454
|
1
|
|
|
|
|
2
|
delete $self->{"fail"}; |
455
|
|
|
|
|
|
|
} |
456
|
|
|
|
|
|
|
} else { |
457
|
37
|
|
|
|
|
178
|
$self->SUPER::fail_with($self->can("failure_handler_auto")); |
458
|
37
|
|
|
|
|
266
|
$self->{"DIE_FOR_LOOKUP_FAILURES"} = 0; |
459
|
|
|
|
|
|
|
} |
460
|
|
|
|
|
|
|
} |
461
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
# Return the current setting |
463
|
|
|
|
|
|
|
return exists $self->{"DIE_FOR_LOOKUP_FAILURES"}? |
464
|
41
|
50
|
|
|
|
119
|
$self->{"DIE_FOR_LOOKUP_FAILURES"}: undef; |
465
|
|
|
|
|
|
|
} |
466
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
# encode_failure: What to do if the text is out of your output encoding |
468
|
|
|
|
|
|
|
# Refer to Encode on possible values of this check |
469
|
|
|
|
|
|
|
sub encode_failure : method { |
470
|
2
|
|
|
2
|
1
|
14
|
local ($_, %_); |
471
|
2
|
|
|
|
|
2
|
my $self; |
472
|
2
|
|
|
|
|
4
|
($self, $_) = @_; |
473
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
# This is not a static method |
475
|
2
|
50
|
|
|
|
5
|
return if ref($self) eq ""; |
476
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
# Specify the action used in the keys |
478
|
2
|
50
|
|
|
|
6
|
$self->{"ENCODE_FAILURE"} = $_ if @_ > 1; |
479
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
# Return the encoding |
481
|
2
|
50
|
|
|
|
6
|
return $self->{"ENCODE_FAILURE"} if exists $self->{"ENCODE_FAILURE"}; |
482
|
0
|
|
|
|
|
0
|
return undef; |
483
|
|
|
|
|
|
|
} |
484
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
# failure_handler_auto: Our local version of failure_handler_auto(), |
486
|
|
|
|
|
|
|
# Copied and rewritten from Locale::Maketext, with bug#33938 patch applied. |
487
|
|
|
|
|
|
|
# See http://rt.perl.org/rt3//Public/Bug/Display.html?id=33938 |
488
|
|
|
|
|
|
|
sub failure_handler_auto : method { |
489
|
69
|
|
|
69
|
1
|
3883
|
local ($_, %_); |
490
|
69
|
|
|
|
|
105
|
my ($self, $key, @param, $r); |
491
|
69
|
|
|
|
|
120
|
($self, $key, @param) = @_; |
492
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
# This is not a static method |
494
|
69
|
50
|
|
|
|
144
|
return if ref($self) eq ""; |
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
# Remove the context |
497
|
|
|
|
|
|
|
# We assume there is no one using EOF either in the context or message. |
498
|
|
|
|
|
|
|
# That does not work in GNU gettext, anyway. |
499
|
69
|
|
|
|
|
190
|
$key =~ s/^[^\x04]*\x04//; |
500
|
|
|
|
|
|
|
|
501
|
69
|
100
|
|
|
|
168
|
$self->{"failure_lex"} = {} if !exists $self->{"failure_lex"}; |
502
|
36
|
|
|
|
|
859
|
${$self->{"failure_lex"}}{$key} = $self->_compile($key) |
503
|
69
|
100
|
|
|
|
97
|
if !exists ${$self->{"failure_lex"}}{$key}; |
|
69
|
|
|
|
|
228
|
|
504
|
69
|
|
|
|
|
99
|
$_ = ${$self->{"failure_lex"}}{$key}; |
|
69
|
|
|
|
|
120
|
|
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
# A scalar result |
507
|
69
|
100
|
|
|
|
264
|
return $$_ if ref($_) eq "SCALAR"; |
508
|
8
|
50
|
|
|
|
22
|
return $_ unless ref($_) eq "CODE"; |
509
|
|
|
|
|
|
|
# A compiled subroutine |
510
|
|
|
|
|
|
|
{ |
511
|
8
|
|
|
|
|
9
|
local $SIG{"__DIE__"}; |
|
8
|
|
|
|
|
25
|
|
512
|
8
|
|
|
|
|
10
|
$r = eval { |
513
|
8
|
|
|
|
|
138
|
$_ = &$_($self, @param); |
514
|
8
|
|
|
|
|
263
|
return 1; |
515
|
|
|
|
|
|
|
}; |
516
|
|
|
|
|
|
|
} |
517
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
# If we make it here, there was an exception thrown in the |
519
|
|
|
|
|
|
|
# call to $value, and so scream: |
520
|
8
|
50
|
|
|
|
17
|
if (!defined $r) { |
521
|
0
|
|
|
|
|
0
|
$_ = $@; |
522
|
|
|
|
|
|
|
# pretty up the error message |
523
|
0
|
|
|
|
|
0
|
s<\s+at\s+\(eval\s+\d+\)\s+line\s+(\d+)\.?\n?> |
524
|
0
|
|
|
|
|
0
|
<\n in bracket code [compiled line $1],>s; |
525
|
0
|
|
|
|
|
0
|
Carp::croak "Error in maketexting \"$key\":\n$_ as used"; |
526
|
|
|
|
|
|
|
return; |
527
|
|
|
|
|
|
|
} |
528
|
|
|
|
|
|
|
|
529
|
8
|
|
|
|
|
23
|
# OK |
530
|
|
|
|
|
|
|
return $_; |
531
|
|
|
|
|
|
|
} |
532
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
return 1; |
534
|
|
|
|
|
|
|
|
535
|
|
|
|
|
|
|
__END__ |