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
@@ -20,6 +20,110 @@ module Num2words
20
20
  DATETIME_TEMPLATE = I18n.t("num2words.datetime.template", locale: :fi)
21
21
 
22
22
  ORDINALS = I18n.t("num2words.numbers.ordinals", locale: :fi)
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 << pluralize(number, *SCALES[scale_idx]) 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 ? "ja" : 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
+ "pilkku"
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
+ ordinal(day, :default)
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[hundreds]]
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 = [TENS[tens]]
120
+ words << ONES_MASC[ones] if ones.positive?
121
+ words.join
122
+ end
123
+
124
+ def pluralize(number, singular, few, _plural)
125
+ number.abs == 1 ? singular : few
126
+ end
23
127
  end
24
128
 
25
129
  register :fi, FI
@@ -20,6 +20,127 @@ module Num2words
20
20
  DATETIME_TEMPLATE = I18n.t("num2words.datetime.template", locale: :fr)
21
21
 
22
22
  ORDINALS = I18n.t("num2words.numbers.ordinals", locale: :fr)
23
+
24
+ module_function
25
+
26
+ def minus_word
27
+ GRAMMAR[:minus]
28
+ end
29
+
30
+ def fraction_joiner(_joiner)
31
+ GRAMMAR[:conjunction]
32
+ end
33
+
34
+ def default_fraction_word
35
+ GRAMMAR[:default_fraction]
36
+ end
37
+
38
+ def fraction_numerator_feminine?
39
+ false
40
+ end
41
+
42
+ def decimal_separator_word
43
+ "virgule"
44
+ end
45
+
46
+ def decimal_fraction_words(fraction_string)
47
+ fraction_string.chars.map { |digit| under_thousand(digit.to_i) }.join(" ")
48
+ end
49
+
50
+ def time_unit_feminine?(unit)
51
+ unit == :hour || unit == :minute || unit == :second
52
+ end
53
+
54
+ def currency_major_feminine?(currency)
55
+ %i[GBP TRY UAH CZK SEK NOK DKK INR IDR PKR].include?(currency)
56
+ end
57
+
58
+ def currency_minor_feminine?(currency)
59
+ %i[ILS BGN SAR].include?(currency)
60
+ end
61
+
62
+ def triple_to_words(number, scale_idx, feminine: false)
63
+ words = scale_idx == 1 && number == 1 ? [] : under_thousand(number, feminine: feminine).split
64
+
65
+ unless scale_idx.zero?
66
+ scale_forms = SCALES[scale_idx]
67
+ words << (number == 1 ? scale_forms[0] : scale_forms[2])
68
+ end
69
+
70
+ words
71
+ end
72
+
73
+ def date_day(day, format:, date_case:)
74
+ return "premier" if day == 1
75
+
76
+ under_thousand(day)
77
+ end
78
+
79
+ def date_year(year, format:)
80
+ groups = year.to_s
81
+ .chars.reverse.each_slice(3).map(&:reverse)
82
+ .map(&:join).map!(&:to_i).reverse
83
+
84
+ words = []
85
+ groups.each_with_index do |group_value, index|
86
+ scale_index = groups.size - index - 1
87
+ words.concat triple_to_words(group_value, scale_index)
88
+ end
89
+
90
+ words.join(" ")
91
+ end
92
+
93
+ def under_thousand(number, feminine: false)
94
+ hundreds = number / 100
95
+ rest = number % 100
96
+
97
+ return under_hundred(rest, feminine: feminine) if hundreds.zero?
98
+
99
+ hundred_words = if hundreds == 1
100
+ HUNDREDS[1]
101
+ elsif rest.zero?
102
+ HUNDREDS[hundreds]
103
+ else
104
+ HUNDREDS[hundreds].sub(/s\z/, "")
105
+ end
106
+
107
+ return hundred_words if rest.zero?
108
+
109
+ [hundred_words, under_hundred(rest, feminine: feminine)].join(" ")
110
+ end
111
+
112
+ def under_hundred(number, feminine: false)
113
+ ones_data = feminine ? ONES_FEM : ONES_MASC
114
+
115
+ return ones_data[number] if number < 10
116
+ return TEENS[number - 10] if number < 20
117
+
118
+ case number
119
+ when 20..69
120
+ tens = number / 10
121
+ ones = number % 10
122
+ return TENS[tens] if ones.zero?
123
+ return "#{TENS[tens]} et #{ones_data[ones]}" if ones == 1
124
+
125
+ "#{TENS[tens]} #{ones_data[ones]}"
126
+ when 70..79
127
+ teen = number - 60
128
+ return "soixante et #{TEENS[1]}" if teen == 11
129
+
130
+ "soixante #{under_hundred(teen, feminine: feminine)}"
131
+ when 80
132
+ "quatre-vingts"
133
+ else
134
+ rest = number - 80
135
+ return "quatre-vingt" if rest.zero?
136
+
137
+ "quatre-vingt #{under_hundred(rest, feminine: feminine)}"
138
+ end
139
+ end
140
+
141
+ def pluralize(number, singular, _few, plural)
142
+ number.abs == 1 ? singular : plural
143
+ end
23
144
  end
24
145
 
25
146
  register :fr, FR
@@ -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