gettext 2.3.0 → 2.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. data/.yardopts +6 -0
  2. data/Rakefile +7 -6
  3. data/doc/text/news.md +51 -2
  4. data/gettext.gemspec +1 -0
  5. data/lib/gettext/runtime/locale_path.rb +0 -1
  6. data/lib/gettext/runtime/mofile.rb +8 -2
  7. data/lib/gettext/runtime/textdomain.rb +19 -21
  8. data/lib/gettext/runtime/textdomain_manager.rb +0 -1
  9. data/lib/gettext/tools/msginit.rb +19 -9
  10. data/lib/gettext/tools/msgmerge.rb +28 -15
  11. data/lib/gettext/tools/parser/erb.rb +25 -5
  12. data/lib/gettext/tools/parser/glade.rb +4 -3
  13. data/lib/gettext/tools/parser/ruby.rb +23 -5
  14. data/lib/gettext/tools/poparser.rb +2 -1
  15. data/lib/gettext/tools/xgettext.rb +187 -136
  16. data/lib/gettext/version.rb +1 -1
  17. data/po/ja/gettext.po +82 -41
  18. data/samples/cgi/locale/bg/LC_MESSAGES/main.mo +0 -0
  19. data/samples/cgi/locale/bs/LC_MESSAGES/main.mo +0 -0
  20. data/samples/cgi/locale/ca/LC_MESSAGES/main.mo +0 -0
  21. data/samples/cgi/locale/cs/LC_MESSAGES/main.mo +0 -0
  22. data/samples/cgi/locale/de/LC_MESSAGES/main.mo +0 -0
  23. data/samples/cgi/locale/el/LC_MESSAGES/main.mo +0 -0
  24. data/samples/cgi/locale/eo/LC_MESSAGES/main.mo +0 -0
  25. data/samples/cgi/locale/es/LC_MESSAGES/main.mo +0 -0
  26. data/samples/po/hello.pot +3 -3
  27. data/samples/po/hello2.pot +3 -3
  28. data/samples/po/hello_glade2.pot +3 -3
  29. data/samples/po/hello_gtk2.pot +3 -3
  30. data/samples/po/hello_noop.pot +3 -3
  31. data/samples/po/hello_plural.pot +3 -3
  32. data/samples/po/hello_tk.pot +3 -3
  33. data/src/poparser.ry +1 -0
  34. data/test/fixtures/_.rb +4 -4
  35. data/test/fixtures/{erb.rhtml → erb/ascii.rhtml} +0 -0
  36. data/test/fixtures/{erb.rxml → erb/ascii.rxml} +0 -0
  37. data/test/fixtures/erb/non_ascii.rhtml +13 -0
  38. data/test/fixtures/untranslated.rb +12 -0
  39. data/test/gettext-test-utils.rb +23 -0
  40. data/test/locale/ja/LC_MESSAGES/untranslated.mo +0 -0
  41. data/test/parser/test_ruby.rb +48 -1
  42. data/test/po/_.pot +4 -4
  43. data/test/po/ascii.pot +23 -0
  44. data/test/po/backslash.pot +3 -3
  45. data/test/po/ja/untranslated.po +22 -0
  46. data/test/po/no_exist_msgid.pot +20 -0
  47. data/test/po/non_ascii.pot +3 -3
  48. data/test/po/not_existed_msgid.pot +20 -0
  49. data/test/po/np_.pot +3 -3
  50. data/test/po/ns_.pot +3 -3
  51. data/test/po/p_.pot +3 -3
  52. data/test/po/s_.pot +3 -3
  53. data/test/po/untranslated.pot +23 -0
  54. data/test/run-test.rb +1 -1
  55. data/test/test_gettext.rb +2 -2
  56. data/test/test_mofile.rb +10 -0
  57. data/test/test_parser.rb +45 -19
  58. data/test/test_po_parser.rb +14 -1
  59. data/test/tools/test_msginit.rb +52 -36
  60. data/test/tools/test_msgmerge.rb +44 -6
  61. data/test/tools/test_xgettext.rb +203 -5
  62. metadata +143 -146
  63. data/po/de/gettext.po +0 -668
  64. data/po/de/gettext.po.bak +0 -589
  65. data/po/el/gettext.po +0 -571
  66. data/po/fr/gettext.po +0 -589
  67. data/po/gettext.pot +0 -638
  68. data/po/gettext.pot~ +0 -638
  69. data/po/it/gettext.po +0 -589
  70. data/po/uk/gettext.po +0 -571
  71. data/test/locale/ja/LC_MESSAGES/npgettext.mo +0 -0
  72. data/test/locale/ja/LC_MESSAGES/nsgettext.mo +0 -0
  73. data/test/locale/ja/LC_MESSAGES/pgettext.mo +0 -0
  74. data/test/locale/ja/LC_MESSAGES/sgettext.mo +0 -0
