gettext 3.3.5 → 3.3.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 (121) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +4 -0
  3. data/doc/text/news.md +220 -0
  4. data/gettext.gemspec +4 -4
  5. data/lib/gettext/locale_path.rb +12 -8
  6. data/lib/gettext/mo.rb +7 -5
  7. data/lib/gettext/tools/msginit.rb +221 -50
  8. data/lib/gettext/tools/msgmerge.rb +13 -0
  9. data/lib/gettext/tools/parser/erb.rb +9 -1
  10. data/lib/gettext/tools/parser/glade.rb +38 -40
  11. data/lib/gettext/tools/parser/gtk_builder_ui_definitions.rb +6 -6
  12. data/lib/gettext/tools/parser/ruby.rb +2 -2
  13. data/lib/gettext/version.rb +2 -2
  14. data/locale/bg/LC_MESSAGES/gettext.mo +0 -0
  15. data/locale/bs/LC_MESSAGES/gettext.mo +0 -0
  16. data/locale/ca/LC_MESSAGES/gettext.mo +0 -0
  17. data/locale/cs/LC_MESSAGES/gettext.mo +0 -0
  18. data/locale/de/LC_MESSAGES/gettext.mo +0 -0
  19. data/locale/el/LC_MESSAGES/gettext.mo +0 -0
  20. data/locale/eo/LC_MESSAGES/gettext.mo +0 -0
  21. data/locale/es/LC_MESSAGES/gettext.mo +0 -0
  22. data/locale/et/LC_MESSAGES/gettext.mo +0 -0
  23. data/locale/fr/LC_MESSAGES/gettext.mo +0 -0
  24. data/locale/hr/LC_MESSAGES/gettext.mo +0 -0
  25. data/locale/hu/LC_MESSAGES/gettext.mo +0 -0
  26. data/locale/it/LC_MESSAGES/gettext.mo +0 -0
  27. data/locale/ja/LC_MESSAGES/gettext.mo +0 -0
  28. data/locale/ko/LC_MESSAGES/gettext.mo +0 -0
  29. data/locale/lv/LC_MESSAGES/gettext.mo +0 -0
  30. data/locale/nb/LC_MESSAGES/gettext.mo +0 -0
  31. data/locale/nl/LC_MESSAGES/gettext.mo +0 -0
  32. data/locale/pt_BR/LC_MESSAGES/gettext.mo +0 -0
  33. data/locale/ru/LC_MESSAGES/gettext.mo +0 -0
  34. data/locale/sr/LC_MESSAGES/gettext.mo +0 -0
  35. data/locale/uk/LC_MESSAGES/gettext.mo +0 -0
  36. data/locale/vi/LC_MESSAGES/gettext.mo +0 -0
  37. data/locale/zh/LC_MESSAGES/gettext.mo +0 -0
  38. data/locale/zh_TW/LC_MESSAGES/gettext.mo +0 -0
  39. data/po/bg/gettext.edit.po +36 -554
  40. data/po/bg/gettext.po +0 -423
  41. data/po/bs/gettext.edit.po +36 -554
  42. data/po/bs/gettext.po +0 -423
  43. data/po/ca/gettext.edit.po +36 -554
  44. data/po/ca/gettext.po +0 -423
  45. data/po/cs/gettext.edit.po +36 -554
  46. data/po/cs/gettext.po +0 -423
  47. data/po/de/gettext.edit.po +36 -554
  48. data/po/de/gettext.po +0 -423
  49. data/po/el/gettext.edit.po +36 -554
  50. data/po/el/gettext.po +0 -423
  51. data/po/eo/gettext.edit.po +36 -554
  52. data/po/eo/gettext.po +0 -423
  53. data/po/es/gettext.edit.po +36 -554
  54. data/po/es/gettext.po +0 -423
  55. data/po/et/gettext.edit.po +36 -554
  56. data/po/et/gettext.po +0 -423
  57. data/po/fr/gettext.edit.po +36 -554
  58. data/po/fr/gettext.po +0 -423
  59. data/po/gettext.pot +37 -619
  60. data/po/hr/gettext.edit.po +36 -554
  61. data/po/hr/gettext.po +0 -423
  62. data/po/hu/gettext.edit.po +36 -554
  63. data/po/hu/gettext.po +0 -423
  64. data/po/it/gettext.edit.po +36 -554
  65. data/po/it/gettext.po +0 -423
  66. data/po/ja/gettext.edit.po +36 -554
  67. data/po/ja/gettext.po +0 -423
  68. data/po/ko/gettext.edit.po +36 -554
  69. data/po/ko/gettext.po +0 -423
  70. data/po/lv/gettext.edit.po +36 -554
  71. data/po/lv/gettext.po +0 -423
  72. data/po/nb/gettext.edit.po +36 -554
  73. data/po/nb/gettext.po +0 -423
  74. data/po/nl/gettext.edit.po +36 -554
  75. data/po/nl/gettext.po +0 -423
  76. data/po/pt_BR/gettext.edit.po +36 -554
  77. data/po/pt_BR/gettext.po +0 -423
  78. data/po/ru/gettext.edit.po +36 -554
  79. data/po/ru/gettext.po +0 -423
  80. data/po/sr/gettext.edit.po +36 -554
  81. data/po/sr/gettext.po +0 -423
  82. data/po/sv/gettext.edit.po +34 -555
  83. data/po/sv/gettext.po +0 -423
  84. data/po/uk/gettext.edit.po +36 -554
  85. data/po/uk/gettext.po +0 -423
  86. data/po/vi/gettext.edit.po +36 -554
  87. data/po/vi/gettext.po +0 -423
  88. data/po/zh/gettext.edit.po +36 -554
  89. data/po/zh/gettext.po +0 -423
  90. data/po/zh_TW/gettext.edit.po +36 -554
  91. data/po/zh_TW/gettext.po +0 -423
  92. data/test/fixtures/_.rb +1 -1
  93. data/test/fixtures/erb/minus.rhtml +12 -0
  94. data/test/fixtures/{gladeparser.glade → glade/2.glade} +0 -0
  95. data/test/fixtures/glade/3.glade +63 -0
  96. data/test/fixtures/gtk_builder_ui_definitions.ui~ +68 -0
  97. data/test/fixtures/multi_text_domain.rb +12 -12
  98. data/test/fixtures/np_.rb +1 -1
  99. data/test/fixtures/ns_.rb +1 -1
  100. data/test/fixtures/p_.rb +1 -1
  101. data/test/fixtures/ruby/{percent_i.rb → percent_lower_i.rb} +0 -0
  102. data/test/fixtures/ruby/{percent_w.rb → percent_lower_w.rb} +0 -0
  103. data/test/fixtures/ruby/{percent_I.rb → percent_upper_i.rb} +0 -0
  104. data/test/fixtures/ruby/{percent_W.rb → percent_upper_w.rb} +0 -0
  105. data/test/fixtures/s_.rb +1 -1
  106. data/test/fixtures/simple.rb +1 -1
  107. data/test/fixtures/upper_nn_.rb +77 -0
  108. data/test/po/_.pot +20 -4
  109. data/test/po/ja/_.edit.po +24 -0
  110. data/test/po/np_.pot +8 -5
  111. data/test/po/ns_.pot +6 -4
  112. data/test/po/p_.pot +3 -3
  113. data/test/po/s_.pot +6 -4
  114. data/test/run-test.rb +0 -1
  115. data/test/test_parser.rb +42 -17
  116. data/test/tools/parser/test_glade.rb +91 -0
  117. data/test/tools/parser/test_gtk_builder_ui_definitions.rb +19 -1
  118. data/test/tools/parser/test_ruby.rb +4 -4
  119. data/test/tools/test_msginit.rb +77 -3
  120. data/test/tools/test_msgmerge.rb +34 -0
  121. metadata +29 -25
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5391b52687ca78f695890c2d0b7d78b322ba32ce7b4978c12de1cbde7f2e682f
4
- data.tar.gz: b589d0b3dc0a057526b17b5a196171365280d1e60fdc2f939be5a2381ecd1e4d
3
+ metadata.gz: bf480f5774043884c6583daea1fc41264e3ce96c90c287f61a5336054f69f428
4
+ data.tar.gz: daa8334ee3ccecb4cf90d9ea016392068c6ae3bdf11b395df706fd4b1e5cff0d
5
5
  SHA512:
6
- metadata.gz: 774e933f6950156d08af1957e0f67d4a07b717ca42761c84fd6bf9ee2758304eb5ac0e58bdfbd6cce0a892ecce7ea6de4708cfee5ba39e58a64e325cb5acb885
7
- data.tar.gz: c614dbf745ba89e691e4e40c38f73a2daba026eb58af0af0f638753a169f5ef18f2b93e9bf1311df4f086e916294db73ab0d3597f26fdd9ad51cf539c923ff26
6
+ metadata.gz: 7040a0b37b61e221055ab90bfafb0d538b24641211c45f8a4ce04adbc08b22dba247369ba5e695f7d1565a4fffbf67a317065933f39a788c34bf8e45f3b37b3f
7
+ data.tar.gz: 9d0f862577acd733cabdb1d66b90cde9b5c896d2dc468dac36b205172f72546902648e1dcaa509c7fc920ba805155d1241c79ebdc3b928d59745a309ca7c9c44
data/Rakefile CHANGED
@@ -86,6 +86,10 @@ end
86
86
  xgettext_options = ["--add-comments=TRANSLATORS:"]
87
87
  GetText::Tools::Task.define do |task|
88
88
  task.spec = spec
89
+ task.files = task.files.reject do |file|
90
+ file.start_with?("samples/") or
91
+ file.start_with?("test/")
92
+ end
89
93
  task.xgettext_options.concat(xgettext_options)
