gettext 3.3.3 → 3.3.8

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 (122) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +4 -0
  3. data/doc/text/news.md +231 -0
  4. data/gettext.gemspec +1 -1
  5. data/lib/gettext/locale_path.rb +12 -8
  6. data/lib/gettext/mo.rb +7 -5
  7. data/lib/gettext/tools/msginit.rb +216 -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 +50 -29
  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/_/pipe.rb +32 -0
  94. data/test/fixtures/erb/minus.rhtml +12 -0
  95. data/test/fixtures/{gladeparser.glade → glade/2.glade} +0 -0
  96. data/test/fixtures/glade/3.glade +63 -0
  97. data/test/fixtures/gtk_builder_ui_definitions.ui~ +68 -0
  98. data/test/fixtures/multi_text_domain.rb +12 -12
  99. data/test/fixtures/np_.rb +1 -1
  100. data/test/fixtures/ns_.rb +1 -1
  101. data/test/fixtures/p_.rb +1 -1
  102. data/test/fixtures/ruby/percent_lower_i.rb +1 -0
  103. data/test/fixtures/ruby/percent_lower_w.rb +1 -0
  104. data/test/fixtures/ruby/percent_upper_i.rb +1 -0
  105. data/test/fixtures/ruby/percent_upper_w.rb +1 -0
  106. data/test/fixtures/s_.rb +1 -1
  107. data/test/fixtures/simple.rb +1 -1
  108. data/test/fixtures/upper_nn_.rb +77 -0
  109. data/test/po/_.pot +20 -4
  110. data/test/po/ja/_.edit.po +24 -0
  111. data/test/po/np_.pot +8 -5
  112. data/test/po/ns_.pot +6 -4
  113. data/test/po/p_.pot +3 -3
  114. data/test/po/s_.pot +6 -4
  115. data/test/run-test.rb +0 -1
  116. data/test/test_parser.rb +42 -17
  117. data/test/tools/parser/test_glade.rb +91 -0
  118. data/test/tools/parser/test_gtk_builder_ui_definitions.rb +19 -1
  119. data/test/tools/parser/test_ruby.rb +42 -0
  120. data/test/tools/test_msginit.rb +77 -3
  121. data/test/tools/test_msgmerge.rb +34 -0
  122. metadata +37 -28
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a2b035c2e33e7e5d59eb90ca4bc2ec5f002300cd597bb7170b265ee3dea1017b
4
- data.tar.gz: c964321d37fb3e9608527d08c96a3aef18791fc4ce41f9efdc950e49086cdf53
3
+ metadata.gz: 854c34e40028ef9e71045cbd1c8f77a4846c5f668de2cef716017b52d05515b2
4
+ data.tar.gz: bc0a5bcb8a1a30ed0b5de8272bae275a996f5ef5e6533a281997a67bf99f3f95
5
5
  SHA512:
6
- metadata.gz: ff63d36681ef49c5d9ae4478da15f671046b67422477f01a3f408c6a6ee653688354d1502c44f0923691b706fdf2ca8de0fa267715c31f85ac8cb4c531ac7c5f
7
- data.tar.gz: 41cc509f2ab0502e3220ca39e37c201a056cbf372aca206fc3f3eb240b49308388c64f09b80aa26397f5cd92d35f750a09cd5f279ca7cd887bea134e119f0514
6
+ metadata.gz: 6978df6c5a2e52c5eb9b1101bb89fd2ec3febec663bf1418b054929572a333935cd02cfba15b93818ae3b89971b2fb442b2f8f48c0370fd516bacd7085eac915
7
+ data.tar.gz: a7fbb7a6b3e93a374440ad2ae3c69f43aeb238c54479825c45e8b14f5f90408fa05b2c06db05078af531defecc7b181bda30e0a2e53068718422ba66bbd7ae94
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,82 @@
1
1
  # News
2
2
 
