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_ZH_HK.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
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 .lang_ZH import Num2Word_ZH
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class Num2Word_ZH_HK(Num2Word_ZH):
|
|
24
|
+
CURRENCY_FLOATS_CHILD = ["毫", "仙"]
|
|
25
|
+
|
|
26
|
+
CURRENCY_FORMS_CHILD = {
|
|
27
|
+
"EUR": "歐羅",
|
|
28
|
+
"JPY": "日圓",
|
|
29
|
+
"CAD": "加元",
|
|
30
|
+
"AUD": "澳元",
|
|
31
|
+
"KRW": "韓圜",
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
CAP_map_CHILD = [
|
|
35
|
+
("毫", "角"),
|
|
36
|
+
("仙", "分"),
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
def __init__(self):
|
|
40
|
+
super().__init__()
|
|
41
|
+
self.CURRENCY_FLOATS = self.CURRENCY_FLOATS_CHILD.copy()
|
|
42
|
+
self.CURRENCY_FORMS = self.CURRENCY_FORMS.copy()
|
|
43
|
+
self.CAP_map = self.CAP_map.copy()
|
|
44
|
+
|
|
45
|
+
for k, v in self.CURRENCY_FORMS_CHILD.items():
|
|
46
|
+
self.CURRENCY_FORMS[k] = v
|
|
47
|
+
for item in self.CAP_map_CHILD:
|
|
48
|
+
self.CAP_map.append(item)
|
num2words2/lang_ZH_TW.py
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
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 .compat import to_s
|
|
21
|
+
from .lang_ZH import Num2Word_ZH
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class Num2Word_ZH_TW(Num2Word_ZH):
|
|
25
|
+
CURRENCY_FORMS_CHILD = {
|
|
26
|
+
"XXX": (("元",), ("ㄩㄢˊ",)), # Generic dollar
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
cheque_suffix = (("正",), ("ㄓㄥˋ",))
|
|
30
|
+
year = (("年",), ("ㄋㄧㄢˊ",))
|
|
31
|
+
year_prefix = (("公元", "西元"), ("ㄍㄨㄥ ㄩㄢˊ", "ㄒㄧㄩㄢˊ"))
|
|
32
|
+
year_bce = (("前",), ("ㄑㄧㄢˊ",))
|
|
33
|
+
ord_prefix = (("第",), ("ㄉㄧˋ",))
|
|
34
|
+
ROC_era = (("民國",), ("ㄇㄧㄣˊㄍㄨㄛˊ",))
|
|
35
|
+
|
|
36
|
+
def __init__(self):
|
|
37
|
+
super().__init__()
|
|
38
|
+
self.CURRENCY_FORMS = self.CURRENCY_FORMS.copy()
|
|
39
|
+
|
|
40
|
+
for k, v in self.CURRENCY_FORMS_CHILD.items():
|
|
41
|
+
self.CURRENCY_FORMS[k] = v
|
|
42
|
+
|
|
43
|
+
# Get reading for negword
|
|
44
|
+
def to_cardinal(self, value, stuff_zero=2, reading=False, prefer=None):
|
|
45
|
+
self.stuff_zero = stuff_zero
|
|
46
|
+
self.set_str_selection(reading, prefer)
|
|
47
|
+
|
|
48
|
+
try:
|
|
49
|
+
assert int(value) == value
|
|
50
|
+
except (ValueError, TypeError, AssertionError):
|
|
51
|
+
return self.to_cardinal_float(value, reading, prefer)
|
|
52
|
+
|
|
53
|
+
out = ""
|
|
54
|
+
if value < 0:
|
|
55
|
+
value = abs(value)
|
|
56
|
+
out = "%s " % self.select_text(self.negword).strip()
|
|
57
|
+
|
|
58
|
+
if value >= self.MAXVAL:
|
|
59
|
+
raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL))
|
|
60
|
+
|
|
61
|
+
val = self.splitnum(value)
|
|
62
|
+
words, num = self.clean(val)
|
|
63
|
+
out = self.title(out + words)
|
|
64
|
+
|
|
65
|
+
out = self.zh_to_cap(out, reading == "capital")
|
|
66
|
+
return out.replace(" ", "")
|
|
67
|
+
|
|
68
|
+
# Get reading for pointword
|
|
69
|
+
def to_cardinal_float(self, value, reading=False, prefer=None):
|
|
70
|
+
try:
|
|
71
|
+
float(value) == value
|
|
72
|
+
except (ValueError, TypeError, AssertionError, AttributeError):
|
|
73
|
+
raise TypeError(self.errmsg_nonnum % value)
|
|
74
|
+
|
|
75
|
+
pre, post = self.float2tuple(float(value))
|
|
76
|
+
|
|
77
|
+
post = str(post)
|
|
78
|
+
post = '0' * (self.precision - len(post)) + post
|
|
79
|
+
|
|
80
|
+
out = [self.to_cardinal(pre, reading=reading, prefer=prefer)]
|
|
81
|
+
if value < 0 and pre == 0:
|
|
82
|
+
out = [self.select_text(self.negword).strip()] + out
|
|
83
|
+
|
|
84
|
+
if self.precision:
|
|
85
|
+
out.append(self.select_text(self.title(self.pointword)))
|
|
86
|
+
|
|
87
|
+
for i in range(self.precision):
|
|
88
|
+
curr = int(post[i])
|
|
89
|
+
out.append(
|
|
90
|
+
to_s(
|
|
91
|
+
self.to_cardinal(
|
|
92
|
+
curr,
|
|
93
|
+
reading=reading,
|
|
94
|
+
prefer=prefer)))
|
|
95
|
+
|
|
96
|
+
out = self.zh_to_cap(" ".join(out), self.capital)
|
|
97
|
+
return out.replace(" ", "")
|
|
98
|
+
|
|
99
|
+
def to_ordinal(self, value, counter="", reading=False, prefer=None):
|
|
100
|
+
self.set_str_selection(reading, prefer)
|
|
101
|
+
if reading is True:
|
|
102
|
+
if counter not in self.counters and counter:
|
|
103
|
+
raise NotImplementedError(
|
|
104
|
+
f"Reading not implemented for {counter}")
|
|
105
|
+
counter = self.counters.get(counter, "")
|
|
106
|
+
return super().to_ordinal(
|
|
107
|
+
value, counter=counter, reading=reading, prefer=prefer)
|
|
108
|
+
|
|
109
|
+
def to_ordinal_num(self, value, counter="", reading=False, prefer=None):
|
|
110
|
+
self.set_str_selection(reading, prefer)
|
|
111
|
+
if self.reading is True:
|
|
112
|
+
if counter not in self.counters and counter:
|
|
113
|
+
raise NotImplementedError(
|
|
114
|
+
f"Reading not implemented for {counter}")
|
|
115
|
+
counter = self.counters.get(counter, "")
|
|
116
|
+
return super().to_ordinal_num(
|
|
117
|
+
value, counter=counter, reading=reading, prefer=prefer)
|
|
118
|
+
|
|
119
|
+
def to_year(self, value, era=False, reading=False, prefer=None):
|
|
120
|
+
self.set_str_selection(reading, prefer)
|
|
121
|
+
if not era:
|
|
122
|
+
return super().to_year(value, reading=reading, prefer=prefer)
|
|
123
|
+
|
|
124
|
+
if not value == int(value):
|
|
125
|
+
raise TypeError(self.errmsg_floatyear % value)
|
|
126
|
+
|
|
127
|
+
min_year = 1912
|
|
128
|
+
if value < min_year:
|
|
129
|
+
raise ValueError(
|
|
130
|
+
"Can't convert years less than %s to ROC era" %
|
|
131
|
+
min_year)
|
|
132
|
+
era_year = abs(int(value - min_year + 1))
|
|
133
|
+
|
|
134
|
+
if reading == "arabic":
|
|
135
|
+
era_year_words = era_year
|
|
136
|
+
elif era_year == 1:
|
|
137
|
+
era_year_words = self.select_text((("元",), ("ㄩㄢˊ",)))
|
|
138
|
+
elif era_year < 101:
|
|
139
|
+
era_year_words = self.to_cardinal(era_year)
|
|
140
|
+
else:
|
|
141
|
+
era_year_words = "".join(
|
|
142
|
+
[self.select_text(self.cards[int(s)]) for s in str(era_year)])
|
|
143
|
+
|
|
144
|
+
return "%s%s%s" % (self.select_text(self.ROC_era),
|
|
145
|
+
era_year_words, self.select_text(self.year))
|
|
146
|
+
|
|
147
|
+
def setup(self):
|
|
148
|
+
super().setup()
|
|
149
|
+
self.negword = (("負",), ("ㄈㄨˋ",))
|
|
150
|
+
self.pointword = (("點",), ("ㄉㄧㄢˇ",))
|
|
151
|
+
self.exclude_title = [self.negword, self.pointword]
|
|
152
|
+
|
|
153
|
+
self.high_numwords = [
|
|
154
|
+
(("萬",), ("ㄨㄢˋ",)), # 10**4
|
|
155
|
+
(("億",), ("ㄧˋ",)), # 10**8
|
|
156
|
+
(("兆",), ("ㄓㄠˋ",)), # 10**12
|
|
157
|
+
(("京",), ("ㄐㄧㄥ",)), # 10**16
|
|
158
|
+
(("垓",), ("ㄍㄞ",)), # 10**20
|
|
159
|
+
(("秭",), ("ㄗˇ",)), # 10**24
|
|
160
|
+
(("穣",), ("ㄖㄤ",)), # 10**28
|
|
161
|
+
(("溝",), ("ㄍㄡ",)), # 10**32
|
|
162
|
+
(("澗",), ("ㄐㄧㄢˋ",)), # 10**36
|
|
163
|
+
(("正",), ("ㄓㄥˋ",)), # 10**40
|
|
164
|
+
(("載",), ("ㄗㄞˇ",)), # 10**44
|
|
165
|
+
(("極",), ("ㄐㄧˊ",)), # 10**48
|
|
166
|
+
(("恆河沙",), ("ㄏㄥˊㄏㄜˊㄕㄚ",)), # 10**52
|
|
167
|
+
(("阿僧祇",), ("ㄚㄙㄥㄑㄧˊ",)), # 10**56
|
|
168
|
+
(("那由他",), ("ㄋㄚˋㄧㄡˊㄊㄚ",)), # 10**60
|
|
169
|
+
(("不可思議",), ("ㄅㄨˋㄎㄜˇㄙㄧˋ",)), # 10**64
|
|
170
|
+
(("無量",), ("ㄨˊㄌㄧㄤˋ",)), # 10**68
|
|
171
|
+
(("不可說",), ("ㄅㄨˋㄎㄜˇㄕㄨㄛ",)) # 10**72
|
|
172
|
+
]
|
|
173
|
+
self.high_numwords.reverse()
|
|
174
|
+
|
|
175
|
+
self.counters = {
|
|
176
|
+
"個": "˙ㄍㄜ",
|
|
177
|
+
"名": "ㄇㄧㄥˊ",
|
|
178
|
+
"位": "ㄨㄟˋ"
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
self.mid_numwords = [
|
|
182
|
+
(1000, (("千",), ("ㄑㄧㄢ",))),
|
|
183
|
+
(100, (("百",), ("ㄅㄞˇ",))),
|
|
184
|
+
]
|
|
185
|
+
|
|
186
|
+
self.low_numwords = [
|
|
187
|
+
(("十", "拾"), ("ㄕˊ",)), # 10
|
|
188
|
+
(("九", "玖"), ("ㄐㄧㄡˇ",)), # 9
|
|
189
|
+
(("八", "捌"), ("ㄅㄚ",)), # 8
|
|
190
|
+
(("七", "柒"), ("ㄑㄧ",)), # 7
|
|
191
|
+
(("六", "陸"), ("ㄌㄧㄡˋ",)), # 6
|
|
192
|
+
(("五", "伍"), ("ㄨˇ",)), # 5
|
|
193
|
+
(("四", "肆"), ("ㄙˋ",)), # 4
|
|
194
|
+
(("三", "參"), ("ㄙㄢ",)), # 3
|
|
195
|
+
(("二", "貳"), ("ㄦˋ",)), # 2
|
|
196
|
+
(("一", "壹"), ("ㄧ",)), # 1
|
|
197
|
+
(("零", "〇"), ("ㄌㄧㄥˊ",)), # 0
|
|
198
|
+
]
|
num2words2/utils.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
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
|
+
|
|
19
|
+
def splitbyx(n, x, format_int=True):
|
|
20
|
+
length = len(n)
|
|
21
|
+
if length > x:
|
|
22
|
+
start = length % x
|
|
23
|
+
if start > 0:
|
|
24
|
+
result = n[:start]
|
|
25
|
+
yield int(result) if format_int else result
|
|
26
|
+
for i in range(start, length, x):
|
|
27
|
+
result = n[i:i + x]
|
|
28
|
+
yield int(result) if format_int else result
|
|
29
|
+
else:
|
|
30
|
+
yield int(n) if format_int else n
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def get_digits(n):
|
|
34
|
+
a = [int(x) for x in reversed(list(('%03d' % n)[-3:]))]
|
|
35
|
+
return a
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
#!python
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
|
4
|
+
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
|
5
|
+
|
|
6
|
+
# This library is free software; you can redistribute it and/or
|
|
7
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
8
|
+
# License as published by the Free Software Foundation; either
|
|
9
|
+
# version 2.1 of the License, or (at your option) any later version.
|
|
10
|
+
# This library is distributed in the hope that it will be useful,
|
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
13
|
+
# Lesser General Public License for more details.
|
|
14
|
+
# You should have received a copy of the GNU Lesser General Public
|
|
15
|
+
# License along with this library; if not, write to the Free Software
|
|
16
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
17
|
+
# MA 02110-1301 USA
|
|
18
|
+
|
|
19
|
+
"""num2words2: convert numbers into words.
|
|
20
|
+
|
|
21
|
+
Usage:
|
|
22
|
+
num2words2 [options] <number>
|
|
23
|
+
num2words2 --list-languages
|
|
24
|
+
num2words2 --list-converters
|
|
25
|
+
num2words2 --help
|
|
26
|
+
|
|
27
|
+
Arguments:
|
|
28
|
+
<number> Number you want to convert into words
|
|
29
|
+
|
|
30
|
+
Options:
|
|
31
|
+
-L --list-languages Show all languages.
|
|
32
|
+
-C --list-converters Show all converters.
|
|
33
|
+
-l --lang=<lang> Output language [default: en].
|
|
34
|
+
-t --to=<to> Output converter [default: cardinal].
|
|
35
|
+
-h --help Show this message.
|
|
36
|
+
-v --version Show version.
|
|
37
|
+
|
|
38
|
+
Examples:
|
|
39
|
+
$ num2words2 10001
|
|
40
|
+
ten thousand and one
|
|
41
|
+
|
|
42
|
+
$ num2words2 24,120.10
|
|
43
|
+
twenty-four thousand, one hundred and twenty point one
|
|
44
|
+
|
|
45
|
+
$ num2words2 24,120.10 -l es
|
|
46
|
+
veinticuatro mil ciento veinte punto uno
|
|
47
|
+
|
|
48
|
+
$num2words2 2.14 -l es --to currency
|
|
49
|
+
dos euros con catorce céntimos
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
from __future__ import print_function, unicode_literals
|
|
53
|
+
|
|
54
|
+
import os
|
|
55
|
+
import sys
|
|
56
|
+
|
|
57
|
+
from docopt import docopt
|
|
58
|
+
|
|
59
|
+
import num2words2 as num2words
|
|
60
|
+
|
|
61
|
+
__version__ = "0.5.16"
|
|
62
|
+
__license__ = "LGPL"
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def get_languages():
|
|
66
|
+
return sorted(list(num2words.CONVERTER_CLASSES.keys()))
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def get_converters():
|
|
70
|
+
return sorted(list(num2words.CONVERTES_TYPES))
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def main():
|
|
74
|
+
version = "{}=={}".format(os.path.basename(__file__), __version__)
|
|
75
|
+
args = docopt(__doc__, argv=None, help=True, version=version, options_first=False)
|
|
76
|
+
if args["--list-languages"]:
|
|
77
|
+
for lang in get_languages():
|
|
78
|
+
sys.stdout.write(lang)
|
|
79
|
+
sys.stdout.write(os.linesep)
|
|
80
|
+
sys.exit(0)
|
|
81
|
+
if args["--list-converters"]:
|
|
82
|
+
for cvt in get_converters():
|
|
83
|
+
sys.stdout.write(cvt)
|
|
84
|
+
sys.stdout.write(os.linesep)
|
|
85
|
+
sys.exit(0)
|
|
86
|
+
try:
|
|
87
|
+
words = num2words.num2words(args['<number>'], lang=args['--lang'], to=args['--to'])
|
|
88
|
+
sys.stdout.write(words + os.linesep)
|
|
89
|
+
sys.exit(0)
|
|
90
|
+
except Exception as err:
|
|
91
|
+
sys.stderr.write(str(args['<number>']))
|
|
92
|
+
sys.stderr.write(str(err) + os.linesep)
|
|
93
|
+
sys.stderr.write(__doc__)
|
|
94
|
+
sys.exit(1)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
if __name__ == '__main__':
|
|
98
|
+
main()
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: num2words2
|
|
3
|
+
Version: 0.1.0.dev1
|
|
4
|
+
Summary: Modern, actively maintained fork of num2words optimized for LLM/AI/speech applications.
|
|
5
|
+
Home-page: https://github.com/jqueguiner/num2words
|
|
6
|
+
Author: Jean-Louis Queguiner
|
|
7
|
+
Author-email: Jean-Louis Queguiner <jean-louis.queguiner@gmail.com>
|
|
8
|
+
Maintainer: Jean-Louis Queguiner
|
|
9
|
+
Maintainer-email: Jean-Louis Queguiner <jean-louis.queguiner@gmail.com>
|
|
10
|
+
License: LGPL-2.1
|
|
11
|
+
Project-URL: Homepage, https://github.com/jqueguiner/num2words
|
|
12
|
+
Project-URL: Repository, https://github.com/jqueguiner/num2words.git
|
|
13
|
+
Project-URL: Bug Tracker, https://github.com/jqueguiner/num2words/issues
|
|
14
|
+
Keywords: number,word,numbers,words,convert,conversion,i18n,localisation,localization,internationalisation,internationalization
|
|
15
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
16
|
+
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Topic :: Software Development :: Internationalization
|
|
25
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
26
|
+
Classifier: Topic :: Software Development :: Localization
|
|
27
|
+
Classifier: Topic :: Text Processing :: Linguistic
|
|
28
|
+
Requires-Python: >=3.8
|
|
29
|
+
Description-Content-Type: text/x-rst
|
|
30
|
+
License-File: COPYING
|
|
31
|
+
Requires-Dist: docopt>=0.6.2
|
|
32
|
+
Dynamic: author
|
|
33
|
+
Dynamic: home-page
|
|
34
|
+
Dynamic: license
|
|
35
|
+
Dynamic: license-file
|
|
36
|
+
Dynamic: maintainer
|
|
37
|
+
|
|
38
|
+
num2words2 library - Convert numbers to words in multiple languages
|
|
39
|
+
===================================================================
|
|
40
|
+
|
|
41
|
+
.. image:: https://img.shields.io/pypi/v/num2words2.svg
|
|
42
|
+
:target: https://pypi.python.org/pypi/num2words2
|
|
43
|
+
|
|
44
|
+
.. image:: https://github.com/jqueguiner/num2words/workflows/CI/badge.svg
|
|
45
|
+
:target: https://github.com/jqueguiner/num2words/actions
|
|
46
|
+
|
|
47
|
+
.. image:: https://coveralls.io/repos/github/jqueguiner/num2words/badge.svg?branch=master
|
|
48
|
+
:target: https://coveralls.io/github/jqueguiner/num2words?branch=master
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
``num2words2`` is a modern, actively maintained fork of the original num2words library
|
|
52
|
+
that converts numbers like ``42`` to words like ``forty-two``. It supports multiple
|
|
53
|
+
languages (see the list below for full list of languages) and can even generate
|
|
54
|
+
ordinal numbers like ``forty-second``. This fork was created to address the maintenance
|
|
55
|
+
gap in the original project and optimize for modern AI/LLM/speech applications.
|
|
56
|
+
|
|
57
|
+
The project is hosted on GitHub_. Contributions are welcome.
|
|
58
|
+
|
|
59
|
+
.. _GitHub: https://github.com/jqueguiner/num2words
|
|
60
|
+
|
|
61
|
+
Installation
|
|
62
|
+
------------
|
|
63
|
+
|
|
64
|
+
The easiest way to install ``num2words2`` is to use pip::
|
|
65
|
+
|
|
66
|
+
pip install num2words2
|
|
67
|
+
|
|
68
|
+
Otherwise, you can download the source package and then execute::
|
|
69
|
+
|
|
70
|
+
python setup.py install
|
|
71
|
+
|
|
72
|
+
The test suite in this library is new, so it's rather thin, but it can be run with::
|
|
73
|
+
|
|
74
|
+
python setup.py test
|
|
75
|
+
|
|
76
|
+
To run the full CI test suite which includes linting and multiple python environments::
|
|
77
|
+
|
|
78
|
+
pip install tox
|
|
79
|
+
tox
|
|
80
|
+
|
|
81
|
+
Development Setup
|
|
82
|
+
-----------------
|
|
83
|
+
The project uses pre-commit hooks to ensure code quality. To set up your development environment::
|
|
84
|
+
|
|
85
|
+
# Install pre-commit
|
|
86
|
+
pip install pre-commit
|
|
87
|
+
|
|
88
|
+
# Install the git hook scripts
|
|
89
|
+
pre-commit install
|
|
90
|
+
|
|
91
|
+
# Run hooks on all files (optional, useful for initial setup)
|
|
92
|
+
pre-commit run --all-files
|
|
93
|
+
|
|
94
|
+
This will automatically format and lint your code before each commit using:
|
|
95
|
+
|
|
96
|
+
* autopep8 - PEP 8 formatting
|
|
97
|
+
* autoflake - removes unused imports and variables
|
|
98
|
+
* isort - sorts imports
|
|
99
|
+
* flake8 - style and quality checks
|
|
100
|
+
* trailing-whitespace removal
|
|
101
|
+
* end-of-file fixing
|
|
102
|
+
|
|
103
|
+
Usage
|
|
104
|
+
-----
|
|
105
|
+
Command line::
|
|
106
|
+
|
|
107
|
+
$ num2words2 10001
|
|
108
|
+
ten thousand and one
|
|
109
|
+
$ num2words2 24,120.10
|
|
110
|
+
twenty-four thousand, one hundred and twenty point one
|
|
111
|
+
$ num2words2 24,120.10 -l es
|
|
112
|
+
veinticuatro mil ciento veinte punto uno
|
|
113
|
+
$ num2words2 2.14 -l es --to currency
|
|
114
|
+
dos euros con catorce céntimos
|
|
115
|
+
|
|
116
|
+
In code there's only one function to use::
|
|
117
|
+
|
|
118
|
+
>>> from num2words2 import num2words
|
|
119
|
+
>>> num2words(42)
|
|
120
|
+
forty-two
|
|
121
|
+
>>> num2words(42, to='ordinal')
|
|
122
|
+
forty-second
|
|
123
|
+
>>> num2words(42, lang='fr')
|
|
124
|
+
quarante-deux
|
|
125
|
+
|
|
126
|
+
Besides the numerical argument, there are two main optional arguments, ``to:`` and ``lang:``
|
|
127
|
+
|
|
128
|
+
**to:** The converter to use. Supported values are:
|
|
129
|
+
|
|
130
|
+
* ``cardinal`` (default)
|
|
131
|
+
* ``ordinal``
|
|
132
|
+
* ``ordinal_num``
|
|
133
|
+
* ``year``
|
|
134
|
+
* ``currency``
|
|
135
|
+
|
|
136
|
+
**lang:** The language in which to convert the number. Supported values are:
|
|
137
|
+
|
|
138
|
+
* ``en`` (English, default)
|
|
139
|
+
* ``am`` (Amharic)
|
|
140
|
+
* ``ar`` (Arabic)
|
|
141
|
+
* ``az`` (Azerbaijani)
|
|
142
|
+
* ``be`` (Belarusian)
|
|
143
|
+
* ``bn`` (Bangladeshi)
|
|
144
|
+
* ``ca`` (Catalan)
|
|
145
|
+
* ``ce`` (Chechen)
|
|
146
|
+
* ``cs`` (Czech)
|
|
147
|
+
* ``cy`` (Welsh)
|
|
148
|
+
* ``da`` (Danish)
|
|
149
|
+
* ``de`` (German)
|
|
150
|
+
* ``en_GB`` (English - Great Britain)
|
|
151
|
+
* ``en_IN`` (English - India)
|
|
152
|
+
* ``en_NG`` (English - Nigeria)
|
|
153
|
+
* ``es`` (Spanish)
|
|
154
|
+
* ``es_CO`` (Spanish - Colombia)
|
|
155
|
+
* ``es_CR`` (Spanish - Costa Rica)
|
|
156
|
+
* ``es_GT`` (Spanish - Guatemala)
|
|
157
|
+
* ``es_VE`` (Spanish - Venezuela)
|
|
158
|
+
* ``eu`` (EURO)
|
|
159
|
+
* ``fa`` (Farsi)
|
|
160
|
+
* ``fi`` (Finnish)
|
|
161
|
+
* ``fr`` (French)
|
|
162
|
+
* ``fr_BE`` (French - Belgium)
|
|
163
|
+
* ``fr_CH`` (French - Switzerland)
|
|
164
|
+
* ``fr_DZ`` (French - Algeria)
|
|
165
|
+
* ``he`` (Hebrew)
|
|
166
|
+
* ``hi`` (Hindi)
|
|
167
|
+
* ``hu`` (Hungarian)
|
|
168
|
+
* ``hy`` (Armenian)
|
|
169
|
+
* ``id`` (Indonesian)
|
|
170
|
+
* ``is`` (Icelandic)
|
|
171
|
+
* ``it`` (Italian)
|
|
172
|
+
* ``ja`` (Japanese)
|
|
173
|
+
* ``kn`` (Kannada)
|
|
174
|
+
* ``ko`` (Korean)
|
|
175
|
+
* ``kz`` (Kazakh)
|
|
176
|
+
* ``mn`` (Mongolian)
|
|
177
|
+
* ``lt`` (Lithuanian)
|
|
178
|
+
* ``lv`` (Latvian)
|
|
179
|
+
* ``nl`` (Dutch)
|
|
180
|
+
* ``no`` (Norwegian)
|
|
181
|
+
* ``pl`` (Polish)
|
|
182
|
+
* ``pt`` (Portuguese)
|
|
183
|
+
* ``pt_BR`` (Portuguese - Brazilian)
|
|
184
|
+
* ``ro`` (Romanian)
|
|
185
|
+
* ``ru`` (Russian)
|
|
186
|
+
* ``sl`` (Slovene)
|
|
187
|
+
* ``sk`` (Slovak)
|
|
188
|
+
* ``sr`` (Serbian)
|
|
189
|
+
* ``sv`` (Swedish)
|
|
190
|
+
* ``te`` (Telugu)
|
|
191
|
+
* ``tet`` (Tetum)
|
|
192
|
+
* ``tg`` (Tajik)
|
|
193
|
+
* ``tr`` (Turkish)
|
|
194
|
+
* ``th`` (Thai)
|
|
195
|
+
* ``uk`` (Ukrainian)
|
|
196
|
+
* ``vi`` (Vietnamese)
|
|
197
|
+
* ``zh`` (Chinese - Traditional)
|
|
198
|
+
* ``zh_CN`` (Chinese - Simplified / Mainland China)
|
|
199
|
+
* ``zh_TW`` (Chinese - Traditional / Taiwan)
|
|
200
|
+
* ``zh_HK`` (Chinese - Traditional / Hong Kong)
|
|
201
|
+
|
|
202
|
+
You can supply values like ``fr_FR``; if the country doesn't exist but the
|
|
203
|
+
language does, the code will fall back to the base language (i.e. ``fr``). If
|
|
204
|
+
you supply an unsupported language, ``NotImplementedError`` is raised.
|
|
205
|
+
Therefore, if you want to call ``num2words`` with a fallback, you can do::
|
|
206
|
+
|
|
207
|
+
try:
|
|
208
|
+
return num2words(42, lang=mylang)
|
|
209
|
+
except NotImplementedError:
|
|
210
|
+
return num2words(42, lang='en')
|
|
211
|
+
|
|
212
|
+
Additionally, some converters and languages support other optional arguments
|
|
213
|
+
that are needed to make the converter useful in practice.
|
|
214
|
+
|
|
215
|
+
Wiki
|
|
216
|
+
----
|
|
217
|
+
For additional information on some localization please check the Wiki_.
|
|
218
|
+
And feel free to propose wiki enhancement.
|
|
219
|
+
|
|
220
|
+
.. _Wiki: https://github.com/jqueguiner/num2words/wiki
|
|
221
|
+
|
|
222
|
+
History
|
|
223
|
+
-------
|
|
224
|
+
|
|
225
|
+
``num2words`` is based on an old library, ``pynum2word``, created by Taro Ogawa
|
|
226
|
+
in 2003. Unfortunately, the library stopped being maintained and the author
|
|
227
|
+
can't be reached. There was another developer, Marius Grigaitis, who in 2011
|
|
228
|
+
added Lithuanian support, but didn't take over maintenance of the project.
|
|
229
|
+
|
|
230
|
+
Virgil Dupras from Savoir-faire Linux based himself on Marius Grigaitis' improvements
|
|
231
|
+
and re-published ``pynum2word`` as ``num2words``.
|
|
232
|
+
|
|
233
|
+
``num2words2`` Fork
|
|
234
|
+
-------------------
|
|
235
|
+
|
|
236
|
+
``num2words2`` is a modern fork of the original ``num2words`` library, created to address
|
|
237
|
+
the maintenance gap and optimize for modern AI/LLM/speech applications. This fork:
|
|
238
|
+
|
|
239
|
+
* Provides active maintenance aligned with rapidly evolving AI/ML ecosystem
|
|
240
|
+
* Fixes critical bugs affecting machine learning pipelines
|
|
241
|
+
* Adds enhanced language support for global AI applications
|
|
242
|
+
* Maintains backward compatibility with the original library
|
|
243
|
+
|
|
244
|
+
Jean-Louis Queguiner
|