gettext 3.3.6 → 3.4.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (207) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/Rakefile +5 -3
  4. data/doc/text/news.md +168 -0
  5. data/gettext.gemspec +7 -4
  6. data/lib/gettext/mo.rb +12 -19
  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 +221 -50
  12. data/lib/gettext/tools/msgmerge.rb +24 -6
  13. data/lib/gettext/tools/parser/erubi.rb +88 -0
  14. data/lib/gettext/tools/parser/glade.rb +38 -40
  15. data/lib/gettext/tools/parser/gtk_builder_ui_definitions.rb +6 -3
  16. data/lib/gettext/tools/parser/ruby.rb +2 -2
  17. data/lib/gettext/tools/task.rb +3 -5
  18. data/lib/gettext/tools/xgettext.rb +15 -4
  19. data/lib/gettext/version.rb +3 -3
  20. data/locale/bg/LC_MESSAGES/gettext.mo +0 -0
  21. data/locale/bs/LC_MESSAGES/gettext.mo +0 -0
  22. data/locale/ca/LC_MESSAGES/gettext.mo +0 -0
  23. data/locale/cs/LC_MESSAGES/gettext.mo +0 -0
  24. data/locale/de/LC_MESSAGES/gettext.mo +0 -0
  25. data/locale/el/LC_MESSAGES/gettext.mo +0 -0
  26. data/locale/eo/LC_MESSAGES/gettext.mo +0 -0
  27. data/locale/es/LC_MESSAGES/gettext.mo +0 -0
  28. data/locale/et/LC_MESSAGES/gettext.mo +0 -0
  29. data/locale/fr/LC_MESSAGES/gettext.mo +0 -0
  30. data/locale/hr/LC_MESSAGES/gettext.mo +0 -0
  31. data/locale/hu/LC_MESSAGES/gettext.mo +0 -0
  32. data/locale/it/LC_MESSAGES/gettext.mo +0 -0
  33. data/locale/ja/LC_MESSAGES/gettext.mo +0 -0
  34. data/locale/ko/LC_MESSAGES/gettext.mo +0 -0
  35. data/locale/lv/LC_MESSAGES/gettext.mo +0 -0
  36. data/locale/nb/LC_MESSAGES/gettext.mo +0 -0
  37. data/locale/nl/LC_MESSAGES/gettext.mo +0 -0
  38. data/locale/pt_BR/LC_MESSAGES/gettext.mo +0 -0
  39. data/locale/ru/LC_MESSAGES/gettext.mo +0 -0
  40. data/locale/sr/LC_MESSAGES/gettext.mo +0 -0
  41. data/locale/uk/LC_MESSAGES/gettext.mo +0 -0
  42. data/locale/vi/LC_MESSAGES/gettext.mo +0 -0
  43. data/locale/zh/LC_MESSAGES/gettext.mo +0 -0
  44. data/locale/zh_TW/LC_MESSAGES/gettext.mo +0 -0
  45. data/po/bg/gettext.edit.po +80 -593
  46. data/po/bg/gettext.po +6 -423
  47. data/po/bs/gettext.edit.po +80 -593
  48. data/po/bs/gettext.po +6 -423
  49. data/po/ca/gettext.edit.po +80 -593
  50. data/po/ca/gettext.po +6 -423
  51. data/po/cs/gettext.edit.po +80 -593
  52. data/po/cs/gettext.po +6 -423
  53. data/po/de/gettext.edit.po +80 -593
  54. data/po/de/gettext.po +6 -423
  55. data/po/el/gettext.edit.po +80 -593
  56. data/po/el/gettext.po +6 -423
  57. data/po/eo/gettext.edit.po +80 -593
  58. data/po/eo/gettext.po +6 -423
  59. data/po/es/gettext.edit.po +80 -593
  60. data/po/es/gettext.po +6 -423
  61. data/po/et/gettext.edit.po +80 -593
  62. data/po/et/gettext.po +6 -423
  63. data/po/fr/gettext.edit.po +80 -593
  64. data/po/fr/gettext.po +6 -423
  65. data/po/gettext.pot +92 -665
  66. data/po/hr/gettext.edit.po +80 -593
  67. data/po/hr/gettext.po +6 -423
  68. data/po/hu/gettext.edit.po +80 -593
  69. data/po/hu/gettext.po +6 -423
  70. data/po/it/gettext.edit.po +80 -593
  71. data/po/it/gettext.po +6 -423
  72. data/po/ja/gettext.edit.po +81 -594
  73. data/po/ja/gettext.po +7 -424
  74. data/po/ko/gettext.edit.po +80 -593
  75. data/po/ko/gettext.po +6 -423
  76. data/po/lv/gettext.edit.po +80 -593
  77. data/po/lv/gettext.po +6 -423
  78. data/po/nb/gettext.edit.po +80 -593
  79. data/po/nb/gettext.po +6 -423
  80. data/po/nl/gettext.edit.po +80 -593
  81. data/po/nl/gettext.po +6 -423
  82. data/po/pt_BR/gettext.edit.po +80 -593
  83. data/po/pt_BR/gettext.po +6 -423
  84. data/po/ru/gettext.edit.po +80 -593
  85. data/po/ru/gettext.po +6 -423
  86. data/po/sr/gettext.edit.po +80 -593
  87. data/po/sr/gettext.po +6 -423
  88. data/po/sv/gettext.edit.po +80 -593
  89. data/po/sv/gettext.po +6 -423
  90. data/po/uk/gettext.edit.po +80 -593
  91. data/po/uk/gettext.po +6 -423
  92. data/po/vi/gettext.edit.po +80 -593
  93. data/po/vi/gettext.po +6 -423
  94. data/po/zh/gettext.edit.po +80 -593
  95. data/po/zh/gettext.po +6 -423
  96. data/po/zh_TW/gettext.edit.po +80 -593
  97. data/po/zh_TW/gettext.po +6 -423
  98. data/samples/cgi/po/helloerb1.pot +3 -3
  99. data/samples/cgi/po/helloerb2.pot +3 -3
  100. data/samples/cgi/po/hellolib.pot +3 -3
  101. data/samples/cgi/po/main.pot +3 -3
  102. data/samples/po/bg/hello_gtk_builder.edit.po +15 -0
  103. data/samples/po/bg/hello_gtk_builder.po +12 -0
  104. data/samples/po/bs/hello_gtk_builder.edit.po +15 -0
  105. data/samples/po/bs/hello_gtk_builder.po +12 -0
  106. data/samples/po/ca/hello_gtk_builder.edit.po +15 -0
  107. data/samples/po/ca/hello_gtk_builder.po +12 -0
  108. data/samples/po/cs/hello_gtk_builder.edit.po +15 -0
  109. data/samples/po/cs/hello_gtk_builder.po +12 -0
  110. data/samples/po/de/hello_gtk_builder.edit.po +15 -0
  111. data/samples/po/de/hello_gtk_builder.po +12 -0
  112. data/samples/po/el/hello_gtk_builder.edit.po +15 -0
  113. data/samples/po/el/hello_gtk_builder.po +12 -0
  114. data/samples/po/eo/hello_gtk_builder.edit.po +15 -0
  115. data/samples/po/eo/hello_gtk_builder.po +12 -0
  116. data/samples/po/es/hello_gtk_builder.edit.po +15 -0
  117. data/samples/po/es/hello_gtk_builder.po +12 -0
  118. data/samples/po/fr/hello_gtk_builder.edit.po +15 -0
  119. data/samples/po/fr/hello_gtk_builder.po +12 -0
  120. data/samples/po/hello.pot +3 -3
  121. data/samples/po/hello2.pot +4 -4
  122. data/samples/po/hello_glade2.pot +8 -5
  123. data/samples/po/hello_gtk2.pot +4 -4
  124. data/samples/po/hello_gtk_builder.pot +18 -4
  125. data/samples/po/hello_noop.pot +4 -4
  126. data/samples/po/hello_plural.pot +4 -4
  127. data/samples/po/hello_tk.pot +4 -4
  128. data/samples/po/hr/hello_gtk_builder.edit.po +15 -0
  129. data/samples/po/hr/hello_gtk_builder.po +12 -0
  130. data/samples/po/hu/hello_gtk_builder.edit.po +15 -0
  131. data/samples/po/hu/hello_gtk_builder.po +12 -0
  132. data/samples/po/it/hello_gtk_builder.edit.po +15 -0
  133. data/samples/po/it/hello_gtk_builder.po +12 -0
  134. data/samples/po/ja/hello_gtk_builder.edit.po +15 -0
  135. data/samples/po/ja/hello_gtk_builder.po +12 -0
  136. data/samples/po/ko/hello_gtk_builder.edit.po +15 -0
  137. data/samples/po/ko/hello_gtk_builder.po +12 -0
  138. data/samples/po/lv/hello_gtk_builder.edit.po +15 -0
  139. data/samples/po/lv/hello_gtk_builder.po +12 -0
  140. data/samples/po/nb/hello_gtk_builder.edit.po +15 -0
  141. data/samples/po/nb/hello_gtk_builder.po +12 -0
  142. data/samples/po/nl/hello_gtk_builder.edit.po +15 -0
  143. data/samples/po/nl/hello_gtk_builder.po +12 -0
  144. data/samples/po/pt_BR/hello_gtk_builder.edit.po +15 -0
  145. data/samples/po/pt_BR/hello_gtk_builder.po +12 -0
  146. data/samples/po/ru/hello_gtk_builder.edit.po +15 -0
  147. data/samples/po/ru/hello_gtk_builder.po +12 -0
  148. data/samples/po/sr/hello_gtk_builder.edit.po +15 -0
  149. data/samples/po/sr/hello_gtk_builder.po +12 -0
  150. data/samples/po/sv/hello_gtk_builder.edit.po +15 -0
  151. data/samples/po/sv/hello_gtk_builder.po +12 -0
  152. data/samples/po/uk/hello_gtk_builder.edit.po +15 -0
  153. data/samples/po/uk/hello_gtk_builder.po +12 -0
  154. data/samples/po/vi/hello_gtk_builder.edit.po +15 -0
  155. data/samples/po/vi/hello_gtk_builder.po +12 -0
  156. data/samples/po/zh/hello_gtk_builder.edit.po +15 -0
  157. data/samples/po/zh/hello_gtk_builder.po +12 -0
  158. data/samples/po/zh_TW/hello_gtk_builder.edit.po +15 -0
  159. data/samples/po/zh_TW/hello_gtk_builder.po +12 -0
  160. data/src/po_parser.ry +48 -42
  161. data/test/fixtures/_.rb +1 -1
  162. data/test/fixtures/erb/case.rhtml +16 -0
  163. data/test/fixtures/{gtk_builder_ui_definitions.ui~ → glade/3.glade} +12 -17
  164. data/test/fixtures/multi_text_domain.rb +12 -12
  165. data/test/fixtures/np_.rb +1 -1
  166. data/test/fixtures/ns_.rb +1 -1
  167. data/test/fixtures/p_.rb +1 -1
  168. data/test/fixtures/s_.rb +1 -1
  169. data/test/fixtures/simple.rb +5 -1
  170. data/test/fixtures/upper_nn_.rb +77 -0
  171. data/test/locale/fr/LC_MESSAGES/test1.mo +0 -0
  172. data/test/locale/fr_BE/LC_MESSAGES/test1.mo +0 -0
  173. data/test/locale/fr_BE_Foo/LC_MESSAGES/test1.mo +0 -0
  174. data/test/locale/ja/LC_MESSAGES/_.mo +0 -0
  175. data/test/po/_.pot +20 -4
  176. data/test/po/backslash.pot +6 -4
  177. data/test/po/fr/test1.po +7 -0
  178. data/test/po/fr_BE/test1.po +24 -0
  179. data/test/po/fr_BE_Foo/test1.po +20 -0
  180. data/test/po/hello.pot +3 -3
  181. data/test/po/ja/_.edit.po +27 -3
  182. data/test/po/ja/_.po +15 -0
  183. data/test/po/ja/hello.edit.po +0 -1
  184. data/test/po/non_ascii.pot +4 -4
  185. data/test/po/np_.pot +8 -5
  186. data/test/po/ns_.pot +6 -4
  187. data/test/po/p_.pot +3 -3
  188. data/test/po/s_.pot +6 -4
  189. data/test/po/untranslated.pot +4 -4
  190. data/test/test_gettext.rb +23 -0
  191. data/test/test_locale_path.rb +12 -4
  192. data/test/test_parser.rb +97 -17
  193. data/test/test_po_entry.rb +20 -4
  194. data/test/test_po_parser.rb +44 -1
  195. data/test/tools/parser/test_glade.rb +91 -0
  196. data/test/tools/parser/test_gtk_builder_ui_definitions.rb +19 -1
  197. data/test/tools/parser/test_ruby.rb +4 -4
  198. data/test/tools/test_msgcat.rb +21 -1
  199. data/test/tools/test_msginit.rb +82 -3
  200. data/test/tools/test_msgmerge.rb +75 -3
  201. data/test/tools/test_xgettext.rb +100 -3
  202. metadata +70 -19
  203. /data/test/fixtures/{gladeparser.glade → glade/2.glade} +0 -0
  204. /data/test/fixtures/ruby/{percent_i.rb → percent_lower_i.rb} +0 -0
  205. /data/test/fixtures/ruby/{percent_w.rb → percent_lower_w.rb} +0 -0
  206. /data/test/fixtures/ruby/{percent_I.rb → percent_upper_i.rb} +0 -0
  207. /data/test/fixtures/ruby/{percent_W.rb → percent_upper_w.rb} +0 -0
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2014-2017 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
  #
