num2words 0.1.6 → 0.3.0

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 (111) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +65 -0
  3. data/README.md +145 -135
  4. data/bin/console +2 -14
  5. data/config/locales/ar.yml +5 -1
  6. data/config/locales/be.yml +4 -0
  7. data/config/locales/bg.yml +4 -0
  8. data/config/locales/bn.yml +4 -0
  9. data/config/locales/cs.yml +6 -2
  10. data/config/locales/da.yml +4 -0
  11. data/config/locales/de.yml +8 -4
  12. data/config/locales/el.yml +4 -0
  13. data/config/locales/en.yml +4 -0
  14. data/config/locales/es.yml +4 -0
  15. data/config/locales/et.yml +9 -5
  16. data/config/locales/fa.yml +15 -11
  17. data/config/locales/fi.yml +8 -4
  18. data/config/locales/fr.yml +4 -0
  19. data/config/locales/gu.yml +4 -0
  20. data/config/locales/he.yml +6 -2
  21. data/config/locales/hi.yml +4 -0
  22. data/config/locales/hr.yml +8 -4
  23. data/config/locales/hu.yml +6 -2
  24. data/config/locales/id.yml +4 -0
  25. data/config/locales/it.yml +4 -0
  26. data/config/locales/ja.yml +10 -5
  27. data/config/locales/kn.yml +186 -10
  28. data/config/locales/ko.yml +184 -13
  29. data/config/locales/kz.yml +183 -17
  30. data/config/locales/lt.yml +184 -8
  31. data/config/locales/lv.yml +188 -12
  32. data/config/locales/ml.yml +189 -13
  33. data/config/locales/mr.yml +184 -8
  34. data/config/locales/ms.yml +184 -8
  35. data/config/locales/nb.yml +183 -17
  36. data/config/locales/nl.yml +184 -13
  37. data/config/locales/pa.yml +189 -13
  38. data/config/locales/pl.yml +184 -13
  39. data/config/locales/pt.yml +184 -13
  40. data/config/locales/ro.yml +183 -12
  41. data/config/locales/ru.yml +8 -0
  42. data/config/locales/sk.yml +184 -8
  43. data/config/locales/sl.yml +185 -9
  44. data/config/locales/sr.yml +186 -15
  45. data/config/locales/sv.yml +182 -13
  46. data/config/locales/sw.yml +184 -8
  47. data/config/locales/ta.yml +184 -8
  48. data/config/locales/te.yml +185 -9
  49. data/config/locales/th.yml +183 -12
  50. data/config/locales/tr.yml +183 -12
  51. data/config/locales/uk.yml +189 -18
  52. data/config/locales/ur.yml +187 -11
  53. data/config/locales/vi.yml +183 -12
  54. data/config/locales/zh.yml +191 -9
  55. data/exe/num2words-console +7 -0
  56. data/lib/num2words/console.rb +16 -0
  57. data/lib/num2words/converter.rb +195 -47
  58. data/lib/num2words/locales/ar.rb +130 -0
  59. data/lib/num2words/locales/be.rb +101 -0
  60. data/lib/num2words/locales/bg.rb +127 -0
  61. data/lib/num2words/locales/bn.rb +112 -0
  62. data/lib/num2words/locales/cs.rb +106 -0
  63. data/lib/num2words/locales/da.rb +97 -0
  64. data/lib/num2words/locales/de.rb +119 -0
  65. data/lib/num2words/locales/el.rb +143 -0
  66. data/lib/num2words/locales/en.rb +90 -0
  67. data/lib/num2words/locales/es.rb +185 -0
  68. data/lib/num2words/locales/et.rb +104 -0
  69. data/lib/num2words/locales/fa.rb +104 -0
  70. data/lib/num2words/locales/fi.rb +104 -0
  71. data/lib/num2words/locales/fr.rb +121 -0
  72. data/lib/num2words/locales/gu.rb +112 -0
  73. data/lib/num2words/locales/he.rb +130 -0
  74. data/lib/num2words/locales/hi.rb +112 -0
  75. data/lib/num2words/locales/hr.rb +117 -0
  76. data/lib/num2words/locales/hu.rb +111 -0
  77. data/lib/num2words/locales/id.rb +104 -0
  78. data/lib/num2words/locales/it.rb +142 -0
  79. data/lib/num2words/locales/ja.rb +126 -0
  80. data/lib/num2words/locales/kn.rb +122 -2
  81. data/lib/num2words/locales/ko.rb +158 -2
  82. data/lib/num2words/locales/kz.rb +137 -2
  83. data/lib/num2words/locales/lt.rb +146 -2
  84. data/lib/num2words/locales/lv.rb +148 -2
  85. data/lib/num2words/locales/ml.rb +142 -2
  86. data/lib/num2words/locales/mr.rb +142 -2
  87. data/lib/num2words/locales/ms.rb +134 -2
  88. data/lib/num2words/locales/nb.rb +153 -0
  89. data/lib/num2words/locales/nl.rb +142 -2
  90. data/lib/num2words/locales/pa.rb +122 -2
  91. data/lib/num2words/locales/pl.rb +149 -2
  92. data/lib/num2words/locales/pt.rb +164 -2
  93. data/lib/num2words/locales/ro.rb +165 -2
  94. data/lib/num2words/locales/ru.rb +100 -0
  95. data/lib/num2words/locales/sk.rb +124 -2
  96. data/lib/num2words/locales/sl.rb +154 -2
  97. data/lib/num2words/locales/sr.rb +141 -3
  98. data/lib/num2words/locales/sv.rb +141 -2
  99. data/lib/num2words/locales/sw.rb +133 -2
  100. data/lib/num2words/locales/ta.rb +142 -2
  101. data/lib/num2words/locales/te.rb +142 -2
  102. data/lib/num2words/locales/th.rb +133 -2
  103. data/lib/num2words/locales/tr.rb +141 -2
  104. data/lib/num2words/locales/uk.rb +134 -2
  105. data/lib/num2words/locales/ur.rb +130 -2
  106. data/lib/num2words/locales/vi.rb +142 -2
  107. data/lib/num2words/locales/zh.rb +172 -2
  108. data/lib/num2words/version.rb +1 -1
  109. data/num2words.gemspec +3 -3
  110. metadata +13 -10
  111. data/lib/num2words/locales/no.rb +0 -19
