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.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +22 -0
  3. data/README.md +113 -144
  4. data/config/locales/ar.yml +5 -1
  5. data/config/locales/be.yml +4 -0
  6. data/config/locales/bg.yml +4 -0
  7. data/config/locales/bn.yml +4 -0
  8. data/config/locales/cs.yml +6 -2
  9. data/config/locales/da.yml +4 -0
  10. data/config/locales/de.yml +8 -4
  11. data/config/locales/el.yml +4 -0
  12. data/config/locales/en.yml +4 -0
  13. data/config/locales/es.yml +4 -0
  14. data/config/locales/et.yml +9 -5
  15. data/config/locales/fa.yml +15 -11
  16. data/config/locales/fi.yml +8 -4
  17. data/config/locales/fr.yml +4 -0
  18. data/config/locales/gu.yml +4 -0
  19. data/config/locales/he.yml +6 -2
  20. data/config/locales/hi.yml +4 -0
  21. data/config/locales/hr.yml +8 -4
  22. data/config/locales/hu.yml +6 -2
  23. data/config/locales/id.yml +4 -0
  24. data/config/locales/it.yml +4 -0
  25. data/config/locales/ja.yml +10 -5
  26. data/config/locales/kn.yml +186 -10
  27. data/config/locales/ko.yml +184 -13
  28. data/config/locales/kz.yml +183 -17
  29. data/config/locales/lt.yml +184 -8
  30. data/config/locales/lv.yml +188 -12
  31. data/config/locales/ml.yml +189 -13
  32. data/config/locales/mr.yml +184 -8
  33. data/config/locales/ms.yml +184 -8
  34. data/config/locales/nb.yml +183 -17
  35. data/config/locales/nl.yml +184 -13
  36. data/config/locales/pa.yml +189 -13
  37. data/config/locales/pl.yml +184 -13
  38. data/config/locales/pt.yml +184 -13
  39. data/config/locales/ro.yml +183 -12
  40. data/config/locales/ru.yml +4 -0
  41. data/config/locales/sk.yml +184 -8
  42. data/config/locales/sl.yml +185 -9
  43. data/config/locales/sr.yml +186 -15
  44. data/config/locales/sv.yml +182 -13
  45. data/config/locales/sw.yml +184 -8
  46. data/config/locales/ta.yml +184 -8
  47. data/config/locales/te.yml +185 -9
  48. data/config/locales/th.yml +183 -12
  49. data/config/locales/tr.yml +183 -12
  50. data/config/locales/uk.yml +189 -18
  51. data/config/locales/ur.yml +187 -11
  52. data/config/locales/vi.yml +183 -12
  53. data/config/locales/zh.yml +191 -9
  54. data/lib/num2words/converter.rb +144 -35
  55. data/lib/num2words/locales/ar.rb +130 -0
  56. data/lib/num2words/locales/be.rb +101 -0
  57. data/lib/num2words/locales/bg.rb +127 -0
  58. data/lib/num2words/locales/bn.rb +112 -0
  59. data/lib/num2words/locales/cs.rb +106 -0
  60. data/lib/num2words/locales/da.rb +97 -0
  61. data/lib/num2words/locales/de.rb +119 -0
  62. data/lib/num2words/locales/el.rb +143 -0
  63. data/lib/num2words/locales/en.rb +90 -0
  64. data/lib/num2words/locales/es.rb +185 -0
  65. data/lib/num2words/locales/et.rb +104 -0
  66. data/lib/num2words/locales/fa.rb +104 -0
  67. data/lib/num2words/locales/fi.rb +104 -0
  68. data/lib/num2words/locales/fr.rb +121 -0
  69. data/lib/num2words/locales/gu.rb +112 -0
  70. data/lib/num2words/locales/he.rb +130 -0
  71. data/lib/num2words/locales/hi.rb +112 -0
  72. data/lib/num2words/locales/hr.rb +117 -0
  73. data/lib/num2words/locales/hu.rb +111 -0
  74. data/lib/num2words/locales/id.rb +104 -0
  75. data/lib/num2words/locales/it.rb +142 -0
  76. data/lib/num2words/locales/ja.rb +126 -0
  77. data/lib/num2words/locales/kn.rb +122 -2
  78. data/lib/num2words/locales/ko.rb +158 -2
  79. data/lib/num2words/locales/kz.rb +137 -2
  80. data/lib/num2words/locales/lt.rb +146 -2
  81. data/lib/num2words/locales/lv.rb +148 -2
  82. data/lib/num2words/locales/ml.rb +142 -2
  83. data/lib/num2words/locales/mr.rb +142 -2
  84. data/lib/num2words/locales/ms.rb +134 -2
  85. data/lib/num2words/locales/nb.rb +153 -0
  86. data/lib/num2words/locales/nl.rb +142 -2
  87. data/lib/num2words/locales/pa.rb +122 -2
  88. data/lib/num2words/locales/pl.rb +149 -2
  89. data/lib/num2words/locales/pt.rb +164 -2
  90. data/lib/num2words/locales/ro.rb +165 -2
  91. data/lib/num2words/locales/ru.rb +100 -0
  92. data/lib/num2words/locales/sk.rb +124 -2
  93. data/lib/num2words/locales/sl.rb +154 -2
  94. data/lib/num2words/locales/sr.rb +141 -3
  95. data/lib/num2words/locales/sv.rb +141 -2
  96. data/lib/num2words/locales/sw.rb +133 -2
  97. data/lib/num2words/locales/ta.rb +142 -2
  98. data/lib/num2words/locales/te.rb +142 -2
  99. data/lib/num2words/locales/th.rb +133 -2
  100. data/lib/num2words/locales/tr.rb +141 -2
  101. data/lib/num2words/locales/uk.rb +134 -2
  102. data/lib/num2words/locales/ur.rb +130 -2
  103. data/lib/num2words/locales/vi.rb +142 -2
  104. data/lib/num2words/locales/zh.rb +172 -2
  105. data/lib/num2words/version.rb +1 -1
  106. data/num2words.gemspec +2 -2
  107. metadata +6 -6
  108. data/lib/num2words/locales/no.rb +0 -19
