gettext 3.0.2 → 3.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/doc/text/news.md +30 -0
- data/lib/gettext/class_info.rb +0 -6
- data/lib/gettext/locale_path.rb +0 -7
- data/lib/gettext/po_entry.rb +21 -7
- data/lib/gettext/text_domain_manager.rb +2 -2
- data/lib/gettext/tools/msgmerge.rb +123 -107
- data/lib/gettext/tools/task.rb +11 -0
- data/lib/gettext/tools/xgettext.rb +31 -24
- data/lib/gettext/version.rb +1 -1
- data/po/gettext.pot +50 -38
- data/test/test_locale_path.rb +0 -4
- data/test/test_po_entry.rb +101 -15
- data/test/tools/test_msgmerge.rb +133 -30
- data/test/tools/test_xgettext.rb +11 -2
- metadata +27 -50
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5dd7b69714925629b741151ac292ea6cdd610594
|
4
|
+
data.tar.gz: d46007fce3f43d56375c311bcf13c0edbc493adb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e902eb611d9e036c68aafcd6b2f0cb462c43344b683ee841a5792e2a5061dc587f351ddf172e0234eebad4a0f0d87aa7c9ef3c563a04b129ecba94dec35e0399
|
7
|
+
data.tar.gz: 57ab4f506008399e3b5b0c52a2ecdb09cbc2f1f401abdfd8005a238228b9fcbe4e90f182dfb5db4d57b7a8c14f5f9b532d74b1dd5c4d479873936311f5d63e78
|
data/doc/text/news.md
CHANGED
@@ -1,5 +1,35 @@
|
|
1
1
|
# News
|
2
2
|
|
3
|
+
## <a id="3-0-3">3.0.3</a>: 2013-12-15
|
4
|
+
|
5
|
+
### Improvements
|
6
|
+
|
7
|
+
* Documented {GetText::Tools::Task#namespace_prefix}.
|
8
|
+
* Added `--copyright-year` option to {GetText::Tools::XGetText}.
|
9
|
+
[GitHub#25] [Debian #726941] [Reported by Francesco Poli]
|
10
|
+
[Reported by 375gnu]
|
11
|
+
* {GetText::Tools::XGetText} respects new lines in translate target
|
12
|
+
message.
|
13
|
+
* Added {GetText::POEntry#header?}.
|
14
|
+
* Added {GetText::POEntry#obsolete?}.
|
15
|
+
* Added `--no-fuzzy-matching` option to {GetText::Tools::MsgMerge}.
|
16
|
+
[GitHub#28] [Reported by Sam Lown]
|
17
|
+
|
18
|
+
### Fixes
|
19
|
+
|
20
|
+
* Fixed cache key hash conflict on armv7hl. Memoization feature is
|
21
|
+
removed for this fix. If you get performance issue. Please report
|
22
|
+
it. We will solve the issue. See also locale gem's GitHub issue #3.
|
23
|
+
[GitHub#22] [Reported by mtasaka]
|
24
|
+
* Fixed a bug that obsolete comment misses the last new line.
|
25
|
+
|
26
|
+
### Thanks
|
27
|
+
|
28
|
+
* Francesco Poli
|
29
|
+
* 375gnu
|
30
|
+
* Sam Lown
|
31
|
+
* mtasaka
|
32
|
+
|
3
33
|
## <a id="3-0-2">3.0.2</a>: 2013-09-29
|
4
34
|
|
5
35
|
### Improvements
|
data/lib/gettext/class_info.rb
CHANGED
@@ -1,15 +1,11 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
|
3
|
-
require 'locale/util/memoizable'
|
4
|
-
|
5
3
|
module GetText
|
6
4
|
# For normalize/finding the related classes/modules.
|
7
5
|
# This is used for realizing the scope of TextDomain.
|
8
6
|
# (see: http://www.yotabanana.com/hiki/ruby-gettext-scope.html)
|
9
7
|
module ClassInfo
|
10
8
|
extend self
|
11
|
-
include Locale::Util::Memoizable
|
12
|
-
|
13
9
|
# normalize the class name
|
14
10
|
# klass should kind of the class, not object.
|
15
11
|
def normalize_class(klass)
|
@@ -23,7 +19,6 @@ module GetText
|
|
23
19
|
def root_ancestors # :nodoc:
|
24
20
|
Object.ancestors
|
25
21
|
end
|
26
|
-
memoize :root_ancestors
|
27
22
|
|
28
23
|
# Internal method for related_classes.
|
29
24
|
def related_classes_internal(klass, all_classes = [], analyzed_classes = [] )
|
@@ -64,6 +59,5 @@ module GetText
|
|
64
59
|
end
|
65
60
|
ret
|
66
61
|
end
|
67
|
-
memoize :related_classes
|
68
62
|
end
|
69
63
|
end
|
data/lib/gettext/locale_path.rb
CHANGED
@@ -15,8 +15,6 @@ require 'rbconfig'
|
|
15
15
|
module GetText
|
16
16
|
# Treats locale-path for mo-files.
|
17
17
|
class LocalePath
|
18
|
-
include Locale::Util::Memoizable
|
19
|
-
|
20
18
|
# The default locale paths.
|
21
19
|
CONFIG_PREFIX = RbConfig::CONFIG['prefix'].gsub(/\/local/, "")
|
22
20
|
DEFAULT_RULES = [
|
@@ -29,8 +27,6 @@ module GetText
|
|
29
27
|
].uniq
|
30
28
|
|
31
29
|
class << self
|
32
|
-
include Locale::Util::Memoizable
|
33
|
-
|
34
30
|
# Add default locale path. Usually you should use GetText.add_default_locale_path instead.
|
35
31
|
# * path: a new locale path. (e.g.) "/usr/share/locale/%{lang}/LC_MESSAGES/%{name}.mo"
|
36
32
|
# ('locale' => "ja_JP", 'name' => "textdomain")
|
@@ -66,7 +62,6 @@ module GetText
|
|
66
62
|
Dir.glob(path % {:lang => "*", :name => "*"}).size > 0}.uniq
|
67
63
|
default_path_rules
|
68
64
|
end
|
69
|
-
memoize_dup :default_path_rules
|
70
65
|
end
|
71
66
|
|
72
67
|
attr_reader :locale_paths, :supported_locales
|
@@ -114,7 +109,5 @@ module GetText
|
|
114
109
|
end
|
115
110
|
nil
|
116
111
|
end
|
117
|
-
memoize :current_path
|
118
|
-
|
119
112
|
end
|
120
113
|
end
|
data/lib/gettext/po_entry.rb
CHANGED
@@ -165,6 +165,18 @@ module GetText
|
|
165
165
|
[:plural, :msgctxt_plural].include?(@type)
|
166
166
|
end
|
167
167
|
|
168
|
+
# @return true if the entry is header entry, false otherwise.
|
169
|
+
# Header entry is normal type and has empty msgid.
|
170
|
+
def header?
|
171
|
+
@type == :normal and @msgid == ""
|
172
|
+
end
|
173
|
+
|
174
|
+
# @return true if the entry is obsolete entry, false otherwise.
|
175
|
+
# Obsolete entry is normal type and has :last msgid.
|
176
|
+
def obsolete?
|
177
|
+
@type == :normal and @msgid == :last
|
178
|
+
end
|
179
|
+
|
168
180
|
def [](number)
|
169
181
|
param = @param_type[number]
|
170
182
|
raise ParseError, 'no more string parameters expected' unless param
|
@@ -220,8 +232,7 @@ module GetText
|
|
220
232
|
end
|
221
233
|
|
222
234
|
def format
|
223
|
-
|
224
|
-
if @entry.msgid == :last
|
235
|
+
if @entry.obsolete?
|
225
236
|
return format_obsolete_comment(@entry.comment)
|
226
237
|
end
|
227
238
|
|
@@ -343,7 +354,7 @@ module GetText
|
|
343
354
|
formatted_comment = ""
|
344
355
|
comment.each_line do |comment_line|
|
345
356
|
if /\A#[^~]/ =~ comment_line or comment_line.start_with?(mark)
|
346
|
-
formatted_comment << comment_line
|
357
|
+
formatted_comment << "#{comment_line.chomp}\n"
|
347
358
|
elsif comment_line == "\n"
|
348
359
|
formatted_comment << "\n"
|
349
360
|
else
|
@@ -373,13 +384,16 @@ module GetText
|
|
373
384
|
return [message] if message.empty?
|
374
385
|
|
375
386
|
max_line_width = @options[:max_line_width]
|
376
|
-
return [message] if max_line_width <= 0
|
377
387
|
|
378
388
|
chunks = []
|
379
389
|
message.each_line do |line|
|
380
|
-
|
381
|
-
|
382
|
-
|
390
|
+
if max_line_width <= 0
|
391
|
+
chunks << line
|
392
|
+
else
|
393
|
+
# TODO: use character width instead of the number of characters
|
394
|
+
line.scan(/.{1,#{max_line_width}}/m) do |chunk|
|
395
|
+
chunks << chunk
|
396
|
+
end
|
383
397
|
end
|
384
398
|
end
|
385
399
|
chunks
|
@@ -96,7 +96,7 @@ module GetText
|
|
96
96
|
# it returns a last part of msgid separeted "div".
|
97
97
|
def translate_singular_message(klass, msgid, div = nil)
|
98
98
|
klass = ClassInfo.normalize_class(klass)
|
99
|
-
key = [Locale.current, klass, msgid, div]
|
99
|
+
key = [Locale.current, klass, msgid, div]
|
100
100
|
msg = @@singular_message_cache[key]
|
101
101
|
return msg if msg and @@cached
|
102
102
|
# Find messages from related classes.
|
@@ -156,7 +156,7 @@ module GetText
|
|
156
156
|
div = arg4
|
157
157
|
end
|
158
158
|
|
159
|
-
key = [Locale.current, klass, msgid, msgid_plural, div]
|
159
|
+
key = [Locale.current, klass, msgid, msgid_plural, div]
|
160
160
|
msgs = @@plural_message_cache[key]
|
161
161
|
unless (msgs and @@cached)
|
162
162
|
# Find messages from related classes.
|
@@ -29,7 +29,49 @@ require "gettext/po"
|
|
29
29
|
module GetText
|
30
30
|
module Tools
|
31
31
|
class MsgMerge
|
32
|
-
class
|
32
|
+
class << self
|
33
|
+
# (see #run)
|
34
|
+
#
|
35
|
+
# This method is provided just for convenience. It equals to
|
36
|
+
# `new.run(*command_line)`.
|
37
|
+
def run(*command_line)
|
38
|
+
new.run(*command_line)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Merge a po-file inluding translated messages and a new pot-file.
|
43
|
+
#
|
44
|
+
# @param [Array<String>] command_line
|
45
|
+
# command line arguments for rmsgmerge.
|
46
|
+
# @return [void]
|
47
|
+
def run(*command_line)
|
48
|
+
config = Config.new
|
49
|
+
config.parse(command_line)
|
50
|
+
|
51
|
+
parser = POParser.new
|
52
|
+
parser.ignore_fuzzy = false
|
53
|
+
definition_po = PO.new
|
54
|
+
reference_pot = PO.new
|
55
|
+
parser.parse_file(config.definition_po, definition_po)
|
56
|
+
parser.parse_file(config.reference_pot, reference_pot)
|
57
|
+
|
58
|
+
merger = Merger.new(reference_pot, definition_po, config)
|
59
|
+
result = merger.merge
|
60
|
+
result.order = config.order
|
61
|
+
p result if $DEBUG
|
62
|
+
print result.generate_po if $DEBUG
|
63
|
+
|
64
|
+
if config.output.is_a?(String)
|
65
|
+
File.open(File.expand_path(config.output), "w+") do |file|
|
66
|
+
file.write(result.to_s(config.po_format_options))
|
67
|
+
end
|
68
|
+
else
|
69
|
+
puts(result.to_s(config.po_format_options))
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# @private
|
74
|
+
class Merger
|
33
75
|
# Merge the reference with the definition: take the #. and
|
34
76
|
# #: comments from the reference, take the # comments from
|
35
77
|
# the definition, take the msgstr from the definition. Add
|
@@ -38,55 +80,60 @@ module GetText
|
|
38
80
|
POT_DATE_EXTRACT_RE = /POT-Creation-Date:\s*(.*)?\s*$/
|
39
81
|
POT_DATE_RE = /POT-Creation-Date:.*?$/
|
40
82
|
|
41
|
-
def
|
83
|
+
def initialize(reference, definition, config)
|
84
|
+
@reference = reference
|
85
|
+
@definition = definition
|
86
|
+
@translated_entries = @definition.reject do |entry|
|
87
|
+
entry.msgstr.nil?
|
88
|
+
end
|
89
|
+
@config = config
|
90
|
+
end
|
91
|
+
|
92
|
+
def merge
|
42
93
|
result = GetText::PO.new
|
43
94
|
|
44
|
-
|
45
|
-
entry.
|
95
|
+
@reference.each do |entry|
|
96
|
+
id = [entry.msgctxt, entry.msgid]
|
97
|
+
result[*id] = merge_definition(entry)
|
46
98
|
end
|
47
99
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
id = [msgctxt, msgid]
|
100
|
+
add_obsolete_entry(result)
|
101
|
+
result
|
102
|
+
end
|
52
103
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
104
|
+
private
|
105
|
+
def merge_definition(entry)
|
106
|
+
msgid = entry.msgid
|
107
|
+
msgctxt = entry.msgctxt
|
108
|
+
id = [msgctxt, msgid]
|
57
109
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
result[nil, msgid] = merge_fuzzy_entry(same_msgid_entry, entry)
|
62
|
-
next
|
63
|
-
end
|
64
|
-
end
|
110
|
+
if @definition.has_key?(*id)
|
111
|
+
return merge_entry(entry, @definition[*id])
|
112
|
+
end
|
65
113
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
114
|
+
return entry unless @config.enable_fuzzy_matching?
|
115
|
+
|
116
|
+
if msgctxt.nil?
|
117
|
+
same_msgid_entry = find_by_msgid(@translated_entries, msgid)
|
118
|
+
if same_msgid_entry and same_msgid_entry.msgctxt
|
119
|
+
return merge_fuzzy_entry(entry, same_msgid_entry)
|
70
120
|
end
|
121
|
+
end
|
71
122
|
|
72
|
-
|
123
|
+
fuzzy_entry = find_fuzzy_entry(@translated_entries, msgid, msgctxt)
|
124
|
+
if fuzzy_entry
|
125
|
+
return merge_fuzzy_entry(entry, fuzzy_entry)
|
73
126
|
end
|
74
127
|
|
75
|
-
|
76
|
-
result
|
128
|
+
entry
|
77
129
|
end
|
78
130
|
|
79
|
-
def merge_entry(
|
80
|
-
if definition_entry.
|
81
|
-
|
82
|
-
return new_header
|
131
|
+
def merge_entry(reference_entry, definition_entry)
|
132
|
+
if definition_entry.header?
|
133
|
+
return merge_header(reference_entry, definition_entry)
|
83
134
|
end
|
84
135
|
|
85
|
-
if definition_entry.flag == "fuzzy"
|
86
|
-
entry = definition_entry
|
87
|
-
entry.flag = "fuzzy"
|
88
|
-
return entry
|
89
|
-
end
|
136
|
+
return definition_entry if definition_entry.flag == "fuzzy"
|
90
137
|
|
91
138
|
entry = reference_entry
|
92
139
|
entry.translator_comment = definition_entry.translator_comment
|
@@ -100,7 +147,7 @@ module GetText
|
|
100
147
|
entry
|
101
148
|
end
|
102
149
|
|
103
|
-
def merge_header(
|
150
|
+
def merge_header(new_header, old_header)
|
104
151
|
header = old_header
|
105
152
|
if POT_DATE_EXTRACT_RE =~ new_header.msgstr
|
106
153
|
create_date = $1
|
@@ -121,8 +168,8 @@ module GetText
|
|
121
168
|
same_msgid_entries.first
|
122
169
|
end
|
123
170
|
|
124
|
-
def merge_fuzzy_entry(
|
125
|
-
merged_entry = merge_entry(
|
171
|
+
def merge_fuzzy_entry(entry, fuzzy_entry)
|
172
|
+
merged_entry = merge_entry(entry, fuzzy_entry)
|
126
173
|
merged_entry.flag = "fuzzy"
|
127
174
|
merged_entry
|
128
175
|
end
|
@@ -155,40 +202,38 @@ module GetText
|
|
155
202
|
Text::Levenshtein.distance(source, destination) / max_size.to_f
|
156
203
|
end
|
157
204
|
|
158
|
-
def add_obsolete_entry(result
|
159
|
-
obsolete_entry = generate_obsolete_entry(result
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
result
|
205
|
+
def add_obsolete_entry(result)
|
206
|
+
obsolete_entry = generate_obsolete_entry(result)
|
207
|
+
return if obsolete_entry.nil?
|
208
|
+
|
209
|
+
result[:last] = obsolete_entry
|
164
210
|
end
|
165
211
|
|
166
|
-
def generate_obsolete_entry(result
|
167
|
-
|
212
|
+
def generate_obsolete_entry(result)
|
213
|
+
obsolete_entries = extract_obsolete_entries(result)
|
214
|
+
obsolete_comments = obsolete_entries.collect do |entry|
|
215
|
+
entry.to_s
|
216
|
+
end
|
168
217
|
|
169
|
-
|
170
|
-
unless obsolete_entries.empty?
|
171
|
-
obsolete_comment = []
|
218
|
+
return nil if obsolete_comments.empty?
|
172
219
|
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
obsolete_entry = POEntry.new(:normal)
|
177
|
-
obsolete_entry.msgid = :last
|
178
|
-
obsolete_entry.comment = obsolete_comment.join("\n")
|
179
|
-
end
|
220
|
+
obsolete_entry = POEntry.new(:normal)
|
221
|
+
obsolete_entry.msgid = :last
|
222
|
+
obsolete_entry.comment = obsolete_comments.join("\n")
|
180
223
|
obsolete_entry
|
181
224
|
end
|
182
225
|
|
183
|
-
def extract_obsolete_entries(result
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
226
|
+
def extract_obsolete_entries(result)
|
227
|
+
@definition.find_all do |entry|
|
228
|
+
if entry.obsolete?
|
229
|
+
true
|
230
|
+
elsif entry.msgstr.nil?
|
231
|
+
false
|
232
|
+
else
|
233
|
+
id = [entry.msgctxt, entry.msgid]
|
234
|
+
not result.has_key?(*id)
|
189
235
|
end
|
190
236
|
end
|
191
|
-
obsolete_entries
|
192
237
|
end
|
193
238
|
end
|
194
239
|
|
@@ -199,13 +244,16 @@ module GetText
|
|
199
244
|
bindtextdomain("gettext")
|
200
245
|
|
201
246
|
attr_accessor :definition_po, :reference_pot
|
202
|
-
attr_accessor :output, :
|
247
|
+
attr_accessor :output, :update
|
203
248
|
attr_accessor :order
|
204
249
|
attr_accessor :po_format_options
|
205
250
|
|
206
251
|
# update mode options
|
207
252
|
attr_accessor :backup, :suffix
|
208
253
|
|
254
|
+
# (#see #enable_fuzzy_matching?)
|
255
|
+
attr_writer :enable_fuzzy_matching
|
256
|
+
|
209
257
|
# The result is written back to def.po.
|
210
258
|
# --backup=CONTROL make a backup of def.po
|
211
259
|
# --suffix=SUFFIX override the usual backup suffix
|
@@ -228,7 +276,7 @@ module GetText
|
|
228
276
|
@po_format_options = {
|
229
277
|
:max_line_width => POEntry::Formatter::DEFAULT_MAX_LINE_WIDTH,
|
230
278
|
}
|
231
|
-
@
|
279
|
+
@enable_fuzzy_matching = true
|
232
280
|
@update = nil
|
233
281
|
@backup = ENV["VERSION_CONTROL"]
|
234
282
|
@suffix = ENV["SIMPLE_BACKUP_SUFFIX"] || "~"
|
@@ -248,6 +296,11 @@ module GetText
|
|
248
296
|
@output = @definition_po if @update
|
249
297
|
end
|
250
298
|
|
299
|
+
# @return [Bool] true if fuzzy matching is enabled, false otherwise.
|
300
|
+
def enable_fuzzy_matching?
|
301
|
+
@enable_fuzzy_matching
|
302
|
+
end
|
303
|
+
|
251
304
|
private
|
252
305
|
def create_option_parser
|
253
306
|
parser = OptionParser.new
|
@@ -312,7 +365,11 @@ module GetText
|
|
312
365
|
@po_format_options[:max_line_width] = max_line_width
|
313
366
|
end
|
314
367
|
|
315
|
-
|
368
|
+
parser.on("--[no-]fuzzy-matching",
|
369
|
+
_("Disable fuzzy matching"),
|
370
|
+
_("(enable)")) do |boolean|
|
371
|
+
@enable_fuzzy_matching = boolean
|
372
|
+
end
|
316
373
|
|
317
374
|
parser.on("-h", "--help", _("Display this help and exit")) do
|
318
375
|
puts(parser.help)
|
@@ -328,47 +385,6 @@ module GetText
|
|
328
385
|
parser
|
329
386
|
end
|
330
387
|
end
|
331
|
-
|
332
|
-
class << self
|
333
|
-
# (see #run)
|
334
|
-
#
|
335
|
-
# This method is provided just for convenience. It equals to
|
336
|
-
# `new.run(*command_line)`.
|
337
|
-
def run(*command_line)
|
338
|
-
new.run(*command_line)
|
339
|
-
end
|
340
|
-
end
|
341
|
-
|
342
|
-
# Merge a po-file inluding translated messages and a new pot-file.
|
343
|
-
#
|
344
|
-
# @param [Array<String>] command_line
|
345
|
-
# command line arguments for rmsgmerge.
|
346
|
-
# @return [void]
|
347
|
-
def run(*command_line)
|
348
|
-
config = Config.new
|
349
|
-
config.parse(command_line)
|
350
|
-
|
351
|
-
parser = POParser.new
|
352
|
-
parser.ignore_fuzzy = false
|
353
|
-
definition_po = PO.new
|
354
|
-
reference_pot = PO.new
|
355
|
-
parser.parse_file(config.definition_po, definition_po)
|
356
|
-
parser.parse_file(config.reference_pot, reference_pot)
|
357
|
-
|
358
|
-
merger = Merger.new
|
359
|
-
result = merger.merge(definition_po, reference_pot)
|
360
|
-
result.order = config.order
|
361
|
-
p result if $DEBUG
|
362
|
-
print result.generate_po if $DEBUG
|
363
|
-
|
364
|
-
if config.output.is_a?(String)
|
365
|
-
File.open(File.expand_path(config.output), "w+") do |file|
|
366
|
-
file.write(result.to_s(config.po_format_options))
|
367
|
-
end
|
368
|
-
else
|
369
|
-
puts(result.to_s(config.po_format_options))
|
370
|
-
end
|
371
|
-
end
|
372
388
|
end
|
373
389
|
end
|
374
390
|
end
|