gettext 3.3.8 → 3.4.9

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.
Files changed (165) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/Rakefile +1 -3
  4. data/doc/text/news.md +132 -0
  5. data/gettext.gemspec +7 -5
  6. data/lib/gettext/mo.rb +5 -14
  7. data/lib/gettext/po_entry.rb +31 -21
  8. data/lib/gettext/po_parser.rb +65 -59
  9. data/lib/gettext/text_domain_manager.rb +6 -5
  10. data/lib/gettext/tools/msgcat.rb +9 -2
  11. data/lib/gettext/tools/msginit.rb +11 -6
  12. data/lib/gettext/tools/msgmerge.rb +11 -6
  13. data/lib/gettext/tools/parser/erubi.rb +88 -0
  14. data/lib/gettext/tools/task.rb +3 -5
  15. data/lib/gettext/tools/xgettext.rb +15 -4
  16. data/lib/gettext/version.rb +3 -3
  17. data/locale/ja/LC_MESSAGES/gettext.mo +0 -0
  18. data/po/bg/gettext.edit.po +80 -75
  19. data/po/bg/gettext.po +6 -0
  20. data/po/bs/gettext.edit.po +80 -75
  21. data/po/bs/gettext.po +6 -0
  22. data/po/ca/gettext.edit.po +80 -75
  23. data/po/ca/gettext.po +6 -0
  24. data/po/cs/gettext.edit.po +80 -75
  25. data/po/cs/gettext.po +6 -0
  26. data/po/de/gettext.edit.po +80 -75
  27. data/po/de/gettext.po +6 -0
  28. data/po/el/gettext.edit.po +80 -75
  29. data/po/el/gettext.po +6 -0
  30. data/po/eo/gettext.edit.po +80 -75
  31. data/po/eo/gettext.po +6 -0
  32. data/po/es/gettext.edit.po +80 -75
  33. data/po/es/gettext.po +6 -0
  34. data/po/et/gettext.edit.po +80 -75
  35. data/po/et/gettext.po +6 -0
  36. data/po/fr/gettext.edit.po +80 -75
  37. data/po/fr/gettext.po +6 -0
  38. data/po/gettext.pot +92 -83
  39. data/po/hr/gettext.edit.po +80 -75
  40. data/po/hr/gettext.po +6 -0
  41. data/po/hu/gettext.edit.po +80 -75
  42. data/po/hu/gettext.po +6 -0
  43. data/po/it/gettext.edit.po +80 -75
  44. data/po/it/gettext.po +6 -0
  45. data/po/ja/gettext.edit.po +81 -76
  46. data/po/ja/gettext.po +7 -1
  47. data/po/ko/gettext.edit.po +80 -75
  48. data/po/ko/gettext.po +6 -0
  49. data/po/lv/gettext.edit.po +80 -75
  50. data/po/lv/gettext.po +6 -0
  51. data/po/nb/gettext.edit.po +80 -75
  52. data/po/nb/gettext.po +6 -0
  53. data/po/nl/gettext.edit.po +80 -75
  54. data/po/nl/gettext.po +6 -0
  55. data/po/pt_BR/gettext.edit.po +80 -75
  56. data/po/pt_BR/gettext.po +6 -0
  57. data/po/ru/gettext.edit.po +80 -75
  58. data/po/ru/gettext.po +6 -0
  59. data/po/sr/gettext.edit.po +80 -75
  60. data/po/sr/gettext.po +6 -0
  61. data/po/sv/gettext.edit.po +80 -72
  62. data/po/sv/gettext.po +6 -0
  63. data/po/uk/gettext.edit.po +80 -75
  64. data/po/uk/gettext.po +6 -0
  65. data/po/vi/gettext.edit.po +80 -75
  66. data/po/vi/gettext.po +6 -0
  67. data/po/zh/gettext.edit.po +80 -75
  68. data/po/zh/gettext.po +6 -0
  69. data/po/zh_TW/gettext.edit.po +80 -75
  70. data/po/zh_TW/gettext.po +6 -0
  71. data/samples/cgi/po/helloerb1.pot +3 -3
  72. data/samples/cgi/po/helloerb2.pot +3 -3
  73. data/samples/cgi/po/hellolib.pot +3 -3
  74. data/samples/cgi/po/main.pot +3 -3
  75. data/samples/po/bg/hello_gtk_builder.edit.po +15 -0
  76. data/samples/po/bg/hello_gtk_builder.po +12 -0
  77. data/samples/po/bs/hello_gtk_builder.edit.po +15 -0
  78. data/samples/po/bs/hello_gtk_builder.po +12 -0
  79. data/samples/po/ca/hello_gtk_builder.edit.po +15 -0
  80. data/samples/po/ca/hello_gtk_builder.po +12 -0
  81. data/samples/po/cs/hello_gtk_builder.edit.po +15 -0
  82. data/samples/po/cs/hello_gtk_builder.po +12 -0
  83. data/samples/po/de/hello_gtk_builder.edit.po +15 -0
  84. data/samples/po/de/hello_gtk_builder.po +12 -0
  85. data/samples/po/el/hello_gtk_builder.edit.po +15 -0
  86. data/samples/po/el/hello_gtk_builder.po +12 -0
  87. data/samples/po/eo/hello_gtk_builder.edit.po +15 -0
  88. data/samples/po/eo/hello_gtk_builder.po +12 -0
  89. data/samples/po/es/hello_gtk_builder.edit.po +15 -0
  90. data/samples/po/es/hello_gtk_builder.po +12 -0
  91. data/samples/po/fr/hello_gtk_builder.edit.po +15 -0
  92. data/samples/po/fr/hello_gtk_builder.po +12 -0
  93. data/samples/po/hello.pot +3 -3
  94. data/samples/po/hello2.pot +4 -4
  95. data/samples/po/hello_glade2.pot +8 -5
  96. data/samples/po/hello_gtk2.pot +4 -4
  97. data/samples/po/hello_gtk_builder.pot +18 -4
  98. data/samples/po/hello_noop.pot +4 -4
  99. data/samples/po/hello_plural.pot +4 -4
  100. data/samples/po/hello_tk.pot +4 -4
  101. data/samples/po/hr/hello_gtk_builder.edit.po +15 -0
  102. data/samples/po/hr/hello_gtk_builder.po +12 -0
  103. data/samples/po/hu/hello_gtk_builder.edit.po +15 -0
  104. data/samples/po/hu/hello_gtk_builder.po +12 -0
  105. data/samples/po/it/hello_gtk_builder.edit.po +15 -0
  106. data/samples/po/it/hello_gtk_builder.po +12 -0
  107. data/samples/po/ja/hello_gtk_builder.edit.po +15 -0
  108. data/samples/po/ja/hello_gtk_builder.po +12 -0
  109. data/samples/po/ko/hello_gtk_builder.edit.po +15 -0
  110. data/samples/po/ko/hello_gtk_builder.po +12 -0
  111. data/samples/po/lv/hello_gtk_builder.edit.po +15 -0
  112. data/samples/po/lv/hello_gtk_builder.po +12 -0
  113. data/samples/po/nb/hello_gtk_builder.edit.po +15 -0
  114. data/samples/po/nb/hello_gtk_builder.po +12 -0
  115. data/samples/po/nl/hello_gtk_builder.edit.po +15 -0
  116. data/samples/po/nl/hello_gtk_builder.po +12 -0
  117. data/samples/po/pt_BR/hello_gtk_builder.edit.po +15 -0
  118. data/samples/po/pt_BR/hello_gtk_builder.po +12 -0
  119. data/samples/po/ru/hello_gtk_builder.edit.po +15 -0
  120. data/samples/po/ru/hello_gtk_builder.po +12 -0
  121. data/samples/po/sr/hello_gtk_builder.edit.po +15 -0
  122. data/samples/po/sr/hello_gtk_builder.po +12 -0
  123. data/samples/po/sv/hello_gtk_builder.edit.po +15 -0
  124. data/samples/po/sv/hello_gtk_builder.po +12 -0
  125. data/samples/po/uk/hello_gtk_builder.edit.po +15 -0
  126. data/samples/po/uk/hello_gtk_builder.po +12 -0
  127. data/samples/po/vi/hello_gtk_builder.edit.po +15 -0
  128. data/samples/po/vi/hello_gtk_builder.po +12 -0
  129. data/samples/po/zh/hello_gtk_builder.edit.po +15 -0
  130. data/samples/po/zh/hello_gtk_builder.po +12 -0
  131. data/samples/po/zh_TW/hello_gtk_builder.edit.po +15 -0
  132. data/samples/po/zh_TW/hello_gtk_builder.po +12 -0
  133. data/src/po_parser.ry +48 -42
  134. data/test/fixtures/erb/case.rhtml +16 -0
  135. data/test/fixtures/simple.rb +4 -0
  136. data/test/locale/fr/LC_MESSAGES/test1.mo +0 -0
  137. data/test/locale/fr_BE/LC_MESSAGES/test1.mo +0 -0
  138. data/test/locale/fr_BE_Foo/LC_MESSAGES/test1.mo +0 -0
  139. data/test/locale/ja/LC_MESSAGES/_.mo +0 -0
  140. data/test/po/_.pot +3 -3
  141. data/test/po/backslash.pot +6 -4
  142. data/test/po/fr/test1.po +7 -0
  143. data/test/po/fr_BE/test1.po +24 -0
  144. data/test/po/fr_BE_Foo/test1.po +20 -0
  145. data/test/po/hello.pot +3 -3
  146. data/test/po/ja/_.edit.po +3 -3
  147. data/test/po/ja/_.po +15 -0
  148. data/test/po/ja/hello.edit.po +0 -1
  149. data/test/po/non_ascii.pot +4 -4
  150. data/test/po/np_.pot +3 -3
  151. data/test/po/ns_.pot +3 -3
  152. data/test/po/p_.pot +3 -3
  153. data/test/po/s_.pot +3 -3
  154. data/test/po/untranslated.pot +4 -4
  155. data/test/test_gettext.rb +23 -0
  156. data/test/test_locale_path.rb +12 -4
  157. data/test/test_parser.rb +62 -0
  158. data/test/test_po_entry.rb +20 -4
  159. data/test/test_po_parser.rb +44 -1
  160. data/test/tools/test_msgcat.rb +21 -1
  161. data/test/tools/test_msginit.rb +7 -2
  162. data/test/tools/test_msgmerge.rb +41 -3
  163. data/test/tools/test_xgettext.rb +100 -3
  164. metadata +49 -15
  165. data/test/fixtures/gtk_builder_ui_definitions.ui~ +0 -68
