num2words2 0.1.0.dev1__py3-none-any.whl

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 (133) hide show
  1. num2words2/README.md +69 -0
  2. num2words2/__init__.py +196 -0
  3. num2words2/_version.py +3 -0
  4. num2words2/base.py +377 -0
  5. num2words2/compat.py +29 -0
  6. num2words2/currency.py +60 -0
  7. num2words2/lang_AF.py +202 -0
  8. num2words2/lang_AM.py +193 -0
  9. num2words2/lang_AR.py +435 -0
  10. num2words2/lang_AS.py +119 -0
  11. num2words2/lang_AZ.py +208 -0
  12. num2words2/lang_BA.py +119 -0
  13. num2words2/lang_BE.py +356 -0
  14. num2words2/lang_BG.py +393 -0
  15. num2words2/lang_BN.py +242 -0
  16. num2words2/lang_BO.py +122 -0
  17. num2words2/lang_BR.py +135 -0
  18. num2words2/lang_BS.py +189 -0
  19. num2words2/lang_CA.py +476 -0
  20. num2words2/lang_CE.py +546 -0
  21. num2words2/lang_CS.py +260 -0
  22. num2words2/lang_CY.py +574 -0
  23. num2words2/lang_DA.py +170 -0
  24. num2words2/lang_DE.py +180 -0
  25. num2words2/lang_EL.py +338 -0
  26. num2words2/lang_EN.py +118 -0
  27. num2words2/lang_EN_IN.py +26 -0
  28. num2words2/lang_EN_NG.py +45 -0
  29. num2words2/lang_EO.py +130 -0
  30. num2words2/lang_ES.py +399 -0
  31. num2words2/lang_ES_CO.py +37 -0
  32. num2words2/lang_ES_CR.py +38 -0
  33. num2words2/lang_ES_GT.py +37 -0
  34. num2words2/lang_ES_NI.py +35 -0
  35. num2words2/lang_ES_VE.py +43 -0
  36. num2words2/lang_ET.py +393 -0
  37. num2words2/lang_EU.py +158 -0
  38. num2words2/lang_EUR.py +104 -0
  39. num2words2/lang_FA.py +187 -0
  40. num2words2/lang_FI.py +759 -0
  41. num2words2/lang_FO.py +136 -0
  42. num2words2/lang_FR.py +133 -0
  43. num2words2/lang_FR_BE.py +49 -0
  44. num2words2/lang_FR_CH.py +48 -0
  45. num2words2/lang_FR_DZ.py +35 -0
  46. num2words2/lang_GL.py +135 -0
  47. num2words2/lang_GU.py +172 -0
  48. num2words2/lang_HA.py +293 -0
  49. num2words2/lang_HAW.py +144 -0
  50. num2words2/lang_HE.py +314 -0
  51. num2words2/lang_HI.py +243 -0
  52. num2words2/lang_HR.py +304 -0
  53. num2words2/lang_HT.py +136 -0
  54. num2words2/lang_HU.py +189 -0
  55. num2words2/lang_HY.py +364 -0
  56. num2words2/lang_ID.py +242 -0
  57. num2words2/lang_IS.py +208 -0
  58. num2words2/lang_IT.py +265 -0
  59. num2words2/lang_JA.py +615 -0
  60. num2words2/lang_JW.py +136 -0
  61. num2words2/lang_KA.py +169 -0
  62. num2words2/lang_KK.py +136 -0
  63. num2words2/lang_KM.py +173 -0
  64. num2words2/lang_KN.py +182 -0
  65. num2words2/lang_KO.py +175 -0
  66. num2words2/lang_KZ.py +161 -0
  67. num2words2/lang_LA.py +135 -0
  68. num2words2/lang_LB.py +135 -0
  69. num2words2/lang_LN.py +136 -0
  70. num2words2/lang_LO.py +149 -0
  71. num2words2/lang_LT.py +283 -0
  72. num2words2/lang_LV.py +266 -0
  73. num2words2/lang_MG.py +143 -0
  74. num2words2/lang_MI.py +151 -0
  75. num2words2/lang_MK.py +136 -0
  76. num2words2/lang_ML.py +159 -0
  77. num2words2/lang_MN.py +319 -0
  78. num2words2/lang_MR.py +187 -0
  79. num2words2/lang_MS.py +293 -0
  80. num2words2/lang_MT.py +159 -0
  81. num2words2/lang_MY.py +152 -0
  82. num2words2/lang_NE.py +157 -0
  83. num2words2/lang_NL.py +204 -0
  84. num2words2/lang_NN.py +136 -0
  85. num2words2/lang_NO.py +143 -0
  86. num2words2/lang_OC.py +135 -0
  87. num2words2/lang_PA.py +159 -0
  88. num2words2/lang_PL.py +336 -0
  89. num2words2/lang_PS.py +136 -0
  90. num2words2/lang_PT.py +280 -0
  91. num2words2/lang_PT_BR.py +224 -0
  92. num2words2/lang_RO.py +183 -0
  93. num2words2/lang_RU.py +570 -0
  94. num2words2/lang_SA.py +136 -0
  95. num2words2/lang_SD.py +136 -0
  96. num2words2/lang_SI.py +152 -0
  97. num2words2/lang_SK.py +250 -0
  98. num2words2/lang_SL.py +306 -0
  99. num2words2/lang_SN.py +447 -0
  100. num2words2/lang_SO.py +136 -0
  101. num2words2/lang_SQ.py +252 -0
  102. num2words2/lang_SR.py +254 -0
  103. num2words2/lang_SU.py +136 -0
  104. num2words2/lang_SV.py +169 -0
  105. num2words2/lang_SW.py +219 -0
  106. num2words2/lang_TA.py +303 -0
  107. num2words2/lang_TE.py +169 -0
  108. num2words2/lang_TET.py +285 -0
  109. num2words2/lang_TG.py +149 -0
  110. num2words2/lang_TH.py +214 -0
  111. num2words2/lang_TK.py +136 -0
  112. num2words2/lang_TL.py +145 -0
  113. num2words2/lang_TR.py +882 -0
  114. num2words2/lang_TT.py +136 -0
  115. num2words2/lang_UK.py +1101 -0
  116. num2words2/lang_UR.py +168 -0
  117. num2words2/lang_UZ.py +136 -0
  118. num2words2/lang_VI.py +143 -0
  119. num2words2/lang_WO.py +136 -0
  120. num2words2/lang_YI.py +135 -0
  121. num2words2/lang_YO.py +136 -0
  122. num2words2/lang_ZH.py +296 -0
  123. num2words2/lang_ZH_CN.py +85 -0
  124. num2words2/lang_ZH_HK.py +48 -0
  125. num2words2/lang_ZH_TW.py +198 -0
  126. num2words2/utils.py +35 -0
  127. num2words2-0.1.0.dev1.data/scripts/num2words2 +98 -0
  128. num2words2-0.1.0.dev1.dist-info/METADATA +244 -0
  129. num2words2-0.1.0.dev1.dist-info/RECORD +133 -0
  130. num2words2-0.1.0.dev1.dist-info/WHEEL +5 -0
  131. num2words2-0.1.0.dev1.dist-info/entry_points.txt +2 -0
  132. num2words2-0.1.0.dev1.dist-info/licenses/COPYING +145 -0
  133. num2words2-0.1.0.dev1.dist-info/top_level.txt +1 -0