@@ -10,8 +10,128 @@ module Num2words
10
10
  HUNDREDS = I18n.t("num2words.hundreds", locale: :kn)
11
11
  SCALES = I18n.t("num2words.scales", locale: :kn)
12
12
 
13
- MAJOR_UNIT = I18n.t("num2words.currencies.INR.name", locale: :kn)
14
- MINOR_UNIT = I18n.t("num2words.currencies.INR.fractional.name", locale: :kn)
13
+ FRACTIONS = I18n.t("num2words.fractions", locale: :kn)
14
+ GRAMMAR = I18n.t("num2words.grammar", locale: :kn)
15
+
16
+ DATE = I18n.t("num2words.date", locale: :kn)
17
+ DATE_TEMPLATE = I18n.t("num2words.date.template", locale: :kn)
18
+ TIME = I18n.t("num2words.time", locale: :kn)
19
+ TIME_TEMPLATE = I18n.t("num2words.time.template", locale: :kn)
20
+ DATETIME_TEMPLATE = I18n.t("num2words.datetime.template", locale: :kn)
21
+
22
+ ORDINALS = I18n.t("num2words.numbers.ordinals", locale: :kn)
23
+
24
+ UNDER_HUNDRED = [
25
+ "ಸೊನ್ನೆ", "ಒಂದು", "ಎರಡು", "ಮೂರು", "ನಾಲ್ಕು", "ಐದು", "ಆರು", "ಏಳು", "ಎಂಟು", "ಒಂಬತ್ತು",
26
+ "ಹತ್ತು", "ಹನ್ನೊಂದು", "ಹನ್ನೆರಡು", "ಹದಿಮೂರು", "ಹದಿನಾಲ್ಕು", "ಹದಿನೈದು", "ಹದಿನಾರು", "ಹದಿನೇಳು", "ಹದಿನೆಂಟು", "ಹತ್ತೊಂಬತ್ತು",
27
+ "ಇಪ್ಪತ್ತು", "ಇಪ್ಪತ್ತೊಂದು", "ಇಪ್ಪತ್ತೆರಡು", "ಇಪ್ಪತ್ತಮೂರು", "ಇಪ್ಪತ್ತನಾಲ್ಕು", "ಇಪ್ಪತ್ತೈದು", "ಇಪ್ಪತ್ತಾರು", "ಇಪ್ಪತ್ತೇಳು", "ಇಪ್ಪತ್ತೆಂಟು", "ಇಪ್ಪತ್ತೊಂಬತ್ತು",
28
+ "ಮೂವತ್ತು", "ಮೂವತ್ತೊಂದು", "ಮೂವತ್ತೆರಡು", "ಮೂವತ್ತಮೂರು", "ಮೂವತ್ತನಾಲ್ಕು", "ಮೂವತ್ತೈದು", "ಮೂವತ್ತಾರು", "ಮೂವತ್ತೇಳು", "ಮೂವತ್ತೆಂಟು", "ಮೂವತ್ತೊಂಬತ್ತು",
29
+ "ನಲವತ್ತು", "ನಲವತ್ತೊಂದು", "ನಲವತ್ತೆರಡು", "ನಲವತ್ತಮೂರು", "ನಲವತ್ತನಾಲ್ಕು", "ನಲವತ್ತೈದು", "ನಲವತ್ತಾರು", "ನಲವತ್ತೇಳು", "ನಲವತ್ತೆಂಟು", "ನಲವತ್ತೊಂಬತ್ತು",
30
+ "ಐವತ್ತು", "ಐವತ್ತೊಂದು", "ಐವತ್ತೆರಡು", "ಐವತ್ತಮೂರು", "ಐವತ್ತನಾಲ್ಕು", "ಐವತ್ತೈದು", "ಐವತ್ತಾರು", "ಐವತ್ತೇಳು", "ಐವತ್ತೆಂಟು", "ಐವತ್ತೊಂಬತ್ತು",
31
+ "ಅರವತ್ತು", "ಅರವತ್ತೊಂದು", "ಅರವತ್ತೆರಡು", "ಅರವತ್ತಮೂರು", "ಅರವತ್ತನಾಲ್ಕು", "ಅರವತ್ತೈದು", "ಅರವತ್ತಾರು", "ಅರವತ್ತೇಳು", "ಅರವತ್ತೆಂಟು", "ಅರವತ್ತೊಂಬತ್ತು",
32
+ "ಎಪ್ಪತ್ತು", "ಎಪ್ಪತ್ತೊಂದು", "ಎಪ್ಪತ್ತೆರಡು", "ಎಪ್ಪತ್ತಮೂರು", "ಎಪ್ಪತ್ತನಾಲ್ಕು", "ಎಪ್ಪತ್ತೈದು", "ಎಪ್ಪತ್ತಾರು", "ಎಪ್ಪತ್ತೇಳು", "ಎಪ್ಪತ್ತೆಂಟು", "ಎಪ್ಪತ್ತೊಂಬತ್ತು",
33
+ "ಎಂಬತ್ತು", "ಎಂಬತ್ತೊಂದು", "ಎಂಬತ್ತೆರಡು", "ಎಂಬತ್ತಮೂರು", "ಎಂಬತ್ತನಾಲ್ಕು", "ಎಂಬತ್ತೈದು", "ಎಂಬತ್ತಾರು", "ಎಂಬತ್ತೇಳು", "ಎಂಬತ್ತೆಂಟು", "ಎಂಬತ್ತೊಂಬತ್ತು",
34
+ "ತೊಂಬತ್ತು", "ತೊಂಬತ್ತೊಂದು", "ತೊಂಬತ್ತೆರಡು", "ತೊಂಬತ್ತಮೂರು", "ತೊಂಬತ್ತನಾಲ್ಕು", "ತೊಂಬತ್ತೈದು", "ತೊಂಬತ್ತಾರು", "ತೊಂಬತ್ತೇಳು", "ತೊಂಬತ್ತೆಂಟು", "ತೊಂಬತ್ತೊಂಬತ್ತು"
35
+ ].freeze
36
+
37
+ INDIAN_SCALES = [
38
+ [1_000_000_000, "ಅರಬ್"],
39
+ [10_000_000, "ಕೋಟಿ"],
40
+ [100_000, "ಲಕ್ಷ"],
41
+ [1_000, "ಸಾವಿರ"]
42
+ ].freeze
43
+
44
+ module_function
45
+
46
+ def integer_to_words(number, feminine: false)
47
+ cardinal(number)
48
+ end
49
+
50
+ def triple_to_words(number, scale_idx, feminine: false)
51
+ return [] if number.zero?
52
+
53
+ words = [under_thousand(number)]
54
+ words << SCALES[scale_idx][0] unless scale_idx.zero?
55
+ words
56
+ end
57
+
58
+ def minus_word
59
+ GRAMMAR[:minus]
60
+ end
61
+
62
+ def fraction_joiner(joiner)
63
+ joiner.to_sym == :and ? "ಮತ್ತು" : GRAMMAR[:conjunction]
64
+ end
65
+
66
+ def default_fraction_word
67
+ GRAMMAR[:default_fraction]
68
+ end
69
+
70
+ def fraction_numerator_feminine?
71
+ false
72
+ end
73
+
74
+ def decimal_separator_word
75
+ "ದಶಮಾಂಶ"
76
+ end
77
+
78
+ def decimal_fraction_words(fraction_string)
79
+ fraction_string.chars.map { |digit| cardinal(digit.to_i) }.join(" ")
80
+ end
81
+
82
+ def date_day(day, format:, date_case:)
83
+ ordinal(day, :default)
84
+ end
85
+
86
+ def date_year(year, format:)
87
+ cardinal(year)
88
+ end
89
+
90
+ def ordinal(value, format, gender: :masculine)
91
+ ordinals = ORDINALS[format] || ORDINALS[:default] || ORDINALS[:nominative]
92
+ gender_data = ordinals[gender] || ordinals[:masculine]
93
+
94
+ return gender_data[value - 1] if value.between?(1, gender_data.length)
95
+
96
+ cardinal(value)
97
+ end
98
+
99
+ def cardinal(number)
100
+ integer_value = Integer(number)
101
+ negative = integer_value.negative?
102
+ integer_value = integer_value.abs
103
+
104
+ return UNDER_HUNDRED[0] if integer_value.zero?
105
+
106
+ remainder = integer_value
107
+ words = []
108
+
109
+ INDIAN_SCALES.each do |value, label|
110
+ next if remainder < value
111
+
112
+ group_value = remainder / value
113
+ remainder %= value
114
+ words << [cardinal(group_value), label].join(" ")
115
+ end
116
+
117
+ words << under_thousand(remainder) if remainder.positive?
118
+ words.unshift(minus_word) if negative
119
+ words.join(" ")
120
+ end
121
+
122
+ def under_thousand(number)
123
+ return UNDER_HUNDRED[number] if number < 100
124
+
125
+ hundreds = number / 100
126
+ rest = number % 100
127
+ words = [HUNDREDS[hundreds]]
128
+ words << UNDER_HUNDRED[rest] if rest.positive?
129
+ words.join(" ")
130
+ end
131
+
132
+ def pluralize(number, singular, few, _plural)
133
+ number.abs == 1 ? singular : few
134
+ end
15
135
  end