data/test/po/ns_.pot CHANGED
@@ -6,10 +6,10 @@
6
6
  #, fuzzy
7
7
  msgid ""
8
8
  msgstr ""
9
- "Project-Id-Version: ns_ 3.3.8\n"
9
+ "Project-Id-Version: ns_ 3.4.4\n"
10
10
  "Report-Msgid-Bugs-To: \n"
11
- "POT-Creation-Date: 2021-06-09 11:31+0900\n"
12
- "PO-Revision-Date: 2021-06-09 11:31+0900\n"
11
+ "POT-Creation-Date: 2023-06-11 06:20+0900\n"
12
+ "PO-Revision-Date: 2023-06-11 06:20+0900\n"
13
13
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14
14
  "Language-Team: LANGUAGE <LL@li.org>\n"
15
15
  "Language: \n"
data/test/po/p_.pot CHANGED
@@ -6,10 +6,10 @@
6
6
  #, fuzzy
7
7
  msgid ""
8
8
  msgstr ""
9
- "Project-Id-Version: p_ 3.3.8\n"
9
+ "Project-Id-Version: p_ 3.4.4\n"
10
10
  "Report-Msgid-Bugs-To: \n"
11
- "POT-Creation-Date: 2021-06-09 11:31+0900\n"
12
- "PO-Revision-Date: 2021-06-09 11:31+0900\n"
11
+ "POT-Creation-Date: 2023-06-11 06:20+0900\n"
12
+ "PO-Revision-Date: 2023-06-11 06:20+0900\n"
13
13
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14
14
  "Language-Team: LANGUAGE <LL@li.org>\n"