@@ -20,6 +20,118 @@ module Num2words
20
20
  DATETIME_TEMPLATE = I18n.t("num2words.datetime.template", locale: :gu)
21
21
 
22
22
  ORDINALS = I18n.t("num2words.numbers.ordinals", locale: :gu)
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
+ 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
23
135
  end
24
136
 
25
137
  register :gu, GU
@@ -20,6 +20,136 @@ module Num2words
20
20
  DATETIME_TEMPLATE = I18n.t("num2words.datetime.template", locale: :he)
21
21
 
22
22
  ORDINALS = I18n.t("num2words.numbers.ordinals", locale: :he)
23
+
24
+ FEMININE_MAJOR_CURRENCIES = %i[TRY UAH CZK SEK NOK DKK INR IDR PKR].freeze
25
+ FEMININE_MINOR_CURRENCIES = %i[ILS RUB UAH BGN BYN SAR INR PKR RSD BDT].freeze
26
+
27
+ module_function
28
+
29
+ def integer_to_words(number, feminine: false)
30
+ cardinal(number, feminine: feminine)
31
+ end
32
+
33
+ def triple_to_words(number, scale_idx, feminine: false)
34
+ return [] if number.zero?
35
+
36
+ words = []
37
+ scale_forms = SCALES[scale_idx]
38
+
39
+ if scale_idx == 1
40
+ return [scale_forms[0]] if number == 1
41
+ return [scale_forms[1]] if number == 2
42
+ elsif scale_idx.positive? && number == 1
43
+ return [scale_forms[0]]
44
+ end
45
+
46
+ words << under_thousand(number, feminine: feminine)
47
+ words << pluralize(number, *scale_forms) unless scale_idx.zero?
48
+ words
49
+ end
50
+
51
+ def minus_word
52
+ GRAMMAR[:minus]
53
+ end
54
+
55
+ def fraction_joiner(joiner)
56
+ joiner.to_sym == :and ? "ו" : GRAMMAR[:conjunction]
57
+ end
58
+
59
+ def default_fraction_word
60
+ GRAMMAR[:default_fraction]
61
+ end
62
+
63
+ def fraction_numerator_feminine?
64
+ true
65
+ end
66
+
67
+ def decimal_separator_word
68
+ "נקודה"
69
+ end
70
+
71
+ def decimal_fraction_words(fraction_string)
72
+ fraction_string.chars.map { |digit| cardinal(digit.to_i) }.join(" ")
73
+ end
74
+
75
+ def time_unit_feminine?(unit)
76
+ unit == :hour || unit == :minute || unit == :second
77
+ end
78
+
79
+ def currency_major_feminine?(currency)
80
+ FEMININE_MAJOR_CURRENCIES.include?(currency)
81
+ end
82
+
83
+ def currency_minor_feminine?(currency)
84
+ FEMININE_MINOR_CURRENCIES.include?(currency)
85
+ end
86
+
87
+ def date_day(day, format:, date_case:)
88
+ ordinal(day, :default)
89
+ end
90
+
91
+ def date_year(year, format:)
92
+ cardinal(year)
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
+ words.concat triple_to_words(group_value, scale_idx, feminine: feminine)
121
+ end
122
+
123
+ words.unshift(minus_word) if negative
124
+ words.join(" ")
125
+ end
126
+
127
+ def under_thousand(number, feminine: false)
128
+ return under_hundred(number, feminine: feminine) if number < 100
129
+
130
+ hundreds = number / 100
131
+ rest = number % 100
132
+ words = [HUNDREDS[hundreds]]
133
+ words << under_hundred(rest, feminine: feminine) if rest.positive?
134
+ words.join(" ")
135
+ end
136
+
137
+ def under_hundred(number, feminine: false)
138
+ ones_data = feminine ? ONES_FEM : ONES_MASC
139
+
140
+ return ones_data[number] if number < 10
141
+ return TEENS[number - 10] if number < 20
142
+
143
+ tens = number / 10
144
+ ones = number % 10
145
+ words = [TENS[tens]]
146
+ words << "ו#{ones_data[ones]}" if ones.positive?
147
+ words.join(" ")
148
+ end
149
+
150
+ def pluralize(number, singular, _few, plural)
151
+ number.abs == 1 ? singular : plural
152
+ end
23
153
  end
24
154
 
25
155
  register :he, HE
@@ -20,6 +20,118 @@ module Num2words
20
20
  DATETIME_TEMPLATE = I18n.t("num2words.datetime.template", locale: :hi)
21
21
 
22
22
  ORDINALS = I18n.t("num2words.numbers.ordinals", locale: :hi)
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
23
135
  end
24
136
 
25
137
  register :hi, HI
@@ -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
@@ -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