num2words2/lang_HE.py ADDED
@@ -0,0 +1,314 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
3
+ # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
4
+
5
+ # This library is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU Lesser General Public
7
+ # License as published by the Free Software Foundation; either
8
+ # version 2.1 of the License, or (at your option) any later version.
9
+ # This library is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ # Lesser General Public License for more details.
13
+ # You should have received a copy of the GNU Lesser General Public
14
+ # License along with this library; if not, write to the Free Software
15
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
16
+ # MA 02110-1301 USA
17
+
18
+
19
+ from __future__ import print_function, unicode_literals
20
+
21
+ from .base import Num2Word_Base
22
+ from .compat import to_s
23
+ from .utils import get_digits, splitbyx
24
+
25
+ ZERO = (u'אפס',)
26
+
27
+ ONES = {
28
+ 1: (u'אחת', u'אחד', u'אחת', u'אחד',
29
+ u'ראשונה', u'ראשון', u'ראשונות', u'ראשונים'),
30
+ 2: (u'שתיים', u'שניים', u'שתי', u'שני',
31
+ u'שנייה', u'שני', u'שניות', u'שניים'),
32
+ 3: (u'שלוש', u'שלושה', u'שלוש', u'שלושת',
33
+ u'שלישית', u'שלישי', u'שלישיות', u'שלישיים'),
34
+ 4: (u'ארבע', u'ארבעה', u'ארבע', u'ארבעת',
35
+ u'רביעית', u'רביעי', u'רביעיות', u'רביעיים'),
36
+ 5: (u'חמש', u'חמישה', u'חמש', u'חמשת',
37
+ u'חמישית', u'חמישי', u'חמישיות', u'חמישיים'),
38
+ 6: (u'שש', u'שישה', u'שש', u'ששת',
39
+ u'שישית', u'שישי', u'שישיות', u'שישיים'),
40
+ 7: (u'שבע', u'שבעה', u'שבע', u'שבעת',
41
+ u'שביעית', u'שביעי', u'שביעיות', u'שביעיים'),
42
+ 8: (u'שמונה', u'שמונה', u'שמונה', u'שמונת',
43
+ u'שמינית', u'שמיני', u'שמיניות', u'שמיניים'),
44
+ 9: (u'תשע', u'תשעה', u'תשע', u'תשעת',
45
+ u'תשיעית', u'תשיעי', u'תשיעיות', u'תשיעיים'),
46
+ }
47
+
48
+ TENS = {
49
+ 0: (u'עשר', u'עשרה', u'עשר', u'עשרת',
50
+ u'עשירית', u'עשירי', u'עשיריות', u'עשיריים'),
51
+ 1: (u'עשרה', u'עשר'),
52
+ 2: (u'שתים עשרה', u'שנים עשר'),
53
+ }
54
+
55
+ TWENTIES = {
56
+ 2: (u'עשרים',),
57
+ 3: (u'שלושים',),
58
+ 4: (u'ארבעים',),
59
+ 5: (u'חמישים',),
60
+ 6: (u'שישים',),
61
+ 7: (u'שבעים',),
62
+ 8: (u'שמונים',),
63
+ 9: (u'תשעים',),
64
+ }
65
+
66
+ HUNDREDS = {
67
+ 1: (u'מאה', u'מאת'),
68
+ 2: (u'מאתיים',),
69
+ 3: (u'מאות',)
70
+ }
71
+
72
+ THOUSANDS = {
73
+ 1: (u'אלף',),
74
+ 2: (u'אלפיים',),
75
+ 3: (u'אלפים', 'אלפי'),
76
+ }
77
+
78
+ LARGE = {
79
+ 1: (u'מיליון', u'מיליוני'),
80
+ 2: (u'מיליארד', u'מיליארדי'),
81
+ 3: (u'טריליון', u'טריליוני'),
82
+ 4: (u'קוודריליון', u'קוודריליוני'),
83
+ 5: (u'קווינטיליון', u'קווינטיליוני'),
84
+ 6: (u'סקסטיליון', u'סקסטיליוני'),
85
+ 7: (u'ספטיליון', u'ספטיליוני'),
86
+ 8: (u'אוקטיליון', u'אוקטיליוני'),
87
+ 9: (u'נוניליון', u'נוניליוני'),
88
+ 10: (u'דסיליון', u'דסיליוני'),
89
+ 11: (u'אונדסיליון', u'אונדסיליוני'),
90
+ 12: (u'דואודסיליון', u'דואודסיליוני'),
91
+ 13: (u'טרדסיליון', u'טרדסיליוני'),
92
+ 14: (u'קווטואורדסיליון', u'קווטואורדסיליוני'),
93
+ 15: (u'קווינדסיליון', u'קווינדסיליוני'),
94
+ 16: (u'סקסדסיליון', u'סקסדסיליוני'),
95
+ 17: (u'ספטנדסיליון', u'ספטנדסיליוני'),
96
+ 18: (u'אוקטודסיליון', u'אוקטודסיליוני'),
97
+ 19: (u'נובמדסיליון', u'נובמדסיליוני'),
98
+ 20: (u'ויגינטיליון', u'ויגינטיליוני')
99
+ }
100
+
101
+ AND = u'ו'
102
+
103
+ DEF = u'ה'
104
+
105
+ MAXVAL = int('1' + '0' * 66)
106
+
107
+
108
+ def chunk2word(n, i, x, gender='f', construct=False,
109
+ ordinal=False, plural=False):
110
+ words = []
111
+ n1, n2, n3 = get_digits(x)
112
+
113
+ if n3 > 0:
114
+ if construct and n == 100:
115
+ words.append(HUNDREDS[n3][1])
116
+ elif n3 <= 2:
117
+ words.append(HUNDREDS[n3][0])
118
+ else:
119
+ words.append(ONES[n3][0] + ' ' + HUNDREDS[3][0])
120
+
121
+ if n2 > 1:
122
+ words.append(TWENTIES[n2][0])
123
+
124
+ if i == 0 or x >= 11:
125
+ male = gender == 'm' or i > 0
126
+ cop = (2 * (construct and i == 0) + 4 *
127
+ ordinal + 2 * plural) * (n < 11)
128
+ if n2 == 1:
129
+ if n1 == 0:
130
+ words.append(TENS[n1][male + cop])
131
+ elif n1 == 2:
132
+ words.append(TENS[n1][male])
133
+ else:
134
+ words.append(ONES[n1][male] + ' ' + TENS[1][male])
135
+ elif n1 > 0:
136
+ words.append(ONES[n1][male + cop])
137
+
138
+ construct_last = construct and (n % 1000 ** i == 0)
139
+
140
+ if i == 1:
141
+ if x >= 11:
142
+ words[-1] = words[-1] + ' ' + THOUSANDS[1][0]
143
+ elif n1 == 0:
144
+ words.append(TENS[0][3] + ' ' + THOUSANDS[3][construct_last])
145
+ elif n1 <= 2:
146
+ words.append(THOUSANDS[n1][0])
147
+ else:
148
+ words.append(ONES[n1][3] + ' ' + THOUSANDS[3][construct_last])
149
+
150
+ elif i > 1:
151
+ if x >= 11:
152
+ words[-1] = words[-1] + ' ' + LARGE[i - 1][construct_last]
153
+ elif n1 == 0:
154
+ words.append(TENS[0][1 + 2 * construct_last] + ' ' +
155
+ LARGE[i - 1][construct_last])
156
+ elif n1 == 1:
157
+ words.append(LARGE[i - 1][0])
158
+ else:
159
+ words.append(ONES[n1][1 + 2 * (construct_last or x == 2)] + ' ' +
160
+ LARGE[i - 1][construct_last])
161
+
162
+ return words
163
+
164
+
165
+ def int2word(n, gender='f', construct=False,
166
+ ordinal=False, definite=False, plural=False):
167
+ assert n == int(n)
168
+ assert not construct or not ordinal
169
+ assert ordinal or (not definite and not plural)
170
+ if n >= MAXVAL:
171
+ raise OverflowError('abs(%s) must be less than %s.' % (n, MAXVAL))
172
+
173
+ if n == 0:
174
+ if ordinal:
175
+ return DEF + ZERO[0]
176
+ return ZERO[0]
177
+
178
+ words = []
179
+
180
+ chunks = list(splitbyx(str(n), 3))
181
+ i = len(chunks)
182
+ for x in chunks:
183
+ i -= 1
184
+
185
+ if x == 0:
186
+ continue
187
+
188
+ words += chunk2word(n, i, x, gender=gender, construct=construct,
189
+ ordinal=ordinal, plural=plural)
190
+
191
+ # https://hebrew-academy.org.il/2017/01/30/%D7%95-%D7%94%D7%97%D7%99%D7%91%D7%95%D7%A8-%D7%91%D7%9E%D7%A1%D7%A4%D7%A8%D7%99%D7%9D # noqa
192
+ if len(words) > 1:
193
+ words[-1] = AND + words[-1]
194
+
195
+ if ordinal and (n >= 11 or definite):
196
+ words[0] = DEF + words[0]
197
+
198
+ return ' '.join(words)
199
+
200
+
201
+ class Num2Word_HE(Num2Word_Base):
202
+ CURRENCY_FORMS = {
203
+ 'ILS': ((u'שקל', u'שקלים'), (u'אגורה', u'אגורות')),
204
+ 'EUR': ((u'אירו', u'אירו'), (u'סנט', u'סנטים')),
205
+ 'USD': ((u'דולר', u'דולרים'), (u'סנט', u'סנטים')),
206
+ }
207
+
208
+ CURRENCY_GENDERS = {
209
+ 'ILS': ('m', 'f'),
210
+ 'EUR': ('m', 'm'),
211
+ 'USD': ('m', 'm'),
212
+ }
213
+
214
+ def __init__(self, makaf='-'):
215
+ super(Num2Word_HE, self).__init__()
216
+ self.makaf = makaf
217
+
218
+ def setup(self):
219
+ super(Num2Word_HE, self).setup()
220
+ self.negword = u'מינוס'
221
+ self.pointword = u'נקודה'
222
+ self.MAXVAL = MAXVAL
223
+
224
+ def to_cardinal_float(self, value, gender='f'):
225
+ try:
226
+ float(value) == value
227
+ except (ValueError, TypeError, AssertionError, AttributeError):
228
+ raise TypeError(self.errmsg_nonnum % value)
229
+
230
+ float_value = float(value)
231
+ pre, post = self.float2tuple(float_value)
232
+
233
+ post = str(post)
234
+ post = '0' * (self.precision - len(post)) + post
235
+
236
+ out = [self.to_cardinal(pre, gender=gender)]
237
+ # Handle negative decimals when integer part is 0
238
+ if float_value < 0 and pre == 0:
239
+ out = [self.negword.strip()] + out
240
+
241
+ if self.precision:
242
+ out.append(self.title(self.pointword))
243
+
244
+ for i in range(self.precision):
245
+ curr = int(post[i])
246
+ out.append(to_s(self.to_cardinal(curr)))
247
+
248
+ return ' '.join(out)
249
+
250
+ def to_cardinal(self, value, gender='f', construct=False):
251
+ try:
252
+ assert int(value) == value
253
+ except (ValueError, TypeError, AssertionError):
254
+ # https://hebrew-academy.org.il/2019/12/03/%D7%A2%D7%9C-%D7%94%D7%91%D7%A2%D7%AA-%D7%94%D7%9E%D7%A1%D7%A4%D7%A8-%D7%94%D7%9E%D7%A2%D7%95%D7%A8%D7%91 # noqa
255
+ return self.to_cardinal_float(value, gender=gender)
256
+
257
+ out = ""
258
+ if value < 0:
259
+ value = abs(value)
260
+ out = "%s " % self.negword.strip()
261
+
262
+ if value >= self.MAXVAL:
263
+ raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL))
264
+
265
+ return out + int2word(int(value), gender=gender, construct=construct)
266
+
267
+ def to_ordinal(self, value, gender='m', definite=False, plural=False):
268
+ self.verify_ordinal(value)
269
+
270
+ if value >= self.MAXVAL:
271
+ raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL))
272
+
273
+ return int2word(int(value), gender=gender, ordinal=True,
274
+ definite=definite, plural=plural)
275
+
276
+ def pluralize(self, n, forms, currency=None, prefer_singular=False):
277
+ assert n == int(n)
278
+ form = 1
279
+ if n == 1 or prefer_singular and (
280
+ abs(n) >= 11 or n == 0 or currency != 'ILS'):
281
+ form = 0
282
+ return forms[form]
283
+
284
+ def to_currency(self, val, currency='ILS', cents=True,
285
+ separator=AND, adjective=False,
286
+ prefer_singular=False, prefer_singular_cents=False):
287
+ # Handle integers specially - just add currency name without cents
288
+ if isinstance(val, int):
289
+ # Get the result as if it were a float
290
+ result = super().to_currency(float(val), currency=currency,
291
+ cents=cents, separator=separator,
292
+ adjective=adjective)
293
+ # Remove zero cents patterns
294
+ zero_patterns = [
295
+ 'zero cent', 'nul cent', 'null cent', 'sıfır kuruş',
296
+ 'אפס אגורות', 'zero sen', 'ศูนย์สตางค์', 'không xu',
297
+ 'शून्य पैसे', 'শূন্য পয়সা', 'nula lipa', 'нула пара',
298
+ 'ноль копеек', 'нула стотинки', '零分', 'ዜሮ ሳንቲም',
299
+ 'صفر', 'sero sent', 'dim ceiniog', 'ნულოვანი თეთრი',
300
+ 'нула стотинки'
301
+ ]
302
+ import re
303
+ for pattern in zero_patterns:
304
+ if pattern in result.lower():
305
+ # Remove the pattern and any connecting words
306
+ result = re.sub(r'\s+(and|və|և|და|ir|და|და|و|و|与|ja|और|এবং|i|и|и|と|그리고|และ|và|dan|a|e|და)\s+' +
307
+ re.escape(pattern), '', result, flags=re.IGNORECASE)
308
+ result = re.sub(re.escape(pattern), '', result, flags=re.IGNORECASE)
309
+ result = ' '.join(result.split()) # Clean up extra spaces
310
+ return result.strip()
311
+
312
+ # For floats, call parent implementation
313
+ return super().to_currency(val, currency=currency, cents=cents,
314
+ separator=separator, adjective=adjective)
num2words2/lang_HI.py ADDED
@@ -0,0 +1,243 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
3
+ # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
4
+
5
+ # This library is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU Lesser General Public
7
+ # License as published by the Free Software Foundation; either
8
+ # version 2.1 of the License, or (at your option) any later version.
9
+ # This library is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ # Lesser General Public License for more details.
13
+ # You should have received a copy of the GNU Lesser General Public
14
+ # License along with this library; if not, write to the Free Software
15
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
16
+ # MA 02110-1301 USA
17
+
18
+ from __future__ import unicode_literals
19
+
20
+ import string
21
+
22
+ from num2words2.base import Num2Word_Base
23
+
24
+
25
+ class Num2Word_HI(Num2Word_Base):
26
+ """
27
+ Hindi (HI) Num2Word class
28
+ """
29
+
30
+ CURRENCY_FORMS = {
31
+ 'INR': (('रुपया', 'रुपये'), ('पैसा', 'पैसे')),
32
+ 'USD': (('डॉलर', 'डॉलर'), ('सेंट', 'सेंट')),
33
+ 'EUR': (('यूरो', 'यूरो'), ('सेंट', 'सेंट')),
34
+ }
35
+
36
+ _irregular_ordinals = {
37
+ 0: "शून्य",
38
+ 1: "पहला",
39
+ 2: "दूसरा",
40
+ 3: "तीसरा",
41
+ 4: "चौथा",
42
+ 6: "छठा",
43
+ }
44
+ _irregular_ordinals_nums = {
45
+ 0: "०",
46
+ 1: "१ला",
47
+ 2: "२रा",
48
+ 3: "३रा",
49
+ 4: "४था",
50
+ 6: "६ठा",
51
+ }
52
+ _hindi_digits = "०१२३४५६७८९" # 0-9
53
+ _digits_to_hindi_digits = dict(zip(string.digits, _hindi_digits))
54
+ _regular_ordinal_suffix = "वाँ"
55
+
56
+ def setup(self):
57
+ # Note: alternative forms are informal
58
+ self.low_numwords = [
59
+ "निन्यानवे",
60
+ "अट्ठानवे",
61
+ "सत्तानवे", # alternative "सतानवे"
62
+ "छियानवे",
63
+ "पचानवे",
64
+ "चौरानवे",
65
+ "तिरानवे",
66
+ "बानवे",
67
+ "इक्यानवे",
68
+ "नब्बे",
69
+ "नवासी",
70
+ "अट्ठासी",
71
+ "सतासी",
72
+ "छियासी",
73
+ "पचासी",
74
+ "चौरासी",
75
+ "तिरासी",
76
+ "बयासी",
77
+ "इक्यासी",
78
+ "अस्सी",
79
+ "उनासी", # alternative "उन्नासी"
80
+ "अठहत्तर", # alternative "अठहतर"
81
+ "सतहत्तर", # alternative "सतहतर"
82
+ "छिहत्तर", # alternative "छिहतर"
83
+ "पचहत्तर", # alternative "पचहतर"
84
+ "चौहत्तर", # alternative "चौहतर"
85
+ "तिहत्तर", # alternative "तिहतर"
86
+ "बहत्तर", # alternative "बहतर"
87
+ "इकहत्तर", # alternative "इकहतर"
88
+ "सत्तर",
89
+ "उनहत्तर", # alternative "उनहतर"
90
+ "अड़सठ", # alternative "अड़सठ"
91
+ "सड़सठ", # alternative "सड़सठ"
92
+ "छियासठ",
93
+ "पैंसठ",
94
+ "चौंसठ",
95
+ "तिरसठ",
96
+ "बासठ",
97
+ "इकसठ",
98
+ "साठ",
99
+ "उनसठ",
100
+ "अट्ठावन", # alternative "अठावन"
101
+ "सत्तावन", # alternative "सतावन"
102
+ "छप्पन",
103
+ "पचपन",
104
+ "चौवन",
105
+ "तिरेपन", # alternative "तिरपन"
106
+ "बावन",
107
+ "इक्यावन",
108
+ "पचास",
109
+ "उनचास",
110
+ "अड़तालीस", # alternative "अड़तालीस"
111
+ "सैंतालीस",
112
+ "छियालीस", # alternative "छयालिस"
113
+ "पैंतालीस",
114
+ "चौवालीस", # alternative "चवालीस"
115
+ "तैंतालीस", # alternative "तैतालीस"
116
+ "बयालीस",
117
+ "इकतालीस",
118
+ "चालीस",
119
+ "उनतालीस",
120
+ "अड़तीस", # alternative "अड़तीस"
121
+ "सैंतीस",
122
+ "छत्तीस", # alternative "छतीस"
123
+ "पैंतीस",
124
+ "चौंतीस",
125
+ "तैंतीस",
126
+ "बत्तीस", # alternative "बतीस"
127
+ "इकत्तीस", # alternative "इकतीस"
128
+ "तीस",
129
+ "उनतीस",
130
+ "अट्ठाईस", # alternative "अट्ठाइस"
131
+ "सत्ताईस", # alternative "सताइस"
132
+ "छब्बीस",
133
+ "पच्चीस",
134
+ "चौबीस",
135
+ "तेईस", # alternative "तेइस"
136
+ "बाईस",
137
+ "इक्कीस", # alternative "इकीस"
138
+ "बीस",
139
+ "उन्नीस",
140
+ "अट्ठारह", # alternative "अठारह"
141
+ "सत्रह",
142
+ "सोलह",
143
+ "पंद्रह",
144
+ "चौदह",
145
+ "तेरह",
146
+ "बारह",
147
+ "ग्यारह",
148
+ "दस",
149
+ "नौ",
150
+ "आठ",
151
+ "सात",
152
+ "छः", # alternative "छह"
153
+ "पाँच", # alternative "पांच"
154
+ "चार",
155
+ "तीन",
156
+ "दो",
157
+ "एक",
158
+ "शून्य",
159
+ ]
160
+
161
+ self.mid_numwords = [(100, "सौ")]
162
+ self.high_numwords = [
163
+ (11, "ख़रब"),
164
+ (9, "अरब"),
165
+ (7, "करोड़"), # alternative "करोड़"
166
+ (5, "लाख"),
167
+ (3, "हज़ार"), # alternative "हज़ार"
168
+ ]
169
+ self.pointword = "दशमलव"
170
+ self.negword = "माइनस "
171
+
172
+ def set_high_numwords(self, high):
173
+ for n, word in self.high_numwords:
174
+ self.cards[10**n] = word
175
+
176
+ def merge(self, lpair, rpair):
177
+ ltext, lnum = lpair
178
+ rtext, rnum = rpair
179
+ # Remove "एक" prefix for certain major units (but keep for हज़ार)
180
+ if lnum == 1 and rnum in [100, 100000, 10000000]: # सौ, लाख, करोड़ (but not हज़ार)
181
+ return rtext, rnum
182
+ elif lnum == 1 and rnum < 100:
183
+ return rtext, rnum
184
+ elif lnum >= 100 > rnum:
185
+ return "%s %s" % (ltext, rtext), lnum + rnum
186
+ elif rnum > lnum:
187
+ return "%s %s" % (ltext, rtext), lnum * rnum
188
+ return "%s %s" % (ltext, rtext), lnum + rnum
189
+
190
+ def pluralize(self, count, forms):
191
+ """Return the proper plural form for Hindi"""
192
+ if count == 1:
193
+ return forms[0]
194
+ return forms[1] if len(forms) > 1 else forms[0]
195
+
196
+ def to_currency(self, val, currency='INR', cents=True, separator=',',
197
+ adjective=False):
198
+ # Handle integers specially - just add currency name without cents
199
+ if isinstance(val, int):
200
+ try:
201
+ cr1, cr2 = self.CURRENCY_FORMS[currency]
202
+ except (KeyError, AttributeError):
203
+ # Fallback to base implementation for unknown currency
204
+ return super(Num2Word_HI, self).to_currency(
205
+ val, currency=currency, cents=cents, separator=separator,
206
+ adjective=adjective)
207
+
208
+ minus_str = self.negword if val < 0 else ""
209
+ abs_val = abs(val)
210
+ money_str = self.to_cardinal(abs_val)
211
+
212
+ # Proper pluralization for currency
213
+ if abs_val == 1:
214
+ currency_str = cr1[0] if isinstance(cr1, tuple) else cr1
215
+ else:
216
+ currency_str = cr1[1] if isinstance(cr1, tuple) and len(cr1) > 1 else (cr1[0] if isinstance(cr1, tuple) else cr1)
217
+
218
+ return (u'%s %s %s' % (minus_str, money_str, currency_str)).strip()
219
+
220
+ # For floats, use the parent class implementation
221
+ return super(Num2Word_HI, self).to_currency(
222
+ val, currency=currency, cents=cents, separator=separator,
223
+ adjective=adjective)
224
+
225
+ def to_ordinal(self, value):
226
+ if value in self._irregular_ordinals:
227
+ return self._irregular_ordinals[value]
228
+
229
+ # regular Hindi ordinals are derived from cardinals
230
+ # by modifying the last member of the expression.
231
+ cardinal = self.to_cardinal(value)
232
+ return cardinal + self._regular_ordinal_suffix
233
+
234
+ def _convert_to_hindi_numerals(self, value):
235
+ return "".join(map(self._digits_to_hindi_digits.__getitem__,
236
+ str(value)))
237
+
238
+ def to_ordinal_num(self, value):
239
+ if value in self._irregular_ordinals_nums:
240
+ return self._irregular_ordinals_nums[value]
241
+
242
+ return self._convert_to_hindi_numerals(value) \
243
+ + self._regular_ordinal_suffix