15
15
  "Language: \n"
data/test/po/s_.pot CHANGED
@@ -6,10 +6,10 @@
6
6
  #, fuzzy
7
7
  msgid ""
8
8
  msgstr ""
9
- "Project-Id-Version: s_ 3.3.8\n"
9
+ "Project-Id-Version: s_ 3.4.4\n"
10
10
  "Report-Msgid-Bugs-To: \n"
11
- "POT-Creation-Date: 2021-06-09 11:31+0900\n"
12
- "PO-Revision-Date: 2021-06-09 11:31+0900\n"
11
+ "POT-Creation-Date: 2023-06-11 06:20+0900\n"
12
+ "PO-Revision-Date: 2023-06-11 06:20+0900\n"
13
13
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14
14
  "Language-Team: LANGUAGE <LL@li.org>\n"
15
15
  "Language: \n"
@@ -1,15 +1,15 @@
1
1
  # SOME DESCRIPTIVE TITLE.
2
2
  # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
3
- # This file is distributed under the same license as the gettext package.
3
+ # This file is distributed under the same license as the untranslated package.
4
4
  # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
5
5
  #
6
6
  #, fuzzy
7
7
  msgid ""
8
8
  msgstr ""
9
- "Project-Id-Version: gettext 3.0.0\n"
9
+ "Project-Id-Version: untranslated 3.4.4\n"
10
10
  "Report-Msgid-Bugs-To: \n"