@@ -200,7 +200,8 @@ module GetText
200
200
  @output = nil
201
201
  @order = nil
202
202
  @po_format_options = {
203
- :max_line_width => POEntry::Formatter::DEFAULT_MAX_LINE_WIDTH,
203
+ max_line_width: POEntry::Formatter::DEFAULT_MAX_LINE_WIDTH,
204
+ use_one_line_per_reference: false,
204
205
  }
205
206
  @include_fuzzy = true
206
207
  @report_warning = true
@@ -322,6 +323,12 @@ module GetText
322
323
  @po_format_options[:max_line_width] = max_line_width
323
324
  end
324
325
 
326
+ parser.on("--[no-]use-one-line-per-reference",
327
+ _("Use one line for each reference comment"),
328
+ "(#{@po_format_options[:use_one_line_per_reference]})") do |use|
329
+ @po_format_options[:use_one_line_per_reference] = use
330
+ end
331
+
325
332
  parser.on("--no-fuzzy",
326
333
  _("Ignore fuzzy entries")) do |include_fuzzy|
327
334
  @include_fuzzy = include_fuzzy
@@ -1,7 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  #
3
3
  # Copyright (C) 2012 Haruka Yoshihara <yoshihara@clear-code.com>
4
- # Copyright (C) 2012-2014 Kouhei Sutou <kou@clear-code.com>
4
+ # Copyright (C) 2012-2021 Sutou Kouhei <kou@clear-code.com>
5
5
  #