16
136
 
17
137
  register :kn, KN
@@ -10,8 +10,164 @@ module Num2words
10
10
  HUNDREDS = I18n.t("num2words.hundreds", locale: :ko)
11
11
  SCALES = I18n.t("num2words.scales", locale: :ko)
12
12
 
13
- MAJOR_UNIT = I18n.t("num2words.currencies.KRW.name", locale: :ko)
14
- MINOR_UNIT = I18n.t("num2words.currencies.KRW.fractional.name", locale: :ko)
13
+ FRACTIONS = I18n.t("num2words.fractions", locale: :ko)
14
+ GRAMMAR = I18n.t("num2words.grammar", locale: :ko)
15
+
16
+ DATE = I18n.t("num2words.date", locale: :ko)
17
+ DATE_TEMPLATE = I18n.t("num2words.date.template", locale: :ko)
18
+ TIME = I18n.t("num2words.time", locale: :ko)
19
+ TIME_TEMPLATE = I18n.t("num2words.time.template", locale: :ko)
20
+ DATETIME_TEMPLATE = I18n.t("num2words.datetime.template", locale: :ko)
21
+
22
+ ORDINALS = I18n.t("num2words.numbers.ordinals", locale: :ko)
23
+
24
+ LARGE_SCALES = ["", "만", "억", "조", "경"].freeze
25
+
26
+ module_function
27
+
28
+ def integer_to_words(number, feminine: false)
29
+ cardinal(number)
30
+ end
31
+
32
+ def triple_to_words(number, scale_idx, feminine: false)
33
+ return [] if number.zero?
34
+
35
+ words = under_ten_thousand(number)
36
+ scale = LARGE_SCALES[scale_idx].to_s
37
+ ["#{words}#{scale}"]
38
+ end
39
+
40
+ def minus_word
41
+ GRAMMAR[:minus]
42
+ end
43
+
44
+ def fraction_joiner(joiner)
45
+ joiner.to_sym == :and ? "와" : GRAMMAR[:conjunction]
46
+ end
47
+
48
+ def default_fraction_word
49
+ GRAMMAR[:default_fraction]
50
+ end
51
+
52
+ def fraction_numerator_feminine?
53
+ false
54
+ end
55
+
56
+ def decimal_separator_word
57
+ "점"
58
+ end
59
+
60
+ def decimal_fraction_words(fraction_string)
61
+ fraction_string.chars.map { |digit| cardinal(digit.to_i) }.join(" ")
62
+ end
63
+
64
+ def join_fraction_words(words)
65
+ sign_word, integer_words, conjunction_word, numerator_words, denominator_words = words
66
+ [sign_word, integer_words, conjunction_word, denominator_words, numerator_words].compact.reject(&:empty?).join(" ")
67
+ end
68
+
69
+ def date_day(day, format:, date_case:)
70
+ cardinal(day)
71
+ end
72
+
73
+ def date_year(year, format:)
74
+ cardinal(year)
75
+ end
76
+
77
+ def time_unit_feminine?(_unit)
78
+ false
79
+ end
80
+
81
+ def time_number_words(number, unit:)
82
+ cardinal(number)
83
+ end
84
+
85
+ def join_time_words(number_words, unit_words)
86
+ "#{number_words} #{unit_words}"
87
+ end
88
+
89
+ def currency_major_feminine?(_currency)
90
+ false
91
+ end
92
+
93
+ def currency_minor_feminine?(_currency)
94
+ false
95
+ end
96
+
97
+ def currency_number_words(number, _currency, unit:)
98
+ cardinal(number)
99
+ end
100
+
101
+ def join_currency_parts(parts)
102
+ parts.join(" ").strip
103
+ end
104
+
105
+ def ordinal(value, format, gender: :masculine)
106
+ ordinals = ORDINALS[format] || ORDINALS[:default] || ORDINALS[:nominative]
107
+ gender_data = ordinals[gender] || ordinals[:masculine]
108
+
109
+ return gender_data[value - 1] if value.between?(1, gender_data.length)
110
+
111
+ cardinal(value)
112
+ end
113
+
114
+ def cardinal(number)
115
+ integer_value = Integer(number)
116
+ negative = integer_value.negative?
117
+ integer_value = integer_value.abs
118
+
119
+ return ONES_MASC[0] if integer_value.zero?
120
+
121
+ groups = integer_value.to_s
122
+ .chars.reverse.each_slice(4).map(&:reverse)
123
+ .map(&:join).map!(&:to_i).reverse
124
+
125
+ words = groups.each_with_index.filter_map do |group_value, index|
126
+ next if group_value.zero?
127
+
128
+ scale_index = groups.size - index - 1
129
+ scale = LARGE_SCALES.fetch(scale_index, "")
130
+ group_words = under_ten_thousand(group_value)
131
+ scale.empty? ? group_words : "#{group_words}#{scale}"
132
+ end
133
+
134
+ words.unshift(minus_word) if negative
135
+ words.join(" ")
136
+ end
137
+
138
+ def under_ten_thousand(number)
139
+ thousands = number / 1000
140
+ remainder = number % 1000
141
+ hundreds = remainder / 100
142
+ rest = remainder % 100
143
+
144
+ [
145
+ unit_with_scale(thousands, "천"),
146
+ unit_with_scale(hundreds, "백"),
147
+ under_hundred(rest)
148
+ ].compact.reject(&:empty?).join
149
+ end
150
+
151
+ def under_hundred(number)
152
+ return "" if number.zero?
153
+ return TEENS[number - 10] if number.between?(10, 19)
154
+ return ONES_MASC[number] if number < 10
155
+
156
+ tens = number / 10
157
+ ones = number % 10
158
+ [TENS[tens], ones.positive? ? ONES_MASC[ones] : nil].compact.reject(&:empty?).join
159
+ end
160
+
161
+ def unit_with_scale(value, scale)
162
+ return "" if value.zero?
163
+ return scale if value == 1
164
+
165
+ "#{ONES_MASC[value]}#{scale}"
166
+ end
167
+
168
+ def pluralize(_number, singular, _few, _plural)
169
+ singular
170
+ end
15
171
  end
