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 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