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_SV.py ADDED
@@ -0,0 +1,169 @@
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
+ from __future__ import division, print_function, unicode_literals
19
+
20
+ from . import lang_EUR
21
+
22
+
23
+ class Num2Word_SV(lang_EUR.Num2Word_EUR):
24
+ GIGA_SUFFIX = "iljarder"
25
+ MEGA_SUFFIX = "iljoner"
26
+
27
+ def set_high_numwords(self, high):
28
+ cap = 3 + 6 * len(high)
29
+
30
+ for word, n in zip(high, range(cap, 3, -6)):
31
+ if self.GIGA_SUFFIX:
32
+ self.cards[10 ** n] = word + self.GIGA_SUFFIX
33
+
34
+ if self.MEGA_SUFFIX:
35
+ self.cards[10 ** (n - 3)] = word + self.MEGA_SUFFIX
36
+
37
+ def setup(self):
38
+ super(Num2Word_SV, self).setup()
39
+
40
+ self.negword = "minus "
41
+ self.pointword = "komma"
42
+ self.exclude_title = ["och", "komma", "minus"]
43
+
44
+ self.mid_numwords = [(1000, "tusen"), (100, "hundra"),
45
+ (90, "nittio"), (80, "åttio"), (70, "sjuttio"),
46
+ (60, "sextio"), (50, "femtio"), (40, "förtio"),
47
+ (30, "trettio")]
48
+ self.low_numwords = ["tjugo", "nitton", "arton", "sjutton",
49
+ "sexton", "femton", "fjorton", "tretton",
50
+ "tolv", "elva", "tio", "nio", "åtta",
51
+ "sju", "sex", "fem", "fyra", "tre", "två",
52
+ "ett", "noll"]
53
+ self.ords = {"noll": "nollte",
54
+ "ett": "första",
55
+ "två": "andra",
56
+ "tre": "tredje",
57
+ "fyra": "fjärde",
58
+ "fem": "femte",
59
+ "sex": "sjätte",
60
+ "sju": "sjunde",
61
+ "åtta": "åttonde",
62
+ "nio": "nionde",
63
+ "tio": "tionde",
64
+ "elva": "elfte",
65
+ "tolv": "tolfte",
66
+ "tjugo": "tjugonde"}
67
+
68
+ def merge(self, lpair, rpair):
69
+ ltext, lnum = lpair
70
+ rtext, rnum = rpair
71
+ if lnum == 1 and rnum < 100:
72
+ return (rtext, rnum)
73
+ elif 100 > lnum > rnum:
74
+ return ("%s%s" % (ltext, rtext), lnum + rnum)
75
+ elif lnum >= 100 > rnum:
76
+ return ("%s%s" % (ltext, rtext), lnum + rnum)
77
+ elif rnum >= 1000000 and lnum == 1:
78
+ return ("%s %s" % ('en', rtext[:-2]), lnum + rnum)
79
+ elif rnum >= 1000000 and lnum > 1:
80
+ return ("%s %s" % (ltext, rtext), lnum + rnum)
81
+ elif rnum > lnum:
82
+ # Special case: Swedish doesn't use "ett" before "hundra" in compounds
83
+ if lnum == 100 and rnum == 1000:
84
+ return ("hundratusen", 100000)
85
+ return ("%s%s" % (ltext, rtext), lnum * rnum)
86
+ return ("%s %s" % (ltext, rtext), lnum + rnum)
87
+
88
+ def to_currency(self, val, currency='EUR', cents=True, separator=',',
89
+ adjective=False):
90
+ # Handle integers specially - just add currency name without cents
91
+ if isinstance(val, int):
92
+ try:
93
+ cr1, cr2 = self.CURRENCY_FORMS[currency]
94
+ except (KeyError, AttributeError):
95
+ # Fallback to base implementation for unknown currency
96
+ return super(Num2Word_SV, self).to_currency(
97
+ val, currency=currency, cents=cents, separator=separator,
98
+ adjective=adjective)
99
+
100
+ minus_str = self.negword if val < 0 else ""
101
+ abs_val = abs(val)
102
+ money_str = self.to_cardinal(abs_val)
103
+
104
+ # Proper pluralization for currency
105
+ if abs_val == 1:
106
+ currency_str = cr1[0] if isinstance(cr1, tuple) else cr1
107
+ else:
108
+ currency_str = cr1[1] if isinstance(cr1, tuple) and len(cr1) > 1 else (cr1[0] if isinstance(cr1, tuple) else cr1)
109
+
110
+ return (u'%s %s %s' % (minus_str, money_str, currency_str)).strip()
111
+
112
+ # For floats, use the parent class implementation
113
+ return super(Num2Word_SV, self).to_currency(
114
+ val, currency=currency, cents=cents, separator=separator,
115
+ adjective=adjective)
116
+
117
+ def to_ordinal(self, value):
118
+ self.verify_ordinal(value)
119
+ outwords = self.to_cardinal(value).split(" ")
120
+ lastword = outwords[-1]
121
+ ending_length = 0
122
+ try:
123
+ lastword_ending = self.ords[lastword[-4:]]
124
+ ending_length = 4
125
+ except KeyError:
126
+ try:
127
+ lastword_ending = self.ords[lastword[-3:]]
128
+ ending_length = 3
129
+ except KeyError:
130
+ lastword_ending = "de"
131
+ if lastword_ending == 'de':
132
+ lastword_first_part = self.title(lastword)[:]
133
+ else:
134
+ lastword_first_part = self.title(lastword)[:-ending_length]
135
+ lastword_correct = lastword_first_part + lastword_ending
136
+ outwords[-1] = lastword_correct
137
+ return " ".join(outwords)
138
+
139
+ def to_ordinal_num(self, value):
140
+ """Convert to abbreviated ordinal form in Swedish"""
141
+ # Swedish uses :e, :a, :de, :te etc. for ordinals
142
+ if value == 1 or value == 2:
143
+ return str(value) + ':a'
144
+ elif str(value).endswith(('1', '2')) and value not in (11, 12):
145
+ return str(value) + ':a'
146
+ elif str(value).endswith(('3', '4', '5', '6', '7', '8', '9', '0')):
147
+ return str(value) + ':e'
148
+ else:
149
+ return str(value) + ':e'
150
+
151
+ def to_year(self, val, longval=True):
152
+ """Convert number to year representation in Swedish"""
153
+ if val < 0:
154
+ # BC years
155
+ return self.to_cardinal(-val) + " f.Kr."
156
+ elif val < 1000:
157
+ # Years before 1000
158
+ return self.to_cardinal(val)
159
+ elif val < 2000:
160
+ # Years 1000-1999: typically "nittonhundra" style
161
+ century = val // 100
162
+ remainder = val % 100
163
+ if remainder == 0:
164
+ return self.to_cardinal(century) + "hundra"
165
+ else:
166
+ return self.to_cardinal(century) + "hundra" + self.to_cardinal(remainder)
167
+ else:
168
+ # Years 2000+: typically "tvåtusen" style
169
+ return self.to_cardinal(val)
num2words2/lang_SW.py ADDED
@@ -0,0 +1,219 @@
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
+ from __future__ import unicode_literals
19
+
20
+ from .base import Num2Word_Base
21
+
22
+
23
+ class Num2Word_SW(Num2Word_Base):
24
+ CURRENCY_FORMS = {
25
+ 'TZS': (('shilingi', 'shilingi'), ('senti', 'senti')), # Tanzanian Shilling
26
+ 'KES': (('shilingi', 'shilingi'), ('senti', 'senti')), # Kenyan Shilling
27
+ 'UGX': (('shilingi', 'shilingi'), ('senti', 'senti')), # Ugandan Shilling
28
+
29
+ 'USD': (('dola', 'dola'), ('senti', 'senti')), # US Dollar
30
+ 'EUR': (('yuro', 'yuro'), ('senti', 'senti')), # Euro
31
+ 'GBP': (('pauni', 'pauni'), ('peni', 'peni')), # British Pound
32
+ }
33
+
34
+ def setup(self):
35
+ self.negword = "hasi "
36
+ self.pointword = "nukta"
37
+
38
+ # High-level numwords for large numbers
39
+ self.high_numwords = ["trilioni"]
40
+
41
+ self.mid_numwords = [
42
+ (1000000000, "bilioni"),
43
+ (1000000, "milioni"),
44
+ (100000, "laki"),
45
+ (1000, "elfu"),
46
+ (100, "mia"),
47
+ (90, "tisini"),
48
+ (80, "themanini"),
49
+ (70, "sabini"),
50
+ (60, "sitini"),
51
+ (50, "hamsini"),
52
+ (40, "arobaini"),
53
+ (30, "thelathini"),
54
+ (20, "ishirini")
55
+ ]
56
+
57
+ self.low_numwords = [
58
+ "kumi na tisa", # 19
59
+ "kumi na nane", # 18
60
+ "kumi na saba", # 17
61
+ "kumi na sita", # 16
62
+ "kumi na tano", # 15
63
+ "kumi na nne", # 14
64
+ "kumi na tatu", # 13
65
+ "kumi na mbili", # 12
66
+ "kumi na moja", # 11
67
+ "kumi", # 10
68
+ "tisa", # 9
69
+ "nane", # 8
70
+ "saba", # 7
71
+ "sita", # 6
72
+ "tano", # 5
73
+ "nne", # 4
74
+ "tatu", # 3
75
+ "mbili", # 2
76
+ "moja", # 1
77
+ "sifuri" # 0
78
+ ]
79
+
80
+ # Ordinal mappings
81
+ self.ordinal_words = {
82
+ "moja": "kwanza",
83
+ "mbili": "pili",
84
+ "tatu": "tatu",
85
+ "nne": "nne",
86
+ "tano": "tano",
87
+ "sita": "sita",
88
+ "saba": "saba",
89
+ "nane": "nane",
90
+ "tisa": "tisa",
91
+ "kumi": "kumi",
92
+ }
93
+
94
+ def set_high_numwords(self, high):
95
+ """Set high numwords for large numbers."""
96
+ cap = 9 + 9 * len(high)
97
+ for word, n in zip(high, range(cap, 8, -9)):
98
+ self.cards[10 ** n] = word
99
+
100
+ def merge(self, lpair, rpair):
101
+ """Merge two number parts using Swahili grammar rules."""
102
+ ltext, lnum = lpair
103
+ rtext, rnum = rpair
104
+
105
+ if lnum == 1 and rnum < 100:
106
+ return (rtext, rnum)
107
+ elif 100 > lnum > rnum:
108
+ return ("%s na %s" % (ltext, rtext), lnum + rnum)
109
+ elif lnum >= 100 > rnum:
110
+ return ("%s na %s" % (ltext, rtext), lnum + rnum)
111
+ elif rnum >= 1000000:
112
+ # For millions/billions: "milioni moja", "bilioni mbili", etc.
113
+ return ("%s %s" % (rtext, ltext), lnum * rnum)
114
+ elif rnum >= 1000:
115
+ # For thousands: "elfu moja", "elfu mbili", etc.
116
+ if lnum < 1000:
117
+ return ("%s %s" % (rtext, ltext), lnum * rnum)
118
+ else:
119
+ # When combining with other thousands, use "na"
120
+ return ("%s na %s" % (ltext, rtext), lnum + rnum)
121
+ elif rnum >= 100:
122
+ # For hundreds: "mia moja", "mia mbili", etc.
123
+ if lnum < 100:
124
+ return ("%s %s" % (rtext, ltext), lnum * rnum)
125
+ else:
126
+ # When combining with other hundreds or larger, use "na"
127
+ return ("%s na %s" % (ltext, rtext), lnum + rnum)
128
+ elif rnum > lnum:
129
+ return ("%s %s" % (ltext, rtext), lnum * rnum)
130
+ return ("%s na %s" % (ltext, rtext), lnum + rnum)
131
+
132
+ def to_ordinal(self, value):
133
+ """Convert number to ordinal form."""
134
+ self.verify_ordinal(value)
135
+ cardinal_text = self.to_cardinal(value)
136
+
137
+ # Check if we have a special ordinal form
138
+ if cardinal_text in self.ordinal_words:
139
+ return f"wa {self.ordinal_words[cardinal_text]}"
140
+
141
+ # For ordinals, prefix with "wa" (of/the)
142
+ return f"wa {cardinal_text}"
143
+
144
+ def to_ordinal_num(self, value):
145
+ """Convert number to ordinal number format."""
146
+ self.verify_ordinal(value)
147
+ return f"{value}."
148
+
149
+ def to_year(self, value, **kwargs):
150
+ """Convert number to year format."""
151
+ return self.to_cardinal(value)
152
+
153
+ def pluralize(self, number, forms):
154
+ """Handle pluralization - Swahili doesn't change form much."""
155
+ # Swahili typically doesn't change the noun form for plurals
156
+ # So we return the singular form for both cases
157
+ return forms[0] if len(forms) > 0 else forms
158
+
159
+ def _money_verbose(self, number, currency):
160
+ """Convert money amount to verbose format."""
161
+ return self.to_cardinal(number)
162
+
163
+ def _cents_verbose(self, number, currency):
164
+ """Convert cents amount to verbose format."""
165
+ return self.to_cardinal(number)
166
+
167
+ def to_currency(self, val, currency='TZS', cents=True, separator=' na',
168
+ adjective=False):
169
+ """
170
+ Convert number to currency format in Swahili.
171
+ """
172
+ # Import the parse function from the base currency module
173
+ # Check if value has fractional cents
174
+ from decimal import Decimal
175
+
176
+ from .currency import parse_currency_parts
177
+ decimal_val = Decimal(str(val))
178
+ has_fractional_cents = (decimal_val * 100) % 1 != 0
179
+
180
+ # For Swahili, treat integers as whole currency units, not cents
181
+ left, right, is_negative = parse_currency_parts(val, is_int_with_cents=False,
182
+ keep_precision=has_fractional_cents)
183
+
184
+ try:
185
+ cr1, cr2 = self.CURRENCY_FORMS[currency]
186
+ except KeyError:
187
+ raise NotImplementedError(
188
+ 'Currency code "%s" not implemented for "%s"' %
189
+ (currency, self.__class__.__name__))
190
+
191
+ minus_str = "%s " % self.negword.strip() if is_negative else ""
192
+ money_str = self.to_cardinal(left)
193
+
194
+ # Check if input is explicitly a decimal number or has non-zero cents
195
+ has_decimal = isinstance(val, float) or str(val).find('.') != -1
196
+
197
+ # Only include cents if there are actual cents or explicitly decimal
198
+ if has_decimal or right > 0:
199
+ # Handle fractional cents
200
+ from decimal import Decimal
201
+ if isinstance(right, Decimal):
202
+ # Convert fractional cents (e.g., 65.3 cents)
203
+ cents_str = self.to_cardinal_float(float(right)) if cents else str(float(right))
204
+ else:
205
+ cents_str = self.to_cardinal(right) if cents else "%02d" % right
206
+ return u'%s%s %s%s %s %s' % (
207
+ minus_str,
208
+ money_str,
209
+ self.pluralize(left, cr1),
210
+ separator,
211
+ cents_str,
212
+ self.pluralize(right, cr2)
213
+ )
214
+ else:
215
+ return u'%s%s %s' % (
216
+ minus_str,
217
+ money_str,
218
+ self.pluralize(left, cr1)
219
+ )
num2words2/lang_TA.py ADDED
@@ -0,0 +1,303 @@
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
+ from __future__ import unicode_literals
19
+
20
+ from .base import Num2Word_Base
21
+ from .currency import parse_currency_parts
22
+
23
+
24
+ class Num2Word_TA(Num2Word_Base):
25
+ CURRENCY_FORMS = {
26
+ 'INR': (
27
+ ('ரூபாய்', 'ரூபாய்'), ('பைசா', 'பைசா')
28
+ ),
29
+ 'LKR': (
30
+ ('ரூபாய்', 'ரூபாய்'), ('சதம்', 'சதம்')
31
+ ),
32
+ 'USD': (
33
+ ('டாலர்', 'டாலர்'), ('சென்ட்', 'சென்ட்')
34
+ ),
35
+ 'EUR': (
36
+ ('யூரோ', 'யூரோ'), ('சென்ட்', 'சென்ட்')
37
+ ),
38
+ 'GBP': (
39
+ ('பவுண்ட்', 'பவுண்ட்'), ('பென்னி', 'பென்னி')
40
+ ),
41
+ 'SGD': (
42
+ ('டாலர்', 'டாலர்'), ('சென்ட்', 'சென்ட்')
43
+ ),
44
+ 'MYR': (
45
+ ('ரிங்கிட்', 'ரிங்கிட்'), ('சென்', 'சென்')
46
+ ),
47
+ }
48
+
49
+ def __init__(self):
50
+ super(Num2Word_TA, self).__init__()
51
+
52
+ self.ones = [
53
+ '',
54
+ 'ஒன்று',
55
+ 'இரண்டு',
56
+ 'மூன்று',
57
+ 'நான்கு',
58
+ 'ஐந்து',
59
+ 'ஆறு',
60
+ 'ஏழு',
61
+ 'எட்டு',
62
+ 'ஒன்பது'
63
+ ]
64
+
65
+ self.tens = [
66
+ '',
67
+ 'பத்து',
68
+ 'இருபது',
69
+ 'முப்பது',
70
+ 'நாற்பது',
71
+ 'ஐம்பது',
72
+ 'அறுபது',
73
+ 'எழுபது',
74
+ 'எண்பது',
75
+ 'தொண்ணூறு'
76
+ ]
77
+
78
+ self.teens = {
79
+ 11: 'பதினொன்று',
80
+ 12: 'பன்னிரண்டு',
81
+ 13: 'பதின்மூன்று',
82
+ 14: 'பதினான்கு',
83
+ 15: 'பதினைந்து',
84
+ 16: 'பதினாறு',
85
+ 17: 'பதினேழு',
86
+ 18: 'பதினெட்டு',
87
+ 19: 'பத்தொன்பது'
88
+ }
89
+
90
+ self.hundreds_special = {
91
+ 100: 'நூறு',
92
+ 200: 'இருநூறு',
93
+ 300: 'முன்னூறு',
94
+ 400: 'நானூறு',
95
+ 500: 'ஐநூறு',
96
+ 600: 'அறுநூறு',
97
+ 700: 'எழுநூறு',
98
+ 800: 'எண்ணூறு',
99
+ 900: 'தொள்ளாயிரம்'
100
+ }
101
+
102
+ self.scale = {
103
+ 1000: 'ஆயிரம்',
104
+ 100000: 'இலட்சம்',
105
+ 10000000: 'கோடி',
106
+ 1000000000000: 'டிரில்லியன்'
107
+ }
108
+
109
+ self.ordinals = {
110
+ 1: 'முதல்',
111
+ 2: 'இரண்டாம்',
112
+ 3: 'மூன்றாம்',
113
+ 4: 'நான்காம்',
114
+ 5: 'ஐந்தாம்',
115
+ 6: 'ஆறாம்',
116
+ 7: 'ஏழாம்',
117
+ 8: 'எட்டாம்',
118
+ 9: 'ஒன்பதாம்',
119
+ 10: 'பத்தாம்'
120
+ }
121
+
122
+ self.negword = "கழித்தல் "
123
+ self.pointword = "புள்ளி"
124
+
125
+ def _setup(self):
126
+ super(Num2Word_TA, self)._setup()
127
+
128
+ def _int_to_word(self, n):
129
+ """
130
+ Converts a number to words in Tamil.
131
+ Uses Indian numbering system (lakh/crore).
132
+ """
133
+ if n == 0:
134
+ return 'பூஜ்ஜியம்'
135
+
136
+ parts = []
137
+
138
+ # Handle crores (1 crore = 10,000,000)
139
+ if n >= 10000000:
140
+ crores = n // 10000000
141
+ if crores == 1:
142
+ parts.append('ஒரு கோடி')
143
+ else:
144
+ parts.append(self._int_to_word(crores) + ' கோடி')
145
+ n %= 10000000
146
+
147
+ # Handle lakhs (1 lakh = 100,000)
148
+ if n >= 100000:
149
+ lakhs = n // 100000
150
+ if lakhs == 1:
151
+ parts.append('ஒரு இலட்சம்')
152
+ else:
153
+ parts.append(self._int_to_word(lakhs) + ' இலட்சம்')
154
+ n %= 100000
155
+
156
+ # Handle thousands
157
+ if n >= 1000:
158
+ thousands = n // 1000
159
+ if thousands == 1:
160
+ parts.append('ஆயிரம்')
161
+ else:
162
+ parts.append(self._int_to_word(thousands) + ' ஆயிரம்')
163
+ n %= 1000
164
+
165
+ # Handle hundreds with special forms
166
+ if n >= 100:
167
+ hundreds_val = (n // 100) * 100
168
+ if hundreds_val in self.hundreds_special:
169
+ parts.append(self.hundreds_special[hundreds_val])
170
+ else:
171
+ parts.append(self.ones[n // 100] + ' நூறு')
172
+ n %= 100
173
+
174
+ # Handle special case for teens (11-19)
175
+ if 10 < n < 20:
176
+ parts.append(self.teens[n])
177
+ else:
178
+ # Handle tens
179
+ if n >= 10:
180
+ tens_val = n // 10
181
+ parts.append(self.tens[tens_val])
182
+ n %= 10
183
+
184
+ # Handle ones
185
+ if n > 0:
186
+ parts.append(self.ones[n])
187
+
188
+ return ' '.join(parts)
189
+
190
+ def _int_to_cardinal(self, n):
191
+ if n == 0:
192
+ return 'பூஜ்ஜியம்'
193
+
194
+ if n < 0:
195
+ return self.negword + self._int_to_word(-n)
196
+
197
+ return self._int_to_word(n)
198
+
199
+ def _int_to_ordinal(self, n):
200
+ """Convert to ordinal number."""
201
+ if n == 0:
202
+ return 'பூஜ்ஜியம்'
203
+
204
+ # Special cases for first ten ordinals
205
+ if n in self.ordinals:
206
+ return self.ordinals[n]
207
+
208
+ # For other numbers, add "-ஆவது" suffix
209
+ return self._int_to_cardinal(n) + 'ஆவது'
210
+
211
+ def to_cardinal(self, n):
212
+ try:
213
+ if isinstance(n, str):
214
+ n = int(n)
215
+
216
+ return self._int_to_cardinal(n)
217
+ except BaseException:
218
+ return self._int_to_cardinal(int(n))
219
+
220
+ def to_ordinal(self, n):
221
+ try:
222
+ if isinstance(n, str):
223
+ n = int(n)
224
+
225
+ return self._int_to_ordinal(n)
226
+ except BaseException:
227
+ return self._int_to_ordinal(int(n))
228
+
229
+ def to_ordinal_num(self, n):
230
+ try:
231
+ if isinstance(n, str):
232
+ n = int(n)
233
+
234
+ # In Tamil, ordinal numbers use "-ஆவது" suffix
235
+ # But for numeric form, use -வது
236
+ return str(n) + '-வது'
237
+ except BaseException:
238
+ return str(n) + '-வது'
239
+
240
+ def to_currency(self, n, currency='INR'):
241
+ try:
242
+ # Check if value has fractional cents
243
+ from decimal import Decimal
244
+ decimal_val = Decimal(str(n))
245
+ has_fractional_cents = (decimal_val * 100) % 1 != 0
246
+
247
+ left, right, is_negative = parse_currency_parts(n, is_int_with_cents=False,
248
+ keep_precision=has_fractional_cents)
249
+
250
+ if currency not in self.CURRENCY_FORMS:
251
+ raise NotImplementedError(
252
+ 'Currency code "%s" not implemented for "%s"' %
253
+ (currency, self.__class__.__name__))
254
+
255
+ cr_major, cr_minor = self.CURRENCY_FORMS[currency]
256
+
257
+ result = []
258
+
259
+ if is_negative:
260
+ result.append(self.negword.strip())
261
+
262
+ left_words = self._int_to_cardinal(left)
263
+ result.append(left_words)
264
+ result.append(cr_major[0])
265
+
266
+ # Handle paise/cents if non-zero
267
+ if right > 0:
268
+ # Handle fractional paise
269
+ from decimal import Decimal
270
+ if isinstance(right, Decimal):
271
+ # Convert fractional paise (e.g., 65.3 paise)
272
+ right_words = self.to_cardinal(float(right))
273
+ else:
274
+ right_words = self._int_to_cardinal(right)
275
+ result.append(right_words)
276
+ result.append(cr_minor[0])
277
+
278
+ return ' '.join(result)
279
+ except NotImplementedError:
280
+ raise
281
+ except BaseException:
282
+ return str(n) + ' ' + currency
283
+
284
+ def to_year(self, n):
285
+ """Convert to year representation."""
286
+ if n < 1000:
287
+ return self._int_to_cardinal(n)
288
+ elif n < 2000:
289
+ # Years like 1999 -> "ஆயிரத்து தொள்ளாயிரத்து தொண்ணூற்று ஒன்பது"
290
+ thousands = n // 1000
291
+ remainder = n % 1000
292
+ result = 'ஆயிரத்து'
293
+ if remainder > 0:
294
+ result += ' ' + self._int_to_cardinal(remainder)
295
+ return result
296
+ else:
297
+ # Years like 2023 -> "இரண்டாயிரத்து இருபத்து மூன்று"
298
+ thousands = n // 1000
299
+ remainder = n % 1000
300
+ result = self._int_to_cardinal(thousands) + ' ஆயிரத்து'
301
+ if remainder > 0:
302
+ result += ' ' + self._int_to_cardinal(remainder)
303
+ return result