6
6
  # License: Ruby's or LGPL
7
7
  #
@@ -19,11 +19,17 @@
19
19
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
20
20
 
21
21
  require "etc"
22
+ require "optparse"
23
+
24
+ begin
25
+ require "datasets"
26
+ rescue LoadError
27
+ end
28
+ require "locale/info"
29
+
22
30
  require "gettext"
23
31
  require "gettext/po_parser"
24
32
  require "gettext/tools/msgmerge"
25
- require "locale/info"
26
- require "optparse"
27
33
 
28
34
  module GetText
29
35
  module Tools
@@ -320,53 +326,8 @@ module GetText
320
326
  end
321
327
 
322
328
  def plural_forms(language)
323
- case language
324
- when "ja", "vi", "ko", /\Azh.*\z/
325
- nplural = "1"
326
- plural_expression = "0"
327
- when "en", "de", "nl", "sv", "da", "no", "fo", "es", "pt",
328
- "it", "bg", "el", "fi", "et", "he", "eo", "hu", "tr",
329
- "ca", "nb"
330
- nplural = "2"
331
- plural_expression = "n != 1"
332
- when "pt_BR", "fr"
333
- nplural = "2"
334
- plural_expression = "n>1"
335
- when "lv"
336
- nplural = "3"
337
- plural_expression = "n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2"
338
- when "ga"
339
- nplural = "3"
340
- plural_expression = "n==1 ? 0 : n==2 ? 1 : 2"
341
- when "ro"
342
- nplural = "3"
343
- plural_expression = "n==1 ? 0 : " +
344
- "(n==0 || (n%100 > 0 && n%100 < 20)) ? 1 : 2"
345
- when "lt", "bs"
346
- nplural = "3"
347
- plural_expression = "n%10==1 && n%100!=11 ? 0 : " +
348
- "n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2"
349
- when "ru", "uk", "sr", "hr"
350
- nplural = "3"
351
- plural_expression = "n%10==1 && n%100!=11 ? 0 : n%10>=2 && " +
352
- "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2"
353
- when "cs", "sk"
354
- nplural = "3"
355
- plural_expression = "(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2"
356
- when "pl"
357
- nplural = "3"
358
- plural_expression = "n==1 ? 0 : n%10>=2 && " +
359
- "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2"
360
- when "sl"
361
- nplural = "4"
362
- plural_expression = "n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 " +
363
- "|| n%100==4 ? 2 : 3"
364
- else
365
- nplural = nil
366
- plural_expression = nil
367
- end
368
-
369
- "nplurals=#{nplural}; plural=#{plural_expression};"
329
+ converter = CLDRPluralsConverter.new(language)
330
+ converter.convert
370
331
  end
