num2words 0.2.0 → 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +22 -0
- data/README.md +113 -144
- data/config/locales/ar.yml +5 -1
- data/config/locales/be.yml +4 -0
- data/config/locales/bg.yml +4 -0
- data/config/locales/bn.yml +4 -0
- data/config/locales/cs.yml +6 -2
- data/config/locales/da.yml +4 -0
- data/config/locales/de.yml +8 -4
- data/config/locales/el.yml +4 -0
- data/config/locales/en.yml +4 -0
- data/config/locales/es.yml +4 -0
- data/config/locales/et.yml +9 -5
- data/config/locales/fa.yml +15 -11
- data/config/locales/fi.yml +8 -4
- data/config/locales/fr.yml +4 -0
- data/config/locales/gu.yml +4 -0
- data/config/locales/he.yml +6 -2
- data/config/locales/hi.yml +4 -0
- data/config/locales/hr.yml +8 -4
- data/config/locales/hu.yml +6 -2
- data/config/locales/id.yml +4 -0
- data/config/locales/it.yml +4 -0
- data/config/locales/ja.yml +10 -5
- data/config/locales/kn.yml +186 -10
- data/config/locales/ko.yml +184 -13
- data/config/locales/kz.yml +183 -17
- data/config/locales/lt.yml +184 -8
- data/config/locales/lv.yml +188 -12
- data/config/locales/ml.yml +189 -13
- data/config/locales/mr.yml +184 -8
- data/config/locales/ms.yml +184 -8
- data/config/locales/nb.yml +183 -17
- data/config/locales/nl.yml +184 -13
- data/config/locales/pa.yml +189 -13
- data/config/locales/pl.yml +184 -13
- data/config/locales/pt.yml +184 -13
- data/config/locales/ro.yml +183 -12
- data/config/locales/ru.yml +4 -0
- data/config/locales/sk.yml +184 -8
- data/config/locales/sl.yml +185 -9
- data/config/locales/sr.yml +186 -15
- data/config/locales/sv.yml +182 -13
- data/config/locales/sw.yml +184 -8
- data/config/locales/ta.yml +184 -8
- data/config/locales/te.yml +185 -9
- data/config/locales/th.yml +183 -12
- data/config/locales/tr.yml +183 -12
- data/config/locales/uk.yml +189 -18
- data/config/locales/ur.yml +187 -11
- data/config/locales/vi.yml +183 -12
- data/config/locales/zh.yml +191 -9
- data/lib/num2words/converter.rb +144 -35
- data/lib/num2words/locales/ar.rb +130 -0
- data/lib/num2words/locales/be.rb +101 -0
- data/lib/num2words/locales/bg.rb +127 -0
- data/lib/num2words/locales/bn.rb +112 -0
- data/lib/num2words/locales/cs.rb +106 -0
- data/lib/num2words/locales/da.rb +97 -0
- data/lib/num2words/locales/de.rb +119 -0
- data/lib/num2words/locales/el.rb +143 -0
- data/lib/num2words/locales/en.rb +90 -0
- data/lib/num2words/locales/es.rb +185 -0
- data/lib/num2words/locales/et.rb +104 -0
- data/lib/num2words/locales/fa.rb +104 -0
- data/lib/num2words/locales/fi.rb +104 -0
- data/lib/num2words/locales/fr.rb +121 -0
- data/lib/num2words/locales/gu.rb +112 -0
- data/lib/num2words/locales/he.rb +130 -0
- data/lib/num2words/locales/hi.rb +112 -0
- data/lib/num2words/locales/hr.rb +117 -0
- data/lib/num2words/locales/hu.rb +111 -0
- data/lib/num2words/locales/id.rb +104 -0
- data/lib/num2words/locales/it.rb +142 -0
- data/lib/num2words/locales/ja.rb +126 -0
- data/lib/num2words/locales/kn.rb +122 -2
- data/lib/num2words/locales/ko.rb +158 -2
- data/lib/num2words/locales/kz.rb +137 -2
- data/lib/num2words/locales/lt.rb +146 -2
- data/lib/num2words/locales/lv.rb +148 -2
- data/lib/num2words/locales/ml.rb +142 -2
- data/lib/num2words/locales/mr.rb +142 -2
- data/lib/num2words/locales/ms.rb +134 -2
- data/lib/num2words/locales/nb.rb +153 -0
- data/lib/num2words/locales/nl.rb +142 -2
- data/lib/num2words/locales/pa.rb +122 -2
- data/lib/num2words/locales/pl.rb +149 -2
- data/lib/num2words/locales/pt.rb +164 -2
- data/lib/num2words/locales/ro.rb +165 -2
- data/lib/num2words/locales/ru.rb +100 -0
- data/lib/num2words/locales/sk.rb +124 -2
- data/lib/num2words/locales/sl.rb +154 -2
- data/lib/num2words/locales/sr.rb +141 -3
- data/lib/num2words/locales/sv.rb +141 -2
- data/lib/num2words/locales/sw.rb +133 -2
- data/lib/num2words/locales/ta.rb +142 -2
- data/lib/num2words/locales/te.rb +142 -2
- data/lib/num2words/locales/th.rb +133 -2
- data/lib/num2words/locales/tr.rb +141 -2
- data/lib/num2words/locales/uk.rb +134 -2
- data/lib/num2words/locales/ur.rb +130 -2
- data/lib/num2words/locales/vi.rb +142 -2
- data/lib/num2words/locales/zh.rb +172 -2
- data/lib/num2words/version.rb +1 -1
- data/num2words.gemspec +2 -2
- metadata +6 -6
- data/lib/num2words/locales/no.rb +0 -19
data/lib/num2words/locales/tr.rb
CHANGED
|
@@ -10,8 +10,147 @@ module Num2words
|
|
|
10
10
|
HUNDREDS = I18n.t("num2words.hundreds", locale: :tr)
|
|
11
11
|
SCALES = I18n.t("num2words.scales", locale: :tr)
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
FRACTIONS = I18n.t("num2words.fractions", locale: :tr)
|
|
14
|
+
GRAMMAR = I18n.t("num2words.grammar", locale: :tr)
|
|
15
|
+
|
|
16
|
+
DATE = I18n.t("num2words.date", locale: :tr)
|
|
17
|
+
DATE_TEMPLATE = I18n.t("num2words.date.template", locale: :tr)
|
|
18
|
+
TIME = I18n.t("num2words.time", locale: :tr)
|
|
19
|
+
TIME_TEMPLATE = I18n.t("num2words.time.template", locale: :tr)
|
|
20
|
+
DATETIME_TEMPLATE = I18n.t("num2words.datetime.template", locale: :tr)
|
|
21
|
+
|
|
22
|
+
ORDINALS = I18n.t("num2words.numbers.ordinals", locale: :tr)
|
|
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 = []
|
|
34
|
+
number_words = scale_number_words(number, scale_idx)
|
|
35
|
+
words << number_words unless number_words.empty?
|
|
36
|
+
words << SCALES[scale_idx][0] unless scale_idx.zero?
|
|
37
|
+
words
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def minus_word
|
|
41
|
+
GRAMMAR[:minus]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def fraction_joiner(joiner)
|
|
45
|
+
joiner.to_sym == :and ? "ve" : 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
|
+
"virgül"
|
|
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 date_day(day, format:, date_case:)
|
|
65
|
+
ordinal(day, :nominative)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def date_year(year, format:)
|
|
69
|
+
cardinal(year)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def time_unit_feminine?(_unit)
|
|
73
|
+
false
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def time_number_words(number, unit:)
|
|
77
|
+
cardinal(number)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def currency_major_feminine?(_currency)
|
|
81
|
+
false
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def currency_minor_feminine?(_currency)
|
|
85
|
+
false
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def currency_number_words(number, _currency, unit:)
|
|
89
|
+
cardinal(number)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def ordinal(value, format, gender: :masculine)
|
|
93
|
+
ordinals = ORDINALS[format] || ORDINALS[:default] || ORDINALS[:nominative]
|
|
94
|
+
gender_data = ordinals[gender] || ordinals[:masculine]
|
|
95
|
+
|
|
96
|
+
return gender_data[value - 1] if value.between?(1, gender_data.length)
|
|
97
|
+
|
|
98
|
+
cardinal(value)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def cardinal(number)
|
|
102
|
+
integer_value = Integer(number)
|
|
103
|
+
negative = integer_value.negative?
|
|
104
|
+
integer_value = integer_value.abs
|
|
105
|
+
|
|
106
|
+
return ONES_MASC[0] if integer_value.zero?
|
|
107
|
+
|
|
108
|
+
groups = integer_value.to_s
|
|
109
|
+
.chars.reverse.each_slice(3).map(&:reverse)
|
|
110
|
+
.map(&:join).map!(&:to_i).reverse
|
|
111
|
+
|
|
112
|
+
words = []
|
|
113
|
+
groups.each_with_index do |group_value, index|
|
|
114
|
+
next if group_value.zero?
|
|
115
|
+
|
|
116
|
+
scale_idx = groups.size - index - 1
|
|
117
|
+
words.concat triple_to_words(group_value, scale_idx)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
words.unshift(minus_word) if negative
|
|
121
|
+
words.join(" ")
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def scale_number_words(number, scale_idx)
|
|
125
|
+
return "" if scale_idx == 1 && number == 1
|
|
126
|
+
|
|
127
|
+
under_thousand(number)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def under_thousand(number)
|
|
131
|
+
return under_hundred(number) if number < 100
|
|
132
|
+
|
|
133
|
+
hundreds = number / 100
|
|
134
|
+
rest = number % 100
|
|
135
|
+
words = [HUNDREDS[hundreds]]
|
|
136
|
+
words << under_hundred(rest) if rest.positive?
|
|
137
|
+
words.join(" ")
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def under_hundred(number)
|
|
141
|
+
return ONES_MASC[number] if number < 10
|
|
142
|
+
return TEENS[number - 10] if number < 20
|
|
143
|
+
|
|
144
|
+
tens = number / 10
|
|
145
|
+
ones = number % 10
|
|
146
|
+
words = [TENS[tens]]
|
|
147
|
+
words << ONES_MASC[ones] if ones.positive?
|
|
148
|
+
words.join(" ")
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def pluralize(_number, singular, _few, _plural)
|
|
152
|
+
singular
|
|
153
|
+
end
|
|
15
154
|
end
|
|
16
155
|
|
|
17
156
|
register :tr, TR
|
data/lib/num2words/locales/uk.rb
CHANGED
|
@@ -10,8 +10,140 @@ module Num2words
|
|
|
10
10
|
HUNDREDS = I18n.t("num2words.hundreds", locale: :uk)
|
|
11
11
|
SCALES = I18n.t("num2words.scales", locale: :uk)
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
FRACTIONS = I18n.t("num2words.fractions", locale: :uk)
|
|
14
|
+
GRAMMAR = I18n.t("num2words.grammar", locale: :uk)
|
|
15
|
+
|
|
16
|
+
DATE = I18n.t("num2words.date", locale: :uk)
|
|
17
|
+
DATE_TEMPLATE = I18n.t("num2words.date.template", locale: :uk)
|
|
18
|
+
TIME = I18n.t("num2words.time", locale: :uk)
|
|
19
|
+
TIME_TEMPLATE = I18n.t("num2words.time.template", locale: :uk)
|
|
20
|
+
DATETIME_TEMPLATE = I18n.t("num2words.datetime.template", locale: :uk)
|
|
21
|
+
|
|
22
|
+
ORDINALS = I18n.t("num2words.numbers.ordinals", locale: :uk)
|
|
23
|
+
|
|
24
|
+
FEMININE_MAJOR_CURRENCIES = %i[UAH JPY CZK BGN INR IDR PKR TRY BDT KRW].freeze
|
|
25
|
+
FEMININE_MINOR_CURRENCIES = %i[UAH RUB BGN ILS INR IRR RSD BDT PKR].freeze
|
|
26
|
+
|
|
27
|
+
module_function
|
|
28
|
+
|
|
29
|
+
def feminine_group?(scale_idx)
|
|
30
|
+
scale_idx == 1
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def fraction_numerator_feminine?
|
|
34
|
+
true
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def minus_word
|
|
38
|
+
GRAMMAR[:minus]
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def fraction_joiner(joiner)
|
|
42
|
+
joiner.to_sym == :and ? "і" : GRAMMAR[:conjunction]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def default_fraction_word
|
|
46
|
+
GRAMMAR[:default_fraction]
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def triple_to_words(number, scale_idx, feminine: false)
|
|
50
|
+
words = []
|
|
51
|
+
|
|
52
|
+
words << HUNDREDS[number / 100] if number >= 100
|
|
53
|
+
rest = number % 100
|
|
54
|
+
|
|
55
|
+
if rest.between?(10, 19)
|
|
56
|
+
words << TEENS[rest - 10]
|
|
57
|
+
else
|
|
58
|
+
words << TENS[rest / 10] if rest >= 20
|
|
59
|
+
ones = rest % 10
|
|
60
|
+
words << (feminine ? ONES_FEM[ones] : ONES_MASC[ones]) if ones.positive?
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
words << pluralize(number, *SCALES[scale_idx]) unless scale_idx.zero?
|
|
64
|
+
words.compact
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def date_day(day, format:, date_case:)
|
|
68
|
+
return ordinal(day, :default, gender: :masculine) if date_case.to_sym == :genitive
|
|
69
|
+
|
|
70
|
+
ordinal(day, :nominative, gender: :neuter)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def date_year(year, format:)
|
|
74
|
+
ordinal(year, :default)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def currency_major_feminine?(currency)
|
|
78
|
+
FEMININE_MAJOR_CURRENCIES.include?(currency.to_sym)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def currency_minor_feminine?(currency)
|
|
82
|
+
FEMININE_MINOR_CURRENCIES.include?(currency.to_sym)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def currency_number_words(number, currency, unit:)
|
|
86
|
+
cardinal(number, feminine: unit == :major ? currency_major_feminine?(currency) : currency_minor_feminine?(currency))
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def time_unit_feminine?(unit)
|
|
90
|
+
%i[hour minute second].include?(unit)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def time_number_words(number, unit:)
|
|
94
|
+
cardinal(number, feminine: time_unit_feminine?(unit))
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def ordinal(value, format, gender: :masculine)
|
|
98
|
+
ordinals = ORDINALS[format]
|
|
99
|
+
gender_data = ordinals[gender] || ordinals[:masculine]
|
|
100
|
+
|
|
101
|
+
return gender_data[value - 1] if value.between?(1, gender_data.length)
|
|
102
|
+
|
|
103
|
+
if value > 31
|
|
104
|
+
thousands = (value / 100) * 100
|
|
105
|
+
last_two = value % 100
|
|
106
|
+
base_year = cardinal(thousands)
|
|
107
|
+
last_ordinal = gender_data[last_two - 1] || cardinal(last_two)
|
|
108
|
+
|
|
109
|
+
return [base_year, last_ordinal].join(" ")
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
cardinal(value)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def cardinal(number, feminine: false)
|
|
116
|
+
integer_value = Integer(number)
|
|
117
|
+
negative = integer_value.negative?
|
|
118
|
+
integer_value = integer_value.abs
|
|
119
|
+
|
|
120
|
+
return (feminine ? ONES_FEM[0] : ONES_MASC[0]) if integer_value.zero?
|
|
121
|
+
|
|
122
|
+
groups = integer_value.to_s
|
|
123
|
+
.chars.reverse.each_slice(3).map(&:reverse)
|
|
124
|
+
.map(&:join).map!(&:to_i).reverse
|
|
125
|
+
|
|
126
|
+
words = []
|
|
127
|
+
groups.each_with_index do |group_value, index|
|
|
128
|
+
scale_idx = groups.size - index - 1
|
|
129
|
+
group_feminine = feminine_group?(scale_idx) || feminine
|
|
130
|
+
words.concat triple_to_words(group_value, scale_idx, feminine: group_feminine)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
words.unshift(minus_word) if negative
|
|
134
|
+
words.join(" ")
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def pluralize(number, singular, few, plural)
|
|
138
|
+
number = number.abs
|
|
139
|
+
return plural if (11..14).include?(number % 100)
|
|
140
|
+
|
|
141
|
+
case number % 10
|
|
142
|
+
when 1 then singular
|
|
143
|
+
when 2..4 then few
|
|
144
|
+
else plural
|
|
145
|
+
end
|
|
146
|
+
end
|
|
15
147
|
end
|
|
16
148
|
|
|
17
149
|
register :uk, UK
|
data/lib/num2words/locales/ur.rb
CHANGED
|
@@ -10,8 +10,136 @@ module Num2words
|
|
|
10
10
|
HUNDREDS = I18n.t("num2words.hundreds", locale: :ur)
|
|
11
11
|
SCALES = I18n.t("num2words.scales", locale: :ur)
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
FRACTIONS = I18n.t("num2words.fractions", locale: :ur)
|
|
14
|
+
GRAMMAR = I18n.t("num2words.grammar", locale: :ur)
|
|
15
|
+
|
|
16
|
+
DATE = I18n.t("num2words.date", locale: :ur)
|
|
17
|
+
DATE_TEMPLATE = I18n.t("num2words.date.template", locale: :ur)
|
|
18
|
+
TIME = I18n.t("num2words.time", locale: :ur)
|
|
19
|
+
TIME_TEMPLATE = I18n.t("num2words.time.template", locale: :ur)
|
|
20
|
+
DATETIME_TEMPLATE = I18n.t("num2words.datetime.template", locale: :ur)
|
|
21
|
+
|
|
22
|
+
ORDINALS = I18n.t("num2words.numbers.ordinals", locale: :ur)
|
|
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 currency_number_words(number, currency, unit:)
|
|
91
|
+
cardinal(number)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def time_number_words(number, unit:)
|
|
95
|
+
cardinal(number)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def ordinal(value, format, gender: :masculine)
|
|
99
|
+
ordinals = ORDINALS[format] || ORDINALS[:default] || ORDINALS[:nominative]
|
|
100
|
+
gender_data = ordinals[gender] || ordinals[:masculine]
|
|
101
|
+
|
|
102
|
+
return gender_data[value - 1] if value.between?(1, gender_data.length)
|
|
103
|
+
|
|
104
|
+
cardinal(value)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def cardinal(number)
|
|
108
|
+
integer_value = Integer(number)
|
|
109
|
+
negative = integer_value.negative?
|
|
110
|
+
integer_value = integer_value.abs
|
|
111
|
+
|
|
112
|
+
return UNDER_HUNDRED[0] if integer_value.zero?
|
|
113
|
+
|
|
114
|
+
remainder = integer_value
|
|
115
|
+
words = []
|
|
116
|
+
|
|
117
|
+
INDIAN_SCALES.each do |value, label|
|
|
118
|
+
next if remainder < value
|
|
119
|
+
|
|
120
|
+
group_value = remainder / value
|
|
121
|
+
remainder %= value
|
|
122
|
+
words << [cardinal(group_value), label].join(" ")
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
words << under_thousand(remainder) if remainder.positive?
|
|
126
|
+
words.unshift(minus_word) if negative
|
|
127
|
+
words.join(" ")
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def under_thousand(number)
|
|
131
|
+
return UNDER_HUNDRED[number] if number < 100
|
|
132
|
+
|
|
133
|
+
hundreds = number / 100
|
|
134
|
+
rest = number % 100
|
|
135
|
+
words = [HUNDREDS[hundreds]]
|
|
136
|
+
words << UNDER_HUNDRED[rest] if rest.positive?
|
|
137
|
+
words.join(" ")
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def pluralize(number, singular, few, _plural)
|
|
141
|
+
number.abs == 1 ? singular : few
|
|
142
|
+
end
|
|
15
143
|
end
|
|
16
144
|
|
|
17
145
|
register :ur, UR
|
data/lib/num2words/locales/vi.rb
CHANGED
|
@@ -10,8 +10,148 @@ module Num2words
|
|
|
10
10
|
HUNDREDS = I18n.t("num2words.hundreds", locale: :vi)
|
|
11
11
|
SCALES = I18n.t("num2words.scales", locale: :vi)
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
FRACTIONS = I18n.t("num2words.fractions", locale: :vi)
|
|
14
|
+
GRAMMAR = I18n.t("num2words.grammar", locale: :vi)
|
|
15
|
+
|
|
16
|
+
DATE = I18n.t("num2words.date", locale: :vi)
|
|
17
|
+
DATE_TEMPLATE = I18n.t("num2words.date.template", locale: :vi)
|
|
18
|
+
TIME = I18n.t("num2words.time", locale: :vi)
|
|
19
|
+
TIME_TEMPLATE = I18n.t("num2words.time.template", locale: :vi)
|
|
20
|
+
DATETIME_TEMPLATE = I18n.t("num2words.datetime.template", locale: :vi)
|
|
21
|
+
|
|
22
|
+
ORDINALS = I18n.t("num2words.numbers.ordinals", locale: :vi)
|
|
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 ? "và" : 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
|
+
"phẩy"
|
|
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
|
+
cardinal(day)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def date_year(year, format:)
|
|
67
|
+
cardinal(year)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def currency_number_words(number, currency, unit:)
|
|
71
|
+
cardinal(number)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def time_number_words(number, unit:)
|
|
75
|
+
cardinal(number)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def ordinal(value, format, gender: :masculine)
|
|
79
|
+
ordinals = ORDINALS[format] || ORDINALS[:default] || ORDINALS[:nominative]
|
|
80
|
+
gender_data = ordinals[gender] || ordinals[:masculine]
|
|
81
|
+
|
|
82
|
+
return gender_data[value - 1] if value.between?(1, gender_data.length)
|
|
83
|
+
|
|
84
|
+
cardinal(value)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def cardinal(number)
|
|
88
|
+
integer_value = Integer(number)
|
|
89
|
+
negative = integer_value.negative?
|
|
90
|
+
integer_value = integer_value.abs
|
|
91
|
+
|
|
92
|
+
return ONES_MASC[0] if integer_value.zero?
|
|
93
|
+
|
|
94
|
+
groups = integer_value.to_s
|
|
95
|
+
.chars.reverse.each_slice(3).map(&:reverse)
|
|
96
|
+
.map(&:join).map!(&:to_i).reverse
|
|
97
|
+
words = []
|
|
98
|
+
|
|
99
|
+
groups.each_with_index do |group_value, index|
|
|
100
|
+
next if group_value.zero?
|
|
101
|
+
|
|
102
|
+
scale_idx = groups.size - index - 1
|
|
103
|
+
full_group = words.any? && group_value < 100
|
|
104
|
+
group_words = under_thousand(group_value, full: full_group)
|
|
105
|
+
words << [group_words, SCALES[scale_idx][0]].reject(&:empty?).join(" ")
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
words.unshift(minus_word) if negative
|
|
109
|
+
words.join(" ")
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def under_thousand(number, full: false)
|
|
113
|
+
return ONES_MASC[number] if number < 10 && !full
|
|
114
|
+
return under_hundred(number, after_hundreds: false) if number < 100 && !full
|
|
115
|
+
|
|
116
|
+
hundreds = number / 100
|
|
117
|
+
rest = number % 100
|
|
118
|
+
words = []
|
|
119
|
+
|
|
120
|
+
words << (hundreds.positive? ? HUNDREDS[hundreds] : "không trăm")
|
|
121
|
+
words << under_hundred(rest, after_hundreds: true) if rest.positive?
|
|
122
|
+
words.join(" ")
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def under_hundred(number, after_hundreds:)
|
|
126
|
+
return ["linh", ONES_MASC[number]].join(" ") if number < 10 && after_hundreds
|
|
127
|
+
return ONES_MASC[number] if number < 10
|
|
128
|
+
return "mười" if number == 10
|
|
129
|
+
|
|
130
|
+
if number < 20
|
|
131
|
+
ones = number % 10
|
|
132
|
+
return "mười lăm" if ones == 5
|
|
133
|
+
|
|
134
|
+
return ["mười", ONES_MASC[ones]].join(" ")
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
tens = number / 10
|
|
138
|
+
ones = number % 10
|
|
139
|
+
words = [TENS[tens]]
|
|
140
|
+
|
|
141
|
+
words << case ones
|
|
142
|
+
when 0 then nil
|
|
143
|
+
when 1 then "mốt"
|
|
144
|
+
when 4 then "tư"
|
|
145
|
+
when 5 then "lăm"
|
|
146
|
+
else ONES_MASC[ones]
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
words.compact.join(" ")
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def pluralize(number, singular, _few, _plural)
|
|
153
|
+
singular
|
|
154
|
+
end
|
|
15
155
|
end
|
|
16
156
|
|
|
17
157
|
register :vi, VI
|