11
- "POT-Creation-Date: 2013-08-30 22:00+0900\n"
12
- "PO-Revision-Date: 2013-08-30 22:00+0900\n"
11
+ "POT-Creation-Date: 2023-06-11 06:20+0900\n"
12
+ "PO-Revision-Date: 2023-06-11 06:20+0900\n"
13
13
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14
14
  "Language-Team: LANGUAGE <LL@li.org>\n"
15
15
  "Language: \n"
data/test/test_gettext.rb CHANGED
@@ -59,6 +59,29 @@ class TestGetText < Test::Unit::TestCase
59
59
  assert_equal("nomsgstr", _("nomsgstr"))
60
60
  end
61
61
 
62
+ def test_fallbacks
63
+ bindtextdomain("test1", "locale")
64
+ test = Simple.new
65
+
66
+ # Translation present in all candidates
67
+ GetText.set_current_locale("fr_BE_Foo")
68
+ assert_equal("french-Belgium-Foo", test.test)
69
+ GetText.set_current_locale("fr_BE")
70
+ assert_equal("french-Belgium", test.test)
71
+ GetText.set_current_locale("fr")
72
+ assert_equal("french", test.test)
73
+
74
+ # Translation Missing in fr_BE_Foo (fallback to fr_BE)
75
+ GetText.set_current_locale("fr_BE_Foo")
76
+ assert_equal("FRENCH-BELGIUM:ONE IS 1.", test.test_formatted_string)
77
+
78
+ # Translation Missing in fr_BE_Foo *and* fr_BE (both languages fallback to fr)
79
+ GetText.set_current_locale("fr_BE_Foo")
80
+ assert_equal("FRENCH:Il y a 5 pommes.", test.test_plural)
81
+ GetText.set_current_locale("fr_BE")
82
+ assert_equal("FRENCH:Il y a 5 pommes.", test.test_plural)
83
+ end
84
+
62
85
  def test_empty
63
86
  bindtextdomain("test1", "locale")
64
87
  assert_equal("japanese", gettext("language"))
@@ -53,9 +53,11 @@ class TestLocalePath < Test::Unit::TestCase
53
53
  testdir = File.dirname(File.expand_path(__FILE__))
54
54
  path = GetText::LocalePath.new("test1", "#{testdir}/locale")
55
55
  assert_equal({
56
- "ja" => "#{testdir}/locale/ja/LC_MESSAGES/test1.mo",
57
- "fr" => "#{testdir}/locale/fr/LC_MESSAGES/test1.mo",
58
- "zh_Hant" => "#{testdir}/locale/zh_Hant/LC_MESSAGES/test1.mo"
56
+ "ja" => "#{testdir}/locale/ja/LC_MESSAGES/test1.mo",
57
+ "fr" => "#{testdir}/locale/fr/LC_MESSAGES/test1.mo",
58
+ "fr_BE" => "#{testdir}/locale/fr_BE/LC_MESSAGES/test1.mo",
59
+ "fr_BE_Foo" => "#{testdir}/locale/fr_BE_Foo/LC_MESSAGES/test1.mo",
60
+ "zh_Hant" => "#{testdir}/locale/zh_Hant/LC_MESSAGES/test1.mo"
59
61
  },
60
62
  path.locale_paths)
61
63
  assert_equal("#{testdir}/locale/ja/LC_MESSAGES/test1.mo",
@@ -66,6 +68,12 @@ class TestLocalePath < Test::Unit::TestCase
66
68
  path.current_path(Locale::Tag.parse("ja_JP.UTF-8")))