371
332
 
372
333
  DESCRIPTION_TITLE = /^SOME DESCRIPTIVE TITLE\.$/
@@ -408,6 +369,216 @@ module GetText
408
369
  def year
409
370
  now.year
410
371
  end
372
+
373
+ class CLDRPluralsConverter
374
+ def initialize(language)
375
+ @language = language
376
+
377
+ end
378
+
379
+ def convert
380
+ n_plurals = nil
381
+ expression = nil
382
+ if defined?(Datasets::CLDRPlurals)
383
+ plurals = Datasets::CLDRPlurals.new
384
+ plurals.each do |locale|
385
+ next unless locale.name == @language
386
+ n_plurals, expression = convert_plural_rules(locale.rules)
387
+ break
388
+ end
389
+ end
390
+ "nplurals=#{n_plurals}; plural=#{expression};"
391
+ end
392
+
393
+ private
394
+ def convert_plural_rules(rules)
395
+ n_plurals = 1
396
+ conditions = []
397
+ order = [
398
+ "one",
399
+ "zero",
400
+ "two",
401
+ "few",
402
+ "many",
403
+ "other",
404
+ ]
405
+ rules = rules.reject do |rule|
406
+ rule.integer_samples.nil?
407
+ end
408
+ rules = rules.sort_by do |rule|
409
+ order.index(rule.count)
410
+ end
411
+ rules[0..-2].each do |rule|
412
+ next if rule.condition.nil?
413
+ condition = convert_plural_condition(rule.condition)
414
+ next if condition.nil?
415
+ next if condition == false
416
+ n_plurals += 1
417
+ conditions << condition
418
+ end
419
+ expression = ""
420
+ case conditions.size
421
+ when 0
422
+ expression << "0"
423
+ when 1
424
+ condition = conditions[0]
425
+ case condition
426
+ when "(n == 1)"
427
+ expression << "n != 1"
428
+ when "(n <= 1)"
429
+ expression << "n > 1"
430
+ else
431
+ expression << "#{condition} ? 1 : 0"
432
+ end
433
+ else
434
+ (conditions.size + 1).times do |i|
435
+ if i == conditions.size
436
+ expression << i.to_s
437
+ else
438
+ condition = conditions[i]
439
+ expression << "#{condition} ? #{i} : "
440
+ end
441
+ end
442
+ end
443
+ [n_plurals, expression]
444
+ end
445
+
446
+ def convert_plural_condition(condition)
447
+ case condition[0]
448
+ when :and
449
+ gettext_condition = nil
450
+ condition[1..-1].each do |sub_condition|
451
+ sub_gettext_condition = convert_plural_condition(sub_condition)
452
+ case sub_gettext_condition
453
+ when String
454
+ if gettext_condition.is_a?(String)
455
+ gettext_condition << " && #{sub_gettext_condition}"
456
+ else
457
+ gettext_condition = sub_gettext_condition
458
+ end
459
+ when TrueClass
460
+ unless gettext_condition.is_a?(String)
461
+ gettext_condition = true
462
+ end
463
+ when FalseClass
464
+ return false
465
+ else
466
+ raise "unknown value #{sub_gettext_condition.inspect}"
467
+ end
468
+ end
469
+ gettext_condition
470
+ when :or
471
+ gettext_condition = false
472
+ condition[1..-1].each do |sub_condition|
473
+ sub_gettext_condition = convert_plural_condition(sub_condition)
474
+ case sub_gettext_condition
475
+ when String
476
+ if gettext_condition.is_a?(String)
477
+ gettext_condition << " || #{sub_gettext_condition}"
478
+ else
479
+ gettext_condition = sub_gettext_condition
480
+ end
481
+ when TrueClass
482
+ return true
483
+ when FalseClass
484
+ else
485
+ raise "unknown value #{sub_gettext_condition.inspect}"
486
+ end
487
+ end
488
+ gettext_condition
489
+ when :equal
490
+ left = convert_plural_condition(condition[1])
491
+ right = condition[2]
492
+ case left
493
+ when String
494
+ right = compact_equal_values(right)
495
+ gettext_conditions = right.collect do |right_value|
496
+ case right_value
497
+ when Range
498
+ if right_value.begin.zero?
499
+ "(#{left} <= #{right_value.end})"
500
+ else
501
+ "(#{left} >= #{right_value.begin} && " +
502
+ "#{left} <= #{right_value.end})"
503
+ end
504
+ else
505
+ "(#{left} == #{right_value})"
506
+ end
507
+ end
508
+ if gettext_conditions.size == 1
509
+ gettext_conditions[0]
510
+ else
511
+ gettext_conditions.join(" || ")
512
+ end
513
+ when 0
514
+ if right.include?(0)
515
+ true
516
+ else
517
+ false
518
+ end
519
+ else
520
+ false
521
+ end
522
+ when :not_equal
523
+ left = convert_plural_condition(condition[1])
524
+ right = condition[2]
525
+ case left
526
+ when String
527
+ right = compact_equal_values(right)
528
+ gettext_conditions = right.collect do |right_value|
529
+ case right_value
530
+ when Range
531
+ "(#{left} < #{right_value.begin} || " +
532
+ "#{left} > #{right_value.end})"
533
+ else
534
+ "(#{left} != #{right_value})"
535
+ end
536
+ end
537
+ if gettext_conditions.size == 1
538
+ gettext_conditions[0]
539
+ else
540
+ gettext_conditions = gettext_conditions.collect do |gettext_condition|
541
+ "(#{gettext_condition})"
542
+ end
543
+ gettext_conditions.join(" && ")
544
+ end
545
+ when 0
546
+ if right.include?(0)
547
+ false
548
+ else
549
+ true
550
+ end
551
+ else
552
+ false
553
+ end
554
+ when :mod
555
+ left = convert_plural_condition(condition[1])
556
+ right = condition[2]
557
+ case left
558
+ when "n"
559
+ "(n % #{right})"
560
+ else
561
+ false
562
+ end
563
+ when "n", "i"
564
+ "n"
565
+ when "v", "w"
566
+ 0
567
+ when "f", "t", "c", "e"
568
+ false
569
+ else
570
+ raise "unknown operator: #{condition[0].inspect}"
571
+ end
572
+ end
573
+
574
+ def compact_equal_values(values)
575
+ if values == [0, 1]
576
+ [0..1]
577
+ else
578
+ values
579
+ end
580
+ end
581
+ end
411
582
  end
