gettext 3.0.2 → 3.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
@@ -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
@@ -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
@@ -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
- # extracted comments
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
- # TODO: use character width instead of the number of characters
381
- line.scan(/.{1,#{max_line_width}}/m) do |chunk|
382
- chunks << chunk
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].hash
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].hash
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 Merger #:nodoc:
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 merge(definition, reference)
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
- translated_entries = definition.reject do |entry|
45
- entry.msgstr.nil?
95
+ @reference.each do |entry|
96
+ id = [entry.msgctxt, entry.msgid]
97
+ result[*id] = merge_definition(entry)
46
98
  end
47
99
 
48
- reference.each do |entry|
49
- msgid = entry.msgid
50
- msgctxt = entry.msgctxt
51
- id = [msgctxt, msgid]
100
+ add_obsolete_entry(result)
101
+ result
102
+ end
52
103
 
53
- if definition.has_key?(*id)
54
- result[*id] = merge_entry(definition[*id], entry)
55
- next
56
- end
104
+ private
105
+ def merge_definition(entry)
106
+ msgid = entry.msgid
107
+ msgctxt = entry.msgctxt
108
+ id = [msgctxt, msgid]
57
109
 
58
- if msgctxt.nil?
59
- same_msgid_entry = find_by_msgid(translated_entries, msgid)
60
- if not same_msgid_entry.nil? and not same_msgid_entry.msgctxt.nil?
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
- fuzzy_entry = find_fuzzy_entry(translated_entries, msgid, msgctxt)
67
- unless fuzzy_entry.nil?
68
- result[*id] = merge_fuzzy_entry(fuzzy_entry, entry)
69
- next
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
- result[*id] = entry
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
- add_obsolete_entry(result, translated_entries)
76
- result
128
+ entry
77
129
  end
78
130
 
79
- def merge_entry(definition_entry, reference_entry)
80
- if definition_entry.msgid.empty? and definition_entry.msgctxt.nil?
81
- new_header = merge_header(definition_entry, reference_entry)
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(old_header, new_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(fuzzy_entry, entry)
125
- merged_entry = merge_entry(fuzzy_entry, 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, definition)
159
- obsolete_entry = generate_obsolete_entry(result, definition)
160
- unless obsolete_entry.nil?
161
- result[:last] = obsolete_entry
162
- end
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, definition)
167
- obsolete_entry = nil
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
- obsolete_entries = extract_obsolete_entries(result, definition)
170
- unless obsolete_entries.empty?
171
- obsolete_comment = []
218
+ return nil if obsolete_comments.empty?
172
219
 
173
- obsolete_entries.each do |entry|
174
- obsolete_comment << entry.to_s
175
- end
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, definition)
184
- obsolete_entries = []
185
- definition.each do |entry|
186
- id = [entry.msgctxt, entry.msgid]
187
- if not result.has_key?(*id) and not entry.msgid == :last
188
- obsolete_entries << entry
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, :fuzzy, :update
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
- @fuzzy = nil
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
- #parser.on("-F", "--fuzzy-matching")
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