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.
- num2words2/README.md +69 -0
- num2words2/__init__.py +196 -0
- num2words2/_version.py +3 -0
- num2words2/base.py +377 -0
- num2words2/compat.py +29 -0
- num2words2/currency.py +60 -0
- num2words2/lang_AF.py +202 -0
- num2words2/lang_AM.py +193 -0
- num2words2/lang_AR.py +435 -0
- num2words2/lang_AS.py +119 -0
- num2words2/lang_AZ.py +208 -0
- num2words2/lang_BA.py +119 -0
- num2words2/lang_BE.py +356 -0
- num2words2/lang_BG.py +393 -0
- num2words2/lang_BN.py +242 -0
- num2words2/lang_BO.py +122 -0
- num2words2/lang_BR.py +135 -0
- num2words2/lang_BS.py +189 -0
- num2words2/lang_CA.py +476 -0
- num2words2/lang_CE.py +546 -0
- num2words2/lang_CS.py +260 -0
- num2words2/lang_CY.py +574 -0
- num2words2/lang_DA.py +170 -0
- num2words2/lang_DE.py +180 -0
- num2words2/lang_EL.py +338 -0
- num2words2/lang_EN.py +118 -0
- num2words2/lang_EN_IN.py +26 -0
- num2words2/lang_EN_NG.py +45 -0
- num2words2/lang_EO.py +130 -0
- num2words2/lang_ES.py +399 -0
- num2words2/lang_ES_CO.py +37 -0
- num2words2/lang_ES_CR.py +38 -0
- num2words2/lang_ES_GT.py +37 -0
- num2words2/lang_ES_NI.py +35 -0
- num2words2/lang_ES_VE.py +43 -0
- num2words2/lang_ET.py +393 -0
- num2words2/lang_EU.py +158 -0
- num2words2/lang_EUR.py +104 -0
- num2words2/lang_FA.py +187 -0
- num2words2/lang_FI.py +759 -0
- num2words2/lang_FO.py +136 -0
- num2words2/lang_FR.py +133 -0
- num2words2/lang_FR_BE.py +49 -0
- num2words2/lang_FR_CH.py +48 -0
- num2words2/lang_FR_DZ.py +35 -0
- num2words2/lang_GL.py +135 -0
- num2words2/lang_GU.py +172 -0
- num2words2/lang_HA.py +293 -0
- num2words2/lang_HAW.py +144 -0
- num2words2/lang_HE.py +314 -0
- num2words2/lang_HI.py +243 -0
- num2words2/lang_HR.py +304 -0
- num2words2/lang_HT.py +136 -0
- num2words2/lang_HU.py +189 -0
- num2words2/lang_HY.py +364 -0
- num2words2/lang_ID.py +242 -0
- num2words2/lang_IS.py +208 -0
- num2words2/lang_IT.py +265 -0
- num2words2/lang_JA.py +615 -0
- num2words2/lang_JW.py +136 -0
- num2words2/lang_KA.py +169 -0
- num2words2/lang_KK.py +136 -0
- num2words2/lang_KM.py +173 -0
- num2words2/lang_KN.py +182 -0
- num2words2/lang_KO.py +175 -0
- num2words2/lang_KZ.py +161 -0
- num2words2/lang_LA.py +135 -0
- num2words2/lang_LB.py +135 -0
- num2words2/lang_LN.py +136 -0
- num2words2/lang_LO.py +149 -0
- num2words2/lang_LT.py +283 -0
- num2words2/lang_LV.py +266 -0
- num2words2/lang_MG.py +143 -0
- num2words2/lang_MI.py +151 -0
- num2words2/lang_MK.py +136 -0
- num2words2/lang_ML.py +159 -0
- num2words2/lang_MN.py +319 -0
- num2words2/lang_MR.py +187 -0
- num2words2/lang_MS.py +293 -0
- num2words2/lang_MT.py +159 -0
- num2words2/lang_MY.py +152 -0
- num2words2/lang_NE.py +157 -0
- num2words2/lang_NL.py +204 -0
- num2words2/lang_NN.py +136 -0
- num2words2/lang_NO.py +143 -0
- num2words2/lang_OC.py +135 -0
- num2words2/lang_PA.py +159 -0
- num2words2/lang_PL.py +336 -0
- num2words2/lang_PS.py +136 -0
- num2words2/lang_PT.py +280 -0
- num2words2/lang_PT_BR.py +224 -0
- num2words2/lang_RO.py +183 -0
- num2words2/lang_RU.py +570 -0
- num2words2/lang_SA.py +136 -0
- num2words2/lang_SD.py +136 -0
- num2words2/lang_SI.py +152 -0
- num2words2/lang_SK.py +250 -0
- num2words2/lang_SL.py +306 -0
- num2words2/lang_SN.py +447 -0
- num2words2/lang_SO.py +136 -0
- num2words2/lang_SQ.py +252 -0
- num2words2/lang_SR.py +254 -0
- num2words2/lang_SU.py +136 -0
- num2words2/lang_SV.py +169 -0
- num2words2/lang_SW.py +219 -0
- num2words2/lang_TA.py +303 -0
- num2words2/lang_TE.py +169 -0
- num2words2/lang_TET.py +285 -0
- num2words2/lang_TG.py +149 -0
- num2words2/lang_TH.py +214 -0
- num2words2/lang_TK.py +136 -0
- num2words2/lang_TL.py +145 -0
- num2words2/lang_TR.py +882 -0
- num2words2/lang_TT.py +136 -0
- num2words2/lang_UK.py +1101 -0
- num2words2/lang_UR.py +168 -0
- num2words2/lang_UZ.py +136 -0
- num2words2/lang_VI.py +143 -0
- num2words2/lang_WO.py +136 -0
- num2words2/lang_YI.py +135 -0
- num2words2/lang_YO.py +136 -0
- num2words2/lang_ZH.py +296 -0
- num2words2/lang_ZH_CN.py +85 -0
- num2words2/lang_ZH_HK.py +48 -0
- num2words2/lang_ZH_TW.py +198 -0
- num2words2/utils.py +35 -0
- num2words2-0.1.0.dev1.data/scripts/num2words2 +98 -0
- num2words2-0.1.0.dev1.dist-info/METADATA +244 -0
- num2words2-0.1.0.dev1.dist-info/RECORD +133 -0
- num2words2-0.1.0.dev1.dist-info/WHEEL +5 -0
- num2words2-0.1.0.dev1.dist-info/entry_points.txt +2 -0
- num2words2-0.1.0.dev1.dist-info/licenses/COPYING +145 -0
- num2words2-0.1.0.dev1.dist-info/top_level.txt +1 -0
num2words2/currency.py
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
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
|
|
19
|
+
|
|
20
|
+
from decimal import ROUND_HALF_UP, Decimal
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def parse_currency_parts(value, is_int_with_cents=True, keep_precision=False):
|
|
24
|
+
if isinstance(value, int):
|
|
25
|
+
if is_int_with_cents:
|
|
26
|
+
# assume cents if value is integer
|
|
27
|
+
negative = value < 0
|
|
28
|
+
value = abs(value)
|
|
29
|
+
integer, cents = divmod(value, 100)
|
|
30
|
+
else:
|
|
31
|
+
negative = value < 0
|
|
32
|
+
integer, cents = abs(value), 0
|
|
33
|
+
|
|
34
|
+
else:
|
|
35
|
+
# Convert to string first to avoid float precision issues
|
|
36
|
+
value = Decimal(str(value))
|
|
37
|
+
|
|
38
|
+
if not keep_precision:
|
|
39
|
+
# Round to 2 decimal places
|
|
40
|
+
value = value.quantize(
|
|
41
|
+
Decimal('.01'),
|
|
42
|
+
rounding=ROUND_HALF_UP
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
negative = value < 0
|
|
46
|
+
value = abs(value)
|
|
47
|
+
integer, fraction = divmod(value, 1)
|
|
48
|
+
integer = int(integer)
|
|
49
|
+
|
|
50
|
+
if keep_precision:
|
|
51
|
+
# Keep full precision for cents
|
|
52
|
+
cents = fraction * 100 # Keep as Decimal
|
|
53
|
+
else:
|
|
54
|
+
cents = int(fraction * 100)
|
|
55
|
+
|
|
56
|
+
return integer, cents, negative
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def prefix_currency(prefix, base):
|
|
60
|
+
return tuple("%s %s" % (prefix, i) for i in base)
|
num2words2/lang_AF.py
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
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 print_function, unicode_literals
|
|
19
|
+
|
|
20
|
+
from .lang_EUR import Num2Word_EUR
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class Num2Word_AF(Num2Word_EUR):
|
|
24
|
+
CURRENCY_FORMS = {
|
|
25
|
+
'ZAR': (('rand', 'rand'), ('sent', 'sent')),
|
|
26
|
+
'EUR': (('euro', 'euro'), ('sent', 'sent')),
|
|
27
|
+
'GBP': (('pond', 'pond'), ('penny', 'pence')),
|
|
28
|
+
'USD': (('dollar', 'dollar'), ('sent', 'sent')),
|
|
29
|
+
'CNY': (('yuan', 'yuan'), ('jiao', 'fen')),
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
GIGA_SUFFIX = "iljard"
|
|
33
|
+
MEGA_SUFFIX = "iljoen"
|
|
34
|
+
|
|
35
|
+
def setup(self):
|
|
36
|
+
super(Num2Word_AF, self).setup()
|
|
37
|
+
|
|
38
|
+
self.negword = "minus "
|
|
39
|
+
self.pointword = "komma"
|
|
40
|
+
|
|
41
|
+
# Error messages in Afrikaans
|
|
42
|
+
self.errmsg_floatord = (
|
|
43
|
+
"Kan nie die desimale getal %s as 'n ordinale getal behandel nie."
|
|
44
|
+
)
|
|
45
|
+
self.errmsg_nonnum = (
|
|
46
|
+
"Slegs getalle (tipe(%s)) kan na woorde omgeskakel word."
|
|
47
|
+
)
|
|
48
|
+
self.errmsg_negord = (
|
|
49
|
+
"Kan nie die negatiewe getal %s as 'n ordinale getal behandel nie."
|
|
50
|
+
)
|
|
51
|
+
self.errmsg_toobig = "Die getal %s moet minder as %s wees."
|
|
52
|
+
self.exclude_title = []
|
|
53
|
+
|
|
54
|
+
# High number words for very large numbers
|
|
55
|
+
lows = ["non", "okt", "sept", "sext", "kwint", "kwadr", "tr", "b", "m"]
|
|
56
|
+
units = ["", "un", "duo", "tre", "kwattuor", "kwin", "seks", "sept",
|
|
57
|
+
"okto", "novem"]
|
|
58
|
+
tens = ["des", "vigint", "trigint", "kwadragint", "kwinquagint",
|
|
59
|
+
"seksagint", "septuagint", "oktogint", "nonagint"]
|
|
60
|
+
|
|
61
|
+
self.high_numwords = (
|
|
62
|
+
["send"] + self.gen_high_numwords(units, tens, lows))
|
|
63
|
+
|
|
64
|
+
# Mid-range numbers (thousands, hundreds, tens)
|
|
65
|
+
self.mid_numwords = [(1000, "duisend"), (100, "honderd"),
|
|
66
|
+
(90, "negentig"), (80, "tagtig"),
|
|
67
|
+
(70, "sewentig"), (60, "sestig"),
|
|
68
|
+
(50, "vyftig"), (40, "veertig"),
|
|
69
|
+
(30, "dertig")]
|
|
70
|
+
|
|
71
|
+
# Low numbers (0-20)
|
|
72
|
+
self.low_numwords = ["twintig", "negentien", "agttien", "sewentien",
|
|
73
|
+
"sestien", "vyftien", "veertien", "dertien",
|
|
74
|
+
"twaalf", "elf", "tien", "nege", "agt", "sewe",
|
|
75
|
+
"ses", "vyf", "vier", "drie", "twee", "een",
|
|
76
|
+
"nul"]
|
|
77
|
+
|
|
78
|
+
# Ordinal mappings
|
|
79
|
+
self.ords = {
|
|
80
|
+
"nul": "nulld",
|
|
81
|
+
"een": "eerst",
|
|
82
|
+
"twee": "tweed",
|
|
83
|
+
"drie": "derd",
|
|
84
|
+
"vier": "vierd",
|
|
85
|
+
"vyf": "vyfd",
|
|
86
|
+
"ses": "sesd",
|
|
87
|
+
"sewe": "sewend",
|
|
88
|
+
"agt": "agst",
|
|
89
|
+
"nege": "negend",
|
|
90
|
+
"tien": "tiend",
|
|
91
|
+
"elf": "elfd",
|
|
92
|
+
"twaalf": "twaalfd",
|
|
93
|
+
|
|
94
|
+
# Compound endings
|
|
95
|
+
"ig": "igst",
|
|
96
|
+
"erd": "erdst",
|
|
97
|
+
"end": "endst",
|
|
98
|
+
"joen": "joenst",
|
|
99
|
+
"rd": "rdst"
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
def merge(self, curr, next):
|
|
103
|
+
ctext, cnum, ntext, nnum = curr + next
|
|
104
|
+
|
|
105
|
+
if cnum == 1:
|
|
106
|
+
if nnum == 100 or nnum == 1000:
|
|
107
|
+
return ("een " + ntext, nnum)
|
|
108
|
+
elif nnum < 10 ** 6:
|
|
109
|
+
return next
|
|
110
|
+
ctext = "een"
|
|
111
|
+
|
|
112
|
+
if nnum > cnum:
|
|
113
|
+
if nnum >= 10 ** 6:
|
|
114
|
+
ctext += " "
|
|
115
|
+
elif nnum == 100 or nnum == 1000:
|
|
116
|
+
ctext += " "
|
|
117
|
+
val = cnum * nnum
|
|
118
|
+
else:
|
|
119
|
+
if nnum < 10 < cnum < 100:
|
|
120
|
+
if nnum == 1:
|
|
121
|
+
ntext = "een"
|
|
122
|
+
|
|
123
|
+
# Afrikaans compound formation: vier-en-dertig
|
|
124
|
+
ntext = ntext + "-en-" + ctext
|
|
125
|
+
ctext = ""
|
|
126
|
+
elif cnum >= 10 ** 6:
|
|
127
|
+
ctext += " "
|
|
128
|
+
elif cnum >= 100:
|
|
129
|
+
ctext += " "
|
|
130
|
+
val = cnum + nnum
|
|
131
|
+
|
|
132
|
+
word = ctext + ntext
|
|
133
|
+
return word, val
|
|
134
|
+
|
|
135
|
+
def to_ordinal(self, value):
|
|
136
|
+
self.verify_ordinal(value)
|
|
137
|
+
outword = self.to_cardinal(value)
|
|
138
|
+
|
|
139
|
+
# Handle special compound ordinals
|
|
140
|
+
for key in self.ords:
|
|
141
|
+
if outword.endswith(key):
|
|
142
|
+
outword = outword[:len(outword) - len(key)] + self.ords[key]
|
|
143
|
+
break
|
|
144
|
+
|
|
145
|
+
return outword + "e"
|
|
146
|
+
|
|
147
|
+
def to_ordinal_num(self, value):
|
|
148
|
+
self.verify_ordinal(value)
|
|
149
|
+
# Afrikaans uses "de" for some ordinal numbers, "ste" for most
|
|
150
|
+
if value in [2, 3, 4, 5, 6, 7, 8]:
|
|
151
|
+
return str(value) + "de"
|
|
152
|
+
else:
|
|
153
|
+
return str(value) + "ste"
|
|
154
|
+
|
|
155
|
+
def pluralize(self, n, forms):
|
|
156
|
+
"""
|
|
157
|
+
Afrikaans pluralization rules - most currencies don't change form
|
|
158
|
+
:param n: number
|
|
159
|
+
:param forms: tuple of (singular, plural) forms
|
|
160
|
+
:return: appropriate form
|
|
161
|
+
"""
|
|
162
|
+
# Most Afrikaans currencies use the same form for singular and plural
|
|
163
|
+
return forms[0]
|
|
164
|
+
|
|
165
|
+
def to_currency(self, val, currency='ZAR', cents=True, separator=' en',
|
|
166
|
+
adjective=False):
|
|
167
|
+
return super(Num2Word_AF, self).to_currency(
|
|
168
|
+
val, currency=currency, cents=cents, separator=separator,
|
|
169
|
+
adjective=adjective)
|
|
170
|
+
|
|
171
|
+
def to_year(self, val, longval=True):
|
|
172
|
+
# Handle special year cases
|
|
173
|
+
if val >= 2000:
|
|
174
|
+
if val == 2000:
|
|
175
|
+
return self.to_cardinal(val)
|
|
176
|
+
elif val < 2010:
|
|
177
|
+
# 2001-2009: "twee duisend een", etc.
|
|
178
|
+
return self.to_cardinal(2000) + " " + self.to_cardinal(val - 2000)
|
|
179
|
+
|
|
180
|
+
else:
|
|
181
|
+
# 2010+: "twintig tien", "twintig elf", etc.
|
|
182
|
+
century = val // 100
|
|
183
|
+
year_part = val % 100
|
|
184
|
+
if year_part == 0:
|
|
185
|
+
return self.to_cardinal(century) + " honderd"
|
|
186
|
+
else:
|
|
187
|
+
return self.to_cardinal(century) + " " + self.to_cardinal(year_part)
|
|
188
|
+
else:
|
|
189
|
+
# Pre-2000 years: "negentien nege-en-negentig" not "negentien honderd nege-en-negentig"
|
|
190
|
+
|
|
191
|
+
if val < 1000:
|
|
192
|
+
return self.to_cardinal(val)
|
|
193
|
+
elif not (val // 100) % 10:
|
|
194
|
+
return self.to_cardinal(val)
|
|
195
|
+
else:
|
|
196
|
+
# Split as century + year
|
|
197
|
+
century = val // 100
|
|
198
|
+
year_part = val % 100
|
|
199
|
+
if year_part == 0:
|
|
200
|
+
return self.to_cardinal(century) + " honderd"
|
|
201
|
+
else:
|
|
202
|
+
return self.to_cardinal(century) + " " + self.to_cardinal(year_part)
|
num2words2/lang_AM.py
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
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_AM(lang_EUR.Num2Word_EUR):
|
|
24
|
+
CURRENCY_FORMS = {'ETB': (('ብር', 'ብር'), ('ሳንቲም', 'ሳንቲም'), ' ከ'),
|
|
25
|
+
'USD': (('ዶላር', 'ዶላር'), ('ሳንቲም', 'ሳንቲም'), ' ከ'),
|
|
26
|
+
'JPY': (('የን', 'የን'), ('ሴን', 'ሴን'), ' ከ')}
|
|
27
|
+
|
|
28
|
+
GIGA_SUFFIX = 'ቢሊዮን'
|
|
29
|
+
MEGA_SUFFIX = 'ሚሊዮን'
|
|
30
|
+
|
|
31
|
+
def set_high_numwords(self, high):
|
|
32
|
+
cap = 3 * (len(high) + 1)
|
|
33
|
+
|
|
34
|
+
for word, n in zip(high, range(cap, 5, -3)):
|
|
35
|
+
if n == 9:
|
|
36
|
+
self.cards[10 ** n] = word + self.GIGA_SUFFIX
|
|
37
|
+
else:
|
|
38
|
+
self.cards[10 ** n] = word + self.MEGA_SUFFIX
|
|
39
|
+
|
|
40
|
+
def setup(self):
|
|
41
|
+
super(Num2Word_AM, self).setup()
|
|
42
|
+
|
|
43
|
+
self.negword = 'ሰልቢ '
|
|
44
|
+
self.pointword = 'ነጥብ'
|
|
45
|
+
self.exclude_title = ['እና', 'ነጥብ', 'አሉታዊ']
|
|
46
|
+
|
|
47
|
+
self.mid_numwords = [(1000, 'ሺህ'), (100, 'መቶ'), (90, 'ዘጠና'),
|
|
48
|
+
(80, 'ሰማንያ'), (70, 'ሰባ'), (60, 'ስድሳ'),
|
|
49
|
+
(50, 'አምሳ'), (40, 'አርባ'), (30, 'ሠላሳ')]
|
|
50
|
+
self.low_numwords = ['ሃያ', 'አሥራ ዘጠኝ', 'አሥራ ስምንት', 'አሥራ ሰባት',
|
|
51
|
+
'አስራ ስድስት', 'አሥራ አምስት', 'አሥራ አራት', 'አሥራ ሦስት',
|
|
52
|
+
'አሥራ ሁለት', 'አሥራ አንድ', 'አሥር', 'ዘጠኝ', 'ስምንት',
|
|
53
|
+
'ሰባት', 'ስድስት', 'አምስት', 'አራት', 'ሦስት', 'ሁለት',
|
|
54
|
+
'አንድ', 'ዜሮ']
|
|
55
|
+
self.ords = {'አንድ': 'አንደኛ',
|
|
56
|
+
'ሁለት': 'ሁለተኛ',
|
|
57
|
+
'ሦስት': 'ሦስተኛ',
|
|
58
|
+
'አራት': 'አራተኛ',
|
|
59
|
+
'አምስት': 'አምስተኛ',
|
|
60
|
+
'ስድስት': 'ስድስተኛ',
|
|
61
|
+
'ሰባት': 'ሰባተኛ',
|
|
62
|
+
'ስምንት': 'ስምንተኛ',
|
|
63
|
+
'ዘጠኝ': 'ዘጠነኛ',
|
|
64
|
+
'አሥር': 'አሥረኛ',
|
|
65
|
+
'አሥራ አንድ': 'አሥራ አንደኛ',
|
|
66
|
+
'አሥራ ሁለት': 'አሥራ ሁለተኛ',
|
|
67
|
+
'አሥራ ሦስት': 'አሥራ ሦስተኛ',
|
|
68
|
+
'አሥራ አራት': 'አሥራ አራተኛ',
|
|
69
|
+
'አሥራ አምስት': 'አሥራ አምስተኛ',
|
|
70
|
+
'አሥራ ስድስት': 'አሥራ ስድስተኛ',
|
|
71
|
+
'አሥራ ሰባት': 'አሥራ ሰባተኛ',
|
|
72
|
+
'አሥራ ስምንት': 'አሥራ ስምንተኛ',
|
|
73
|
+
'አሥራ ዘጠኝ': 'አሥራ ዘጠነኛ'}
|
|
74
|
+
|
|
75
|
+
def to_cardinal(self, value):
|
|
76
|
+
try:
|
|
77
|
+
assert int(value) == value
|
|
78
|
+
except (ValueError, TypeError, AssertionError):
|
|
79
|
+
return self.to_cardinal_float(value)
|
|
80
|
+
|
|
81
|
+
# Handle negative integers
|
|
82
|
+
if value < 0:
|
|
83
|
+
return self.negword + self.to_cardinal(-value)
|
|
84
|
+
|
|
85
|
+
out = ''
|
|
86
|
+
if value >= self.MAXVAL:
|
|
87
|
+
raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL))
|
|
88
|
+
|
|
89
|
+
if value == 100:
|
|
90
|
+
return self.title(out + 'መቶ')
|
|
91
|
+
else:
|
|
92
|
+
val = self.splitnum(value)
|
|
93
|
+
words, num = self.clean(val)
|
|
94
|
+
return self.title(out + words)
|
|
95
|
+
|
|
96
|
+
def merge(self, lpair, rpair):
|
|
97
|
+
ltext, lnum = lpair
|
|
98
|
+
rtext, rnum = rpair
|
|
99
|
+
if lnum == 1 and rnum < 100:
|
|
100
|
+
return rtext, rnum
|
|
101
|
+
elif 100 > lnum > rnum:
|
|
102
|
+
return '%s %s' % (ltext, rtext), lnum + rnum
|
|
103
|
+
elif lnum >= 100 > rnum:
|
|
104
|
+
return '%s %s' % (ltext, rtext), lnum + rnum
|
|
105
|
+
elif rnum > lnum:
|
|
106
|
+
return '%s %s' % (ltext, rtext), lnum * rnum
|
|
107
|
+
else:
|
|
108
|
+
# Default case: lnum > rnum, both could be >= 100
|
|
109
|
+
return '%s %s' % (ltext, rtext), lnum + rnum
|
|
110
|
+
|
|
111
|
+
def to_ordinal(self, value):
|
|
112
|
+
self.verify_ordinal(value)
|
|
113
|
+
outwords = self.to_cardinal(value).split(' ')
|
|
114
|
+
lastwords = outwords[-1].split('-')
|
|
115
|
+
lastword = lastwords[-1].lower()
|
|
116
|
+
try:
|
|
117
|
+
lastword = self.ords[lastword]
|
|
118
|
+
except KeyError:
|
|
119
|
+
lastword += 'ኛ'
|
|
120
|
+
lastwords[-1] = self.title(lastword)
|
|
121
|
+
outwords[-1] = ' '.join(lastwords)
|
|
122
|
+
return ' '.join(outwords)
|
|
123
|
+
|
|
124
|
+
def to_ordinal_num(self, value):
|
|
125
|
+
self.verify_ordinal(value)
|
|
126
|
+
return '%s%s' % (value, self.to_ordinal(value)[-1:])
|
|
127
|
+
|
|
128
|
+
def to_currency(self, val, currency='ETB', cents=True, separator=',',
|
|
129
|
+
adjective=False):
|
|
130
|
+
# Track if input was originally an integer
|
|
131
|
+
is_integer_input = isinstance(val, int)
|
|
132
|
+
|
|
133
|
+
if is_integer_input:
|
|
134
|
+
left = abs(val)
|
|
135
|
+
right = 0
|
|
136
|
+
is_negative = val < 0
|
|
137
|
+
else:
|
|
138
|
+
from decimal import Decimal
|
|
139
|
+
|
|
140
|
+
from .currency import parse_currency_parts
|
|
141
|
+
|
|
142
|
+
# Check if value has fractional cents
|
|
143
|
+
decimal_val = Decimal(str(val))
|
|
144
|
+
has_fractional_cents = (decimal_val * 100) % 1 != 0
|
|
145
|
+
|
|
146
|
+
left, right, is_negative = parse_currency_parts(val, is_int_with_cents=False,
|
|
147
|
+
keep_precision=has_fractional_cents)
|
|
148
|
+
|
|
149
|
+
try:
|
|
150
|
+
cr1, cr2, default_separator = self.CURRENCY_FORMS[currency]
|
|
151
|
+
if separator == ',': # Use default separator if not overridden
|
|
152
|
+
separator = default_separator
|
|
153
|
+
except KeyError:
|
|
154
|
+
raise NotImplementedError(
|
|
155
|
+
'Currency code "%s" not implemented for "%s"' %
|
|
156
|
+
(currency, self.__class__.__name__))
|
|
157
|
+
|
|
158
|
+
minus_str = "%s " % self.negword.strip() if is_negative else ""
|
|
159
|
+
money_str = self.to_cardinal(left)
|
|
160
|
+
|
|
161
|
+
# For floats, always show cents (even if zero)
|
|
162
|
+
# For integers, don't show cents at all
|
|
163
|
+
if not is_integer_input:
|
|
164
|
+
if cents:
|
|
165
|
+
# Handle fractional cents
|
|
166
|
+
from decimal import Decimal
|
|
167
|
+
if isinstance(right, Decimal):
|
|
168
|
+
# Convert fractional cents (e.g., 65.3 cents)
|
|
169
|
+
cents_str = self.to_cardinal_float(float(right)) if right > 0 else 'ዜሮ'
|
|
170
|
+
else:
|
|
171
|
+
cents_str = self.to_cardinal(right) if right > 0 else 'ዜሮ'
|
|
172
|
+
else:
|
|
173
|
+
cents_str = str(float(right) if isinstance(right, Decimal) else right)
|
|
174
|
+
return u'%s%s %s%s %s %s' % (
|
|
175
|
+
minus_str,
|
|
176
|
+
money_str,
|
|
177
|
+
self.pluralize(left, cr1),
|
|
178
|
+
separator,
|
|
179
|
+
cents_str,
|
|
180
|
+
self.pluralize(right, cr2)
|
|
181
|
+
)
|
|
182
|
+
else:
|
|
183
|
+
# Integer: no cents
|
|
184
|
+
return u'%s%s %s' % (
|
|
185
|
+
minus_str,
|
|
186
|
+
money_str,
|
|
187
|
+
self.pluralize(left, cr1)
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
def to_year(self, val, longval=True):
|
|
191
|
+
if not (val // 100) % 10:
|
|
192
|
+
return self.to_cardinal(val)
|
|
193
|
+
return self.to_splitnum(val, hightxt='መቶ', longval=longval)
|