412
583
  end
413
584
  end
@@ -1,9 +1,7 @@
1
- # -*- coding: utf-8 -*-
2
- #
3
1
  # Copyright (C) 2012-2013 Haruka Yoshihara <yoshihara@clear-code.com>
4
- # Copyright (C) 2012-2015 Kouhei Sutou <kou@clear-code.com>
5
- # Copyright (C) 2005-2009 Masao Mutoh
6
- # Copyright (C) 2005,2006 speakillof
2
+ # Copyright (C) 2012-2023 Sutou Kouhei <kou@clear-code.com>
3
+ # Copyright (C) 2005-2009 Masao Mutoh
4
+ # Copyright (C) 2005,2006 speakillof
7
5
  #
8
6
  # License: Ruby's or LGPL
9
7
  #
@@ -49,6 +47,7 @@ module GetText
49
47
  config.parse(command_line)
50
48
 
51
49
  parser = POParser.new
50
+ parser.report_warning = config.report_warning?
52
51
  parser.ignore_fuzzy = false
53
52
  definition_po = PO.new
54
53
  reference_pot = PO.new
@@ -309,10 +308,12 @@ module GetText
309
308
  @output = nil
310
309
  @order = :reference
311
310
  @po_format_options = {
312
- :max_line_width => POEntry::Formatter::DEFAULT_MAX_LINE_WIDTH,
311
+ max_line_width: POEntry::Formatter::DEFAULT_MAX_LINE_WIDTH,
312
+ use_one_line_per_reference: false,
313
313
  }
