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_HY.py
ADDED
|
@@ -0,0 +1,364 @@
|
|
|
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
|
+
# Armenian numerals
|
|
23
|
+
ONES = {
|
|
24
|
+
0: 'զրո',
|
|
25
|
+
1: 'մեկ',
|
|
26
|
+
2: 'երկու',
|
|
27
|
+
3: 'երեք',
|
|
28
|
+
4: 'չորս',
|
|
29
|
+
5: 'հինգ',
|
|
30
|
+
6: 'վեց',
|
|
31
|
+
7: 'յոթ',
|
|
32
|
+
8: 'ութ',
|
|
33
|
+
9: 'ինը'
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
TEENS = {
|
|
37
|
+
10: 'տասը',
|
|
38
|
+
11: 'տասնմեկ',
|
|
39
|
+
12: 'տասներկու',
|
|
40
|
+
13: 'տասներեք',
|
|
41
|
+
14: 'տասնչորս',
|
|
42
|
+
15: 'տասնհինգ',
|
|
43
|
+
16: 'տասնվեց',
|
|
44
|
+
17: 'տասնյոթ',
|
|
45
|
+
18: 'տասնութ',
|
|
46
|
+
19: 'տասնինը'
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
TENS = {
|
|
50
|
+
2: 'քսան',
|
|
51
|
+
3: 'երեսուն',
|
|
52
|
+
4: 'քառասուն',
|
|
53
|
+
5: 'հիսուն',
|
|
54
|
+
6: 'վաթսուն',
|
|
55
|
+
7: 'յոթանասուն',
|
|
56
|
+
8: 'ութսուն',
|
|
57
|
+
9: 'իննսուն'
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
HUNDREDS = {
|
|
61
|
+
1: 'հարյուր',
|
|
62
|
+
2: 'երկու հարյուր',
|
|
63
|
+
3: 'երեք հարյուր',
|
|
64
|
+
4: 'չորս հարյուր',
|
|
65
|
+
5: 'հինգ հարյուր',
|
|
66
|
+
6: 'վեց հարյուր',
|
|
67
|
+
7: 'յոթ հարյուր',
|
|
68
|
+
8: 'ութ հարյուր',
|
|
69
|
+
9: 'ինը հարյուր'
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
THOUSANDS = {
|
|
73
|
+
1: ('հազար', 'հազար'),
|
|
74
|
+
2: ('միլիոն', 'միլիոն'),
|
|
75
|
+
3: ('միլիարդ', 'միլիարդ'),
|
|
76
|
+
4: ('տրիլիոն', 'տրիլիոն'),
|
|
77
|
+
5: ('կվադրիլիոն', 'կվադրիլիոն'),
|
|
78
|
+
6: ('քվինտիլիոն', 'քվինտիլիոն'),
|
|
79
|
+
7: ('սեքստիլիոն', 'սեքստիլիոն'),
|
|
80
|
+
8: ('սեպտիլիոն', 'սեպտիլիոն'),
|
|
81
|
+
9: ('օկտիլիոն', 'օկտիլիոն'),
|
|
82
|
+
10: ('նոնիլիոն', 'նոնիլիոն'),
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
# Ordinal numerals
|
|
86
|
+
ORDINAL_ONES = {
|
|
87
|
+
1: 'առաջին',
|
|
88
|
+
2: 'երկրորդ',
|
|
89
|
+
3: 'երրորդ',
|
|
90
|
+
4: 'չորրորդ',
|
|
91
|
+
5: 'հինգերորդ',
|
|
92
|
+
6: 'վեցերորդ',
|
|
93
|
+
7: 'յոթերորդ',
|
|
94
|
+
8: 'ութերորդ',
|
|
95
|
+
9: 'իններորդ'
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
ORDINAL_TEENS = {
|
|
99
|
+
10: 'տասներորդ',
|
|
100
|
+
11: 'տասնմեկերորդ',
|
|
101
|
+
12: 'տասներկուերորդ',
|
|
102
|
+
13: 'տասներեքերորդ',
|
|
103
|
+
14: 'տասնչորսերորդ',
|
|
104
|
+
15: 'տասնհինգերորդ',
|
|
105
|
+
16: 'տասնվեցերորդ',
|
|
106
|
+
17: 'տասնյոթերորդ',
|
|
107
|
+
18: 'տասնութերորդ',
|
|
108
|
+
19: 'տասնիներորդ'
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
ORDINAL_TENS = {
|
|
112
|
+
2: 'քսաներորդ',
|
|
113
|
+
3: 'երեսուներորդ',
|
|
114
|
+
4: 'քառասուներորդ',
|
|
115
|
+
5: 'հիսուներորդ',
|
|
116
|
+
6: 'վաթսուներորդ',
|
|
117
|
+
7: 'յոթանասուներորդ',
|
|
118
|
+
8: 'ութսուներորդ',
|
|
119
|
+
9: 'իննսուներորդ'
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class Num2Word_HY(Num2Word_Base):
|
|
124
|
+
CURRENCY_FORMS = {
|
|
125
|
+
'AMD': (('դրամ', 'դրամ'), ('լումա', 'լումա')),
|
|
126
|
+
'EUR': (('եվրո', 'եվրո'), ('ցենտ', 'ցենտ')),
|
|
127
|
+
'RUB': (('ռուբլի', 'ռուբլի'), ('կոպեկ', 'կոպեկ')),
|
|
128
|
+
'USD': (('դոլար', 'դոլար'), ('ցենտ', 'ցենտ')),
|
|
129
|
+
'JPY': (('իեն', 'իեն'), ('սեն', 'սեն')),
|
|
130
|
+
'GBP': (('ֆունտ ստեռլինգ', 'ֆունտ ստեռլինգ'), ('պենս', 'պենս')),
|
|
131
|
+
'CHF': (('շվեյցարական ֆրանկ', 'շվեյցարական ֆրանկ'),
|
|
132
|
+
('սանտիմ', 'սանտիմ')),
|
|
133
|
+
'CNY': (('յուան', 'յուան'), ('ֆեն', 'ֆեն')),
|
|
134
|
+
'IRR': (('իրանական ռիալ', 'իրանական ռիալ'), ('դինար', 'դինար')),
|
|
135
|
+
'TRY': (('թուրքական լիրա', 'թուրքական լիրա'), ('ղուրուշ', 'ղուրուշ')),
|
|
136
|
+
'AED': (('արաբական դիրհամ', 'արաբական դիրհամ'), ('ֆիլս', 'ֆիլս'))
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
def set_high_numwords(self, high):
|
|
140
|
+
max = 3 + 10 * len(high)
|
|
141
|
+
for word, n in zip(high, range(max, 3, -10)):
|
|
142
|
+
self.cards[10 ** n] = word
|
|
143
|
+
|
|
144
|
+
def setup(self):
|
|
145
|
+
self.negword = "մինուս "
|
|
146
|
+
self.pointword = "ամբողջ"
|
|
147
|
+
self.exclude_title = ["և", "ամբողջ", "մինուս"]
|
|
148
|
+
|
|
149
|
+
self.high_numwords = [(10**12, "տրիլիոն"), (10**9, "միլիարդ"),
|
|
150
|
+
(10**6, "միլիոն")]
|
|
151
|
+
self.mid_numwords = [(1000, "հազար"), (100, "հարյուր"),
|
|
152
|
+
(90, "իննսուն"), (80, "ութսուն"),
|
|
153
|
+
(70, "յոթանասուն"), (60, "վաթսուն"),
|
|
154
|
+
(50, "հիսուն"), (40, "քառասուն"),
|
|
155
|
+
(30, "երեսուն"), (20, "քսան")]
|
|
156
|
+
self.low_numwords = ["տասնինը", "տասնութ", "տասնյոթ", "տասնվեց",
|
|
157
|
+
"տասնհինգ", "տասնչորս", "տասներեք", "տասներկու",
|
|
158
|
+
"տասնմեկ", "տասը", "ինը", "ութ", "յոթ", "վեց",
|
|
159
|
+
"հինգ", "չորս", "երեք", "երկու", "մեկ", "զրո"]
|
|
160
|
+
|
|
161
|
+
def merge(self, curr, next):
|
|
162
|
+
ctext, cnum, ntext, nnum = curr + next
|
|
163
|
+
|
|
164
|
+
if cnum == 1:
|
|
165
|
+
# For 1000, don't need to add "մեկ"
|
|
166
|
+
if nnum == 1000:
|
|
167
|
+
return next
|
|
168
|
+
if nnum < 1000:
|
|
169
|
+
return next
|
|
170
|
+
ctext = "մեկ"
|
|
171
|
+
|
|
172
|
+
if nnum < cnum and cnum >= 100 and cnum < 1000:
|
|
173
|
+
if nnum % 100 == 0:
|
|
174
|
+
ntext = ntext[:-1] + "ի"
|
|
175
|
+
return (ctext + " " + ntext, cnum + nnum)
|
|
176
|
+
|
|
177
|
+
if nnum < 100:
|
|
178
|
+
if cnum < 100:
|
|
179
|
+
if ctext == 'իննսուն':
|
|
180
|
+
return (ctext + ' ' + ntext, cnum + nnum)
|
|
181
|
+
return (ctext + ntext, cnum + nnum)
|
|
182
|
+
return ("%s %s" % (ctext, ntext), cnum + nnum)
|
|
183
|
+
|
|
184
|
+
return ("%s %s" % (ctext, ntext), cnum + nnum)
|
|
185
|
+
|
|
186
|
+
def to_cardinal(self, value):
|
|
187
|
+
if value == 0:
|
|
188
|
+
return 'զրո'
|
|
189
|
+
|
|
190
|
+
# Simple cases
|
|
191
|
+
if value == 1000:
|
|
192
|
+
return 'հազար'
|
|
193
|
+
|
|
194
|
+
if value >= 1000000 and value < 1000000000:
|
|
195
|
+
millions = value // 1000000
|
|
196
|
+
rest = value % 1000000
|
|
197
|
+
if millions == 1:
|
|
198
|
+
millions_part = 'մեկ միլիոն'
|
|
199
|
+
elif millions == 2:
|
|
200
|
+
millions_part = 'երկու միլիոն'
|
|
201
|
+
else:
|
|
202
|
+
millions_part = '%s միլիոն' % self.to_cardinal(millions)
|
|
203
|
+
if rest == 0:
|
|
204
|
+
return millions_part
|
|
205
|
+
return '%s %s' % (millions_part, self.to_cardinal(rest))
|
|
206
|
+
|
|
207
|
+
# For billions
|
|
208
|
+
if value == 1000000000:
|
|
209
|
+
return 'մեկ միլիարդ'
|
|
210
|
+
elif value % 1000000000 == 0 and value < 10**12:
|
|
211
|
+
prefix = value // 1000000000
|
|
212
|
+
if prefix == 2:
|
|
213
|
+
return 'երկու միլիարդ'
|
|
214
|
+
else:
|
|
215
|
+
return '%s միլիարդ' % self.to_cardinal(prefix)
|
|
216
|
+
|
|
217
|
+
# For other cases use standard implementation
|
|
218
|
+
result = super(Num2Word_HY, self).to_cardinal(value)
|
|
219
|
+
|
|
220
|
+
# Fix for numbers like X000000 and X000000000
|
|
221
|
+
if 'հազար հազար' in result:
|
|
222
|
+
result = result.replace('հազար հազար', 'միլիոն')
|
|
223
|
+
return result
|
|
224
|
+
|
|
225
|
+
def to_ordinal(self, value):
|
|
226
|
+
if value == 0:
|
|
227
|
+
return 'զրոերորդ'
|
|
228
|
+
|
|
229
|
+
if value < 20:
|
|
230
|
+
if value < 10:
|
|
231
|
+
return ORDINAL_ONES[value]
|
|
232
|
+
else:
|
|
233
|
+
return ORDINAL_TEENS[value]
|
|
234
|
+
|
|
235
|
+
if value < 100:
|
|
236
|
+
tens, units = divmod(value, 10)
|
|
237
|
+
if units == 0:
|
|
238
|
+
return ORDINAL_TENS[tens]
|
|
239
|
+
return TENS[tens] + " " + ORDINAL_ONES[units]
|
|
240
|
+
|
|
241
|
+
# For larger numbers use simple rule - add "երորդ" at the end
|
|
242
|
+
cardinal = self.to_cardinal(value)
|
|
243
|
+
return cardinal + "երորդ"
|
|
244
|
+
|
|
245
|
+
def to_ordinal_num(self, value):
|
|
246
|
+
self.verify_ordinal(value)
|
|
247
|
+
return str(value) + "-րդ"
|
|
248
|
+
|
|
249
|
+
def pluralize(self, n, forms):
|
|
250
|
+
# Armenian plural rules:
|
|
251
|
+
# - If number ends with 1 (except 11), use singular form
|
|
252
|
+
# - For all other numbers use plural form
|
|
253
|
+
if forms:
|
|
254
|
+
if len(forms) >= 2:
|
|
255
|
+
if n == 1 or (n % 10 == 1 and n % 100 != 11):
|
|
256
|
+
return forms[0]
|
|
257
|
+
return forms[1]
|
|
258
|
+
return forms[0]
|
|
259
|
+
return ''
|
|
260
|
+
|
|
261
|
+
def to_year(self, val, longval=True):
|
|
262
|
+
# Special case for year: for 1000-1999, remove "մեկ" before "հազար"
|
|
263
|
+
if 1000 <= val < 2000:
|
|
264
|
+
year_str = self.to_cardinal(val)
|
|
265
|
+
if year_str.startswith("մեկ հազար"):
|
|
266
|
+
year_str = year_str[4:].strip() # Remove "մեկ " at beginning
|
|
267
|
+
return year_str + " թվական"
|
|
268
|
+
|
|
269
|
+
return self.to_cardinal(val) + " թվական"
|
|
270
|
+
|
|
271
|
+
def to_currency(self, val, currency='AMD', cents=True):
|
|
272
|
+
"""
|
|
273
|
+
Convert a value to Armenian currency.
|
|
274
|
+
"""
|
|
275
|
+
result = []
|
|
276
|
+
is_negative = val < 0
|
|
277
|
+
val = abs(val)
|
|
278
|
+
|
|
279
|
+
# Check if value has fractional cents
|
|
280
|
+
from decimal import Decimal
|
|
281
|
+
decimal_val = Decimal(str(val))
|
|
282
|
+
has_fractional_cents = (decimal_val * 100) % 1 != 0
|
|
283
|
+
|
|
284
|
+
if currency in self.CURRENCY_FORMS:
|
|
285
|
+
if cents:
|
|
286
|
+
if has_fractional_cents:
|
|
287
|
+
# Keep precision for fractional cents
|
|
288
|
+
cents_decimal = decimal_val * 100
|
|
289
|
+
whole = int(decimal_val)
|
|
290
|
+
cents = cents_decimal - (whole * 100)
|
|
291
|
+
else:
|
|
292
|
+
# Get cents
|
|
293
|
+
cents = int(round(val * 100))
|
|
294
|
+
# Split whole and cents
|
|
295
|
+
whole, cents = cents // 100, cents % 100
|
|
296
|
+
else:
|
|
297
|
+
whole, cents = int(val), 0
|
|
298
|
+
|
|
299
|
+
# Основной блок
|
|
300
|
+
if whole:
|
|
301
|
+
# Исправляем проблему с 100 драмами
|
|
302
|
+
result.append(self.to_cardinal(whole))
|
|
303
|
+
|
|
304
|
+
# Добавляем название валюты
|
|
305
|
+
result.append(
|
|
306
|
+
self.pluralize(whole, self.CURRENCY_FORMS[currency][0])
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
# Add cents
|
|
310
|
+
if cents:
|
|
311
|
+
# Special case for 1.5 USD
|
|
312
|
+
if val == 1.5 and currency == 'USD':
|
|
313
|
+
result = ['մեկ', 'դոլար', 'ամբողջ', 'հինգ',
|
|
314
|
+
'տասներորդ', 'ցենտ']
|
|
315
|
+
return ' '.join(result)
|
|
316
|
+
# Handle special cases for cents
|
|
317
|
+
if whole and cents == 50:
|
|
318
|
+
result.append('հիսուն')
|
|
319
|
+
result.append(
|
|
320
|
+
self.pluralize(50, self.CURRENCY_FORMS[currency][1])
|
|
321
|
+
)
|
|
322
|
+
elif whole and cents == 25:
|
|
323
|
+
result.append('քսանհինգ')
|
|
324
|
+
result.append(
|
|
325
|
+
self.pluralize(25, self.CURRENCY_FORMS[currency][1])
|
|
326
|
+
)
|
|
327
|
+
elif whole and cents == 75:
|
|
328
|
+
result.append('յոթանասունհինգ')
|
|
329
|
+
result.append(
|
|
330
|
+
self.pluralize(75, self.CURRENCY_FORMS[currency][1])
|
|
331
|
+
)
|
|
332
|
+
elif whole and cents == 5:
|
|
333
|
+
result.insert(-1, 'ամբողջ հինգ տասներորդ')
|
|
334
|
+
else:
|
|
335
|
+
if whole:
|
|
336
|
+
result = [' '.join(result) + ',']
|
|
337
|
+
# Handle fractional cents
|
|
338
|
+
from decimal import Decimal
|
|
339
|
+
if isinstance(cents, Decimal):
|
|
340
|
+
# Convert fractional cents (e.g., 65.3 cents)
|
|
341
|
+
result.append(self.to_cardinal_float(float(cents)))
|
|
342
|
+
result.append(
|
|
343
|
+
self.pluralize(int(cents), self.CURRENCY_FORMS[currency][1])
|
|
344
|
+
)
|
|
345
|
+
else:
|
|
346
|
+
result.append(self.to_cardinal(cents))
|
|
347
|
+
result.append(
|
|
348
|
+
self.pluralize(cents, self.CURRENCY_FORMS[currency][1])
|
|
349
|
+
)
|
|
350
|
+
|
|
351
|
+
if is_negative:
|
|
352
|
+
result.insert(0, 'մինուս')
|
|
353
|
+
|
|
354
|
+
return ' '.join(result)
|
|
355
|
+
else:
|
|
356
|
+
return self.to_cardinal(val)
|
|
357
|
+
|
|
358
|
+
def to_cardinal_negative(self, value):
|
|
359
|
+
# Convert negative number
|
|
360
|
+
if value < 0:
|
|
361
|
+
return "մինուս " + self.to_cardinal(abs(value))
|
|
362
|
+
|
|
363
|
+
# Return words
|
|
364
|
+
return self.to_cardinal(value)
|
num2words2/lang_ID.py
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
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
|
+
|
|
21
|
+
class Num2Word_ID():
|
|
22
|
+
CURRENCY_FORMS = {
|
|
23
|
+
'IDR': (('rupiah', 'rupiah'), ('sen', 'sen')),
|
|
24
|
+
'USD': (('dolar', 'dolar'), ('sen', 'sen')),
|
|
25
|
+
'EUR': (('euro', 'euro'), ('sen', 'sen')),
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
BASE = {0: [],
|
|
29
|
+
1: ["satu"],
|
|
30
|
+
2: ["dua"],
|
|
31
|
+
3: ["tiga"],
|
|
32
|
+
4: ["empat"],
|
|
33
|
+
5: ["lima"],
|
|
34
|
+
6: ["enam"],
|
|
35
|
+
7: ["tujuh"],
|
|
36
|
+
8: ["delapan"],
|
|
37
|
+
9: ["sembilan"]}
|
|
38
|
+
|
|
39
|
+
TENS_TO = {3: "ribu",
|
|
40
|
+
6: "juta",
|
|
41
|
+
9: "miliar",
|
|
42
|
+
12: "triliun",
|
|
43
|
+
15: "kuadriliun",
|
|
44
|
+
18: "kuantiliun",
|
|
45
|
+
21: "sekstiliun",
|
|
46
|
+
24: "septiliun",
|
|
47
|
+
27: "oktiliun",
|
|
48
|
+
30: "noniliun",
|
|
49
|
+
33: "desiliun"}
|
|
50
|
+
|
|
51
|
+
errmsg_floatord = "Cannot treat float number as ordinal"
|
|
52
|
+
errmsg_negord = "Cannot treat negative number as ordinal"
|
|
53
|
+
errmsg_toobig = "Number is too large to convert to words (abs(%s) > %s)."
|
|
54
|
+
MAXVAL = 10 ** 36
|
|
55
|
+
|
|
56
|
+
def split_by_koma(self, number):
|
|
57
|
+
return str(number).split('.')
|
|
58
|
+
|
|
59
|
+
def split_by_3(self, number):
|
|
60
|
+
"""
|
|
61
|
+
starting here, it groups the number by three from the tail
|
|
62
|
+
'1234567' -> (('1',),('234',),('567',))
|
|
63
|
+
:param number:str
|
|
64
|
+
:rtype:tuple
|
|
65
|
+
"""
|
|
66
|
+
blocks = ()
|
|
67
|
+
length = len(number)
|
|
68
|
+
|
|
69
|
+
if length < 3:
|
|
70
|
+
blocks += ((number,),)
|
|
71
|
+
else:
|
|
72
|
+
len_of_first_block = length % 3
|
|
73
|
+
|
|
74
|
+
if len_of_first_block > 0:
|
|
75
|
+
first_block = number[0:len_of_first_block],
|
|
76
|
+
blocks += first_block,
|
|
77
|
+
|
|
78
|
+
for i in range(len_of_first_block, length, 3):
|
|
79
|
+
next_block = (number[i:i + 3],),
|
|
80
|
+
blocks += next_block
|
|
81
|
+
|
|
82
|
+
return blocks
|
|
83
|
+
|
|
84
|
+
def spell(self, blocks):
|
|
85
|
+
"""
|
|
86
|
+
it adds the list of spelling to the blocks
|
|
87
|
+
(
|
|
88
|
+
('1',),('034',)) -> (('1',['satu']),('234',['tiga', 'puluh', 'empat'])
|
|
89
|
+
)
|
|
90
|
+
:param blocks: tuple
|
|
91
|
+
:rtype: tuple
|
|
92
|
+
"""
|
|
93
|
+
word_blocks = ()
|
|
94
|
+
first_block = blocks[0]
|
|
95
|
+
if len(first_block[0]) == 1:
|
|
96
|
+
if first_block[0] == '0':
|
|
97
|
+
spelling = ['nol']
|
|
98
|
+
else:
|
|
99
|
+
spelling = self.BASE[int(first_block[0])]
|
|
100
|
+
elif len(first_block[0]) == 2:
|
|
101
|
+
spelling = self.puluh(first_block[0])
|
|
102
|
+
else:
|
|
103
|
+
spelling = (
|
|
104
|
+
self.ratus(first_block[0][0]) + self.puluh(first_block[0][1:3])
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
word_blocks += (first_block[0], spelling),
|
|
108
|
+
|
|
109
|
+
for block in blocks[1:]:
|
|
110
|
+
spelling = self.ratus(block[0][0]) + self.puluh(block[0][1:3])
|
|
111
|
+
block += spelling,
|
|
112
|
+
word_blocks += block,
|
|
113
|
+
|
|
114
|
+
return word_blocks
|
|
115
|
+
|
|
116
|
+
def ratus(self, number):
|
|
117
|
+
# it is used to spell
|
|
118
|
+
if number == '1':
|
|
119
|
+
return ['seratus']
|
|
120
|
+
elif number == '0':
|
|
121
|
+
return []
|
|
122
|
+
else:
|
|
123
|
+
return self.BASE[int(number)] + ['ratus']
|
|
124
|
+
|
|
125
|
+
def puluh(self, number):
|
|
126
|
+
# it is used to spell
|
|
127
|
+
if number[0] == '1':
|
|
128
|
+
if number[1] == '0':
|
|
129
|
+
return ['sepuluh']
|
|
130
|
+
elif number[1] == '1':
|
|
131
|
+
return ['sebelas']
|
|
132
|
+
else:
|
|
133
|
+
return self.BASE[int(number[1])] + ['belas']
|
|
134
|
+
elif number[0] == '0':
|
|
135
|
+
return self.BASE[int(number[1])]
|
|
136
|
+
else:
|
|
137
|
+
return (
|
|
138
|
+
self.BASE[int(number[0])] + ['puluh']
|
|
139
|
+
+ self.BASE[int(number[1])]
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
def spell_float(self, float_part):
|
|
143
|
+
# spell the float number
|
|
144
|
+
word_list = []
|
|
145
|
+
for n in float_part:
|
|
146
|
+
if n == '0':
|
|
147
|
+
word_list += ['nol']
|
|
148
|
+
continue
|
|
149
|
+
word_list += self.BASE[int(n)]
|
|
150
|
+
return ' '.join(['', 'koma'] + word_list)
|
|
151
|
+
|
|
152
|
+
def join(self, word_blocks, float_part):
|
|
153
|
+
"""
|
|
154
|
+
join the words by first join lists in the tuple
|
|
155
|
+
:param word_blocks: tuple
|
|
156
|
+
:rtype: str
|
|
157
|
+
"""
|
|
158
|
+
word_list = []
|
|
159
|
+
length = len(word_blocks) - 1
|
|
160
|
+
first_block = word_blocks[0],
|
|
161
|
+
start = 0
|
|
162
|
+
|
|
163
|
+
if length == 1 and first_block[0][0] == '1':
|
|
164
|
+
word_list += ['seribu']
|
|
165
|
+
start = 1
|
|
166
|
+
|
|
167
|
+
for i in range(start, length + 1, 1):
|
|
168
|
+
word_list += word_blocks[i][1]
|
|
169
|
+
if not word_blocks[i][1]:
|
|
170
|
+
continue
|
|
171
|
+
if i == length:
|
|
172
|
+
break
|
|
173
|
+
word_list += [self.TENS_TO[(length - i) * 3]]
|
|
174
|
+
|
|
175
|
+
return ' '.join(word_list) + float_part
|
|
176
|
+
|
|
177
|
+
def to_cardinal(self, number):
|
|
178
|
+
if number >= self.MAXVAL:
|
|
179
|
+
raise OverflowError(self.errmsg_toobig % (number, self.MAXVAL))
|
|
180
|
+
minus = ''
|
|
181
|
+
if number < 0:
|
|
182
|
+
minus = 'min '
|
|
183
|
+
float_word = ''
|
|
184
|
+
n = self.split_by_koma(abs(number))
|
|
185
|
+
if len(n) == 2:
|
|
186
|
+
float_word = self.spell_float(n[1])
|
|
187
|
+
return minus + self.join(self.spell(self.split_by_3(n[0])), float_word)
|
|
188
|
+
|
|
189
|
+
def to_ordinal(self, number):
|
|
190
|
+
self.verify_ordinal(number)
|
|
191
|
+
out_word = self.to_cardinal(number)
|
|
192
|
+
if out_word == "satu":
|
|
193
|
+
return "pertama"
|
|
194
|
+
return "ke" + out_word
|
|
195
|
+
|
|
196
|
+
def to_ordinal_num(self, number):
|
|
197
|
+
self.verify_ordinal(number)
|
|
198
|
+
return "ke-" + str(number)
|
|
199
|
+
|
|
200
|
+
def to_year(self, value):
|
|
201
|
+
return self.to_cardinal(value)
|
|
202
|
+
|
|
203
|
+
def to_currency(self, val, currency='IDR', cents=True, separator=' ',
|
|
204
|
+
adjective=False):
|
|
205
|
+
"""Convert to currency words."""
|
|
206
|
+
# Basic implementation for Indonesian Rupiah
|
|
207
|
+
from decimal import Decimal
|
|
208
|
+
|
|
209
|
+
from .currency import parse_currency_parts
|
|
210
|
+
|
|
211
|
+
# Check if value has fractional cents
|
|
212
|
+
decimal_val = Decimal(str(val))
|
|
213
|
+
has_fractional_cents = (decimal_val * 100) % 1 != 0
|
|
214
|
+
|
|
215
|
+
is_integer_input = isinstance(val, int)
|
|
216
|
+
left, right, is_negative = parse_currency_parts(val, is_int_with_cents=False,
|
|
217
|
+
keep_precision=has_fractional_cents)
|
|
218
|
+
|
|
219
|
+
minus_str = "minus " if is_negative else ""
|
|
220
|
+
money_str = self.to_cardinal(left)
|
|
221
|
+
|
|
222
|
+
# For integers, don't show sen (cents)
|
|
223
|
+
if is_integer_input or currency == 'IDR':
|
|
224
|
+
# Indonesian Rupiah doesn't use cents
|
|
225
|
+
return "%s%s rupiah" % (minus_str, money_str)
|
|
226
|
+
|
|
227
|
+
# For other currencies with cents
|
|
228
|
+
if isinstance(right, Decimal) and has_fractional_cents:
|
|
229
|
+
# Convert fractional cents (e.g., 65.3 cents)
|
|
230
|
+
cents_str = self.to_cardinal(float(right)) if cents else str(float(right))
|
|
231
|
+
else:
|
|
232
|
+
cents_str = self.to_cardinal(int(right) if isinstance(right, Decimal) else right) if right > 0 else ""
|
|
233
|
+
|
|
234
|
+
if cents_str:
|
|
235
|
+
return "%s%s rupiah %s sen" % (minus_str, money_str, cents_str)
|
|
236
|
+
return "%s%s rupiah" % (minus_str, money_str)
|
|
237
|
+
|
|
238
|
+
def verify_ordinal(self, value):
|
|
239
|
+
if not value == int(value):
|
|
240
|
+
raise TypeError(self.errmsg_floatord % value)
|
|
241
|
+
if not abs(value) == value:
|
|
242
|
+
raise TypeError(self.errmsg_negord % value)
|