data/.yardopts ADDED
@@ -0,0 +1,6 @@
1
+ --protected
2
+ --no-private
3
+ --output doc/reference/en
4
+ --title "gettext API Reference"
5
+ -
6
+ doc/text/*
data/Rakefile CHANGED
@@ -44,13 +44,15 @@ poparser_rb_path = "lib/gettext/tools/poparser.rb"
44
44
  desc "Create #{poparser_rb_path}"
45
45
  task :poparser => poparser_rb_path
46
46
 
47
+ def fix_racc_output_indent(racc_output)
48
+ racc_output.gsub(/^ (end\s*\# module GetText)$/, '\1')
49
+ end
50
+
47
51
  poparser_ry_path = "src/poparser.ry"
48
52
  file poparser_rb_path => poparser_ry_path do
49
53
  racc = File.join(Gem.bindir, "racc")
50
54
  tempfile = Tempfile.new("gettext-poparser")
51
- command_line = "#{racc} -g #{poparser_ry_path} -o #{tempfile.path}"
52
- ruby(command_line)
53
- $stderr.puts("ruby #{command_line}")
55
+ ruby(racc, "-g", poparser_ry_path, "-o", tempfile.path)
54
56
 
55
57
  File.open(poparser_rb_path, "w") do |poparser_rb|
56
58
  poparser_rb.puts(<<-EOH)
@@ -66,9 +68,8 @@ file poparser_rb_path => poparser_ry_path do
66
68
 
67
69
  EOH
68
70
 
69
- poparser_rb.puts(tempfile.read)
71
+ poparser_rb.puts(fix_racc_output_indent(tempfile.read))
70
72
  end
71
- $stderr.puts "Create #{poparser_rb_path}."
72
73
  end
73
74
 
74
75
  desc "Run all tests"
@@ -117,7 +118,7 @@ task "samples:cgi:gettext"
117
118
 
118
119
  task "samples:gettext" => "samples:cgi:gettext"
119
120
 
120
- ["backslash", "non_ascii", "np_", "p_"].each do |domain|
121
+ ["untranslated", "backslash", "non_ascii", "np_", "p_"].each do |domain|
121
122
  GetText::Task.new(spec) do |task|
122
123
  task.domain = domain
123
124
  task.namespace_prefix = "test:#{domain}"
data/doc/text/news.md CHANGED
@@ -1,4 +1,53 @@
1
1
  # News
2
+ ## <a id="2-3-1">2.3.1</a>: 2012-09-13
3
+
4
+ It's a Bug and package fix release.
5
+ Then, it's also encoding support release, only if you use Ruby 1.9.
6
+
7
+ ### Improvements
8
+
9
+ * [xgettext] Added backword compatibility method
10
+ (GetText::RGetText.run).
11
+ [Suggested by Fotos Georgiadis]
12
+ * [xgettext] Removed deprecated parse argument support.
13
+ * [erb parer] Assumed the encoding in the magic comment of the
14
+ input file as the encoding of it.
15
+ * [ruby parser] Assumed the encoding in the magic comment of the
16
+ input file as the encoding of it.
17
+ * [xgettext] Added the "--output-encoding" option to set encoding of
18
+ output pot file.
19
+ * [xgettext] Used UTF-8 as the default encoding of output pot file.
20
+ * [xgettext] Supported multiple encoding sources.
21
+
22
+ ### Changes
23
+
24
+ * [MoFile] Returned nil instead of "" as msgstr when its msgid isn't
25
+ translated (when this msgstr is "").
26
+ * [PoParser] Converted msgstr from "" to nil when parsing.
27
+
28
+ ### Fixes
29
+
30
+ * Added missing .yardopts file. [Reported by Takahiro Kambe]
31
+ * [news] Fixed Eddie Lau name instead of github name.
32
+ * [msginit] Added the "Plural-Forms:" entry to the header even if a
33
+ pot file doesn't have it.
34
+ * [msgmerge] Fixed the bug the new line between a header and
35
+ contents doesn't exist.
36
+ * [msginit] Fixed the bug that msgstr with msgid_plural aren't
37
+ generated in output po file.
38
+ * [xgettext] Supported class based xgettext parser add API.
39
+ [GitHub #10] [Suggested by Michael Grosser]
40
+ * [erb parer] Fixed erb parser bug with unicode msgid in Ruby 1.9
41
+ ERB templates.
42
+ [Github #9] [Patch by Fotos Georgiadis]
43
+ * Added missing documents for GetText::Tools::XGetText.
44
+
45
+ ### Thanks
46
+
47
+ * Takahiro Kambe
48
+ * Michael Grosser
49
+ * Fotos Georgiadis
50
+
2
51
  ## <a id="2-3-0">2.3.0</a>: 2012-08-28
3
52
 
4
53
  Various improvements, changes and fixes release.
@@ -23,7 +72,7 @@ Various improvements, changes and fixes release.
23
72
 
24
73
  * Renamed the package name from "Ruby-GetText-Package" to "gettext".
25
74
  * Renamed RGetText to XGetText, RMsgMerge to MsgMerge, RMsgFmt to MsgFmt.
26
- * Renamed rgettext to rxgettext, rmsgmerge to msgmerge, rmsgfmt to msgfmt.
75
+ * Renamed rgettext to rxgettext.
27
76
  * Defined tools(XGetText, MsgMerge, MsgFmt) as Class under GetText::Tools
28
77
  module.
29
78
  * Removed shortcuts for tools in GetText module.
@@ -57,7 +106,7 @@ Various improvements, changes and fixes release.
57
106
  * Francesco Poli (wintermute)
58
107
  * 375gnu
59
108
  * Michael Grosser
60
- * 3dd13
109
+ * Eddie Lau
61
110
  * Yves-Eric Martin
62
111
 
63
112
  ## <a id="2-2-0">2.2.0</a>: 2012-03-11
data/gettext.gemspec CHANGED
@@ -21,6 +21,7 @@ So you can use GNU gettext tools for maintaining.
21
21
  Dir.chdir(base_dir) do
22
22
  s.files = Dir.glob("{bin,data,doc/text,lib,po,samples,src,test}/**/*")