314
314
  @enable_fuzzy_matching = true
315
315
  @update = nil
316
+ @report_warning = true
316
317
  @output_obsolete_entries = true
317
318
  @backup = ENV["VERSION_CONTROL"]
318
319
  @suffix = ENV["SIMPLE_BACKUP_SUFFIX"] || "~"
@@ -337,6 +338,12 @@ module GetText
337
338
  @enable_fuzzy_matching
338
339
  end
339
340
 
341
+ # @return [Bool] true if reporting warning is enabled,
342
+ # false otherwise.
343
+ def report_warning?
344
+ @report_warning
345
+ end
346
+
340
347
  # @return [Bool] true if outputting obsolete entries is
341
348
  # enabled, false otherwise.
342
349
  def output_obsolete_entries?
@@ -416,12 +423,23 @@ module GetText
416
423
  @po_format_options[:max_line_width] = max_line_width
417
424
  end
418
425
 
426
+ parser.on("--[no-]use-one-line-per-reference",
427
+ _("Use one line for each reference comment"),
428
+ "(#{@po_format_options[:use_one_line_per_reference]})") do |use|
429
+ @po_format_options[:use_one_line_per_reference] = use
430
+ end
431
+
419
432
  parser.on("--[no-]fuzzy-matching",
420
433
  _("Disable fuzzy matching"),
421
434
  _("(enable)")) do |boolean|
422
435
  @enable_fuzzy_matching = boolean
423
436
  end
424
437
 
438
+ parser.on("--no-report-warning",
439
+ _("Don't report warning messages")) do |report_warning|
440
+ @report_warning = report_warning
441
+ end
442
+
425
443
  parser.on("--no-obsolete-entries",
426
444
  _("Don't output obsolete entries")) do |boolean|
427
445
  @output_obsolete_entries = boolean