67
69
  assert_equal(nil,
68
70
  path.current_path(Locale::Tag.parse("en")))
71
+ assert_equal("#{testdir}/locale/fr/LC_MESSAGES/test1.mo",
72
+ path.current_path(Locale::Tag.parse("fr")))
73
+ assert_equal("#{testdir}/locale/fr_BE/LC_MESSAGES/test1.mo",
74
+ path.current_path(Locale::Tag.parse("fr-BE")))
75
+ assert_equal("#{testdir}/locale/fr_BE_Foo/LC_MESSAGES/test1.mo",
76
+ path.current_path(Locale::Tag.parse("fr-BE-Foo")))
69
77
  assert_equal("#{testdir}/locale/zh_Hant/LC_MESSAGES/test1.mo",
70
78
  path.current_path(Locale::Tag.parse("zh-Hant")))
71
79
  end
@@ -73,7 +81,7 @@ class TestLocalePath < Test::Unit::TestCase
73
81
  def test_supported_locales
74
82
  testdir = File.dirname(File.expand_path(__FILE__))
75
83
  path = GetText::LocalePath.new("test1", "#{testdir}/locale")
76
- assert_equal ["fr", "ja", "zh_Hant"], path.supported_locales
84
+ assert_equal ["fr", "fr_BE", "fr_BE_Foo", "ja", "zh_Hant"], path.supported_locales
77
85
 
78
86
  path = GetText::LocalePath.new("plural", "#{testdir}/locale")
79
87
  assert_equal ["cr", "da", "fr", "ir", "ja", "la", "li", "po", "sl"], path.supported_locales
data/test/test_parser.rb CHANGED
@@ -24,6 +24,7 @@
24
24
  require "tempfile"
25
25
  require "gettext/tools/parser/ruby"
26
26
  require "gettext/tools/parser/erb"
27
+ require "gettext/tools/parser/erubi"
27
28
 
28
29
  require "gettext/tools/xgettext"
29
30
 
@@ -215,6 +216,67 @@ class TestGetTextParser < Test::Unit::TestCase
215
216
 
216
217
  assert_target("Hello", ["#{path}:8"])
217
218
  end
219
+
220
+ def test_case
221
+ path = fixture_path("erb", "case.rhtml")
222
+ @ary = GetText::ErbParser.parse(path)
223
+
224
+ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.0.0')
225
+ assert_target("Hello", ["#{path}:11"])
226
+ assert_target("World", ["#{path}:14"])
227
+ else
228
+ assert_target("Hello", ["#{path}:11"])
229
+ assert_nil(@ary.detect {|elem| elem.msgid == 'World'}) # Not detected. see PR #91
230
+ end
231
+ end
232
+ end
233
+
234
+ class TestErubiParser < self
235
+ include Helper::Path
236
+
237
+ def test_detect_encoding
238
+ euc_file = Tempfile.new("euc-jp.rhtml")
239
+ euc_file.open
240
+ euc_file.puts("<%#-*- coding: euc-jp -*-%>")
241
+ euc_file.close
242
+
243
+ euc_file_content = File.read(euc_file.path)
244
+ encoding = GetText::ErubiParser.new(euc_file.path).detect_encoding(euc_file_content)
245
+
246
+ assert_equal("EUC-JP", encoding)
247
+ end
248
+
249
+ def test_ascii
250
+ path = fixture_path("erb", "ascii.rhtml")
251
+ @ary = GetText::ErubiParser.parse(path)
252
+
253
+ assert_target 'aaa', ["#{path}:8"]
254
+ assert_target "aaa\n", ["#{path}:11"]
255
+ assert_target 'bbb', ["#{path}:12"]
256
+ assert_plural_target "ccc1", "ccc2", ["#{path}:13"]
257
+ end
258
+
259
+ def test_non_ascii
260
+ path = fixture_path("erb", "non_ascii.rhtml")
261
+ @ary = GetText::ErubiParser.parse(path)
262
+
263
+ assert_target('わたし', ["#{path}:12"])
264
+ end
265
+
266
+ def test_minus
267
+ path = fixture_path("erb", "minus.rhtml")
268
+ @ary = GetText::ErubiParser.parse(path)
269
+
270
+ assert_target("Hello", ["#{path}:8"])
271
+ end
272
+
273
+ def test_case
274
+ path = fixture_path("erb", "case.rhtml")
275
+ @ary = GetText::ErubiParser.parse(path)
276
+
277
+ assert_target("Hello", ["#{path}:11"])
278
+ assert_target("World", ["#{path}:14"]) # Detected with Erubi
279
+ end
218
280
  end