16
172
 
17
173
  register :ko, KO
@@ -10,8 +10,143 @@ module Num2words
10
10
  HUNDREDS = I18n.t("num2words.hundreds", locale: :kz)
11
11
  SCALES = I18n.t("num2words.scales", locale: :kz)
12
12
 
13
- MAJOR_UNIT = I18n.t("num2words.currencies.KZT.name", locale: :kz)
14
- MINOR_UNIT = I18n.t("num2words.currencies.KZT.fractional.name", locale: :kz)
13
+ FRACTIONS = I18n.t("num2words.fractions", locale: :kz)
14
+ GRAMMAR = I18n.t("num2words.grammar", locale: :kz)
15
+
16
+ DATE = I18n.t("num2words.date", locale: :kz)
17
+ DATE_TEMPLATE = I18n.t("num2words.date.template", locale: :kz)
18
+ TIME = I18n.t("num2words.time", locale: :kz)
19
+ TIME_TEMPLATE = I18n.t("num2words.time.template", locale: :kz)
20
+ DATETIME_TEMPLATE = I18n.t("num2words.datetime.template", locale: :kz)
21
+
22
+ ORDINALS = I18n.t("num2words.numbers.ordinals", locale: :kz)
23
+
24
+ module_function
25
+
26
+ def integer_to_words(number, feminine: false)
27
+ cardinal(number)
28
+ end
29
+
30
+ def triple_to_words(number, scale_idx, feminine: false)
31
+ return [] if number.zero?
32
+
33
+ words = [under_thousand(number)]
34
+ words << SCALES[scale_idx][0] unless scale_idx.zero?
35
+ words
36
+ end
37
+
38
+ def minus_word
39
+ GRAMMAR[:minus]
40
+ end
41
+
42
+ def fraction_joiner(joiner)
43
+ joiner.to_sym == :and ? "және" : GRAMMAR[:conjunction]
44
+ end
45
+
46
+ def default_fraction_word
47
+ GRAMMAR[:default_fraction]
48
+ end
49
+
50
+ def fraction_numerator_feminine?
51
+ false
52
+ end
53
+
54
+ def decimal_separator_word
55
+ "үтір"
56
+ end
57
+
58
+ def decimal_fraction_words(fraction_string)
59
+ fraction_string.chars.map { |digit| cardinal(digit.to_i) }.join(" ")
60
+ end
61
+
62
+ def date_day(day, format:, date_case:)
63
+ ordinal(day, :default)
64
+ end
65
+
66
+ def date_year(year, format:)
67
+ cardinal(year)
68
+ end
69
+
70
+ def time_unit_feminine?(_unit)
71
+ false
72
+ end
73
+
74
+ def time_number_words(number, unit:)
75
+ cardinal(number)
76
+ end
77
+
78
+ def currency_major_feminine?(_currency)
79
+ false
80
+ end
81
+
82
+ def currency_minor_feminine?(_currency)
83
+ false
84
+ end
85
+
86
+ def currency_number_words(number, _currency, unit:)
87
+ cardinal(number)
88
+ end
89
+
90
+ def ordinal(value, format, gender: :masculine)
91
+ ordinals = ORDINALS[format] || ORDINALS[:default] || ORDINALS[:nominative]
92
+ gender_data = ordinals[gender] || ordinals[:masculine]
93
+
94
+ return gender_data[value - 1] if value.between?(1, gender_data.length)
95
+
96
+ cardinal(value)
97
+ end
98
+
99
+ def cardinal(number)
100
+ integer_value = Integer(number)
101
+ negative = integer_value.negative?
102
+ integer_value = integer_value.abs
103
+
104
+ return ONES_MASC[0] if integer_value.zero?
105
+
106
+ groups = integer_value.to_s
107
+ .chars.reverse.each_slice(3).map(&:reverse)
108
+ .map(&:join).map!(&:to_i).reverse
109
+
110
+ words = []
111
+ groups.each_with_index do |group_value, index|
112
+ next if group_value.zero?
113
+
114
+ scale_index = groups.size - index - 1
115
+ words << under_thousand(group_value)
116
+ words << SCALES[scale_index][0] unless scale_index.zero?
117
+ end
118
+
119
+ words.unshift(minus_word) if negative
120
+ words.join(" ")
121
+ end
122
+
123
+ def under_thousand(number)
124
+ return ONES_MASC[number] if number < 10
125
+ return TEENS[number - 10] if number.between?(10, 19)
126
+ return under_hundred(number) if number < 100
127
+
128
+ hundreds = number / 100
129
+ rest = number % 100
130
+ words = [HUNDREDS[hundreds]]
131
+ words << under_hundred(rest) if rest.positive?
132
+ words.join(" ")
133
+ end
134
+
135
+ def under_hundred(number)
136
+ return "" if number.zero?
137
+ return ONES_MASC[number] if number < 10
138
+ return TEENS[number - 10] if number.between?(10, 19)
139
+
140
+ tens = number / 10
141
+ ones = number % 10
142
+ words = [TENS[tens]]
143
+ words << ONES_MASC[ones] if ones.positive?
144
+ words.join(" ")
145
+ end
146
+
147
+ def pluralize(number, singular, few, _plural)
148
+ number.abs == 1 ? singular : few
149
+ end
15
150
  end