@@ -0,0 +1,88 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ =begin
4
+ parser/erubi.rb - parser for ERB using Erubi
5
+
6
+ Copyright (C) 2005-2009 Masao Mutoh
7
+
8
+ You may redistribute it and/or modify it under the same
9
+ license terms as Ruby or LGPL.
10
+ =end
11
+
12
+ require "erubi"
13
+ require 'gettext/tools/parser/ruby'
14
+
15
+ module GetText
16
+ class ErubiParser
17
+ @config = {
18
+ :extnames => ['.rhtml', '.erb']
19
+ }
20
+
21
+ class << self
22
+ # Sets some preferences to parse ERB files.
23
+ # * config: a Hash of the config. It can takes some values below:
24
+ # * :extnames: An Array of target files extension. Default is [".rhtml"].
25
+ def init(config)
26
+ config.each{|k, v|
27
+ @config[k] = v
28
+ }
29
+ end
30
+
31
+ def target?(file) # :nodoc:
32
+ @config[:extnames].each do |v|
33
+ return true if File.extname(file) == v
34
+ end
35
+ false
36
+ end
37
+
38
+ # Parses eRuby script located at `path`.
39
+ #
40
+ # This is a short cut method. It equals to `new(path,
41
+ # options).parse`.
42
+ #
43
+ # @return [Array<POEntry>] Extracted messages
44
+ # @see #initialize and #parse
45
+ def parse(path, options={})
46
+ parser = new(path, options)
47
+ parser.parse
48
+ end
49
+ end
50
+
51
+ # @param path [String] eRuby script path to be parsed
52
+ # @param options [Hash]
53
+ def initialize(path, options={})
54
+ @path = path
55
+ @options = options
56
+ end
57
+
58
+ # Extracts messages from @path.
59
+ #
60
+ # @return [Array<POEntry>] Extracted messages
61
+ def parse
62
+ content = IO.read(@path)
63
+
64
+ encoding = detect_encoding(content)
65
+ content.force_encoding(encoding)
66
+
67
+ erb = Erubi::Engine.new(content)
68
+ src = erb.src
69
+
70
+ RubyParser.new(@path, @options).parse_source(src)
71
+ end
72
+
73
+ def detect_encoding(content)
74
+ if /#.*coding: (\S*)/ =~ content.lines.first
75
+ $1.upcase
76
+ else
77
+ content.encoding
78
+ end
79
+ end
80
+ end
81
+ end
82
+
83
+ if __FILE__ == $0
84
+ # ex) ruby glade.rhtml foo.rhtml bar.rhtml
85
+ ARGV.each do |file|
86
+ p GetText::ErubiParser.parse(file)
87
+ end
88
+ end
@@ -1,14 +1,20 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- =begin
4
- parser/glade.rb - parser for Glade-2
5
-
6
- Copyright (C) 2013 Kouhei Sutou <kou@clear-code.com>
7
- Copyright (C) 2004,2005 Masao Mutoh
8
-
9
- You may redistribute it and/or modify it under the same
10
- license terms as Ruby or LGPL.
11
- =end
1
+ # Copyright (C) 2004,2005 Masao Mutoh
2
+ # Copyright (C) 2013 Kouhei Sutou <kou@clear-code.com>
3
+ #
4
+ # License: Ruby's or LGPL
5
+ #
6
+ # This library is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU Lesser General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This library is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU Lesser General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Lesser General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
12
18
 
13
19
  require 'cgi'
14
20
  require 'gettext'
@@ -24,15 +30,11 @@ module GetText
24
30
  GLADE_RE = /glade-2.0.dtd/
25
31
 
26
32
  def target?(file) # :nodoc:
27
- data = IO.readlines(file)
28
- if XML_RE =~ data[0] and GLADE_RE =~ data[1]
29
- true
30
- else
31
- if File.extname(file) == '.glade'
32
- raise _("`%{file}' is not glade-2.0 format.") % {:file => file}
33
- end
34
- false
35
- end
33
+ return false unless File.extname(file) == ".glade"
34
+ data = File.read(file)
35
+ return false unless data.include?("<?xml")
36
+ return false unless data.include?("glade-2.0.dtd")
37
+ true
36
38
  end
37
39
 
38
40
  def parse(path, options={})
@@ -57,7 +59,7 @@ module GetText
57
59
 
58
60
  private
59
61
  def parse_source(input) # :nodoc:
60
- targets = []
62
+ po = []
61
63
  target = false
62
64
  start_line_no = nil
63
65
  val = nil
@@ -69,14 +71,14 @@ module GetText
69
71
  target = true
70
72
  if TARGET2 =~ $1
71
73
  val = $1
72
- add_target(val, start_line_no, targets)
74
+ add_po_entry(po, val, start_line_no)
73
75
  val = nil
74
76
  target = false
75
77
  end