219
281
 
220
282
  def test_xgettext_parse
@@ -233,13 +233,15 @@ EOE
233
233
  class TestEscape < self
234
234
  def test_normal
235
235
  entry = GetText::POEntry.new(:normal)
236
- entry.msgid = "He said \"hello.\""
237
- entry.msgstr = "Il a dit \"bonjour.\""
236
+ entry.msgid = "He said \"hello.\"\r\n"
237
+ entry.msgstr = "Il a dit \"bonjour.\"\r\n"
238
238
  entry.references = ["file1:1", "file2:10"]
239
239
  expected_po = <<-EOE
240
240
  #: file1:1 file2:10
241
- msgid "He said \\"hello.\\""
242
- msgstr "Il a dit \\"bonjour.\\""
241
+ msgid ""
242
+ "He said \\"hello.\\"\\r\\n"
243
+ msgstr ""
244
+ "Il a dit \\"bonjour.\\"\\r\\n"
243
245
  EOE
244
246
  assert_equal(expected_po, entry.to_s)
245
247
  end
@@ -342,6 +344,20 @@ EOP
342
344
  assert_equal(expected_po, entry.to_s)
343
345
  end
344
346
 
347
+ def test_multiple_flags
348
+ entry = GetText::POEntry.new(:normal)
349
+ entry.msgid = "msgid"
350
+ entry.msgstr = "msgstr"
351
+ entry.flags = ["It's the flag.", "fuzzy"]
352
+
353
+ expected_po = <<-EOP
354
+ #, It's the flag., fuzzy
355
+ msgid "msgid"
356
+ msgstr "msgstr"
357
+ EOP
358
+ assert_equal(expected_po, entry.to_s)
359
+ end
360
+
345
361
  def test_previous
346
362
  entry = GetText::POEntry.new(:normal)
347
363
  entry.msgid = "msgid"
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2012-2020 Sutou Kouhei <kou@clear-code.com>
1
+ # Copyright (C) 2012-2023 Sutou Kouhei <kou@clear-code.com>
2
2
  # Copyright (C) 2012 Haruka Yoshihara <yoshihara@clear-code.com>
3
3
  #
4
4
  # License: Ruby's or LGPL
@@ -62,6 +62,16 @@ EOP
62
62
  class TestPO < self
63
63
  include Helper::Warning
64
64
 
65
+ def test_msgid_escape
66
+ po_file = create_po_file(<<-'EOP')
67
+ msgid "\\\\r \\r \t \r \n"
68
+ msgstr "\\\\r \\r \t \r \n"
69
+ EOP
70
+ entries = parse_po_file(po_file)
71
+ assert_equal("\\\\r \\r \t \r \n",
72
+ entries["\\\\r \\r \t \r \n"].msgstr)
73
+ end
74
+
65
75
  def test_msgstr
66
76
  po_file = create_po_file(<<-EOP)
67
77
  # This is the comment.
@@ -228,6 +238,39 @@ EOP
228
238
  assert_equal("fuzzy", entries["hello"].flag)
229
239
  end
230
240
 
241
+ def test_fuzzy_ignore
242
+ po_file = create_po_file(<<-PO)
243
+ #, fuzzy
244
+ #: file.rb:10
245
+ msgid "hello"
246
+ msgstr "bonjour"
247
+
248
+ #, c-format, fuzzy , no-sh-format
249
+ #: file.rb:11
250
+ msgid "world"
251
+ msgstr "monde"
252
+
253
+ # This is not fuzzy
254
+ msgid "non-fuzzy"
255
+ msgstr "non-fuzzy string"
256
+ PO
257
+ entries = suppress_warning do
258
+ parse_po_file(po_file)
259
+ end
260
+
261
+ actual = entries.collect do |entry|
262
+ [
263
+ entry.msgid,
264
+ entry.msgstr,
265
+ entry.flags,
266
+ ]
267
+ end
268
+ assert_equal([
269
+ ["non-fuzzy", "non-fuzzy string", []],
270
+ ],
271
+ actual)
272
+ end
273
+
231
274
  private
232
275
  def parse_po_file(po_file, options={:ignore_fuzzy => true})