23
23
  s.files += ["COPYING", "README.rdoc", "Rakefile", "gettext.gemspec"]
24
+ s.files += [".yardopts"]
24
25
  s.executables = Dir.chdir("bin") do
25
26
  Dir.glob("*")
26
27
  end
@@ -100,7 +100,6 @@ module GetText
100
100
  # * lang: a Locale::Tag.
101
101
  def current_path(lang)
102
102
  lang_candidates = lang.to_posix.candidates
103
- search_files = []
104
103
 
105
104
  lang_candidates.each do |tag|
106
105
  path = @locale_paths[tag.to_s]
@@ -152,7 +152,10 @@ module GetText
152
152
  @plural = "0" unless @plural
153
153
  end
154
154
  else
155
- msgstr = convert_encoding(msgstr, msgid)
155
+ msgstr = nil if msgstr.empty?
156
+ unless msgstr.nil?
157
+ msgstr = convert_encoding(msgstr, msgid)
158
+ end
156
159
  end
157
160
  self[convert_encoding(msgid, msgid)] = msgstr.freeze
158
161
  end
@@ -185,7 +188,6 @@ module GetText
185
188
  # 1986, 1987 Bell Telephone Laboratories, Inc.]
186
189
  def hash_string(str)
187
190
  hval = 0
188
- i = 0
189
191
  str.each_byte do |b|
190
192
  break if b == '\0'
191
193
  hval <<= 4
