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/lang_EL.py
ADDED
|
@@ -0,0 +1,338 @@
|
|
|
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_EL(Num2Word_EUR):
|
|
24
|
+
CURRENCY_FORMS = {
|
|
25
|
+
'EUR': (('ευρώ', 'ευρώ'), ('λεπτό', 'λεπτά')),
|
|
26
|
+
'USD': (('δολάριο', 'δολάρια'), ('σεντ', 'σεντς')),
|
|
27
|
+
'GBP': (('λίρα', 'λίρες'), ('πέννα', 'πένες')),
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
def setup(self):
|
|
31
|
+
Num2Word_EUR.setup(self)
|
|
32
|
+
|
|
33
|
+
self.negword = "μείον "
|
|
34
|
+
self.pointword = "κόμμα"
|
|
35
|
+
self.errmsg_nonnum = (
|
|
36
|
+
"Μόνο αριθμοί μπορούν να μετατραπούν σε λέξεις."
|
|
37
|
+
)
|
|
38
|
+
self.errmsg_toobig = (
|
|
39
|
+
"Αριθμός πολύ μεγάλος για να μετατραπεί σε λέξεις (abs(%s) > %s)."
|
|
40
|
+
)
|
|
41
|
+
self.exclude_title = ["και", "κόμμα", "μείον"]
|
|
42
|
+
|
|
43
|
+
# Override the EU settings with Greek
|
|
44
|
+
self.GIGA_SUFFIX = "" # Don't use the EU pattern
|
|
45
|
+
self.MEGA_SUFFIX = "" # Don't use the EU pattern
|
|
46
|
+
|
|
47
|
+
# Mid numbers: thousands and hundreds with tens
|
|
48
|
+
self.mid_numwords = [(1000000000000, "τρισεκατομμύριο"),
|
|
49
|
+
(1000000000, "δισεκατομμύριο"),
|
|
50
|
+
(1000000, "εκατομμύριο"),
|
|
51
|
+
(1000, "χίλια"), (100, "εκατό"),
|
|
52
|
+
(90, "ενενήντα"), (80, "ογδόντα"), (70, "εβδομήντα"),
|
|
53
|
+
(60, "εξήντα"), (50, "πενήντα"), (40, "σαράντα"),
|
|
54
|
+
(30, "τριάντα")]
|
|
55
|
+
|
|
56
|
+
# Low numbers 0-29
|
|
57
|
+
self.low_numwords = ["είκοσι", "δεκαεννέα", "δεκαοκτώ", "δεκαεπτά",
|
|
58
|
+
"δεκαέξι", "δεκαπέντε", "δεκατέσσερα", "δεκατρία",
|
|
59
|
+
"δώδεκα", "έντεκα", "δέκα", "εννέα", "οκτώ",
|
|
60
|
+
"επτά", "έξι", "πέντε", "τέσσερα", "τρία", "δύο",
|
|
61
|
+
"ένα", "μηδέν"]
|
|
62
|
+
|
|
63
|
+
# Ordinal numbers mapping
|
|
64
|
+
self.ordinals = {
|
|
65
|
+
"ένα": "πρώτος",
|
|
66
|
+
"δύο": "δεύτερος",
|
|
67
|
+
"τρία": "τρίτος",
|
|
68
|
+
"τέσσερα": "τέταρτος",
|
|
69
|
+
"πέντε": "πέμπτος",
|
|
70
|
+
"έξι": "έκτος",
|
|
71
|
+
"επτά": "έβδομος",
|
|
72
|
+
"οκτώ": "όγδοος",
|
|
73
|
+
"εννέα": "έννατος",
|
|
74
|
+
"δέκα": "δέκατος",
|
|
75
|
+
"έντεκα": "ενδέκατος",
|
|
76
|
+
"δώδεκα": "δωδέκατος",
|
|
77
|
+
"είκοσι": "εικοστός",
|
|
78
|
+
"εκατό": "εκατοστός",
|
|
79
|
+
"χίλια": "χιλιοστός",
|
|
80
|
+
"εκατομμύριο": "εκατομμυριοστός"
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
def merge(self, curr, next):
|
|
84
|
+
ctext, cnum, ntext, nnum = curr + next
|
|
85
|
+
|
|
86
|
+
# Special handling for 1
|
|
87
|
+
if cnum == 1:
|
|
88
|
+
if nnum == 100:
|
|
89
|
+
return ("εκατό", 100)
|
|
90
|
+
elif nnum == 1000:
|
|
91
|
+
return ("χίλια", 1000)
|
|
92
|
+
elif nnum >= 1000000:
|
|
93
|
+
return ("ένα " + ntext, cnum * nnum)
|
|
94
|
+
elif nnum < 1000000:
|
|
95
|
+
return next
|
|
96
|
+
|
|
97
|
+
# Handle multiplication (larger unit)
|
|
98
|
+
if nnum > cnum:
|
|
99
|
+
if nnum == 100:
|
|
100
|
+
# Hundreds
|
|
101
|
+
if cnum == 2:
|
|
102
|
+
return ("διακόσια", 200)
|
|
103
|
+
elif cnum == 3:
|
|
104
|
+
return ("τριακόσια", 300)
|
|
105
|
+
elif cnum == 4:
|
|
106
|
+
return ("τετρακόσια", 400)
|
|
107
|
+
elif cnum == 5:
|
|
108
|
+
return ("πεντακόσια", 500)
|
|
109
|
+
elif cnum == 6:
|
|
110
|
+
return ("εξακόσια", 600)
|
|
111
|
+
elif cnum == 7:
|
|
112
|
+
return ("επτακόσια", 700)
|
|
113
|
+
elif cnum == 8:
|
|
114
|
+
return ("οκτακόσια", 800)
|
|
115
|
+
elif cnum == 9:
|
|
116
|
+
return ("εννιακόσια", 900)
|
|
117
|
+
elif nnum == 1000:
|
|
118
|
+
# Thousands - need feminine forms for certain numbers
|
|
119
|
+
if cnum == 1:
|
|
120
|
+
# Special case: when merging compound numbers ending with 1
|
|
121
|
+
# For feminine thousands, "ένα" becomes "μία"
|
|
122
|
+
if "ένα" in ctext:
|
|
123
|
+
ctext_fem = ctext.replace("ένα", "μία")
|
|
124
|
+
return (ctext_fem + " χιλιάδες", cnum * nnum)
|
|
125
|
+
else:
|
|
126
|
+
return ("χίλια", 1000)
|
|
127
|
+
elif cnum == 2:
|
|
128
|
+
return ("δύο χιλιάδες", 2000)
|
|
129
|
+
elif cnum == 3:
|
|
130
|
+
return ("τρεις χιλιάδες", 3000)
|
|
131
|
+
elif cnum == 4:
|
|
132
|
+
return ("τέσσερις χιλιάδες", 4000)
|
|
133
|
+
elif cnum == 200:
|
|
134
|
+
return ("διακόσιες χιλιάδες", 200000)
|
|
135
|
+
elif cnum == 300:
|
|
136
|
+
return ("τριακόσιες χιλιάδες", 300000)
|
|
137
|
+
elif cnum == 400:
|
|
138
|
+
return ("τετρακόσιες χιλιάδες", 400000)
|
|
139
|
+
elif cnum == 500:
|
|
140
|
+
return ("πεντακόσιες χιλιάδες", 500000)
|
|
141
|
+
elif cnum == 600:
|
|
142
|
+
return ("εξακόσιες χιλιάδες", 600000)
|
|
143
|
+
elif cnum == 700:
|
|
144
|
+
return ("επτακόσιες χιλιάδες", 700000)
|
|
145
|
+
elif cnum == 800:
|
|
146
|
+
return ("οκτακόσιες χιλιάδες", 800000)
|
|
147
|
+
elif cnum == 900:
|
|
148
|
+
return ("εννιακόσιες χιλιάδες", 900000)
|
|
149
|
+
else:
|
|
150
|
+
# For other numbers, adjust the form for feminine thousands
|
|
151
|
+
ctext_new = ctext
|
|
152
|
+
# Convert "ένα" to "μία" for feminine thousands
|
|
153
|
+
ctext_new = ctext_new.replace("ένα", "μία")
|
|
154
|
+
# Convert all hundreds to feminine form for χιλιάδες
|
|
155
|
+
ctext_new = ctext_new.replace("διακόσια", "διακόσιες")
|
|
156
|
+
ctext_new = ctext_new.replace("τριακόσια", "τριακόσιες")
|
|
157
|
+
ctext_new = ctext_new.replace("τετρακόσια", "τετρακόσιες")
|
|
158
|
+
ctext_new = ctext_new.replace("πεντακόσια", "πεντακόσιες")
|
|
159
|
+
ctext_new = ctext_new.replace("εξακόσια", "εξακόσιες")
|
|
160
|
+
ctext_new = ctext_new.replace("επτακόσια", "επτακόσιες")
|
|
161
|
+
ctext_new = ctext_new.replace("οκτακόσια", "οκτακόσιες")
|
|
162
|
+
ctext_new = ctext_new.replace("εννιακόσια", "εννιακόσιες")
|
|
163
|
+
return (ctext_new + " χιλιάδες", cnum * nnum)
|
|
164
|
+
elif nnum == 1000000:
|
|
165
|
+
# Millions - need special grammar for compound numbers
|
|
166
|
+
if cnum == 1:
|
|
167
|
+
return ("ένα εκατομμύριο", 1000000)
|
|
168
|
+
elif cnum == 2:
|
|
169
|
+
return ("δύο εκατομμύρια", 2000000)
|
|
170
|
+
elif cnum == 3:
|
|
171
|
+
return ("τρία εκατομμύρια", 3000000)
|
|
172
|
+
elif cnum == 4:
|
|
173
|
+
return ("τέσσερα εκατομμύρια", 4000000)
|
|
174
|
+
else:
|
|
175
|
+
# For compound numbers with millions, εκατομμύρια is neuter
|
|
176
|
+
# so we keep the neuter forms (τέσσερα, not τέσσερις)
|
|
177
|
+
return (ctext + " εκατομμύρια", cnum * nnum)
|
|
178
|
+
elif nnum == 1000000000:
|
|
179
|
+
# Billions
|
|
180
|
+
if cnum == 1:
|
|
181
|
+
return ("ένα δισεκατομμύριο", 1000000000)
|
|
182
|
+
else:
|
|
183
|
+
return (ctext + " δισεκατομμύρια", cnum * nnum)
|
|
184
|
+
elif nnum == 1000000000000:
|
|
185
|
+
# Trillions
|
|
186
|
+
if cnum == 1:
|
|
187
|
+
return ("ένα τρισεκατομμύριο", 1000000000000)
|
|
188
|
+
else:
|
|
189
|
+
return (ctext + " τρισεκατομμύρια", cnum * nnum)
|
|
190
|
+
elif nnum >= 1000000:
|
|
191
|
+
# Other large numbers
|
|
192
|
+
if cnum == 1:
|
|
193
|
+
return ("ένα " + ntext, cnum * nnum)
|
|
194
|
+
else:
|
|
195
|
+
return (ctext + " " + ntext, cnum * nnum)
|
|
196
|
+
else:
|
|
197
|
+
# Regular multiplication
|
|
198
|
+
return (ctext + " " + ntext, cnum * nnum)
|
|
199
|
+
|
|
200
|
+
# Handle addition (smaller unit added)
|
|
201
|
+
else:
|
|
202
|
+
return (ctext + " " + ntext, cnum + nnum)
|
|
203
|
+
|
|
204
|
+
def to_ordinal(self, value):
|
|
205
|
+
self.verify_ordinal(value)
|
|
206
|
+
word = self.to_cardinal(value)
|
|
207
|
+
|
|
208
|
+
# Handle special cases first
|
|
209
|
+
for cardinal, ordinal in self.ordinals.items():
|
|
210
|
+
if word == cardinal:
|
|
211
|
+
return ordinal
|
|
212
|
+
|
|
213
|
+
# Handle special compound numbers
|
|
214
|
+
if word == "δεκατέσσερα":
|
|
215
|
+
return "δεκατέταρτος"
|
|
216
|
+
elif word == "δεκατρία":
|
|
217
|
+
return "δεκατρίτος"
|
|
218
|
+
elif word == "ένα εκατομμύριο":
|
|
219
|
+
return "εκατομμυριοστός"
|
|
220
|
+
|
|
221
|
+
# Handle compound ordinals
|
|
222
|
+
parts = word.split()
|
|
223
|
+
if len(parts) > 1:
|
|
224
|
+
# Handle "είκοσι ένα" -> "εικοστός πρώτος"
|
|
225
|
+
if parts[0] == "είκοσι" and parts[1] == "ένα":
|
|
226
|
+
return "εικοστός πρώτος"
|
|
227
|
+
elif parts[0] == "είκοσι" and parts[1] in self.ordinals:
|
|
228
|
+
return "εικοστός " + self.ordinals[parts[1]]
|
|
229
|
+
# Handle "εκατό ένα" -> "εκατοστός πρώτος"
|
|
230
|
+
elif parts[0] == "εκατό" and parts[1] == "ένα":
|
|
231
|
+
return "εκατοστός πρώτος"
|
|
232
|
+
elif parts[0] == "εκατό" and parts[1] in self.ordinals:
|
|
233
|
+
return "εκατοστός " + self.ordinals[parts[1]]
|
|
234
|
+
|
|
235
|
+
# For compound numbers, make only the last part ordinal
|
|
236
|
+
last_part = parts[-1]
|
|
237
|
+
if last_part in self.ordinals:
|
|
238
|
+
# Transform first part if needed
|
|
239
|
+
if parts[0] == "είκοσι":
|
|
240
|
+
parts[0] = "εικοστός"
|
|
241
|
+
elif parts[0] == "εκατό":
|
|
242
|
+
parts[0] = "εκατοστός"
|
|
243
|
+
parts[-1] = self.ordinals[last_part]
|
|
244
|
+
return " ".join(parts)
|
|
245
|
+
# Handle other compound forms
|
|
246
|
+
elif last_part == "τέσσερα":
|
|
247
|
+
parts[-1] = "τέταρτος"
|
|
248
|
+
return " ".join(parts)
|
|
249
|
+
|
|
250
|
+
# Default ordinal formation
|
|
251
|
+
if word.endswith("α"):
|
|
252
|
+
return word[:-1] + "ος"
|
|
253
|
+
elif word.endswith("ο"):
|
|
254
|
+
return word[:-1] + "ος"
|
|
255
|
+
elif word.endswith("ι"):
|
|
256
|
+
return word + "ος"
|
|
257
|
+
else:
|
|
258
|
+
return word + "ος"
|
|
259
|
+
|
|
260
|
+
def to_ordinal_num(self, value):
|
|
261
|
+
self.verify_ordinal(value)
|
|
262
|
+
return str(value) + "ος"
|
|
263
|
+
|
|
264
|
+
def _money_verbose(self, number, currency):
|
|
265
|
+
if currency == 'GBP' and number == 1:
|
|
266
|
+
return "μία" # Feminine form for λίρα
|
|
267
|
+
return self.to_cardinal(number)
|
|
268
|
+
|
|
269
|
+
def _cents_verbose(self, number, currency):
|
|
270
|
+
if currency == 'GBP' and number == 1:
|
|
271
|
+
return "μία" # Feminine form for πέννα
|
|
272
|
+
return self.to_cardinal(number)
|
|
273
|
+
|
|
274
|
+
def to_currency(self, val, currency='EUR', cents=True, separator=' και',
|
|
275
|
+
adjective=False):
|
|
276
|
+
from decimal import Decimal
|
|
277
|
+
|
|
278
|
+
from .currency import parse_currency_parts, prefix_currency
|
|
279
|
+
|
|
280
|
+
# Check if value has fractional cents
|
|
281
|
+
decimal_val = Decimal(str(val))
|
|
282
|
+
has_fractional_cents = (decimal_val * 100) % 1 != 0
|
|
283
|
+
|
|
284
|
+
# Fix the currency parsing issue - integers should be treated as whole units
|
|
285
|
+
if isinstance(val, int):
|
|
286
|
+
left, right, is_negative = parse_currency_parts(val, is_int_with_cents=False)
|
|
287
|
+
else:
|
|
288
|
+
left, right, is_negative = parse_currency_parts(val, is_int_with_cents=False,
|
|
289
|
+
keep_precision=has_fractional_cents)
|
|
290
|
+
|
|
291
|
+
try:
|
|
292
|
+
cr1, cr2 = self.CURRENCY_FORMS[currency]
|
|
293
|
+
except KeyError:
|
|
294
|
+
raise NotImplementedError(
|
|
295
|
+
'Currency code "%s" not implemented for "%s"' %
|
|
296
|
+
(currency, self.__class__.__name__))
|
|
297
|
+
|
|
298
|
+
if adjective and currency in self.CURRENCY_ADJECTIVES:
|
|
299
|
+
cr1 = prefix_currency(self.CURRENCY_ADJECTIVES[currency], cr1)
|
|
300
|
+
|
|
301
|
+
minus_str = "%s " % self.negword.strip() if is_negative else ""
|
|
302
|
+
money_str = self._money_verbose(left, currency)
|
|
303
|
+
|
|
304
|
+
# Explicitly check if input has decimal point or non-zero cents
|
|
305
|
+
has_decimal = isinstance(val, float) or str(val).find('.') != -1
|
|
306
|
+
|
|
307
|
+
# Only include cents if:
|
|
308
|
+
# 1. Input has decimal point OR
|
|
309
|
+
# 2. Cents are non-zero
|
|
310
|
+
if has_decimal or right > 0:
|
|
311
|
+
# Handle fractional cents
|
|
312
|
+
if isinstance(right, Decimal) and has_fractional_cents:
|
|
313
|
+
# Convert fractional cents (e.g., 65.3 cents)
|
|
314
|
+
cents_str = self.to_cardinal_float(float(right)) if cents else str(float(right))
|
|
315
|
+
else:
|
|
316
|
+
cents_str = self._cents_verbose(int(right) if isinstance(right, Decimal) else right, currency) \
|
|
317
|
+
if cents else self._cents_terse(int(right) if isinstance(right, Decimal) else right, currency)
|
|
318
|
+
|
|
319
|
+
return u'%s%s %s%s %s %s' % (
|
|
320
|
+
minus_str,
|
|
321
|
+
money_str,
|
|
322
|
+
self.pluralize(left, cr1),
|
|
323
|
+
separator,
|
|
324
|
+
cents_str,
|
|
325
|
+
self.pluralize(right, cr2)
|
|
326
|
+
)
|
|
327
|
+
else:
|
|
328
|
+
return u'%s%s %s' % (
|
|
329
|
+
minus_str,
|
|
330
|
+
money_str,
|
|
331
|
+
self.pluralize(left, cr1)
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
def pluralize(self, n, forms):
|
|
335
|
+
if n == 1:
|
|
336
|
+
return forms[0]
|
|
337
|
+
else:
|
|
338
|
+
return forms[1]
|
num2words2/lang_EN.py
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
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_EN(lang_EUR.Num2Word_EUR):
|
|
24
|
+
def __init__(self):
|
|
25
|
+
super(Num2Word_EN, self).__init__()
|
|
26
|
+
# Override specific currency forms for proper English pluralization
|
|
27
|
+
self.CURRENCY_FORMS['EUR'] = (('euro', 'euros'), ('cent', 'cents'))
|
|
28
|
+
self.CURRENCY_FORMS['USD'] = (('dollar', 'dollars'), ('cent', 'cents'))
|
|
29
|
+
self.CURRENCY_FORMS['GBP'] = (('pound', 'pounds'), ('penny', 'pence'))
|
|
30
|
+
self.CURRENCY_FORMS['NGN'] = (('naira', 'naira'), ('kobo', 'kobo'))
|
|
31
|
+
|
|
32
|
+
def set_high_numwords(self, high):
|
|
33
|
+
max = 3 + 3 * len(high)
|
|
34
|
+
for word, n in zip(high, range(max, 3, -3)):
|
|
35
|
+
self.cards[10 ** n] = word + "illion"
|
|
36
|
+
|
|
37
|
+
def setup(self):
|
|
38
|
+
super(Num2Word_EN, self).setup()
|
|
39
|
+
|
|
40
|
+
self.negword = "minus "
|
|
41
|
+
self.pointword = "point"
|
|
42
|
+
self.exclude_title = ["and", "point", "minus"]
|
|
43
|
+
|
|
44
|
+
self.mid_numwords = [(1000, "thousand"), (100, "hundred"),
|
|
45
|
+
(90, "ninety"), (80, "eighty"), (70, "seventy"),
|
|
46
|
+
(60, "sixty"), (50, "fifty"), (40, "forty"),
|
|
47
|
+
(30, "thirty")]
|
|
48
|
+
self.low_numwords = ["twenty", "nineteen", "eighteen", "seventeen",
|
|
49
|
+
"sixteen", "fifteen", "fourteen", "thirteen",
|
|
50
|
+
"twelve", "eleven", "ten", "nine", "eight",
|
|
51
|
+
"seven", "six", "five", "four", "three", "two",
|
|
52
|
+
"one", "zero"]
|
|
53
|
+
self.ords = {"one": "first",
|
|
54
|
+
"two": "second",
|
|
55
|
+
"three": "third",
|
|
56
|
+
"four": "fourth",
|
|
57
|
+
"five": "fifth",
|
|
58
|
+
"six": "sixth",
|
|
59
|
+
"seven": "seventh",
|
|
60
|
+
"eight": "eighth",
|
|
61
|
+
"nine": "ninth",
|
|
62
|
+
"ten": "tenth",
|
|
63
|
+
"eleven": "eleventh",
|
|
64
|
+
"twelve": "twelfth"}
|
|
65
|
+
|
|
66
|
+
def merge(self, lpair, rpair):
|
|
67
|
+
ltext, lnum = lpair
|
|
68
|
+
rtext, rnum = rpair
|
|
69
|
+
if lnum == 1 and rnum < 100:
|
|
70
|
+
return (rtext, rnum)
|
|
71
|
+
elif 100 > lnum > rnum:
|
|
72
|
+
return ("%s-%s" % (ltext, rtext), lnum + rnum)
|
|
73
|
+
elif lnum >= 100 > rnum:
|
|
74
|
+
return ("%s and %s" % (ltext, rtext), lnum + rnum)
|
|
75
|
+
elif rnum > lnum:
|
|
76
|
+
return ("%s %s" % (ltext, rtext), lnum * rnum)
|
|
77
|
+
return ("%s, %s" % (ltext, rtext), lnum + rnum)
|
|
78
|
+
|
|
79
|
+
def to_ordinal(self, value):
|
|
80
|
+
self.verify_ordinal(value)
|
|
81
|
+
outwords = self.to_cardinal(value).split(" ")
|
|
82
|
+
lastwords = outwords[-1].split("-")
|
|
83
|
+
lastword = lastwords[-1].lower()
|
|
84
|
+
try:
|
|
85
|
+
lastword = self.ords[lastword]
|
|
86
|
+
except KeyError:
|
|
87
|
+
if lastword[-1] == "y":
|
|
88
|
+
lastword = lastword[:-1] + "ie"
|
|
89
|
+
lastword += "th"
|
|
90
|
+
lastwords[-1] = self.title(lastword)
|
|
91
|
+
outwords[-1] = "-".join(lastwords)
|
|
92
|
+
return " ".join(outwords)
|
|
93
|
+
|
|
94
|
+
def to_ordinal_num(self, value):
|
|
95
|
+
self.verify_ordinal(value)
|
|
96
|
+
return "%s%s" % (value, self.to_ordinal(value)[-2:])
|
|
97
|
+
|
|
98
|
+
def to_year(self, val, suffix=None, longval=True):
|
|
99
|
+
if val < 0:
|
|
100
|
+
val = abs(val)
|
|
101
|
+
suffix = 'BC' if not suffix else suffix
|
|
102
|
+
high, low = (val // 100, val % 100)
|
|
103
|
+
# If year is 00XX, X00X, or beyond 9999, go cardinal.
|
|
104
|
+
if (high == 0
|
|
105
|
+
or (high % 10 == 0 and low < 10)
|
|
106
|
+
or high >= 100):
|
|
107
|
+
valtext = self.to_cardinal(val)
|
|
108
|
+
else:
|
|
109
|
+
hightext = self.to_cardinal(high)
|
|
110
|
+
if low == 0:
|
|
111
|
+
lowtext = "hundred"
|
|
112
|
+
elif low < 10:
|
|
113
|
+
lowtext = "oh-%s" % self.to_cardinal(low)
|
|
114
|
+
else:
|
|
115
|
+
lowtext = self.to_cardinal(low)
|
|
116
|
+
valtext = "%s %s" % (hightext, lowtext)
|
|
117
|
+
return (valtext if not suffix
|
|
118
|
+
else "%s %s" % (valtext, suffix))
|
num2words2/lang_EN_IN.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
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 .lang_EN import Num2Word_EN
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class Num2Word_EN_IN(Num2Word_EN):
|
|
24
|
+
def set_high_numwords(self, high):
|
|
25
|
+
self.cards[10 ** 7] = "crore"
|
|
26
|
+
self.cards[10 ** 5] = "lakh"
|
num2words2/lang_EN_NG.py
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
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 . import lang_EN
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class Num2Word_EN_NG(lang_EN.Num2Word_EN):
|
|
24
|
+
|
|
25
|
+
CURRENCY_FORMS = {
|
|
26
|
+
'NGN': (('naira', 'naira'), ('kobo', 'kobo')),
|
|
27
|
+
'EUR': (('euro', 'euros'), ('cent', 'cents')),
|
|
28
|
+
'USD': (('dollar', 'dollars'), ('cent', 'cents')),
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
CURRENCY_ADJECTIVES = {
|
|
32
|
+
'NGN': 'Nigerian',
|
|
33
|
+
'EUR': 'European',
|
|
34
|
+
'USD': 'US',
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
def to_currency(
|
|
38
|
+
self, val, currency='NGN',
|
|
39
|
+
kobo=True, separator=',',
|
|
40
|
+
adjective=False
|
|
41
|
+
):
|
|
42
|
+
result = super(Num2Word_EN_NG, self).to_currency(
|
|
43
|
+
val, currency=currency, cents=kobo, separator=separator,
|
|
44
|
+
adjective=adjective)
|
|
45
|
+
return result
|
num2words2/lang_EO.py
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (c) 2021, Savoir-faire Linux inc. All Rights Reserved.
|
|
3
|
+
|
|
4
|
+
# This library is free software; you can redistribute it and/or
|
|
5
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
6
|
+
# License as published by the Free Software Foundation; either
|
|
7
|
+
# version 2.1 of the License, or (at your option) any later version.
|
|
8
|
+
# This library is distributed in the hope that it will be useful,
|
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
11
|
+
# Lesser General Public License for more details.
|
|
12
|
+
# You should have received a copy of the GNU Lesser General Public
|
|
13
|
+
# License along with this library; if not, write to the Free Software
|
|
14
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
15
|
+
# MA 02110-1301 USA
|
|
16
|
+
|
|
17
|
+
from __future__ import print_function, unicode_literals
|
|
18
|
+
|
|
19
|
+
from .base import Num2Word_Base
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class Num2Word_EO(Num2Word_Base):
|
|
23
|
+
CURRENCY_FORMS = {
|
|
24
|
+
"EUR": (("eŭro", "eŭroj"), ("centimo", "centimoj")),
|
|
25
|
+
"USD": (("dolaro", "dolaroj"), ("cendo", "cendoj")),
|
|
26
|
+
"FRF": (("franko", "frankoj"), ("centimo", "centimoj")),
|
|
27
|
+
"GBP": (("pundo", "pundoj"), ("penco", "pencoj")),
|
|
28
|
+
"CNY": (("juano", "juanoj"), ("feno", "fenoj")),
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
GIGA_SUFFIX = "iliardo"
|
|
32
|
+
MEGA_SUFFIX = "iliono"
|
|
33
|
+
|
|
34
|
+
def set_high_numwords(self, high):
|
|
35
|
+
cap = 3 + 6 * len(high)
|
|
36
|
+
|
|
37
|
+
for word, n in zip(high, range(cap, 3, -6)):
|
|
38
|
+
if self.GIGA_SUFFIX:
|
|
39
|
+
self.cards[10 ** n] = word + self.GIGA_SUFFIX
|
|
40
|
+
|
|
41
|
+
if self.MEGA_SUFFIX:
|
|
42
|
+
self.cards[10 ** (n - 3)] = word + self.MEGA_SUFFIX
|
|
43
|
+
|
|
44
|
+
def gen_high_numwords(self, units, tens, lows):
|
|
45
|
+
out = [u + t for t in tens for u in units]
|
|
46
|
+
out.reverse()
|
|
47
|
+
return out + lows
|
|
48
|
+
|
|
49
|
+
def setup(self):
|
|
50
|
+
lows = ["naŭ", "ok", "sep", "ses", "kvin", "kvar", "tr", "b", "m"]
|
|
51
|
+
units = ["", "un", "duo", "tre", "kvatuor",
|
|
52
|
+
"kvin", "seks", "septen", "okto", "novem"]
|
|
53
|
+
tens = ["dek", "vigint", "trigint", "kvadragint", "kvinkvagint",
|
|
54
|
+
"seksagint", "septuagint", "oktogint", "nonagint"]
|
|
55
|
+
|
|
56
|
+
self.high_numwords = ["cent"] + self.gen_high_numwords(units, tens,
|
|
57
|
+
lows)
|
|
58
|
+
|
|
59
|
+
self.negword = "minus "
|
|
60
|
+
self.pointword = "komo"
|
|
61
|
+
self.errmsg_nonnum = u"Sole nombroj povas esti konvertita en vortojn."
|
|
62
|
+
self.errmsg_toobig = (
|
|
63
|
+
u"Tro granda nombro por esti konvertita en vortojn (abs(%s) > %s)."
|
|
64
|
+
)
|
|
65
|
+
self.exclude_title = ["kaj", "komo", "minus"]
|
|
66
|
+
self.mid_numwords = [(1000, "mil"), (100, "cent"), (90, "naŭdek"),
|
|
67
|
+
(80, "okdek"), (70, "sepdek"), (60, "sesdek"),
|
|
68
|
+
(50, "kvindek"), (40, "kvardek"), (30, "tridek")]
|
|
69
|
+
self.low_numwords = ["dudek", "dek naŭ", "dek ok", "dek sep",
|
|
70
|
+
"dek ses", "dek kvin", "dek kvar", "dek tri",
|
|
71
|
+
"dek du", "dek unu", "dek", "naŭ", "ok", "sep",
|
|
72
|
+
"ses", "kvin", "kvar", "tri", "du", "unu", "nul"]
|
|
73
|
+
self.ords = {
|
|
74
|
+
"unu": "unua",
|
|
75
|
+
"du": "dua",
|
|
76
|
+
"tri": "tria",
|
|
77
|
+
"kvar": "kvara",
|
|
78
|
+
"kvin": "kvina",
|
|
79
|
+
"ses": "sesa",
|
|
80
|
+
"sep": "sepa",
|
|
81
|
+
"ok": "oka",
|
|
82
|
+
"naŭ": "naŭa",
|
|
83
|
+
"dek": "deka"
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
def merge(self, curr, next):
|
|
87
|
+
ctext, cnum, ntext, nnum = curr + next
|
|
88
|
+
if cnum == 1 and nnum < 1000000:
|
|
89
|
+
return next
|
|
90
|
+
|
|
91
|
+
if nnum >= 10**6 and cnum > 1:
|
|
92
|
+
return ("%s %sj" % (ctext, ntext), cnum + nnum)
|
|
93
|
+
|
|
94
|
+
if nnum == 100:
|
|
95
|
+
return ("%s%s" % (ctext, ntext), cnum + nnum)
|
|
96
|
+
|
|
97
|
+
return ("%s %s" % (ctext, ntext), cnum + nnum)
|
|
98
|
+
|
|
99
|
+
def to_ordinal(self, value):
|
|
100
|
+
self.verify_ordinal(value)
|
|
101
|
+
word = self.to_cardinal(value)
|
|
102
|
+
for src, repl in self.ords.items():
|
|
103
|
+
if word.endswith(src):
|
|
104
|
+
word = word[:-len(src)] + repl
|
|
105
|
+
return word
|
|
106
|
+
|
|
107
|
+
if word.endswith("o"):
|
|
108
|
+
word = word[:-1] + "a"
|
|
109
|
+
elif word.endswith("oj"):
|
|
110
|
+
word = word[:-2] + "a"
|
|
111
|
+
else:
|
|
112
|
+
word = word + "a"
|
|
113
|
+
return word
|
|
114
|
+
|
|
115
|
+
def to_ordinal_num(self, value):
|
|
116
|
+
self.verify_ordinal(value)
|
|
117
|
+
out = str(value)
|
|
118
|
+
out += "a"
|
|
119
|
+
return out
|
|
120
|
+
|
|
121
|
+
def to_currency(self, val, currency="EUR", cents=True, separator=" kaj",
|
|
122
|
+
adjective=False):
|
|
123
|
+
result = super(Num2Word_EO, self).to_currency(
|
|
124
|
+
val, currency=currency, cents=cents, separator=separator,
|
|
125
|
+
adjective=adjective)
|
|
126
|
+
return result
|
|
127
|
+
|
|
128
|
+
def pluralize(self, n, forms):
|
|
129
|
+
form = 0 if n <= 1 else 1
|
|
130
|
+
return forms[form]
|