233
276
  ignore_fuzzy = options[:ignore_fuzzy]
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2014-2018 Kouhei Sutou <kou@clear-code.com>
1
+ # Copyright (C) 2014-2023 Sutou Kouhei <kou@clear-code.com>
2
2
  #
3
3
  # License: Ruby's or LGPL
4
4
  #
@@ -243,6 +243,7 @@ msgstr ""
243
243
  @po = <<-PO
244
244
  # translator comment
245
245
  #: a.rb:1
246
+ #: a.rb:2
246
247
  msgid "Hello"
247
248
  msgstr ""
248
249
  PO
@@ -252,6 +253,25 @@ msgstr ""
252
253
  assert_equal(<<-PO, run_msgcat([@po], "--no-location"))
253
254
  # translator comment
254
255
  msgid "Hello"
256
+ msgstr ""
257
+ PO
258
+ end
259
+
260
+ def test_wrap
261
+ assert_equal(<<-PO, run_msgcat([@po], "--wrap"))
262
+ # translator comment
263
+ #: a.rb:1 a.rb:2
264
+ msgid "Hello"
265
+ msgstr ""
266
+ PO
267
+ end
268
+
269
+ def test_use_one_line_per_reference
270
+ assert_equal(<<-PO, run_msgcat([@po], "--wrap", "--use-one-line-per-reference"))
271
+ # translator comment
272
+ #: a.rb:1
273
+ #: a.rb:2
274
+ msgid "Hello"
255
275
  msgstr ""
256
276
  PO
257
277
  end
@@ -1,5 +1,5 @@
1
1
  # Copyright (C) 2012 Haruka Yoshihara <yoshihara@clear-code.com>
2
- # Copyright (C) 2012-2021 Sutou Kouhei <kou@clear-code.com>
2
+ # Copyright (C) 2012-2023 Sutou Kouhei <kou@clear-code.com>
3
3
  #
4
4
  # License: Ruby's or LGPL
5
5
  #
@@ -312,6 +312,11 @@ EOF
312
312
  end
313
313
 
314
314
  class TestPluralForms < self
315
+ def setup
316
+ super
317
+ omit("Red Datasets is required") unless defined?(Datasets::CLDRPlurals)
318
+ end
319
+
315
320
  def run_msginit(pot_header_options={})
316
321
  create_pot_file("test.pot", pot_header_options)
317
322
  po_file_path = "output.po"
@@ -359,7 +364,7 @@ EOF
359
364
  def test_ro
360
365
  assert_equal("nplurals=3; " +
361
366
  "plural=(n == 1) ? 0 : " +
362
- "(n == 0) || ((n % 100) >= 2 && (n % 100) <= 19) ? 1 : 2;",
367
+ "(n == 0) || (n != 1) && ((n % 100) >= 1 && (n % 100) <= 19) ? 1 : 2;",
363
368
  @msginit.__send__(:plural_forms, "ro"))
364
369
  end
365
370
 
@@ -1,6 +1,4 @@
1
- # -*- coding: utf-8 -*-
2
- #
3
- # Copyright (C) 2012-2020 Sutou Kouhei <kou@clear-code.com>
1
+ # Copyright (C) 2012-2023 Sutou Kouhei <kou@clear-code.com>
4
2
  # Copyright (C) 2010 Eddie Lau <tatonlto@gmail.com>
5
3
  #
6
4
  # License: Ruby's or LGPL
@@ -654,6 +652,46 @@ msgstr ""
654
652
  end
655
653
  end
656
654
 
655
+ class TestUseOneLinePerReference < self
656
+ def pot_content
657
+ super + <<-POT
658
+
659
+ #: hello.rb:10
660
+ #: hello.rb:20
661
+ #: hello.rb:30
662
+ msgid "Good morning"
663
+ msgstr ""
664
+ POT
665
+ end
666
+
667
+ def test_with_wrap
668
+ @msgmerge.run("--update",
669
+ "--wrap",
670
+ "--use-one-line-per-reference",
671
+ @po_file_path, @pot_file_path)
672
+ assert_equal(<<-PO, File.read(@po_file_path))
673
+ #{po_header(@pot_formatted_time, @po_formatted_time)}
674
+ #: hello.rb:1
675
+ msgid "Hello"
676
+ msgstr ""
677
+
678
+ #: hello.rb:2
679
+ msgid "World"
680
+ msgstr "Translated World"
681
+
682
+ #: hello.rb:3
683
+ msgid "Good-bye"
684
+ msgstr ""
685
+
686
+ #: hello.rb:10
687
+ #: hello.rb:20
688
+ #: hello.rb:30
689
+ msgid "Good morning"
690
+ msgstr ""
691
+ PO
692
+ end
693
+ end
694
+
657
695
  class TestWidth < self