@@ -218,6 +220,10 @@ module GetText
218
220
  io.write(header.to_a.pack('a4V*'))
219
221
 
220
222
  ary = to_a
223
+ ary = ary.collect do |msgid, msgstr|
224
+ msgstr ||= ""
225
+ [msgid, msgstr]
226
+ end
221
227
  ary.sort!{|a, b| a[0] <=> b[0]} # sort by original string
222
228
 
223
229
  pos = header.hash_table_size * 4 + header.hash_table_offset
@@ -84,42 +84,40 @@ module GetText
84
84
  return nil
85
85
  end
86
86
 
87
- msgstr = mofile[msgid]
88
- if not msgstr.nil?
89
- if msgstr.empty?
90
- nil
91
- else
92
- msgstr
93
- end
94
- elsif msgid.include?("\000")
87
+ return mofile[msgid] if mofile.has_key?(msgid)
88
+
89
+ ret = nil
90
+ if msgid.include?("\000")
95
91
  # Check "aaa\000bbb" and show warning but return the singular part.
96
- ret = nil
97
92
  msgid_single = msgid.split("\000")[0]
98
93
  msgid_single_prefix_re = /^#{Regexp.quote(msgid_single)}\000/
99
- mofile.each{|key, val|
100
- if key =~ msgid_single_prefix_re
94
+ mofile.each do |key, val|
95
+ if msgid_single_prefix_re =~ key
101
96
  # Usually, this is not caused to make po-files from rgettext.
102
- warn %Q[Warning: n_("#{msgid_single}", "#{msgid.split("\000")[1]}") and n_("#{key.gsub(/\000/, '", "')}") are duplicated.]
97
+ separated_msgid = msgid.gsub(/\000/, '", "')
98
+ duplicated_msgid = key.gsub(/\000/, '", "')
99
+ warn("Warning: " +
100
+ "n_(\"#{separated_msgid}\") and " +
101
+ "n_(\"#{duplicated_msgid}\") " +
102
+ "are duplicated.")
103
103
  ret = val
104
104
  break
105
105
  end
106
- }
107
- ret
106
+ end
108
107
  else
109
- ret = nil
110
108
  msgid_prefix_re = /^#{Regexp.quote(msgid)}\000/
111
- mofile.each{|key, val|
112
- if key =~ msgid_prefix_re
109
+ mofile.each do |key, val|
110
+ if msgid_prefix_re =~ key
113
111
  ret = val.split("\000")[0]
114
112
  break
115
113
  end
116
- }
117
- ret
114
+ end
118
115
  end
116
+ ret
119
117
  end
120
118
 
121
- DEFAULT_PLURAL_CALC = Proc.new{|n| n != 1}
122
- DEFAULT_SINGLE_CALC = Proc.new{|n| 0}
119
+ DEFAULT_PLURAL_CALC = Proc.new {|n| n != 1}
120
+ DEFAULT_SINGLE_CALC = Proc.new {|n| 0}
123
121
 
124
122
  # Translates the translated string.
125
123
  # * lang: Locale::Tag::Simple's subclass.
@@ -79,7 +79,6 @@ module GetText
79
79
  def each_textdomains(klass) #:nodoc:
80
80
  lang = Locale.candidates[0]
81
81
  ClassInfo.related_classes(klass, @@gettext_classes).each do |target|
82
- msg = nil
83
82
  if group = @@textdomain_group_pool[target]
84
83
  group.textdomains.each do |textdomain|
85
84
  yield textdomain, lang
@@ -109,7 +109,7 @@ module GetText
109
109
  @locale = loc
110
110
  end
111
111
 
112
- parser.on("-h", "--help", _("Dispray this help and exit")) do
112
+ parser.on("-h", "--help", _("Display this help and exit")) do
113
113
  puts(parser.help)
114
114
  exit(true)
115
115
  end
@@ -254,9 +254,6 @@ module GetText
254
254
  POT_REVISION_DATE_KEY = /^(PO-Revision-Date:).+/
255
255
 
256
256
  def replace_pot_revision_date #:nodoc:
257
- date = Time.now
258
- revision_date = date.strftime("%Y-%m-%d %H:%M%z")
259
-
260
257
  @entry = @entry.gsub(POT_REVISION_DATE_KEY,
261
258
  "\\1 #{revision_date}")
262
259
  end
@@ -274,7 +271,12 @@ module GetText
274
271
  /^(Plural-Forms:) nplurals=INTEGER; plural=EXPRESSION;$/
275
272
 
276
273
  def replace_plural_forms #:nodoc:
277
- @entry = @entry.gsub(PLURAL_FORMS, "\\1 #{plural_forms(@language)}")
274
+ plural_entry = plural_forms(@language)
275
+ if PLURAL_FORMS =~ @entry
276
+ @entry = @entry.gsub(PLURAL_FORMS, "\\1 #{plural_entry}")
277
+ else
278
+ @entry << "Plural-Forms: #{plural_entry}"
279
+ end
278
280
  end
279
281
 
280
282
  def plural_forms(language) #:nodoc:
@@ -343,8 +345,6 @@ module GetText
343
345
  LAST_TRANSLATOR_KEY = /^(Last-Translator:) FULL NAME <#{EMAIL}>$/
344
346
 
345
347
  def replace_first_author #:nodoc:
346
- year = Time.now.year
347
-
348
348
  @comment = @comment.gsub(YEAR_KEY, "\\1 #{year}.")
349
349
  unless @translator.nil?