3
+ ## 3.3.8: 2021-06-09 {#version-3-3-8}
4
+
5
+ ### Improvements
6
+
7
+ * msginit: Added support for generating plural forms with
8
+ Unicode's CLDR plural rules data.
9
+ [GitHub#85][Suggested by Michaël Hoste]
10
+
11
+ * rxgettext ui: Added support for GtkBuilder UI definitions format
12
+ with `.glade` extension.
13
+ [GitHub#74][Reported by dorle-o]
14
+
15
+ ### Fixes
16
+
17
+ * rxgettext ruby: Fixed a bug that `Nn_` isn't extracted.
18
+ [GitHub#86][Reported by Kai Ramuenke]
19
+
20
+ ### Thanks
21
+
22
+ * Kai Ramuenke
23
+
24
+ * Michaël Hoste
25
+
26
+ * dorle-o
27
+
28
+ ## 3.3.7: 2021-01-18 {#version-3-3-7}
29
+
30
+ ### Improvements
31
+
32
+ * msgmerge: Added `--no-report-warning` option.
33
+ [GitHub#81][Reported by Akim Demaille]
34
+
35
+ ### Thanks
36
+
37
+ * Akim Demaille
38
+
39
+ ## 3.3.6: 2020-08-04 {#version-3-3-6}
40
+
41
+ ### Improvements
42
+
43
+ * erb: Added support for `-%>`.
44
+ [GitHub#77][Reported by lremes]
45
+
46
+ * Removed ChangeLog.
47
+ [GitHub#76][Reported by Will Stephenson]
48
+
49
+ * Don't assume `RbConfig::CONFIG["datadir"]` is available. For
50
+ example, TruffleRuby doesn't provide it.
51
+
52
+ ### Thanks
53
+
54
+ * lremes
55
+
56
+ * Will Stephenson
57
+
58
+ ## 3.3.5: 2020-02-15 {#version-3-3-5}
59
+
60
+ ### Improvements
61
+
62
+ * Added support for `|` method.
63
+ [GitHub#73][Reported by dorle-o]
64
+
65
+ ### Thanks
66
+
67
+ * dorle-o
68
+
69
+ ## 3.3.4: 2020-02-12 {#version-3-3-4}
70
+
71
+ ### Improvements
72
+
73
+ * Added support for `%W`.
74
+ [GitHub#72][Reported by Michaël Hoste]
75
+
76
+ ### Thanks
77
+
78
+ * Michaël Hoste
79
+
3
80
  ## 3.3.3: 2020-02-05 {#version-3-3-3}
4
81
 
5
82
  ### Improvements
@@ -828,3 +905,157 @@ Ruby 1.9 support release.
828
905
  * Gunnar Wolf
829
906
  * Ivan Pirlik
830
907
  * Tatsuki Sugiura
908
+
909
+ ## 2.2.1: 2012-05-20
910
+
911
+ ### Changes
912
+
913
+ * Supported non ASCII string in msgid. [GitHub#1]
914
+ [Patch by Urban Hafner]
915
+ * Stopped overriding String#% on Ruby 1.9.
916
+ * Fixed a bug that "\" is too escaped.
917
+ * Removed GetText.bindtext dependency from GetText::PoParser.
918
+ * Ranamed GetText::MOFile to GetText::MoFile but GetText::MOFile
919
+ is still available.
920
+
921
+ ### Thanks
922
+
923
+ * Urban Hafner
924
+
925
+ ## 2.2.0: 2012-03-11
926
+
927
+ ### Changes
928
+
929
+ * Supported ruby-1.9. [Patch by hallelujah]
930
+ * Supported $SAFE=1. [Patch by bon]
931
+ * Improved argument check. [Suggested by Morus Walter]
932
+ * Supported ruby-1.8.6 again. [Bug#27447] [Reported by Mamoru Tasaka]
933
+ * Fixed Ukrainan translation path. [Bug#28277] [Reported by Gunnar Wolf]
934
+ * Fixed a bug that only the last path in GETTEXT_PATH environment
935
+ variable is used. [Bug#28345] [Reported by Ivan Pirlik]
936
+ * Fixed a bug that Ruby-GetText-Package modifies $LOAD_PATH. [Bug#28094]
937
+ [Reported by Tatsuki Sugiura]
938
+
939
+ ### Thanks
940
+
941
+ * hallelujah
942
+ * bon
943
+ * Morus Walter
944
+ * Mamoru Tasaka
945
+ * Gunnar Wolf
946
+ * Ivan Pirlik
947
+ * Tatsuki Sugiura
948
+
949
+
950
+ ## 2.1.0: 2009-11-14
951
+
952
+ ### Changes
953
+
954
+ * Implemented parsing of translator comments (GNU gettext feature)
955
+ [by Vladimir Dobriakov]
956
+ * Refactor the directory structure.
957
+ * Move files for runtime to lib/gettext/runtime/*.
958
+ * Move files for development(rgettext/rmsgfmt) to
959
+ lib/gettext/tools/*.
960
+ * Refactor parsers for po. po-message object is defined as GetText::PoMessage
961
+ class. [by Vladimir Dobriakov, Masao Mutoh]
962
+ * Speed up when lots of objects are created to share the textdomain in each
963
+ objects. [Reported by Gaël Séchaud.]
964
+ * Fix "%{foo.bar}" %{"foo.bar".to_sym => "a"} doesn't work.
965
+ [Bug#26663, Reported by Danilo Castilho]
966
+ * lib/gettext.rb: Fixed to work unless gem. [Reported by Vladimir Dobriakov]
967
+ * Fixed a wrong String literal in a CGI sample.
968
+ [Bug #26531, by Eugene Mikhailov]
969
+ * Update license information(explicit to use ruby's or LGPL).
970
+ [Pointed out by Masateru Yoshikawa]
971
+ * Code cleanup.
972
+ * Update minor version.
973
+
974
+ ## 2.0.4: 2009-05-23
975
+
976
+ ### Changes
977
+
978
+ * Fix String#% return nil when the string have no place holders. [by okkez]
979
+ * Update pofiles and remove old messages.
980
+ * suppress some warnings on Ruby 1.9.x. [by Nobuhiro IMAI]
981
+ * Fix not to run tests on Win32.
982
+
983
+ ## 2.0.3: 2009-05-09
984
+
985
+ ### Changes
986
+
987
+ * Fixed the dependencies. [Reported by Hans de Graaff]
988
+
989
+ ## 2.0.2: 2009-05-04
990
+
991
+ ### Changes
992
+
993
+ * Support ruby-1.9.1 style format string such as `%<foo>d`.
994
+ * Apply new `Locale.set_app_language_tags` and Locale.candidates.
995
+ [Suggested by Vladimir Dobriakov]
996
+ * Enhance to support ruby-1.9.x [by OZAWA Sakuro]
997
+ * poparser work with proper encoding.
998
+ * string.rb: #bytesize alias to #size in older ruby version such as 1.8.5.
999
+ * Fixed bugs
1000
+ * `n_()` to work when Plural-Forms line in po-file is not correct.
1001
+ [Reported by Sava Chankov (Bug#25570)]
1002
+ * GetText::Locale.default_rules_path : $LOAD_PATH is not well parsed.
1003
+ [by hallelujah]
1004
+ * locale_path.rb: Fixed warning message.
1005
+
1006
+ ### Thanks
1007
+
1008
+ * hallelujah
1009
+ * Sava Chankov
1010
+ * OZAWA Sakuro
1011
+ * Vladimir Dobriakov
1012
+
1013
+ ## 2.0.1: 2009-04-17
1014
+
1015
+ ### Changes
1016
+
1017
+ * Fixed bugs
1018
+ * doesn't work with ruby-1.8.5. [Reported by Dan Coutu]
1019
+ * GetText.locale= can't keep the locale. [Reported by Adam Ilan]
1020
+ * Break backward compatibility of bindtextdomain
1021
+ [Reported by Mamoru Tasaka(#24947), Mathieu Blondel]
1022
+ * Other trivial fixes/improvement.
1023
+ * 1.8 times faster than 2.0.0.
1024
+ * GetText::LocalePath is separated from GetText::TextDomainManager.
1025
+ Improve to find the locale path.
1026
+ * Enhance to support ruby-1.9.x [by OZAWA Sakuro]
1027
+
1028
+ ### Thanks
1029
+
1030
+ * OZAWA Sakuro
1031
+ * Tietew
1032
+ * Adam Ilan
1033
+ * Mamoru Tasaka
1034
+ * Mathieu Blondel
1035
+
1036
+ ## 2.0.0: 2009-03-21
1037
+
1038
+ ### Changes
1039
+
1040
+ * Separate this library to locale and rails-support to locale,
1041
+ locale\_rails, gettext\_activerecord, gettext\_rails.
1042
+ * Depends on locale(ruby-locale).
1043
+ * Removes to support rails.
1044
+ * A lot of referctoring, improvements.
1045
+ * Thread safe.
1046
+ * New APIs for gettext/tools instead of gettext/utils.
1047
+ * Move to github.com.
1048
+
1049
+ ### Special thanks
1050
+
1051
+ * Michael Grosser: A lot of improvement.
1052
+
1053
+ ### Thanks
1054
+
1055
+ * Tietew
1056
+ * Kazuhiro NISHIYAMA
1057
+ * Fabio M.A.
1058
+ * Tuptus
1059
+ * Morus Walter
1060
+ * Vladimir Dobriakov
1061
+ * Ramsey
data/gettext.gemspec CHANGED
@@ -30,13 +30,13 @@ So you can use GNU gettext tools for maintaining.
30
30
  s.required_ruby_version = ">= 2.5.0"
31
31
 
32
32
  s.add_runtime_dependency("locale", ">= 2.0.5")
33
+ s.add_runtime_dependency("red-datasets")
33
34
  s.add_runtime_dependency("text", ">= 1.3.0")
34
35
  s.add_development_dependency("rake")
35
36
  s.add_development_dependency("racc")
36
37
  s.add_development_dependency("yard")
37
38
  s.add_development_dependency("kramdown")
38
39
  s.add_development_dependency("test-unit")
39
- s.add_development_dependency("test-unit-notify")
40
40
  s.add_development_dependency("test-unit-rr")
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,14 @@
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
+ require "datasets"
25
+ require "locale/info"
26
+
22
27
  require "gettext"
23
28
  require "gettext/po_parser"
24
29
  require "gettext/tools/msgmerge"
25
- require "locale/info"
26
- require "optparse"
27
30
 
28
31
  module GetText
29
32
  module Tools
@@ -320,53 +323,8 @@ module GetText
320
323
  end
321
324
 
322
325
  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};"
326
+ converter = CLDRPluralsConverter.new(language)
327
+ converter.convert
370
328
  end
371
329
 
372
330
  DESCRIPTION_TITLE = /^SOME DESCRIPTIVE TITLE\.$/
@@ -408,6 +366,214 @@ module GetText
408
366
  def year
409
367
  now.year
410
368
  end
369
+
370
+ class CLDRPluralsConverter
371
+ def initialize(language)
372
+ @language = language
373
+
374
+ end
375
+
376
+ def convert
377
+ n_plurals = nil
378
+ expression = nil
379
+ plurals = Datasets::CLDRPlurals.new
380
+ plurals.each do |locale|
381
+ next unless locale.name == @language
382
+ n_plurals, expression = convert_plural_rules(locale.rules)
383
+ break
384
+ end
385
+ "nplurals=#{n_plurals}; plural=#{expression};"
386
+ end
387
+
388
+ private
389
+ def convert_plural_rules(rules)
390
+ n_plurals = 1
391
+ conditions = []
392
+ order = [
393
+ "one",
394
+ "zero",
395
+ "two",
396
+ "few",
397
+ "many",
398
+ "other",
399
+ ]
400
+ rules = rules.reject do |rule|
401
+ rule.integer_samples.nil?
402
+ end
403
+ rules = rules.sort_by do |rule|
404
+ order.index(rule.count)
405
+ end
406
+ rules[0..-2].each do |rule|
407
+ next if rule.condition.nil?
408
+ condition = convert_plural_condition(rule.condition)
409
+ next if condition.nil?
410
+ next if condition == false
411
+ n_plurals += 1
412
+ conditions << condition
413
+ end
414
+ expression = ""
415
+ case conditions.size
416
+ when 0
417
+ expression << "0"
418
+ when 1
419
+ condition = conditions[0]
420
+ case condition
421
+ when "(n == 1)"
422
+ expression << "n != 1"
423
+ when "(n <= 1)"
424
+ expression << "n > 1"
425
+ else
426
+ expression << "#{condition} ? 1 : 0"
427
+ end
428
+ else
429
+ (conditions.size + 1).times do |i|
430
+ if i == conditions.size
431
+ expression << i.to_s
432
+ else
433
+ condition = conditions[i]
434
+ expression << "#{condition} ? #{i} : "
435
+ end
436
+ end
437
+ end
438
+ [n_plurals, expression]
439
+ end
440
+
441
+ def convert_plural_condition(condition)
442
+ case condition[0]
443
+ when :and
444
+ gettext_condition = nil
445
+ condition[1..-1].each do |sub_condition|
446
+ sub_gettext_condition = convert_plural_condition(sub_condition)
447
+ case sub_gettext_condition
448
+ when String
449
+ if gettext_condition.is_a?(String)
450
+ gettext_condition << " && #{sub_gettext_condition}"
451
+ else
452
+ gettext_condition = sub_gettext_condition
453
+ end
454
+ when TrueClass
455
+ unless gettext_condition.is_a?(String)
456
+ gettext_condition = true
457
+ end
458
+ when FalseClass
459
+ return false
460
+ else
461
+ raise "unknown value #{sub_gettext_condition.inspect}"
462
+ end
463
+ end
464
+ gettext_condition
465
+ when :or
466
+ gettext_condition = false
467
+ condition[1..-1].each do |sub_condition|
468
+ sub_gettext_condition = convert_plural_condition(sub_condition)
469
+ case sub_gettext_condition
470
+ when String
471
+ if gettext_condition.is_a?(String)
472
+ gettext_condition << " || #{sub_gettext_condition}"
473
+ else
474
+ gettext_condition = sub_gettext_condition
475
+ end
476
+ when TrueClass
477
+ return true
478
+ when FalseClass
479
+ else
480
+ raise "unknown value #{sub_gettext_condition.inspect}"
481
+ end
482
+ end
483
+ gettext_condition
484
+ when :equal
485
+ left = convert_plural_condition(condition[1])
486
+ right = condition[2]
487
+ case left
488
+ when String
489
+ right = compact_equal_values(right)
490
+ gettext_conditions = right.collect do |right_value|
491
+ case right_value
492
+ when Range
493
+ if right_value.begin.zero?
494
+ "(#{left} <= #{right_value.end})"
495
+ else
496
+ "(#{left} >= #{right_value.begin} && " +
497
+ "#{left} <= #{right_value.end})"
498
+ end
499
+ else
500
+ "(#{left} == #{right_value})"
501
+ end
502
+ end
503
+ if gettext_conditions.size == 1
504
+ gettext_conditions[0]
505
+ else
506
+ gettext_conditions.join(" || ")
507
+ end
508
+ when 0
509
+ if right.include?(0)
510
+ true
511
+ else
512
+ false
513
+ end
514
+ else
515
+ false
516
+ end
517
+ when :not_equal
518
+ left = convert_plural_condition(condition[1])
519
+ right = condition[2]
520
+ case left
521
+ when String
522
+ right = compact_equal_values(right)
523
+ gettext_conditions = right.collect do |right_value|
524
+ case right_value
525
+ when Range
526
+ "(#{left} < #{right_value.begin} || " +
527
+ "#{left} > #{right_value.end})"
528
+ else
529
+ "(#{left} != #{right_value})"
530
+ end
531
+ end
532
+ if gettext_conditions.size == 1
533
+ gettext_conditions[0]
534
+ else
535
+ gettext_conditions = gettext_conditions.collect do |gettext_condition|
536
+ "(#{gettext_condition})"
537
+ end
538
+ gettext_conditions.join(" && ")
539
+ end
540
+ when 0
541
+ if right.include?(0)
542
+ false
543
+ else
544
+ true
545
+ end
546
+ else
547
+ false
548
+ end
549
+ when :mod
550
+ left = convert_plural_condition(condition[1])
551
+ right = condition[2]
552
+ case left
553
+ when "n"
554
+ "(n % #{right})"
555
+ else
556
+ false
557
+ end
558
+ when "n", "i"
559
+ "n"
560
+ when "v", "w"
561
+ 0
562
+ when "f", "t", "c", "e"
563
+ false
564
+ else
565
+ raise "unknown operator: #{condition[0].inspect}"
566
+ end
567
+ end
568
+
569
+ def compact_equal_values(values)
570
+ if values == [0, 1]
571
+ [0..1]
572
+ else
573
+ values
574
+ end
575
+ end
576
+ end
411
577
  end
412
578
  end
413
579
  end