16
151
 
17
152
  register :kz, KZ
@@ -10,8 +10,152 @@ module Num2words
10
10
  HUNDREDS = I18n.t("num2words.hundreds", locale: :lt)
11
11
  SCALES = I18n.t("num2words.scales", locale: :lt)
12
12
 
13
- MAJOR_UNIT = I18n.t("num2words.currencies.EUR.name", locale: :lt)
14
- MINOR_UNIT = I18n.t("num2words.currencies.EUR.fractional.name", locale: :lt)
13
+ FRACTIONS = I18n.t("num2words.fractions", locale: :lt)
14
+ GRAMMAR = I18n.t("num2words.grammar", locale: :lt)
15
+
16
+ DATE = I18n.t("num2words.date", locale: :lt)
17
+ DATE_TEMPLATE = I18n.t("num2words.date.template", locale: :lt)
18
+ TIME = I18n.t("num2words.time", locale: :lt)
19
+ TIME_TEMPLATE = I18n.t("num2words.time.template", locale: :lt)
20
+ DATETIME_TEMPLATE = I18n.t("num2words.datetime.template", locale: :lt)
21
+
22
+ ORDINALS = I18n.t("num2words.numbers.ordinals", locale: :lt)
23
+
24
+ module_function
25
+
26
+ def integer_to_words(number, feminine: false)
27
+ cardinal(number, feminine: feminine)
28
+ end
29
+
30
+ def triple_to_words(number, scale_idx, feminine: false)
31
+ return [] if number.zero?
32
+
33
+ words = [under_thousand(number, feminine: feminine)]
34
+ words << pluralize(number, *SCALES[scale_idx]) unless scale_idx.zero?
35
+ words
36
+ end
37
+
38
+ def feminine_group?(scale_idx)
39
+ false
40
+ end
41
+
42
+ def minus_word
43
+ GRAMMAR[:minus]
44
+ end
45
+
46
+ def fraction_joiner(joiner)
47
+ joiner.to_sym == :and ? "ir" : GRAMMAR[:conjunction]
48
+ end
49
+
50
+ def default_fraction_word
51
+ GRAMMAR[:default_fraction]
52
+ end
53
+
54
+ def fraction_numerator_feminine?
55
+ true
56
+ end
57
+
58
+ def decimal_separator_word
59
+ "kablelis"
60
+ end
61
+
62
+ def decimal_fraction_words(fraction_string)
63
+ fraction_string.chars.map { |digit| cardinal(digit.to_i) }.join(" ")
64
+ end
65
+
66
+ def date_day(day, format:, date_case:)
67
+ ordinal(day, :default, gender: :feminine)
68
+ end
69
+
70
+ def date_year(year, format:)
71
+ cardinal(year)
72
+ end
73
+
74
+ def time_unit_feminine?(unit)
75
+ %i[minute second].include?(unit)
76
+ end
77
+
78
+ def time_number_words(number, unit:)
79
+ cardinal(number, feminine: time_unit_feminine?(unit))
80
+ end
81
+
82
+ def currency_major_feminine?(currency)
83
+ %i[BGN BRL BYN CNY CZK DKK IDR INR JPY KZT NOK PKR RON RSD SEK TRY UAH].include?(currency)
84
+ end
85
+
86
+ def currency_minor_feminine?(currency)
87
+ %i[BGN BRL BYN DKK IDR ILS INR NOK PKR RSD RUB SEK SAR TRY UAH].include?(currency)
88
+ end
89
+
90
+ def currency_number_words(number, currency, unit:)
91
+ feminine = unit == :major ? currency_major_feminine?(currency) : currency_minor_feminine?(currency)
92
+ cardinal(number, feminine: feminine)
93
+ end
94
+
95
+ def ordinal(value, format, gender: :masculine)
96
+ ordinals = ORDINALS[format] || ORDINALS[:default] || ORDINALS[:nominative]
97
+ gender_data = ordinals[gender] || ordinals[:masculine]
98
+
99
+ return gender_data[value - 1] if value.between?(1, gender_data.length)
100
+
101
+ cardinal(value)
102
+ end
103
+
104
+ def cardinal(number, feminine: false)
105
+ integer_value = Integer(number)
106
+ negative = integer_value.negative?
107
+ integer_value = integer_value.abs
108
+
109
+ return ONES_MASC[0] if integer_value.zero?
110
+
111
+ groups = integer_value.to_s
112
+ .chars.reverse.each_slice(3).map(&:reverse)
113
+ .map(&:join).map!(&:to_i).reverse
114
+
115
+ words = []
116
+ groups.each_with_index do |group_value, index|
117
+ next if group_value.zero?
118
+
119
+ scale_idx = groups.size - index - 1
120
+ group_feminine = scale_idx.zero? && feminine
121
+ words.concat triple_to_words(group_value, scale_idx, feminine: group_feminine)
122
+ end
123
+
124
+ words.unshift(minus_word) if negative
125
+ words.join(" ")
126
+ end
127
+
128
+ def under_thousand(number, feminine: false)
129
+ return under_hundred(number, feminine: feminine) if number < 100
130
+
131
+ hundreds = number / 100
132
+ rest = number % 100
133
+ words = [HUNDREDS[hundreds]]
134
+ words << under_hundred(rest, feminine: feminine) if rest.positive?
135
+ words.join(" ")
136
+ end
137
+
138
+ def under_hundred(number, feminine: false)
139
+ return (feminine ? ONES_FEM[number] : ONES_MASC[number]) if number < 10
140
+ return TEENS[number - 10] if number < 20
141
+
142
+ tens = number / 10
143
+ ones = number % 10
144
+ words = [TENS[tens]]
145
+ words << (feminine ? ONES_FEM[ones] : ONES_MASC[ones]) if ones.positive?
146
+ words.join(" ")
147
+ end
148
+
149
+ def pluralize(number, singular, few, plural)
150
+ number = number.abs
151
+ return plural if (10..20).include?(number % 100)
152
+
153
+ case number % 10
154
+ when 1 then singular
155
+ when 2..9 then few
156
+ else plural
157
+ end
158
+ end
15
159
  end
16
160
 
17
161
  register :lt, LT