76
78
  elsif target
77
79
  if TARGET2 =~ line
78
80
  val << $1
79
- add_target(val, start_line_no, targets)
81
+ add_po_entry(po, val, start_line_no)
80
82
  val = nil
81
83
  target = false
82
84
  else
@@ -84,26 +86,22 @@ module GetText
84
86
  end
85
87
  end
86
88
  end
87
- targets
89
+ po
88
90
  end
89
91
 
90
- def add_target(val, line_no, targets) # :nodoc:
91
- return unless val.size > 0
92
- assoc_data = targets.assoc(val)
93
- val = CGI.unescapeHTML(val)
94
- if assoc_data
95
- targets[targets.index(assoc_data)] = assoc_data << "#{@path}:#{line_no}"
96
- else
97
- targets << [val.gsub(/\n/, '\n'), "#{@path}:#{line_no}"]
92
+ def add_po_entry(po, value, line_no) # :nodoc:
93
+ return if value.empty?
94
+ value = CGI.unescapeHTML(value)
95
+ value = value.gsub(/\n/, "\n")
96
+ po_entry = po.find do |entry|
97
+ entry.msgid == value
98
98
  end
99
- targets
99
+ if po_entry.nil?
100
+ po_entry = POEntry.new(:normal)
101
+ po_entry.msgid = value
102
+ po << po_entry
103
+ end
104
+ po_entry.references << "#{@path}:#{line_no}"
100
105
  end
101
106
  end
102
107
  end
103
-
104
- if __FILE__ == $0
105
- # ex) ruby glade.rb foo.glade bar.glade
106
- ARGV.each do |file|
107
- p GetText::GladeParser.parse(file)
108
- end
109
- end
@@ -24,13 +24,14 @@ require "gettext/po_entry"
24
24
  module GetText
25
25
  class GtkBuilderUIDefinitionsParser
26
26
  @config = {
27
- :extnames => [".ui"]
27
+ :extnames => [".ui", ".glade"]
28
28
  }
29
29
 
30
30
  class << self
31
31
  # Sets some preferences to parse GtkBuilder UI definitions files.
32
32
  # * config: a Hash of the config. It can takes some values below:
33
- # * :extnames: An Array of target files extension. Default is [".ui"].
33
+ # * :extnames: An Array of target files extension.
34
+ # Default is [".ui", ".glade"].
34
35
  def init(config)
35
36
  config.each do |k, v|
36
37
  @config[k] = v
@@ -39,7 +40,9 @@ module GetText
39
40
 
40
41
  def target?(file) # :nodoc:
41
42
  @config[:extnames].each do |extname|
42
- return true if File.extname(file) == extname
43
+ next unless File.extname(file) == extname
44
+ next unless File.read(file).include?("<interface>")
45
+ return true
43
46
  end
44
47
  false
45
48
  end
@@ -1,7 +1,7 @@
1
1
  =begin
2
2
  parser/ruby.rb - parser for ruby script
3
3
 
4
- Copyright (C) 2013-2019 Sutou Kouhei <kou@clear-code.com>
4
+ Copyright (C) 2013-2021 Sutou Kouhei <kou@clear-code.com>
5
5
  Copyright (C) 2003-2009 Masao Mutoh
6
6
  Copyright (C) 2005 speakillof
7
7
  Copyright (C) 2001,2002 Yasushi Shoji, Masao Mutoh
@@ -95,7 +95,7 @@ module GetText
95
95
 
96
96
  def process_on_const(token, po)
97
97
  case token
98
- when "N_"," Nn_"
98
+ when "N_", "Nn_"
99
99
  # TODO: Check the next token is :on_lparen
100
100
  process_on_ident(token, po)
101
101
  else
@@ -1,6 +1,4 @@
1
- # -*- coding: utf-8 -*-
2
- #
3
- # Copyright (C) 2012-2014 Kouhei Sutou <kou@clear-code.com>
1
+ # Copyright (C) 2012-2023 Sutou Kouhei <kou@clear-code.com>
4
2
  #
5
3
  # License: Ruby's or LGPL
6
4
  #
@@ -452,8 +450,8 @@ module GetText
452
450
  locale = args.locale || ENV["LOCALE"]
453
451
  if locale.nil?
454
452
  raise "specify locale name by " +
455
- "'rake #{_task.name}[${LOCALE}]' or " +
456
- "rake #{_task.name} LOCALE=${LOCALE}'"
453
+ "rake '#{_task.name}[${LOCALE}]' or " +
454
+ "rake #{_task.name} LOCALE=${LOCALE}'"
457
455
  end
458
456
  define_edit_po_file_task(locale)
459
457
  define_po_file_task(locale)