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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +65 -0
- data/README.md +145 -135
- data/bin/console +2 -14
- 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 +8 -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/exe/num2words-console +7 -0
- data/lib/num2words/console.rb +16 -0
- data/lib/num2words/converter.rb +195 -47
- 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 +3 -3
- metadata +13 -10
- data/lib/num2words/locales/no.rb +0 -19
data/lib/num2words/locales/hr.rb
CHANGED
|
@@ -20,6 +20,123 @@ module Num2words
|
|
|
20
20
|
DATETIME_TEMPLATE = I18n.t("num2words.datetime.template", locale: :hr)
|
|
21
21
|
|
|
22
22
|
ORDINALS = I18n.t("num2words.numbers.ordinals", locale: :hr)
|
|
23
|
+
|
|
24
|
+
FEMININE_MAJOR_CURRENCIES = %i[GBP RUB TRY UAH CZK SEK NOK DKK BYN INR IDR BDT PKR].freeze
|
|
25
|
+
FEMININE_MINOR_CURRENCIES = %i[RUB UAH BGN ILS SAR RSD BDT].freeze
|
|
26
|
+
|
|
27
|
+
module_function
|
|
28
|
+
|
|
29
|
+
def feminine_group?(scale_idx)
|
|
30
|
+
scale_idx == 1 || scale_idx == 3
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def fraction_numerator_feminine?
|
|
34
|
+
true
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def currency_major_feminine?(currency)
|
|
38
|
+
FEMININE_MAJOR_CURRENCIES.include?(currency)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def currency_minor_feminine?(currency)
|
|
42
|
+
FEMININE_MINOR_CURRENCIES.include?(currency)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def minus_word
|
|
46
|
+
GRAMMAR[:minus]
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def fraction_joiner(_joiner)
|
|
50
|
+
GRAMMAR[:conjunction]
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def default_fraction_word
|
|
54
|
+
GRAMMAR[:default_fraction]
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def decimal_separator_word
|
|
58
|
+
"zarez"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def decimal_fraction_words(fraction_string)
|
|
62
|
+
fraction_string.chars.map { |digit| cardinal(digit.to_i) }.join(" ")
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def integer_to_words(number, feminine: false)
|
|
66
|
+
cardinal(number, feminine: feminine)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def triple_to_words(number, scale_idx, feminine: false)
|
|
70
|
+
return [] if number.zero?
|
|
71
|
+
|
|
72
|
+
words = []
|
|
73
|
+
words << HUNDREDS[number / 100] if number >= 100
|
|
74
|
+
rest = number % 100
|
|
75
|
+
|
|
76
|
+
if rest.between?(10, 19)
|
|
77
|
+
words << TEENS[rest - 10]
|
|
78
|
+
else
|
|
79
|
+
words << TENS[rest / 10] if rest >= 20
|
|
80
|
+
ones = rest % 10
|
|
81
|
+
words << (feminine ? ONES_FEM[ones] : ONES_MASC[ones]) if ones.positive?
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
words << pluralize(number, *SCALES[scale_idx]) unless scale_idx.zero?
|
|
85
|
+
words.compact
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def date_day(day, format:, date_case:)
|
|
89
|
+
ordinal(day, :default)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def date_year(year, format:)
|
|
93
|
+
cardinal(year)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def ordinal(value, format, gender: :masculine)
|
|
97
|
+
ordinals = ORDINALS[format] || ORDINALS[:default] || ORDINALS[:nominative]
|
|
98
|
+
gender_data = ordinals[gender] || ordinals[:masculine]
|
|
99
|
+
|
|
100
|
+
return gender_data[value - 1] if value.between?(1, gender_data.length)
|
|
101
|
+
|
|
102
|
+
cardinal(value)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def cardinal(number, feminine: false)
|
|
106
|
+
integer_value = Integer(number)
|
|
107
|
+
negative = integer_value.negative?
|
|
108
|
+
integer_value = integer_value.abs
|
|
109
|
+
|
|
110
|
+
return (feminine ? ONES_FEM[0] : ONES_MASC[0]) if integer_value.zero?
|
|
111
|
+
|
|
112
|
+
groups = integer_value.to_s
|
|
113
|
+
.chars.reverse.each_slice(3).map(&:reverse)
|
|
114
|
+
.map(&:join).map!(&:to_i).reverse
|
|
115
|
+
|
|
116
|
+
words = []
|
|
117
|
+
groups.each_with_index do |group_value, index|
|
|
118
|
+
next if group_value.zero?
|
|
119
|
+
|
|
120
|
+
scale_idx = groups.size - index - 1
|
|
121
|
+
group_feminine = feminine_group?(scale_idx) || (feminine && scale_idx.zero?)
|
|
122
|
+
group_words = triple_to_words(group_value, scale_idx, feminine: group_feminine)
|
|
123
|
+
words.concat group_words
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
words.unshift(minus_word) if negative
|
|
127
|
+
words.join(" ")
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def pluralize(number, singular, few, plural)
|
|
131
|
+
number = number.abs
|
|
132
|
+
return plural if (11..14).include?(number % 100)
|
|
133
|
+
|
|
134
|
+
case number % 10
|
|
135
|
+
when 1 then singular
|
|
136
|
+
when 2..4 then few
|
|
137
|
+
else plural
|
|
138
|
+
end
|
|
139
|
+
end
|
|
23
140
|
end
|
|
24
141
|
|
|
25
142
|
register :hr, HR
|
data/lib/num2words/locales/hu.rb
CHANGED
|
@@ -20,6 +20,117 @@ module Num2words
|
|
|
20
20
|
DATETIME_TEMPLATE = I18n.t("num2words.datetime.template", locale: :hu)
|
|
21
21
|
|
|
22
22
|
ORDINALS = I18n.t("num2words.numbers.ordinals", locale: :hu)
|
|
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 ? "és" : 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
|
+
"vessző"
|
|
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 ordinal(value, format, gender: :masculine)
|
|
71
|
+
ordinals = ORDINALS[format] || ORDINALS[:default] || ORDINALS[:nominative]
|
|
72
|
+
gender_data = ordinals[gender] || ordinals[:masculine]
|
|
73
|
+
|
|
74
|
+
return gender_data[value - 1] if value.between?(1, gender_data.length)
|
|
75
|
+
|
|
76
|
+
cardinal(value)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def cardinal(number)
|
|
80
|
+
integer_value = Integer(number)
|
|
81
|
+
negative = integer_value.negative?
|
|
82
|
+
integer_value = integer_value.abs
|
|
83
|
+
|
|
84
|
+
return ONES_MASC[0] if integer_value.zero?
|
|
85
|
+
|
|
86
|
+
groups = integer_value.to_s
|
|
87
|
+
.chars.reverse.each_slice(3).map(&:reverse)
|
|
88
|
+
.map(&:join).map!(&:to_i).reverse
|
|
89
|
+
|
|
90
|
+
words = []
|
|
91
|
+
groups.each_with_index do |group_value, index|
|
|
92
|
+
next if group_value.zero?
|
|
93
|
+
|
|
94
|
+
scale_idx = groups.size - index - 1
|
|
95
|
+
words.concat triple_to_words(group_value, scale_idx)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
words.unshift(minus_word) if negative
|
|
99
|
+
words.join(" ")
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def under_thousand(number)
|
|
103
|
+
return under_hundred(number) if number < 100
|
|
104
|
+
|
|
105
|
+
hundreds = number / 100
|
|
106
|
+
rest = number % 100
|
|
107
|
+
words = [HUNDREDS[hundreds]]
|
|
108
|
+
words << under_hundred(rest) if rest.positive?
|
|
109
|
+
words.join
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def under_hundred(number)
|
|
113
|
+
return ONES_MASC[number] if number < 10
|
|
114
|
+
return TEENS[number - 10] if number < 20
|
|
115
|
+
|
|
116
|
+
tens = number / 10
|
|
117
|
+
ones = number % 10
|
|
118
|
+
return TENS[tens] if ones.zero?
|
|
119
|
+
|
|
120
|
+
"#{tens_stem(tens)}#{ONES_MASC[ones]}"
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def tens_stem(tens)
|
|
124
|
+
case tens
|
|
125
|
+
when 2 then "huszon"
|
|
126
|
+
when 3 then "harminc"
|
|
127
|
+
else TENS[tens]
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def pluralize(_number, singular, _few, _plural)
|
|
132
|
+
singular
|
|
133
|
+
end
|
|
23
134
|
end
|
|
24
135
|
|
|
25
136
|
register :hu, HU
|
data/lib/num2words/locales/id.rb
CHANGED
|
@@ -20,6 +20,110 @@ module Num2words
|
|
|
20
20
|
DATETIME_TEMPLATE = I18n.t("num2words.datetime.template", locale: :id)
|
|
21
21
|
|
|
22
22
|
ORDINALS = I18n.t("num2words.numbers.ordinals", locale: :id)
|
|
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
|
+
words << under_thousand(number) unless scale_idx == 1 && number == 1
|
|
35
|
+
words << SCALES[scale_idx][0] unless scale_idx.zero?
|
|
36
|
+
words
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def minus_word
|
|
40
|
+
GRAMMAR[:minus]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def fraction_joiner(joiner)
|
|
44
|
+
joiner.to_sym == :and ? "dan" : GRAMMAR[:conjunction]
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def default_fraction_word
|
|
48
|
+
GRAMMAR[:default_fraction]
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def fraction_numerator_feminine?
|
|
52
|
+
false
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def decimal_separator_word
|
|
56
|
+
GRAMMAR[:conjunction]
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def decimal_fraction_words(fraction_string)
|
|
60
|
+
fraction_string.chars.map { |digit| cardinal(digit.to_i) }.join(" ")
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def date_day(day, format:, date_case:)
|
|
64
|
+
cardinal(day)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def date_year(year, format:)
|
|
68
|
+
cardinal(year)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def ordinal(value, format, gender: :masculine)
|
|
72
|
+
ordinals = ORDINALS[format] || ORDINALS[:default] || ORDINALS[:nominative]
|
|
73
|
+
gender_data = ordinals[gender] || ordinals[:masculine]
|
|
74
|
+
|
|
75
|
+
return gender_data[value - 1] if value.between?(1, gender_data.length)
|
|
76
|
+
|
|
77
|
+
cardinal(value)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def cardinal(number)
|
|
81
|
+
integer_value = Integer(number)
|
|
82
|
+
negative = integer_value.negative?
|
|
83
|
+
integer_value = integer_value.abs
|
|
84
|
+
|
|
85
|
+
return ONES_MASC[0] if integer_value.zero?
|
|
86
|
+
|
|
87
|
+
groups = integer_value.to_s
|
|
88
|
+
.chars.reverse.each_slice(3).map(&:reverse)
|
|
89
|
+
.map(&:join).map!(&:to_i).reverse
|
|
90
|
+
|
|
91
|
+
words = []
|
|
92
|
+
groups.each_with_index do |group_value, index|
|
|
93
|
+
next if group_value.zero?
|
|
94
|
+
|
|
95
|
+
scale_idx = groups.size - index - 1
|
|
96
|
+
words.concat triple_to_words(group_value, scale_idx)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
words.unshift(minus_word) if negative
|
|
100
|
+
words.join(" ")
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def under_thousand(number)
|
|
104
|
+
return under_hundred(number) if number < 100
|
|
105
|
+
|
|
106
|
+
hundreds = number / 100
|
|
107
|
+
rest = number % 100
|
|
108
|
+
words = [hundreds == 1 ? "seratus" : "#{ONES_MASC[hundreds]} ratus"]
|
|
109
|
+
words << under_hundred(rest) if rest.positive?
|
|
110
|
+
words.join(" ")
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def under_hundred(number)
|
|
114
|
+
return ONES_MASC[number] if number < 10
|
|
115
|
+
return TEENS[number - 10] if number < 20
|
|
116
|
+
|
|
117
|
+
tens = number / 10
|
|
118
|
+
ones = number % 10
|
|
119
|
+
words = ["#{ONES_MASC[tens]} puluh"]
|
|
120
|
+
words << ONES_MASC[ones] if ones.positive?
|
|
121
|
+
words.join(" ")
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def pluralize(_number, singular, _few, _plural)
|
|
125
|
+
singular
|
|
126
|
+
end
|
|
23
127
|
end
|
|
24
128
|
|
|
25
129
|
register :id, ID
|
data/lib/num2words/locales/it.rb
CHANGED
|
@@ -20,6 +20,148 @@ module Num2words
|
|
|
20
20
|
DATETIME_TEMPLATE = I18n.t("num2words.datetime.template", locale: :it)
|
|
21
21
|
|
|
22
22
|
ORDINALS = I18n.t("num2words.numbers.ordinals", locale: :it)
|
|
23
|
+
|
|
24
|
+
FEMININE_MAJOR_CURRENCIES = %i[GBP TRY UAH CZK SEK NOK DKK INR IDR PKR].freeze
|
|
25
|
+
|
|
26
|
+
module_function
|
|
27
|
+
|
|
28
|
+
def integer_to_words(number, feminine: false)
|
|
29
|
+
cardinal(number, feminine: feminine)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def triple_to_words(number, scale_idx, feminine: false)
|
|
33
|
+
return [] if number.zero?
|
|
34
|
+
|
|
35
|
+
words = []
|
|
36
|
+
|
|
37
|
+
if scale_idx == 1
|
|
38
|
+
return [SCALES[1][0]] if number == 1
|
|
39
|
+
|
|
40
|
+
words << under_thousand(number, feminine: feminine)
|
|
41
|
+
words << SCALES[1][1]
|
|
42
|
+
elsif scale_idx.positive?
|
|
43
|
+
words << (number == 1 ? "un" : under_thousand(number, feminine: feminine))
|
|
44
|
+
words << pluralize(number, *SCALES[scale_idx])
|
|
45
|
+
else
|
|
46
|
+
words << under_thousand(number, feminine: feminine)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
words
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def minus_word
|
|
53
|
+
GRAMMAR[:minus]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def fraction_joiner(joiner)
|
|
57
|
+
joiner.to_sym == :and ? "e" : GRAMMAR[:conjunction]
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def default_fraction_word
|
|
61
|
+
GRAMMAR[:default_fraction]
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def fraction_numerator_feminine?
|
|
65
|
+
false
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def decimal_separator_word
|
|
69
|
+
GRAMMAR[:conjunction]
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def decimal_fraction_words(fraction_string)
|
|
73
|
+
fraction_string.chars.map { |digit| cardinal(digit.to_i) }.join(" ")
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def time_unit_feminine?(unit)
|
|
77
|
+
unit == :hour
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def currency_major_feminine?(currency)
|
|
81
|
+
FEMININE_MAJOR_CURRENCIES.include?(currency)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def currency_minor_feminine?(_currency)
|
|
85
|
+
false
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def currency_number_words(number, currency, unit:)
|
|
89
|
+
feminine = unit == :major ? currency_major_feminine?(currency) : currency_minor_feminine?(currency)
|
|
90
|
+
|
|
91
|
+
cardinal(number, feminine: feminine)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def date_day(day, format:, date_case:)
|
|
95
|
+
cardinal(day)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def date_year(year, format:)
|
|
99
|
+
cardinal(year)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def ordinal(value, format, gender: :masculine)
|
|
103
|
+
ordinals = ORDINALS[format] || ORDINALS[:default] || ORDINALS[:nominative]
|
|
104
|
+
gender_data = ordinals[gender] || ordinals[:masculine]
|
|
105
|
+
|
|
106
|
+
return gender_data[value - 1] if value.between?(1, gender_data.length)
|
|
107
|
+
|
|
108
|
+
cardinal(value)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def cardinal(number, feminine: false)
|
|
112
|
+
integer_value = Integer(number)
|
|
113
|
+
negative = integer_value.negative?
|
|
114
|
+
integer_value = integer_value.abs
|
|
115
|
+
|
|
116
|
+
return ONES_MASC[0] if integer_value.zero?
|
|
117
|
+
|
|
118
|
+
groups = integer_value.to_s
|
|
119
|
+
.chars.reverse.each_slice(3).map(&:reverse)
|
|
120
|
+
.map(&:join).map!(&:to_i).reverse
|
|
121
|
+
|
|
122
|
+
words = []
|
|
123
|
+
groups.each_with_index do |group_value, index|
|
|
124
|
+
next if group_value.zero?
|
|
125
|
+
|
|
126
|
+
scale_idx = groups.size - index - 1
|
|
127
|
+
words.concat triple_to_words(group_value, scale_idx, feminine: feminine)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
words.unshift(minus_word) if negative
|
|
131
|
+
words.join(" ")
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def under_thousand(number, feminine: false)
|
|
135
|
+
return under_hundred(number, feminine: feminine) if number < 100
|
|
136
|
+
|
|
137
|
+
hundreds = number / 100
|
|
138
|
+
rest = number % 100
|
|
139
|
+
hundred_word = HUNDREDS[hundreds]
|
|
140
|
+
hundred_word = hundred_word[0...-1] if rest.between?(80, 89)
|
|
141
|
+
|
|
142
|
+
return hundred_word if rest.zero?
|
|
143
|
+
|
|
144
|
+
"#{hundred_word}#{under_hundred(rest, feminine: feminine)}"
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def under_hundred(number, feminine: false)
|
|
148
|
+
ones_data = feminine ? ONES_FEM : ONES_MASC
|
|
149
|
+
|
|
150
|
+
return ones_data[number] if number < 10
|
|
151
|
+
return TEENS[number - 10] if number < 20
|
|
152
|
+
|
|
153
|
+
tens = number / 10
|
|
154
|
+
ones = number % 10
|
|
155
|
+
return TENS[tens] if ones.zero?
|
|
156
|
+
|
|
157
|
+
tens_word = TENS[tens]
|
|
158
|
+
tens_word = tens_word[0...-1] if [1, 8].include?(ones)
|
|
159
|
+
"#{tens_word}#{ones_data[ones]}"
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def pluralize(number, singular, _few, plural)
|
|
163
|
+
number.abs == 1 ? singular : plural
|
|
164
|
+
end
|
|
23
165
|
end
|
|
24
166
|
|
|
25
167
|
register :it, IT
|
data/lib/num2words/locales/ja.rb
CHANGED
|
@@ -20,6 +20,132 @@ module Num2words
|
|
|
20
20
|
DATETIME_TEMPLATE = I18n.t("num2words.datetime.template", locale: :ja)
|
|
21
21
|
|
|
22
22
|
ORDINALS = I18n.t("num2words.numbers.ordinals", locale: :ja)
|
|
23
|
+
|
|
24
|
+
THOUSANDS = ["", "せん", "にせん", "さんぜん", "よんせん", "ごせん", "ろくせん", "ななせん", "はっせん", "きゅうせん"].freeze
|
|
25
|
+
LARGE_SCALES = ["", "まん", "おく", "ちょう", "けい"].freeze
|
|
26
|
+
|
|
27
|
+
class << self
|
|
28
|
+
def integer_to_words(number, feminine: false)
|
|
29
|
+
integer_value = Integer(number)
|
|
30
|
+
negative = integer_value.negative?
|
|
31
|
+
integer_value = integer_value.abs
|
|
32
|
+
|
|
33
|
+
return ONES_MASC[0] if integer_value.zero?
|
|
34
|
+
|
|
35
|
+
groups = integer_value.to_s
|
|
36
|
+
.chars.reverse.each_slice(4).map(&:reverse)
|
|
37
|
+
.map(&:join).map!(&:to_i).reverse
|
|
38
|
+
|
|
39
|
+
words = groups.each_with_index.filter_map do |group_value, index|
|
|
40
|
+
next if group_value.zero?
|
|
41
|
+
|
|
42
|
+
scale_index = groups.size - index - 1
|
|
43
|
+
"#{under_ten_thousand(group_value)}#{LARGE_SCALES.fetch(scale_index, '')}"
|
|
44
|
+
end.join
|
|
45
|
+
|
|
46
|
+
negative ? "#{minus_word}#{words}" : words
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def triple_to_words(number, scale_idx, feminine: false)
|
|
50
|
+
words = under_ten_thousand(number)
|
|
51
|
+
scale = LARGE_SCALES[scale_idx].to_s
|
|
52
|
+
["#{words}#{scale}"]
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def minus_word
|
|
56
|
+
GRAMMAR[:minus]
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def fraction_joiner(joiner)
|
|
60
|
+
joiner.to_sym == :and ? "と" : GRAMMAR[:conjunction]
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def default_fraction_word
|
|
64
|
+
GRAMMAR[:default_fraction]
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def decimal_separator_word
|
|
68
|
+
GRAMMAR[:decimal_separator] || "てん"
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def decimal_fraction_words(fraction_string)
|
|
72
|
+
fraction_string.chars.map { |digit| ONES_MASC[digit.to_i] }.join
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def join_decimal_words(words)
|
|
76
|
+
words.compact.reject(&:empty?).join
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def join_fraction_words(words)
|
|
80
|
+
sign_word, integer_words, conjunction_word, numerator_words, denominator_words = words
|
|
81
|
+
numerator_words = "" if denominator_words.to_s.end_with?(numerator_words.to_s)
|
|
82
|
+
|
|
83
|
+
[sign_word, integer_words, conjunction_word, denominator_words, numerator_words].compact.reject(&:empty?).join
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def pluralize(number, singular, few, _plural)
|
|
87
|
+
number == 1 ? singular : few
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def currency_major_feminine?(_currency)
|
|
91
|
+
false
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def currency_minor_feminine?(_currency)
|
|
95
|
+
false
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def currency_number_words(number, _currency, unit:)
|
|
99
|
+
integer_to_words(number)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def join_currency_parts(parts)
|
|
103
|
+
parts.join
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def time_unit_feminine?(_unit)
|
|
107
|
+
false
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def time_number_words(number, unit:)
|
|
111
|
+
integer_to_words(number)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def join_time_words(number_words, unit_words)
|
|
115
|
+
"#{number_words}#{unit_words}"
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def date_day(day, format: :default, date_case: :default)
|
|
119
|
+
integer_to_words(day)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def date_year(year, format: :default)
|
|
123
|
+
integer_to_words(year)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def under_ten_thousand(number)
|
|
127
|
+
thousands = number / 1000
|
|
128
|
+
remainder = number % 1000
|
|
129
|
+
hundreds = remainder / 100
|
|
130
|
+
rest = remainder % 100
|
|
131
|
+
|
|
132
|
+
[
|
|
133
|
+
THOUSANDS[thousands],
|
|
134
|
+
HUNDREDS[hundreds],
|
|
135
|
+
under_hundred(rest)
|
|
136
|
+
].compact.reject(&:empty?).join
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def under_hundred(number)
|
|
140
|
+
return "" if number.zero?
|
|
141
|
+
return TEENS[number - 10] if number.between?(10, 19)
|
|
142
|
+
|
|
143
|
+
tens = number / 10
|
|
144
|
+
ones = number % 10
|
|
145
|
+
|
|
146
|
+
[TENS[tens], ones.positive? ? ONES_MASC[ones] : nil].compact.reject(&:empty?).join
|
|
147
|
+
end
|
|
148
|
+
end
|
|
23
149
|
end
|
|
24
150
|
|
|
25
151
|
register :ja, JA
|