350
350
  @comment = @comment.gsub(FIRST_AUTHOR_KEY,
@@ -354,9 +354,19 @@ module GetText
354
354
 
355
355
  COPYRIGHT_KEY = /(\s*#\s* Copyright \(C\)) YEAR (THE PACKAGE'S COPYRIGHT HOLDER)$/
356
356
  def replace_copyright_year #:nodoc:
357
- date = Time.now
357
+ @comment = @comment.gsub(COPYRIGHT_KEY, "\\1 #{year} \\2")
358
+ end
359
+
360
+ def now
361
+ @now ||= Time.now
362
+ end
363
+
364
+ def revision_date
365
+ now.strftime("%Y-%m-%d %H:%M%z")
366
+ end
358
367
 
359
- @comment = @comment.gsub(COPYRIGHT_KEY, "\\1 #{date.year} \\2")
368
+ def year
369
+ now.year
360
370
  end
361
371
  end
362
372
  end
@@ -57,7 +57,7 @@ module GetText
57
57
 
58
58
  def []=(msgid, msgstr)
59
59
  # Retain the order
60
- if @msgid2msgstr[msgid].nil?
60
+ unless @msgid2msgstr.has_key?(msgid)
61
61
  @msgids << msgid
62
62
  end
63
63
 
@@ -98,6 +98,7 @@ module GetText
98
98
  def generate_po
99
99
  str = ""
100
100
  str << generate_po_header
101
+ str << "\n"
101
102
 
102
103
  po_entries = []
103
104
  self.each_msgid do |id|
@@ -120,7 +121,7 @@ module GetText
120
121
  str << 'msgstr ""' << "\n"
121
122
  msgstr = @msgid2msgstr[""].gsub(/"/, '\"').gsub(/\r/, "")
122
123
  msgstr = msgstr.gsub(/^(.*)$/, '"\1\n"')
123
- str << msgstr
124
+ str << msgstr.chomp
124
125
  str << "\n"
125
126
 
126
127
  str
@@ -134,7 +135,12 @@ module GetText
134
135
  end
135
136
 
136
137
  id = msgid.gsub(/\r/, "")
137
- msgstr = @msgid2msgstr[msgid].gsub(/\r/, "")
138
+ msgstr = @msgid2msgstr[msgid]
139
+ if msgstr.nil?
140
+ msgstr = ""
141
+ else
142
+ msgstr = msgstr.gsub(/\r/, "")
143
+ end
138
144
 
139
145
  if id.include?("\004")
140
146
  ids = id.split(/\004/)
@@ -150,8 +156,14 @@ module GetText
150
156
  str << "msgid_plural " << __conv(single_id) << "\n"
151
157
  end
152
158
 
153
- msgstr.split("\000", -1).each_with_index do |m, n|
154
- str << "msgstr[#{n}] " << __conv(m) << "\n"
159
+ if msgstr.empty?
160
+ nplurals.times do |id_count|
161
+ str << "msgstr[#{id_count}] " << '""' << "\n"
162
+ end
163
+ else
164
+ msgstr.split("\000", -1).each_with_index do |m, n|
165
+ str << "msgstr[#{n}] " << __conv(m) << "\n"
166
+ end
155
167
  end
156
168
  else
157
169
  str << "msgid " << __conv(id) << "\n"
@@ -199,6 +211,16 @@ module GetText
199
211
  POT_DATE_RE = /POT-Creation-Date:.*?$/
200
212
 
201
213
  def merge(definition, reference)
214
+ definition.each_msgid do |msgid|
215
+ msgstr = definition[msgid] || ""
216
+ definition[msgid] = msgstr
217
+ end
218
+
219
+ reference.each_msgid do |msgid|
220
+ msgstr = reference[msgid] || ""
221
+ reference[msgid] = msgstr
222
+ end
223
+
202
224
  # deep copy
203
225
  result = Marshal.load( Marshal.dump(reference) )
204
226
 
@@ -422,15 +444,6 @@ module GetText
422
444
  def check_command_line_options(*options) #:nodoc:
423
445
  options, output = parse_arguments(*options)
424
446
 
425
- if output.nil?
426
- output = nil
427
- else
428
- if not FileTest.exist?(output)
429
- $stderr.puts(_("File '%s' has already existed.") % out)
430
- exit(false)
431
- end
432
- end
433
-
434
447
  config = Config.new
435
448
  config.output = output
436
449
  config.defpo = options[0]
@@ -469,7 +482,7 @@ module GetText
469
482
 
470
483
  #parser.on("-F", "--fuzzy-matching")
471
484
 
472
- parser.on("-h", "--help", _("Dispray this help and exit")) do
485
+ parser.on("-h", "--help", _("Display this help and exit")) do
473
486
  puts(parser.help)
474
487
  exit(true)
475
488
  end
@@ -29,12 +29,32 @@ module GetText
29
29
  }
30
30
  end
31
31
 
32
- def parse(file, targets = []) # :nodoc:
33
- src = ERB.new(IO.readlines(file).join).src
34
- # Remove magic comment prepended by erb in Ruby 1.9.
35
- src.sub!(/\A#.*?coding[:=].*?\n/, '') if src.respond_to?(:encode)
32
+ MAGIC_COMMENT = /\A#coding:.*\n/
33
+
34
+ def parse(file) # :nodoc:
35
+ content = IO.read(file)
36
+ src = ERB.new(content).src
37
+
38
+ if src.respond_to?(:encode)
39
+ # Force the src encoding back to the encoding in magic comment
40
+ # or original content.
41
+ encoding = detect_encoding(src) || content.encoding
42
+ src.force_encoding(encoding)
43
+
44
+ # Remove magic comment prepended by erb in Ruby 1.9.
45
+ src = src.gsub(MAGIC_COMMENT, "")
46
+ end
47
+
36
48
  erb = src.split(/$/)
37
- RubyParser.parse_lines(file, erb, targets)
49
+ RubyParser.parse_lines(file, erb)
50
+ end
51
+
52
+ def detect_encoding(erb_source)
53
+ if /\A#coding:(.*)\n/ =~ erb_source
54
+ $1
55
+ else
56
+ nil
57
+ end
38
58
  end
39
59
 
40
60
  def target?(file) # :nodoc:
@@ -22,13 +22,14 @@ module GetText
22
22
  TARGET1 = /<property.*translatable="yes">(.*)/
23
23
  TARGET2 = /(.*)<\/property>/
24
24
 
25
- def parse(file, targets = []) # :nodoc:
25
+ def parse(file) # :nodoc:
26
26
  lines = IO.readlines(file)
27
- parse_lines(file, lines, targets)
27
+ parse_lines(file, lines)
28
28
  end
29
29
 
30
30
  #from ary of lines.
31
- def parse_lines(file, lines, targets) # :nodoc:
31
+ def parse_lines(file, lines) # :nodoc:
32
+ targets = []
32
33
  cnt = 0
33
34
  target = false
34
35
  line_no = 0