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_ET.py
ADDED
|
@@ -0,0 +1,393 @@
|
|
|
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_ET(Num2Word_Base):
|
|
25
|
+
CURRENCY_FORMS = {
|
|
26
|
+
'EUR': (
|
|
27
|
+
('euro', 'eurot'), ('sent', 'senti')
|
|
28
|
+
),
|
|
29
|
+
'USD': (
|
|
30
|
+
('dollar', 'dollarit'), ('sent', 'senti')
|
|
31
|
+
),
|
|
32
|
+
'GBP': (
|
|
33
|
+
('nael', 'naela'), ('penn', 'penni')
|
|
34
|
+
),
|
|
35
|
+
'SEK': (
|
|
36
|
+
('kroon', 'krooni'), ('ööri', 'ööri')
|
|
37
|
+
),
|
|
38
|
+
'NOK': (
|
|
39
|
+
('kroon', 'krooni'), ('ööri', 'ööri')
|
|
40
|
+
),
|
|
41
|
+
'DKK': (
|
|
42
|
+
('kroon', 'krooni'), ('ööri', 'ööri')
|
|
43
|
+
),
|
|
44
|
+
'RUB': (
|
|
45
|
+
('rubla', 'rubla'), ('kopikas', 'kopikat')
|
|
46
|
+
),
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
def __init__(self):
|
|
50
|
+
super(Num2Word_ET, self).__init__()
|
|
51
|
+
|
|
52
|
+
self.ones = [
|
|
53
|
+
'',
|
|
54
|
+
'üks',
|
|
55
|
+
'kaks',
|
|
56
|
+
'kolm',
|
|
57
|
+
'neli',
|
|
58
|
+
'viis',
|
|
59
|
+
'kuus',
|
|
60
|
+
'seitse',
|
|
61
|
+
'kaheksa',
|
|
62
|
+
'üheksa'
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
self.tens = [
|
|
66
|
+
'',
|
|
67
|
+
'kümme',
|
|
68
|
+
'kakskümmend',
|
|
69
|
+
'kolmkümmend',
|
|
70
|
+
'nelikümmend',
|
|
71
|
+
'viiskümmend',
|
|
72
|
+
'kuuskümmend',
|
|
73
|
+
'seitsekümmend',
|
|
74
|
+
'kaheksakümmend',
|
|
75
|
+
'üheksakümmend'
|
|
76
|
+
]
|
|
77
|
+
|
|
78
|
+
self.scale = {
|
|
79
|
+
100: 'sada',
|
|
80
|
+
1000: 'tuhat',
|
|
81
|
+
1000000: 'miljon',
|
|
82
|
+
1000000000: 'miljard',
|
|
83
|
+
1000000000000: 'triljon'
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
self.ordinals_ones = [
|
|
87
|
+
'',
|
|
88
|
+
'esimene',
|
|
89
|
+
'teine',
|
|
90
|
+
'kolmas',
|
|
91
|
+
'neljas',
|
|
92
|
+
'viies',
|
|
93
|
+
'kuues',
|
|
94
|
+
'seitsmes',
|
|
95
|
+
'kaheksas',
|
|
96
|
+
'üheksas'
|
|
97
|
+
]
|
|
98
|
+
|
|
99
|
+
self.ordinals_tens = [
|
|
100
|
+
'',
|
|
101
|
+
'kümnes',
|
|
102
|
+
'kahekümnes',
|
|
103
|
+
'kolmekümnes',
|
|
104
|
+
'nelikümnes',
|
|
105
|
+
'viiekümnes',
|
|
106
|
+
'kuuekümnes',
|
|
107
|
+
'seitsmekümnes',
|
|
108
|
+
'kaheksakümnes',
|
|
109
|
+
'üheksakümnes'
|
|
110
|
+
]
|
|
111
|
+
|
|
112
|
+
self.negword = "miinus "
|
|
113
|
+
self.pointword = "koma"
|
|
114
|
+
|
|
115
|
+
def _setup(self):
|
|
116
|
+
super(Num2Word_ET, self)._setup()
|
|
117
|
+
|
|
118
|
+
def _int_to_word(self, n):
|
|
119
|
+
"""
|
|
120
|
+
Converts a number to words in Estonian.
|
|
121
|
+
"""
|
|
122
|
+
if n == 0:
|
|
123
|
+
return 'null'
|
|
124
|
+
|
|
125
|
+
parts = []
|
|
126
|
+
|
|
127
|
+
# Handle trillions
|
|
128
|
+
if n >= 1000000000000:
|
|
129
|
+
trillions = n // 1000000000000
|
|
130
|
+
if trillions == 1:
|
|
131
|
+
parts.append('üks triljon')
|
|
132
|
+
else:
|
|
133
|
+
parts.append(self._int_to_word(trillions) + ' triljonit')
|
|
134
|
+
n %= 1000000000000
|
|
135
|
+
|
|
136
|
+
# Handle billions
|
|
137
|
+
if n >= 1000000000:
|
|
138
|
+
billions = n // 1000000000
|
|
139
|
+
if billions == 1:
|
|
140
|
+
parts.append('üks miljard')
|
|
141
|
+
else:
|
|
142
|
+
parts.append(self._int_to_word(billions) + ' miljardit')
|
|
143
|
+
n %= 1000000000
|
|
144
|
+
|
|
145
|
+
# Handle millions
|
|
146
|
+
if n >= 1000000:
|
|
147
|
+
millions = n // 1000000
|
|
148
|
+
if millions == 1:
|
|
149
|
+
parts.append('üks miljon')
|
|
150
|
+
else:
|
|
151
|
+
parts.append(self._int_to_word(millions) + ' miljonit')
|
|
152
|
+
n %= 1000000
|
|
153
|
+
|
|
154
|
+
# Handle thousands
|
|
155
|
+
if n >= 1000:
|
|
156
|
+
thousands = n // 1000
|
|
157
|
+
if thousands == 1:
|
|
158
|
+
parts.append('tuhat')
|
|
159
|
+
elif thousands == 100:
|
|
160
|
+
# Special case: 100000 should be "sada tuhat" not "ükssada tuhat"
|
|
161
|
+
parts.append('sada tuhat')
|
|
162
|
+
else:
|
|
163
|
+
parts.append(self._int_to_word(thousands) + ' tuhat')
|
|
164
|
+
n %= 1000
|
|
165
|
+
|
|
166
|
+
# Handle hundreds
|
|
167
|
+
if n >= 100:
|
|
168
|
+
hundreds = n // 100
|
|
169
|
+
if hundreds == 1:
|
|
170
|
+
parts.append('ükssada')
|
|
171
|
+
elif hundreds == 2:
|
|
172
|
+
parts.append('kakssada')
|
|
173
|
+
elif hundreds == 3:
|
|
174
|
+
parts.append('kolmsada')
|
|
175
|
+
elif hundreds == 4:
|
|
176
|
+
parts.append('nelisada')
|
|
177
|
+
elif hundreds == 5:
|
|
178
|
+
parts.append('viissada')
|
|
179
|
+
elif hundreds == 6:
|
|
180
|
+
parts.append('kuussada')
|
|
181
|
+
elif hundreds == 7:
|
|
182
|
+
parts.append('seitsesada')
|
|
183
|
+
elif hundreds == 8:
|
|
184
|
+
parts.append('kaheksasada')
|
|
185
|
+
elif hundreds == 9:
|
|
186
|
+
parts.append('üheksasada')
|
|
187
|
+
n %= 100
|
|
188
|
+
|
|
189
|
+
# Handle special case for teens (11-19)
|
|
190
|
+
if 10 < n < 20:
|
|
191
|
+
teens_map = {
|
|
192
|
+
11: 'üksteist',
|
|
193
|
+
12: 'kaksteist',
|
|
194
|
+
13: 'kolmteist',
|
|
195
|
+
14: 'neliteist',
|
|
196
|
+
15: 'viisteist',
|
|
197
|
+
16: 'kuusteist',
|
|
198
|
+
17: 'seitseteist',
|
|
199
|
+
18: 'kaheksateist',
|
|
200
|
+
19: 'üheksateist'
|
|
201
|
+
}
|
|
202
|
+
parts.append(teens_map[n])
|
|
203
|
+
else:
|
|
204
|
+
# Handle tens
|
|
205
|
+
if n >= 10:
|
|
206
|
+
tens_val = n // 10
|
|
207
|
+
parts.append(self.tens[tens_val])
|
|
208
|
+
n %= 10
|
|
209
|
+
|
|
210
|
+
# Handle ones
|
|
211
|
+
if n > 0:
|
|
212
|
+
parts.append(self.ones[n])
|
|
213
|
+
|
|
214
|
+
return ' '.join(parts)
|
|
215
|
+
|
|
216
|
+
def _int_to_cardinal(self, n):
|
|
217
|
+
if n == 0:
|
|
218
|
+
return 'null'
|
|
219
|
+
|
|
220
|
+
if n < 0:
|
|
221
|
+
return self.negword + self._int_to_word(-n)
|
|
222
|
+
|
|
223
|
+
return self._int_to_word(n)
|
|
224
|
+
|
|
225
|
+
def _int_to_ordinal(self, n):
|
|
226
|
+
"""Convert to ordinal number."""
|
|
227
|
+
if n == 0:
|
|
228
|
+
return 'nullis'
|
|
229
|
+
|
|
230
|
+
if n < 10:
|
|
231
|
+
return self.ordinals_ones[n]
|
|
232
|
+
|
|
233
|
+
if n == 10:
|
|
234
|
+
return 'kümnes'
|
|
235
|
+
|
|
236
|
+
if n < 20:
|
|
237
|
+
teens_ordinals = {
|
|
238
|
+
11: 'üheteistkümnes',
|
|
239
|
+
12: 'kaheteistkümnes',
|
|
240
|
+
13: 'kolmeteistkümnes',
|
|
241
|
+
14: 'neljateistkümnes',
|
|
242
|
+
15: 'viieteistkümnes',
|
|
243
|
+
16: 'kuueteistkümnes',
|
|
244
|
+
17: 'seitsmeteistkümnes',
|
|
245
|
+
18: 'kaheksateistkümnes',
|
|
246
|
+
19: 'üheksateistkümnes'
|
|
247
|
+
}
|
|
248
|
+
return teens_ordinals[n]
|
|
249
|
+
|
|
250
|
+
if n < 100:
|
|
251
|
+
tens_val = n // 10
|
|
252
|
+
ones_val = n % 10
|
|
253
|
+
if ones_val == 0:
|
|
254
|
+
return self.ordinals_tens[tens_val]
|
|
255
|
+
else:
|
|
256
|
+
# For compound numbers, make the last part ordinal
|
|
257
|
+
return self.tens[tens_val] + ' ' + self.ordinals_ones[ones_val]
|
|
258
|
+
|
|
259
|
+
if n == 100:
|
|
260
|
+
return 'sajas'
|
|
261
|
+
|
|
262
|
+
if n == 1000:
|
|
263
|
+
return 'tuhandes'
|
|
264
|
+
|
|
265
|
+
# For larger numbers, convert to cardinal and add 's' suffix
|
|
266
|
+
cardinal = self._int_to_cardinal(n)
|
|
267
|
+
return cardinal + 's'
|
|
268
|
+
|
|
269
|
+
def to_cardinal(self, n):
|
|
270
|
+
try:
|
|
271
|
+
if isinstance(n, str):
|
|
272
|
+
n = float(n)
|
|
273
|
+
|
|
274
|
+
# Handle floats with decimal places
|
|
275
|
+
if isinstance(n, float) and n != int(n):
|
|
276
|
+
pre, post = self.float2tuple(n)
|
|
277
|
+
|
|
278
|
+
# Handle negative decimals
|
|
279
|
+
if n < 0:
|
|
280
|
+
result = self.negword
|
|
281
|
+
pre = abs(pre)
|
|
282
|
+
else:
|
|
283
|
+
result = ""
|
|
284
|
+
|
|
285
|
+
# Integer part
|
|
286
|
+
result += self._int_to_cardinal(pre)
|
|
287
|
+
|
|
288
|
+
# Decimal part
|
|
289
|
+
if self.precision > 0:
|
|
290
|
+
result += " " + self.pointword
|
|
291
|
+
|
|
292
|
+
# Convert post to string with proper padding
|
|
293
|
+
post_str = str(post)
|
|
294
|
+
post_str = '0' * (self.precision - len(post_str)) + post_str
|
|
295
|
+
|
|
296
|
+
# Say each digit individually
|
|
297
|
+
for digit in post_str:
|
|
298
|
+
result += " " + self.ones[int(digit)]
|
|
299
|
+
|
|
300
|
+
return result.strip()
|
|
301
|
+
|
|
302
|
+
# For integers
|
|
303
|
+
return self._int_to_cardinal(int(n))
|
|
304
|
+
except BaseException:
|
|
305
|
+
return self._int_to_cardinal(int(n))
|
|
306
|
+
|
|
307
|
+
def to_ordinal(self, n):
|
|
308
|
+
try:
|
|
309
|
+
if isinstance(n, str):
|
|
310
|
+
n = int(n)
|
|
311
|
+
|
|
312
|
+
return self._int_to_ordinal(n)
|
|
313
|
+
except BaseException:
|
|
314
|
+
return self._int_to_ordinal(int(n))
|
|
315
|
+
|
|
316
|
+
def to_ordinal_num(self, n):
|
|
317
|
+
try:
|
|
318
|
+
if isinstance(n, str):
|
|
319
|
+
n = int(n)
|
|
320
|
+
|
|
321
|
+
return str(n) + '.'
|
|
322
|
+
except BaseException:
|
|
323
|
+
return str(n) + '.'
|
|
324
|
+
|
|
325
|
+
def to_currency(self, val, currency='EUR', cents=True, separator=' ja ',
|
|
326
|
+
adjective=False):
|
|
327
|
+
"""Convert a number to currency words."""
|
|
328
|
+
# Track if input was originally an integer
|
|
329
|
+
is_integer_input = isinstance(val, int)
|
|
330
|
+
|
|
331
|
+
# Check if value has fractional cents
|
|
332
|
+
if not is_integer_input:
|
|
333
|
+
from decimal import Decimal
|
|
334
|
+
decimal_val = Decimal(str(val))
|
|
335
|
+
has_fractional_cents = (decimal_val * 100) % 1 != 0
|
|
336
|
+
else:
|
|
337
|
+
has_fractional_cents = False
|
|
338
|
+
|
|
339
|
+
left, right, is_negative = parse_currency_parts(val, is_int_with_cents=False,
|
|
340
|
+
keep_precision=has_fractional_cents)
|
|
341
|
+
|
|
342
|
+
try:
|
|
343
|
+
cr1, cr2 = self.CURRENCY_FORMS[currency]
|
|
344
|
+
except KeyError:
|
|
345
|
+
raise NotImplementedError(
|
|
346
|
+
'Currency "%s" not implemented for "%s"' % (
|
|
347
|
+
currency, self.__class__.__name__))
|
|
348
|
+
|
|
349
|
+
minus_str = "miinus " if is_negative else ""
|
|
350
|
+
money_str = self._int_to_cardinal(left)
|
|
351
|
+
|
|
352
|
+
# Determine currency form based on the number
|
|
353
|
+
if left == 1:
|
|
354
|
+
currency_str = cr1[0] # singular
|
|
355
|
+
else:
|
|
356
|
+
currency_str = cr1[1] # plural
|
|
357
|
+
|
|
358
|
+
# For integers, don't show cents
|
|
359
|
+
if is_integer_input:
|
|
360
|
+
return "%s%s %s" % (minus_str, money_str, currency_str)
|
|
361
|
+
|
|
362
|
+
# For floats, always show cents (even if zero)
|
|
363
|
+
if cents:
|
|
364
|
+
# Handle fractional cents
|
|
365
|
+
from decimal import Decimal
|
|
366
|
+
if isinstance(right, Decimal):
|
|
367
|
+
# Convert fractional cents (e.g., 65.3 cents)
|
|
368
|
+
cents_str = self.to_cardinal(float(right)) if right > 0 else "null"
|
|
369
|
+
else:
|
|
370
|
+
cents_str = self._int_to_cardinal(right) if right > 0 else "null"
|
|
371
|
+
else:
|
|
372
|
+
cents_str = str(float(right) if isinstance(right, Decimal) else right)
|
|
373
|
+
|
|
374
|
+
# Determine cents form
|
|
375
|
+
if right == 1:
|
|
376
|
+
cents_currency = cr2[0] # singular
|
|
377
|
+
else:
|
|
378
|
+
cents_currency = cr2[1] # plural
|
|
379
|
+
|
|
380
|
+
return "%s%s %s%s%s %s" % (
|
|
381
|
+
minus_str, money_str, currency_str,
|
|
382
|
+
separator, cents_str, cents_currency)
|
|
383
|
+
|
|
384
|
+
def to_year(self, n):
|
|
385
|
+
"""Convert to year representation."""
|
|
386
|
+
if n < 1000:
|
|
387
|
+
return self._int_to_cardinal(n)
|
|
388
|
+
elif n < 2000:
|
|
389
|
+
# Years like 1999 -> "tuhat üheksasada üheksakümmend üheksa"
|
|
390
|
+
return self._int_to_cardinal(n)
|
|
391
|
+
else:
|
|
392
|
+
# Years like 2023 -> "kaks tuhat kakskümmend kolm"
|
|
393
|
+
return self._int_to_cardinal(n)
|
num2words2/lang_EU.py
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
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
|
+
# Basque language support
|
|
24
|
+
class Num2Word_EU(Num2Word_Base):
|
|
25
|
+
CURRENCY_FORMS = {
|
|
26
|
+
'EUR': (('euro', 'euro'), ('zentimo', 'zentimo')),
|
|
27
|
+
'USD': (('dolar', 'dolar'), ('zentabo', 'zentabo')),
|
|
28
|
+
'GBP': (('libera', 'libera'), ('penike', 'penike')),
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
def setup(self):
|
|
32
|
+
self.negword = "minus "
|
|
33
|
+
self.pointword = "koma"
|
|
34
|
+
|
|
35
|
+
def to_cardinal(self, number):
|
|
36
|
+
"""Convert a number to its word representation in Basque."""
|
|
37
|
+
n = str(number).strip()
|
|
38
|
+
|
|
39
|
+
if n.startswith('-'):
|
|
40
|
+
n = n[1:]
|
|
41
|
+
ret = self.negword
|
|
42
|
+
else:
|
|
43
|
+
ret = ""
|
|
44
|
+
|
|
45
|
+
if '.' in n:
|
|
46
|
+
left, right = n.split('.', 1)
|
|
47
|
+
ret += self._int_to_word(int(left)) + " " + self.pointword + " "
|
|
48
|
+
ret += " ".join(self._int_to_word(int(d)) for d in right)
|
|
49
|
+
return ret
|
|
50
|
+
else:
|
|
51
|
+
return ret + self._int_to_word(int(n))
|
|
52
|
+
|
|
53
|
+
def _int_to_word(self, number):
|
|
54
|
+
"""Convert an integer to its word representation in Basque."""
|
|
55
|
+
if number == 0:
|
|
56
|
+
return "zero"
|
|
57
|
+
|
|
58
|
+
ones = ["", "bat", "bi", "hiru", "lau", "bost", "sei", "zazpi", "zortzi", "bederatzi"]
|
|
59
|
+
tens = ["", "hamar", "hogei", "hogeita hamar", "berrogei", "berrogeita hamar",
|
|
60
|
+
"hirurogei", "hirurogeita hamar", "laurogei", "laurogeita hamar"]
|
|
61
|
+
|
|
62
|
+
if number < 10:
|
|
63
|
+
return ones[number]
|
|
64
|
+
elif number == 10:
|
|
65
|
+
return "hamar"
|
|
66
|
+
elif number < 20:
|
|
67
|
+
return "hama" + ones[number - 10]
|
|
68
|
+
elif number < 100:
|
|
69
|
+
ten_val = number // 10
|
|
70
|
+
one_val = number % 10
|
|
71
|
+
if one_val == 0:
|
|
72
|
+
return tens[ten_val]
|
|
73
|
+
else:
|
|
74
|
+
return tens[ten_val] + "ta " + ones[one_val]
|
|
75
|
+
elif number < 1000:
|
|
76
|
+
hundred_val = number // 100
|
|
77
|
+
remainder = number % 100
|
|
78
|
+
if hundred_val == 1:
|
|
79
|
+
result = "ehun"
|
|
80
|
+
else:
|
|
81
|
+
result = ones[hundred_val] + "ehun"
|
|
82
|
+
if remainder:
|
|
83
|
+
result += " eta " + self._int_to_word(remainder)
|
|
84
|
+
return result
|
|
85
|
+
elif number < 1000000:
|
|
86
|
+
thousand_val = number // 1000
|
|
87
|
+
remainder = number % 1000
|
|
88
|
+
if thousand_val == 1:
|
|
89
|
+
result = "mila"
|
|
90
|
+
else:
|
|
91
|
+
result = self._int_to_word(thousand_val) + " mila"
|
|
92
|
+
if remainder:
|
|
93
|
+
result += " " + self._int_to_word(remainder)
|
|
94
|
+
return result
|
|
95
|
+
elif number < 1000000000:
|
|
96
|
+
million_val = number // 1000000
|
|
97
|
+
remainder = number % 1000000
|
|
98
|
+
if million_val == 1:
|
|
99
|
+
result = "milioi bat"
|
|
100
|
+
else:
|
|
101
|
+
result = self._int_to_word(million_val) + " milioi"
|
|
102
|
+
if remainder:
|
|
103
|
+
result += " " + self._int_to_word(remainder)
|
|
104
|
+
return result
|
|
105
|
+
else:
|
|
106
|
+
billion_val = number // 1000000000
|
|
107
|
+
remainder = number % 1000000000
|
|
108
|
+
result = self._int_to_word(billion_val) + " mila milioi"
|
|
109
|
+
if remainder:
|
|
110
|
+
result += " " + self._int_to_word(remainder)
|
|
111
|
+
return result
|
|
112
|
+
|
|
113
|
+
def to_ordinal(self, number):
|
|
114
|
+
"""Convert to ordinal."""
|
|
115
|
+
cardinal = self.to_cardinal(number)
|
|
116
|
+
if cardinal.endswith('t'):
|
|
117
|
+
return cardinal + "garren"
|
|
118
|
+
else:
|
|
119
|
+
return cardinal + "garren"
|
|
120
|
+
|
|
121
|
+
def to_ordinal_num(self, number):
|
|
122
|
+
"""Convert to abbreviated ordinal."""
|
|
123
|
+
return str(number) + "."
|
|
124
|
+
|
|
125
|
+
def to_year(self, val, longval=True):
|
|
126
|
+
"""Convert to year."""
|
|
127
|
+
return self.to_cardinal(val) + ". urtea"
|
|
128
|
+
|
|
129
|
+
def to_currency(self, val, currency='EUR', cents=True, separator=' eta ', adjective=False):
|
|
130
|
+
"""Convert to currency."""
|
|
131
|
+
try:
|
|
132
|
+
left, right, is_negative = self.parse_currency(val)
|
|
133
|
+
except AttributeError:
|
|
134
|
+
is_negative = False
|
|
135
|
+
if val < 0:
|
|
136
|
+
is_negative = True
|
|
137
|
+
val = abs(val)
|
|
138
|
+
|
|
139
|
+
left, right = self._split_currency(val)
|
|
140
|
+
|
|
141
|
+
cr1, cr2 = self.CURRENCY_FORMS.get(currency, self.CURRENCY_FORMS['EUR'])
|
|
142
|
+
|
|
143
|
+
left_str = self._int_to_word(int(left))
|
|
144
|
+
cents_str = self._int_to_word(int(right)) if cents and right else ""
|
|
145
|
+
|
|
146
|
+
result = left_str + " " + cr1[0]
|
|
147
|
+
|
|
148
|
+
if cents_str:
|
|
149
|
+
result += separator + cents_str + " " + cr2[0]
|
|
150
|
+
|
|
151
|
+
return self.negword + result if is_negative else result
|
|
152
|
+
|
|
153
|
+
def _split_currency(self, n):
|
|
154
|
+
"""Split currency into whole and fraction parts."""
|
|
155
|
+
parts = str(n).split('.')
|
|
156
|
+
left = int(parts[0]) if parts[0] else 0
|
|
157
|
+
right = int(parts[1][:2].ljust(2, '0')) if len(parts) > 1 and parts[1] else 0
|
|
158
|
+
return left, right
|
num2words2/lang_EUR.py
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
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
|
+
GENERIC_DOLLARS = ('dollar', 'dollars')
|
|
23
|
+
GENERIC_CENTS = ('cent', 'cents')
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class Num2Word_EUR(Num2Word_Base):
|
|
27
|
+
CURRENCY_FORMS = {
|
|
28
|
+
'AUD': (GENERIC_DOLLARS, GENERIC_CENTS),
|
|
29
|
+
'BYN': (('rouble', 'roubles'), ('kopek', 'kopeks')),
|
|
30
|
+
'CAD': (GENERIC_DOLLARS, GENERIC_CENTS),
|
|
31
|
+
# repalced by EUR
|
|
32
|
+
'EEK': (('kroon', 'kroons'), ('sent', 'senti')),
|
|
33
|
+
'EUR': (('euro', 'euro'), GENERIC_CENTS),
|
|
34
|
+
'GBP': (('pound sterling', 'pounds sterling'), ('penny', 'pence')),
|
|
35
|
+
# replaced by EUR
|
|
36
|
+
'LTL': (('litas', 'litas'), GENERIC_CENTS),
|
|
37
|
+
# replaced by EUR
|
|
38
|
+
'LVL': (('lat', 'lats'), ('santim', 'santims')),
|
|
39
|
+
'USD': (GENERIC_DOLLARS, GENERIC_CENTS),
|
|
40
|
+
'RUB': (('rouble', 'roubles'), ('kopek', 'kopeks')),
|
|
41
|
+
'SEK': (('krona', 'kronor'), ('öre', 'öre')),
|
|
42
|
+
'NOK': (('krone', 'kroner'), ('øre', 'øre')),
|
|
43
|
+
'PLN': (('zloty', 'zlotys', 'zlotu'), ('grosz', 'groszy')),
|
|
44
|
+
'MXN': (('peso', 'pesos'), GENERIC_CENTS),
|
|
45
|
+
'RON': (('leu', 'lei', 'de lei'), ('ban', 'bani', 'de bani')),
|
|
46
|
+
'INR': (('rupee', 'rupees'), ('paisa', 'paise')),
|
|
47
|
+
'HUF': (('forint', 'forint'), ('fillér', 'fillér')),
|
|
48
|
+
'ISK': (('króna', 'krónur'), ('aur', 'aurar')),
|
|
49
|
+
'UZS': (('sum', 'sums'), ('tiyin', 'tiyins')),
|
|
50
|
+
'SAR': (('saudi riyal', 'saudi riyals'), ('halalah', 'halalas')),
|
|
51
|
+
'JPY': (('yen', 'yen'), ('sen', 'sen')),
|
|
52
|
+
'KRW': (('won', 'won'), ('jeon', 'jeon')),
|
|
53
|
+
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
CURRENCY_ADJECTIVES = {
|
|
57
|
+
'AUD': 'Australian',
|
|
58
|
+
'BYN': 'Belarusian',
|
|
59
|
+
'CAD': 'Canadian',
|
|
60
|
+
'EEK': 'Estonian',
|
|
61
|
+
'USD': 'US',
|
|
62
|
+
'RUB': 'Russian',
|
|
63
|
+
'NOK': 'Norwegian',
|
|
64
|
+
'MXN': 'Mexican',
|
|
65
|
+
'RON': 'Romanian',
|
|
66
|
+
'INR': 'Indian',
|
|
67
|
+
'HUF': 'Hungarian',
|
|
68
|
+
'ISK': 'íslenskar',
|
|
69
|
+
'UZS': 'Uzbekistan',
|
|
70
|
+
'SAR': 'Saudi',
|
|
71
|
+
'JPY': 'Japanese',
|
|
72
|
+
'KRW': 'Korean',
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
GIGA_SUFFIX = "illiard"
|
|
76
|
+
MEGA_SUFFIX = "illion"
|
|
77
|
+
|
|
78
|
+
def set_high_numwords(self, high):
|
|
79
|
+
cap = 3 + 6 * len(high)
|
|
80
|
+
|
|
81
|
+
for word, n in zip(high, range(cap, 3, -6)):
|
|
82
|
+
if self.GIGA_SUFFIX:
|
|
83
|
+
self.cards[10 ** n] = word + self.GIGA_SUFFIX
|
|
84
|
+
|
|
85
|
+
if self.MEGA_SUFFIX:
|
|
86
|
+
self.cards[10 ** (n - 3)] = word + self.MEGA_SUFFIX
|
|
87
|
+
|
|
88
|
+
def gen_high_numwords(self, units, tens, lows):
|
|
89
|
+
out = [u + t for t in tens for u in units]
|
|
90
|
+
out.reverse()
|
|
91
|
+
return out + lows
|
|
92
|
+
|
|
93
|
+
def pluralize(self, n, forms):
|
|
94
|
+
form = 0 if n == 1 else 1
|
|
95
|
+
return forms[form]
|
|
96
|
+
|
|
97
|
+
def setup(self):
|
|
98
|
+
lows = ["non", "oct", "sept", "sext", "quint", "quadr", "tr", "b", "m"]
|
|
99
|
+
units = ["", "un", "duo", "tre", "quattuor", "quin", "sex", "sept",
|
|
100
|
+
"octo", "novem"]
|
|
101
|
+
tens = ["dec", "vigint", "trigint", "quadragint", "quinquagint",
|
|
102
|
+
"sexagint", "septuagint", "octogint", "nonagint"]
|
|
103
|
+
self.high_numwords = ["cent"] + self.gen_high_numwords(units, tens,
|
|
104
|
+
lows)
|