90
94
  end
91
95
 
data/doc/text/news.md CHANGED
@@ -1,5 +1,71 @@
1
1
  # News
2
2
 
3
+ ## 3.3.9: 2021-08-26 {#version-3-3-9}
4
+
5
+ ### Improvements
6
+
7
+ * msginit: Made Red Datasets dependency optional.
8
+ [GitHub:red-datatools/red-datasets#105][Suggested by Mamoru TASAKA]
9
+
10
+ ### Thanks
11
+
12
+ * Mamoru TASAKA
13
+
14
+ ## 3.3.8: 2021-06-09 {#version-3-3-8}
15
+
16
+ ### Improvements
17
+
18
+ * msginit: Added support for generating plural forms with
19
+ Unicode's CLDR plural rules data.
20
+ [GitHub#85][Suggested by Michaël Hoste]
21
+
22
+ * rxgettext ui: Added support for GtkBuilder UI definitions format
23
+ with `.glade` extension.
24
+ [GitHub#74][Reported by dorle-o]
25
+
26
+ ### Fixes
27
+
28
+ * rxgettext ruby: Fixed a bug that `Nn_` isn't extracted.
29
+ [GitHub#86][Reported by Kai Ramuenke]
30
+
31
+ ### Thanks
32
+
33
+ * Kai Ramuenke
34
+
35
+ * Michaël Hoste
36
+
37
+ * dorle-o
38
+
39
+ ## 3.3.7: 2021-01-18 {#version-3-3-7}
40
+
41
+ ### Improvements
42
+
43
+ * msgmerge: Added `--no-report-warning` option.
44
+ [GitHub#81][Reported by Akim Demaille]
45
+
46
+ ### Thanks
47
+
48
+ * Akim Demaille
49
+
50
+ ## 3.3.6: 2020-08-04 {#version-3-3-6}
51
+
52
+ ### Improvements
53
+
54
+ * erb: Added support for `-%>`.
55
+ [GitHub#77][Reported by lremes]
56
+
57
+ * Removed ChangeLog.
58
+ [GitHub#76][Reported by Will Stephenson]
59
+
60
+ * Don't assume `RbConfig::CONFIG["datadir"]` is available. For
61
+ example, TruffleRuby doesn't provide it.
62
+
63
+ ### Thanks
64
+
65
+ * lremes
66
+
67
+ * Will Stephenson
68
+
3
69
  ## 3.3.5: 2020-02-15 {#version-3-3-5}
4
70
 
5
71
  ### Improvements
@@ -850,3 +916,157 @@ Ruby 1.9 support release.
850
916
  * Gunnar Wolf
851
917
  * Ivan Pirlik
852
918
  * Tatsuki Sugiura
919
+
920
+ ## 2.2.1: 2012-05-20
921
+
922
+ ### Changes
923
+
924
+ * Supported non ASCII string in msgid. [GitHub#1]
925
+ [Patch by Urban Hafner]
926
+ * Stopped overriding String#% on Ruby 1.9.
927
+ * Fixed a bug that "\" is too escaped.
928
+ * Removed GetText.bindtext dependency from GetText::PoParser.
929
+ * Ranamed GetText::MOFile to GetText::MoFile but GetText::MOFile
930
+ is still available.
931
+
932
+ ### Thanks
933
+
934
+ * Urban Hafner
935
+
936
+ ## 2.2.0: 2012-03-11
937
+
938
+ ### Changes
939
+
940
+ * Supported ruby-1.9. [Patch by hallelujah]
941
+ * Supported $SAFE=1. [Patch by bon]
942
+ * Improved argument check. [Suggested by Morus Walter]
943
+ * Supported ruby-1.8.6 again. [Bug#27447] [Reported by Mamoru Tasaka]
944
+ * Fixed Ukrainan translation path. [Bug#28277] [Reported by Gunnar Wolf]
945
+ * Fixed a bug that only the last path in GETTEXT_PATH environment
946
+ variable is used. [Bug#28345] [Reported by Ivan Pirlik]
947
+ * Fixed a bug that Ruby-GetText-Package modifies $LOAD_PATH. [Bug#28094]
948
+ [Reported by Tatsuki Sugiura]
949
+
950
+ ### Thanks
951
+
952
+ * hallelujah
953
+ * bon
954
+ * Morus Walter
955
+ * Mamoru Tasaka
956
+ * Gunnar Wolf
957
+ * Ivan Pirlik
958
+ * Tatsuki Sugiura
959
+
960
+
961
+ ## 2.1.0: 2009-11-14
962
+
963
+ ### Changes
964
+
965
+ * Implemented parsing of translator comments (GNU gettext feature)
966
+ [by Vladimir Dobriakov]
967
+ * Refactor the directory structure.
968
+ * Move files for runtime to lib/gettext/runtime/*.
969
+ * Move files for development(rgettext/rmsgfmt) to
970
+ lib/gettext/tools/*.
971
+ * Refactor parsers for po. po-message object is defined as GetText::PoMessage
972
+ class. [by Vladimir Dobriakov, Masao Mutoh]
973
+ * Speed up when lots of objects are created to share the textdomain in each
974
+ objects. [Reported by Gaël Séchaud.]
975
+ * Fix "%{foo.bar}" %{"foo.bar".to_sym => "a"} doesn't work.
976
+ [Bug#26663, Reported by Danilo Castilho]
977
+ * lib/gettext.rb: Fixed to work unless gem. [Reported by Vladimir Dobriakov]
978
+ * Fixed a wrong String literal in a CGI sample.
979
+ [Bug #26531, by Eugene Mikhailov]
980
+ * Update license information(explicit to use ruby's or LGPL).
981
+ [Pointed out by Masateru Yoshikawa]
982
+ * Code cleanup.
983
+ * Update minor version.
984
+
985
+ ## 2.0.4: 2009-05-23
986
+
987
+ ### Changes
988
+
989
+ * Fix String#% return nil when the string have no place holders. [by okkez]
990
+ * Update pofiles and remove old messages.
991
+ * suppress some warnings on Ruby 1.9.x. [by Nobuhiro IMAI]
992
+ * Fix not to run tests on Win32.
993
+
994
+ ## 2.0.3: 2009-05-09
995
+
996
+ ### Changes
997
+
998
+ * Fixed the dependencies. [Reported by Hans de Graaff]
999
+
1000
+ ## 2.0.2: 2009-05-04
1001
+
1002
+ ### Changes
1003
+
1004
+ * Support ruby-1.9.1 style format string such as `%<foo>d`.
1005
+ * Apply new `Locale.set_app_language_tags` and Locale.candidates.
1006
+ [Suggested by Vladimir Dobriakov]
1007
+ * Enhance to support ruby-1.9.x [by OZAWA Sakuro]
1008
+ * poparser work with proper encoding.
1009
+ * string.rb: #bytesize alias to #size in older ruby version such as 1.8.5.
1010
+ * Fixed bugs
1011
+ * `n_()` to work when Plural-Forms line in po-file is not correct.
1012
+ [Reported by Sava Chankov (Bug#25570)]
1013
+ * GetText::Locale.default_rules_path : $LOAD_PATH is not well parsed.
1014
+ [by hallelujah]
1015
+ * locale_path.rb: Fixed warning message.
1016
+
1017
+ ### Thanks
1018
+
1019
+ * hallelujah
1020
+ * Sava Chankov
1021
+ * OZAWA Sakuro
1022
+ * Vladimir Dobriakov
1023
+
1024
+ ## 2.0.1: 2009-04-17
1025
+
1026
+ ### Changes
1027
+
1028
+ * Fixed bugs
1029
+ * doesn't work with ruby-1.8.5. [Reported by Dan Coutu]
1030
+ * GetText.locale= can't keep the locale. [Reported by Adam Ilan]
1031
+ * Break backward compatibility of bindtextdomain
1032
+ [Reported by Mamoru Tasaka(#24947), Mathieu Blondel]
1033
+ * Other trivial fixes/improvement.
1034
+ * 1.8 times faster than 2.0.0.
1035
+ * GetText::LocalePath is separated from GetText::TextDomainManager.
1036
+ Improve to find the locale path.
1037
+ * Enhance to support ruby-1.9.x [by OZAWA Sakuro]
1038
+
1039
+ ### Thanks
1040
+
1041
+ * OZAWA Sakuro
1042
+ * Tietew
1043
+ * Adam Ilan
1044
+ * Mamoru Tasaka
1045
+ * Mathieu Blondel
1046
+
1047
+ ## 2.0.0: 2009-03-21
1048
+
1049
+ ### Changes
1050
+
1051
+ * Separate this library to locale and rails-support to locale,
1052
+ locale\_rails, gettext\_activerecord, gettext\_rails.
1053
+ * Depends on locale(ruby-locale).
1054
+ * Removes to support rails.
1055
+ * A lot of referctoring, improvements.
1056
+ * Thread safe.
1057
+ * New APIs for gettext/tools instead of gettext/utils.
1058
+ * Move to github.com.
1059
+
1060
+ ### Special thanks
1061
+
1062
+ * Michael Grosser: A lot of improvement.
1063
+
1064
+ ### Thanks
1065
+
1066
+ * Tietew
1067
+ * Kazuhiro NISHIYAMA
1068
+ * Fabio M.A.
1069
+ * Tuptus
1070
+ * Morus Walter
1071
+ * Vladimir Dobriakov
1072
+ * Ramsey
data/gettext.gemspec CHANGED
@@ -31,12 +31,12 @@ So you can use GNU gettext tools for maintaining.
31
31
 
32
32
  s.add_runtime_dependency("locale", ">= 2.0.5")
33
33
  s.add_runtime_dependency("text", ">= 1.3.0")
34
- s.add_development_dependency("rake")
35
- s.add_development_dependency("racc")
36
- s.add_development_dependency("yard")
37
34
  s.add_development_dependency("kramdown")
35
+ s.add_development_dependency("racc")
36
+ s.add_development_dependency("rake")
37
+ s.add_development_dependency("red-datasets")
38
38
  s.add_development_dependency("test-unit")
39
- s.add_development_dependency("test-unit-notify")
40
39
  s.add_development_dependency("test-unit-rr")
40
+ s.add_development_dependency("yard")
41
41
  s.license = "Ruby or LGPLv3+"
42
42
  end
@@ -17,14 +17,18 @@ module GetText
17
17
  class LocalePath
18
18
  # The default locale paths.
19
19
  CONFIG_PREFIX = RbConfig::CONFIG['prefix'].gsub(/\/local/, "")
20
- DEFAULT_RULES = [
21
- "./locale/%{lang}/LC_MESSAGES/%{name}.mo",
22
- "./locale/%{lang}/%{name}.mo",
23
- "#{RbConfig::CONFIG['datadir']}/locale/%{lang}/LC_MESSAGES/%{name}.mo",
24
- "#{RbConfig::CONFIG['datadir'].gsub(/\/local/, "")}/locale/%{lang}/LC_MESSAGES/%{name}.mo",
25
- "#{CONFIG_PREFIX}/share/locale/%{lang}/LC_MESSAGES/%{name}.mo",
26
- "#{CONFIG_PREFIX}/local/share/locale/%{lang}/LC_MESSAGES/%{name}.mo"
27
- ].uniq
20
+ default_rules_candidates = [
21
+ "./locale/%{lang}/LC_MESSAGES/%{name}.mo",
22
+ "./locale/%{lang}/%{name}.mo",
23
+ ]
24
+ data_dir = RbConfig::CONFIG["datadir"]
25
+ if data_dir
26
+ default_rules_candidates << "#{data_dir}/locale/%{lang}/LC_MESSAGES/%{name}.mo"
27
+ default_rules_candidates << "#{data_dir.gsub(/\/local/, "")}/locale/%{lang}/LC_MESSAGES/%{name}.mo"
28
+ end
29
+ default_rules_candidates << "#{CONFIG_PREFIX}/share/locale/%{lang}/LC_MESSAGES/%{name}.mo"
30
+ default_rules_candidates << "#{CONFIG_PREFIX}/local/share/locale/%{lang}/LC_MESSAGES/%{name}.mo"
31
+ DEFAULT_RULES = default_rules_candidates.uniq
28
32
 
29
33
  class << self
30
34
  # Add default locale path. Usually you should use GetText.add_default_locale_path instead.
data/lib/gettext/mo.rb CHANGED
@@ -278,11 +278,13 @@ module GetText
278
278
 
279
279
  def load_from_file(filename)
280
280
  @filename = filename
281
- begin
282
- File.open(filename, 'rb'){|f| load_from_stream(f)}
283
- rescue => e
284
- e.set_backtrace("File: #{@filename}")
285
- raise e
281
+ File.open(filename, 'rb') do |f|
282
+ begin
283
+ load_from_stream(f)
284
+ rescue => e
285
+ e.set_backtrace(["#{filename}:#{f.lineno}"] + e.backtrace)
286
+ raise e
287
+ end
286
288
  end
287
289
  end
288
290
 
@@ -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