658
696
  def pot_content
659
697
  <<-POT
@@ -1,6 +1,4 @@
1
- # -*- coding: utf-8 -*-
2
- #
3
- # Copyright (C) 2012-2020 Sutou Kouhei <kou@clear-code.com>
1
+ # Copyright (C) 2012-2023 Sutou Kouhei <kou@clear-code.com>
4
2
  # Copyright (C) 2012 Haruka Yoshihara <yoshihara@clear-code.com>
5
3
  #
6
4
  # License: Ruby's or LGPL
@@ -116,6 +114,105 @@ msgid "Hello"
116
114
  msgstr ""
117
115
  EOP
118
116
  end
117
+
118
+ def test_use_one_line_per_reference
119
+ pot_content = generate(<<-RUBY, "--use-one-line-per-reference")
120
+ _("Hello")
121
+ _("Hello")
122
+ RUBY
123
+ assert_equal(<<-POT, pot_content)
124
+ #{header}
125
+ #: ../lib/xgettext.rb:1
126
+ #: ../lib/xgettext.rb:2
127
+ msgid "Hello"
128
+ msgstr ""
129
+ POT
130
+ end
131
+ end
132
+
133
+ class TestParser < self
134
+ # Default ERB parser (don't find anything after "case")
135
+ def test_erb
136
+ rhtml = <<-EOR
137
+ <div>
138
+ <%= _('Hello') %>
139
+ <% case 1 %>
140
+ <% end %>
141
+ <%= _('World') %>
142
+ </div>
143
+ EOR
144
+
145
+ File.open(@rhtml_file_path, "w") do |rhtml_file|
146
+ rhtml_file.puts(rhtml)
147
+ end
148
+
149
+ @xgettext.run(
150
+ "--output", @pot_file_path,
151
+ @rhtml_file_path
152
+ )
153
+
154
+ pot_content = File.read(@pot_file_path)
155
+
156
+ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.0.0')
157
+ expected_content = <<-EOP
158
+ #{header}
159
+ #: ../templates/xgettext.rhtml:2
160
+ msgid "Hello"
161
+ msgstr ""
162
+
163
+ #: ../templates/xgettext.rhtml:5
164
+ msgid "World"
165
+ msgstr ""
166
+ EOP
167
+ else
168
+ # "World" not detected. see PR #91
169
+ expected_content = <<-EOP
170
+ #{header}
171
+ #: ../templates/xgettext.rhtml:2
172
+ msgid "Hello"
173
+ msgstr ""
174
+ EOP
175
+ end
176
+
177
+ assert_equal(expected_content, pot_content)
178
+ end
179
+
180
+ # Optional Erubi parser (find text after "case")
181
+ def test_erubi
182
+ rhtml = <<-EOR
183
+ <div>
184
+ <%= _('Hello') %>
185
+ <% case 1 %>
186
+ <% end %>
187
+ <%= _('World') %>
188
+ </div>
189
+ EOR
190
+
191
+ File.open(@rhtml_file_path, "w") do |rhtml_file|
192
+ rhtml_file.puts(rhtml)
193
+ end
194
+
195
+ @xgettext.run(
196
+ "--output", @pot_file_path,
197
+ '--require', 'gettext/tools/parser/erubi',
198
+ '--parser', 'GetText::ErubiParser',
199
+ @rhtml_file_path
200
+ )
201
+
202
+ pot_content = File.read(@pot_file_path)
203
+ expected_content = <<-EOP
204
+ #{header}
205
+ #: ../templates/xgettext.rhtml:2
206
+ msgid "Hello"
207
+ msgstr ""
208
+
209
+ #: ../templates/xgettext.rhtml:5
210
+ msgid "World"
211
+ msgstr ""
212
+ EOP
213
+
214
+ assert_equal(expected_content, pot_content)
215
+ end
119
216
  end
120
217
 
121
218
  class TestEncoding < self