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_BO.py
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
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
|
+
# Tibetan language support
|
|
24
|
+
class Num2Word_BO(Num2Word_Base):
|
|
25
|
+
CURRENCY_FORMS = {
|
|
26
|
+
'CNY': (('སྒོར་', 'སྒོར་'), ('ཕན་', 'ཕན་')),
|
|
27
|
+
'USD': (('ཌོ་ལར་', 'ཌོ་ལར་'), ('སེན་', 'སེན་')),
|
|
28
|
+
'EUR': (('ཡུ་རོ་', 'ཡུ་རོ་'), ('སེན་', 'སེན་')),
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
def setup(self):
|
|
32
|
+
self.negword = "མེད་ཆ་ "
|
|
33
|
+
self.pointword = "ཚེག་"
|
|
34
|
+
|
|
35
|
+
def to_cardinal(self, number):
|
|
36
|
+
"""Convert a number to its word representation in Tibetan."""
|
|
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 Tibetan."""
|
|
55
|
+
if number == 0:
|
|
56
|
+
return "ཀླད་ཀོར་"
|
|
57
|
+
|
|
58
|
+
ones = ["", "གཅིག་", "གཉིས་", "གསུམ་", "བཞི་", "ལྔ་", "དྲུག་", "བདུན་", "བརྒྱད་", "དགུ་"]
|
|
59
|
+
tens = ["", "བཅུ་", "ཉི་ཤུ་", "སུམ་ཅུ་", "བཞི་བཅུ་", "ལྔ་བཅུ་", "དྲུག་ཅུ་", "བདུན་ཅུ་", "བརྒྱད་ཅུ་", "དགུ་བཅུ་"]
|
|
60
|
+
|
|
61
|
+
if number < 10:
|
|
62
|
+
return ones[number]
|
|
63
|
+
elif number < 100:
|
|
64
|
+
return tens[number // 10] + (ones[number % 10] if number % 10 else "")
|
|
65
|
+
elif number < 1000:
|
|
66
|
+
return ones[number // 100] + "བརྒྱ་" + (self._int_to_word(number % 100) if number % 100 else "")
|
|
67
|
+
elif number < 10000:
|
|
68
|
+
return self._int_to_word(number // 1000) + "སྟོང་" + (self._int_to_word(number % 1000) if number % 1000 else "")
|
|
69
|
+
elif number < 100000:
|
|
70
|
+
return self._int_to_word(number // 10000) + "ཁྲི་" + (self._int_to_word(number % 10000) if number % 10000 else "")
|
|
71
|
+
elif number < 1000000:
|
|
72
|
+
return self._int_to_word(number // 100000) + "འབུམ་" + (self._int_to_word(number % 100000) if number % 100000 else "")
|
|
73
|
+
elif number < 10000000:
|
|
74
|
+
return self._int_to_word(number // 1000000) + "ས་ཡ་" + (self._int_to_word(number % 1000000) if number % 1000000 else "")
|
|
75
|
+
elif number < 100000000:
|
|
76
|
+
return self._int_to_word(number // 10000000) + "བྱེ་བ་" + (self._int_to_word(number % 10000000) if number % 10000000 else "")
|
|
77
|
+
else:
|
|
78
|
+
return self._int_to_word(number // 100000000) + "དུང་ཕྱུར་" + (self._int_to_word(number % 100000000) if number % 100000000 else "")
|
|
79
|
+
|
|
80
|
+
def to_ordinal(self, number):
|
|
81
|
+
"""Convert to ordinal."""
|
|
82
|
+
cardinal = self.to_cardinal(number)
|
|
83
|
+
return cardinal + "པ་"
|
|
84
|
+
|
|
85
|
+
def to_ordinal_num(self, number):
|
|
86
|
+
"""Convert to abbreviated ordinal."""
|
|
87
|
+
return str(number) + "པ"
|
|
88
|
+
|
|
89
|
+
def to_year(self, val, longval=True):
|
|
90
|
+
"""Convert to year."""
|
|
91
|
+
return "སྤྱི་ལོ་" + self.to_cardinal(val)
|
|
92
|
+
|
|
93
|
+
def to_currency(self, val, currency='CNY', cents=True, separator=' དང་ ', adjective=False):
|
|
94
|
+
"""Convert to currency."""
|
|
95
|
+
try:
|
|
96
|
+
left, right, is_negative = self.parse_currency(val)
|
|
97
|
+
except AttributeError:
|
|
98
|
+
is_negative = False
|
|
99
|
+
if val < 0:
|
|
100
|
+
is_negative = True
|
|
101
|
+
val = abs(val)
|
|
102
|
+
|
|
103
|
+
left, right = self._split_currency(val)
|
|
104
|
+
|
|
105
|
+
cr1, cr2 = self.CURRENCY_FORMS.get(currency, self.CURRENCY_FORMS['CNY'])
|
|
106
|
+
|
|
107
|
+
left_str = self._int_to_word(int(left))
|
|
108
|
+
cents_str = self._int_to_word(int(right)) if cents and right else ""
|
|
109
|
+
|
|
110
|
+
result = left_str + " " + cr1[0]
|
|
111
|
+
|
|
112
|
+
if cents_str:
|
|
113
|
+
result += separator + cents_str + " " + cr2[0]
|
|
114
|
+
|
|
115
|
+
return self.negword + result if is_negative else result
|
|
116
|
+
|
|
117
|
+
def _split_currency(self, n):
|
|
118
|
+
"""Split currency into whole and fraction parts."""
|
|
119
|
+
parts = str(n).split('.')
|
|
120
|
+
left = int(parts[0]) if parts[0] else 0
|
|
121
|
+
right = int(parts[1][:2].ljust(2, '0')) if len(parts) > 1 and parts[1] else 0
|
|
122
|
+
return left, right
|
num2words2/lang_BR.py
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
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
|
+
# Breton language support
|
|
24
|
+
class Num2Word_BR(Num2Word_Base):
|
|
25
|
+
CURRENCY_FORMS = {
|
|
26
|
+
'EUR': (('euro', 'euroioù'), ('sentim', 'sentimoù')),
|
|
27
|
+
'USD': (('dollar', 'dollars'), ('cent', 'cents'))
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
def setup(self):
|
|
31
|
+
self.negword = "minus "
|
|
32
|
+
self.pointword = "point"
|
|
33
|
+
self.ones = ['', 'unan', 'daou', 'tri', 'pevar', 'pemp', "c'hwec'h", 'seizh', 'eizh', 'nav']
|
|
34
|
+
self.tens = ['', 'dek', 'ugent', 'tregont', 'daou-ugent', 'hanter-kant', 'tri-ugent', 'dek ha tri-ugent', 'pevar-ugent', 'dek ha pevar-ugent']
|
|
35
|
+
self.hundred = "kant"
|
|
36
|
+
self.thousand = "mil"
|
|
37
|
+
self.million = "milion"
|
|
38
|
+
|
|
39
|
+
def to_cardinal(self, number):
|
|
40
|
+
"""Convert a number to its word representation in Breton."""
|
|
41
|
+
n = str(number).strip()
|
|
42
|
+
|
|
43
|
+
if n.startswith('-'):
|
|
44
|
+
n = n[1:]
|
|
45
|
+
ret = self.negword
|
|
46
|
+
else:
|
|
47
|
+
ret = ""
|
|
48
|
+
|
|
49
|
+
if '.' in n:
|
|
50
|
+
left, right = n.split('.', 1)
|
|
51
|
+
ret += self._int_to_word(int(left)) + " " + self.pointword + " "
|
|
52
|
+
for digit in right:
|
|
53
|
+
ret += self._int_to_word(int(digit)) + " "
|
|
54
|
+
return ret.strip()
|
|
55
|
+
else:
|
|
56
|
+
return (ret + self._int_to_word(int(n))).strip()
|
|
57
|
+
|
|
58
|
+
def _int_to_word(self, number):
|
|
59
|
+
"""Convert an integer to its word representation in Breton."""
|
|
60
|
+
if number == 0:
|
|
61
|
+
return self.ones[0] if self.ones[0] else "zero"
|
|
62
|
+
|
|
63
|
+
if number < 0:
|
|
64
|
+
return self.negword + self._int_to_word(abs(number))
|
|
65
|
+
elif number < 10:
|
|
66
|
+
return self.ones[number]
|
|
67
|
+
elif number < 100:
|
|
68
|
+
tens_val = number // 10
|
|
69
|
+
ones_val = number % 10
|
|
70
|
+
if ones_val == 0:
|
|
71
|
+
return self.tens[tens_val]
|
|
72
|
+
else:
|
|
73
|
+
return self.tens[tens_val] + " " + self.ones[ones_val]
|
|
74
|
+
elif number < 1000:
|
|
75
|
+
hundreds_val = number // 100
|
|
76
|
+
remainder = number % 100
|
|
77
|
+
result = self.ones[hundreds_val] + " " + self.hundred
|
|
78
|
+
if remainder:
|
|
79
|
+
result += " " + self._int_to_word(remainder)
|
|
80
|
+
return result
|
|
81
|
+
elif number < 1000000:
|
|
82
|
+
thousands_val = number // 1000
|
|
83
|
+
remainder = number % 1000
|
|
84
|
+
result = self._int_to_word(thousands_val) + " " + self.thousand
|
|
85
|
+
if remainder:
|
|
86
|
+
result += " " + self._int_to_word(remainder)
|
|
87
|
+
return result
|
|
88
|
+
elif number < 1000000000:
|
|
89
|
+
millions_val = number // 1000000
|
|
90
|
+
remainder = number % 1000000
|
|
91
|
+
result = self._int_to_word(millions_val) + " " + self.million
|
|
92
|
+
if remainder:
|
|
93
|
+
result += " " + self._int_to_word(remainder)
|
|
94
|
+
return result
|
|
95
|
+
else:
|
|
96
|
+
return str(number) # Fallback for very large numbers
|
|
97
|
+
|
|
98
|
+
def to_ordinal(self, number):
|
|
99
|
+
"""Convert to ordinal in Breton."""
|
|
100
|
+
cardinal = self.to_cardinal(number)
|
|
101
|
+
# Language-specific ordinal suffix
|
|
102
|
+
return cardinal + "-vet"
|
|
103
|
+
|
|
104
|
+
def to_ordinal_num(self, number):
|
|
105
|
+
"""Convert to abbreviated ordinal."""
|
|
106
|
+
return str(number) + "."
|
|
107
|
+
|
|
108
|
+
def to_year(self, val, longval=True):
|
|
109
|
+
"""Convert to year in Breton."""
|
|
110
|
+
return self.to_cardinal(val)
|
|
111
|
+
|
|
112
|
+
def to_currency(self, val, currency='EUR', cents=True, separator=' ', adjective=False):
|
|
113
|
+
"""Convert to currency in Breton."""
|
|
114
|
+
is_negative = False
|
|
115
|
+
if val < 0:
|
|
116
|
+
is_negative = True
|
|
117
|
+
val = abs(val)
|
|
118
|
+
|
|
119
|
+
parts = str(val).split('.')
|
|
120
|
+
left = int(parts[0]) if parts[0] else 0
|
|
121
|
+
right = int(parts[1][:2].ljust(2, '0')) if len(parts) > 1 and parts[1] else 0
|
|
122
|
+
|
|
123
|
+
cr1, cr2 = self.CURRENCY_FORMS.get(currency, list(self.CURRENCY_FORMS.values())[0])
|
|
124
|
+
|
|
125
|
+
left_str = self._int_to_word(left)
|
|
126
|
+
result = left_str + " " + (cr1[1] if left != 1 else cr1[0])
|
|
127
|
+
|
|
128
|
+
if cents and right:
|
|
129
|
+
cents_str = self._int_to_word(right)
|
|
130
|
+
result += separator + cents_str + " " + (cr2[1] if right != 1 else cr2[0])
|
|
131
|
+
|
|
132
|
+
if is_negative:
|
|
133
|
+
result = self.negword + result
|
|
134
|
+
|
|
135
|
+
return result.strip()
|
num2words2/lang_BS.py
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
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
|
+
# Bosnian language support (Latin script)
|
|
24
|
+
class Num2Word_BS(Num2Word_Base):
|
|
25
|
+
CURRENCY_FORMS = {
|
|
26
|
+
'BAM': (('marka', 'marke', 'maraka'), ('feninga', 'feninga', 'feninga')),
|
|
27
|
+
'EUR': (('euro', 'eura', 'eura'), ('cent', 'centa', 'centi')),
|
|
28
|
+
'USD': (('dolar', 'dolara', 'dolara'), ('cent', 'centa', 'centi')),
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
def setup(self):
|
|
32
|
+
self.negword = "minus "
|
|
33
|
+
self.pointword = "zarez"
|
|
34
|
+
|
|
35
|
+
# Bosnian numbers in Latin script
|
|
36
|
+
self.ones = [
|
|
37
|
+
'', 'jedan', 'dva', 'tri', 'četiri',
|
|
38
|
+
'pet', 'šest', 'sedam', 'osam', 'devet'
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
self.tens = [
|
|
42
|
+
'', 'deset', 'dvadeset', 'trideset', 'četrdeset',
|
|
43
|
+
'pedeset', 'šezdeset', 'sedamdeset', 'osamdeset', 'devedeset'
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
self.scale = {
|
|
47
|
+
100: ('sto', 'stotine', 'stotina'),
|
|
48
|
+
1000: ('hiljada', 'hiljade', 'hiljada'),
|
|
49
|
+
1000000: ('milion', 'miliona', 'miliona'),
|
|
50
|
+
1000000000: ('milijarda', 'milijarde', 'milijardi'),
|
|
51
|
+
1000000000000: ('bilion', 'biliona', 'biliona'),
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
def to_cardinal(self, number):
|
|
55
|
+
"""Convert a number to its word representation in Bosnian."""
|
|
56
|
+
n = str(number).strip()
|
|
57
|
+
|
|
58
|
+
if n.startswith('-'):
|
|
59
|
+
n = n[1:]
|
|
60
|
+
ret = self.negword
|
|
61
|
+
else:
|
|
62
|
+
ret = ""
|
|
63
|
+
|
|
64
|
+
if '.' in n:
|
|
65
|
+
left, right = n.split('.', 1)
|
|
66
|
+
ret += self._int_to_word(int(left)) + " " + self.pointword + " "
|
|
67
|
+
for digit in right:
|
|
68
|
+
ret += self._int_to_word(int(digit)) + " "
|
|
69
|
+
return ret.strip()
|
|
70
|
+
else:
|
|
71
|
+
return (ret + self._int_to_word(int(n))).strip()
|
|
72
|
+
|
|
73
|
+
def _int_to_word(self, number):
|
|
74
|
+
"""Convert an integer to its word representation in Bosnian."""
|
|
75
|
+
if number == 0:
|
|
76
|
+
return "nula"
|
|
77
|
+
|
|
78
|
+
if number < 0:
|
|
79
|
+
return self.negword + self._int_to_word(abs(number))
|
|
80
|
+
elif number < 10:
|
|
81
|
+
return self.ones[number]
|
|
82
|
+
elif number == 10:
|
|
83
|
+
return self.tens[1]
|
|
84
|
+
elif number < 20:
|
|
85
|
+
return self.ones[number - 10] + "aest"
|
|
86
|
+
elif number < 100:
|
|
87
|
+
tens_val = number // 10
|
|
88
|
+
ones_val = number % 10
|
|
89
|
+
if ones_val == 0:
|
|
90
|
+
return self.tens[tens_val]
|
|
91
|
+
else:
|
|
92
|
+
return self.tens[tens_val] + " " + self.ones[ones_val]
|
|
93
|
+
elif number < 1000:
|
|
94
|
+
hundreds_val = number // 100
|
|
95
|
+
remainder = number % 100
|
|
96
|
+
if hundreds_val == 1:
|
|
97
|
+
result = "sto"
|
|
98
|
+
elif hundreds_val == 2:
|
|
99
|
+
result = "dvjesto"
|
|
100
|
+
elif hundreds_val == 3 or hundreds_val == 4:
|
|
101
|
+
result = self.ones[hundreds_val] + "sto"
|
|
102
|
+
else:
|
|
103
|
+
result = self.ones[hundreds_val] + "sto"
|
|
104
|
+
if remainder:
|
|
105
|
+
result += " " + self._int_to_word(remainder)
|
|
106
|
+
return result
|
|
107
|
+
elif number < 1000000:
|
|
108
|
+
thousands_val = number // 1000
|
|
109
|
+
remainder = number % 1000
|
|
110
|
+
if thousands_val == 1:
|
|
111
|
+
result = "hiljada"
|
|
112
|
+
elif thousands_val < 5:
|
|
113
|
+
result = self._int_to_word(thousands_val) + " hiljade"
|
|
114
|
+
else:
|
|
115
|
+
result = self._int_to_word(thousands_val) + " hiljada"
|
|
116
|
+
if remainder:
|
|
117
|
+
result += " " + self._int_to_word(remainder)
|
|
118
|
+
return result
|
|
119
|
+
elif number < 1000000000:
|
|
120
|
+
millions_val = number // 1000000
|
|
121
|
+
remainder = number % 1000000
|
|
122
|
+
if millions_val == 1:
|
|
123
|
+
result = "milion"
|
|
124
|
+
else:
|
|
125
|
+
result = self._int_to_word(millions_val) + " miliona"
|
|
126
|
+
if remainder:
|
|
127
|
+
result += " " + self._int_to_word(remainder)
|
|
128
|
+
return result
|
|
129
|
+
else:
|
|
130
|
+
return str(number) # Fallback for very large numbers
|
|
131
|
+
|
|
132
|
+
def to_ordinal(self, number):
|
|
133
|
+
"""Convert to ordinal in Bosnian."""
|
|
134
|
+
# Basic implementation with ordinal suffix
|
|
135
|
+
if number == 1:
|
|
136
|
+
return "prvi"
|
|
137
|
+
elif number == 2:
|
|
138
|
+
return "drugi"
|
|
139
|
+
elif number == 3:
|
|
140
|
+
return "treći"
|
|
141
|
+
else:
|
|
142
|
+
return self.to_cardinal(number) + "."
|
|
143
|
+
|
|
144
|
+
def to_ordinal_num(self, number):
|
|
145
|
+
"""Convert to abbreviated ordinal."""
|
|
146
|
+
return str(number) + "."
|
|
147
|
+
|
|
148
|
+
def to_year(self, val, longval=True):
|
|
149
|
+
"""Convert to year in Bosnian."""
|
|
150
|
+
return self.to_cardinal(val)
|
|
151
|
+
|
|
152
|
+
def to_currency(self, val, currency='BAM', cents=True, separator=' ', adjective=False):
|
|
153
|
+
"""Convert to currency in Bosnian."""
|
|
154
|
+
is_negative = False
|
|
155
|
+
if val < 0:
|
|
156
|
+
is_negative = True
|
|
157
|
+
val = abs(val)
|
|
158
|
+
|
|
159
|
+
parts = str(val).split('.')
|
|
160
|
+
left = int(parts[0]) if parts[0] else 0
|
|
161
|
+
right = int(parts[1][:2].ljust(2, '0')) if len(parts) > 1 and parts[1] else 0
|
|
162
|
+
|
|
163
|
+
cr1, cr2 = self.CURRENCY_FORMS.get(currency, self.CURRENCY_FORMS['BAM'])
|
|
164
|
+
|
|
165
|
+
left_str = self._int_to_word(left)
|
|
166
|
+
# Select correct form based on number
|
|
167
|
+
if left == 1:
|
|
168
|
+
currency_word = cr1[0]
|
|
169
|
+
elif left % 10 in [2, 3, 4] and left % 100 not in [12, 13, 14]:
|
|
170
|
+
currency_word = cr1[1]
|
|
171
|
+
else:
|
|
172
|
+
currency_word = cr1[2]
|
|
173
|
+
result = left_str + " " + currency_word
|
|
174
|
+
|
|
175
|
+
if cents and right:
|
|
176
|
+
cents_str = self._int_to_word(right)
|
|
177
|
+
# Select correct form for cents
|
|
178
|
+
if right == 1:
|
|
179
|
+
cents_word = cr2[0]
|
|
180
|
+
elif right % 10 in [2, 3, 4] and right % 100 not in [12, 13, 14]:
|
|
181
|
+
cents_word = cr2[1]
|
|
182
|
+
else:
|
|
183
|
+
cents_word = cr2[2]
|
|
184
|
+
result += separator + cents_str + " " + cents_word
|
|
185
|
+
|
|
186
|
+
if is_negative:
|
|
187
|
+
result = self.negword + result
|
|
188
|
+
|
|
189
|
+
return result.strip()
|