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.
Files changed (133) hide show
  1. num2words2/README.md +69 -0
  2. num2words2/__init__.py +196 -0
  3. num2words2/_version.py +3 -0
  4. num2words2/base.py +377 -0
  5. num2words2/compat.py +29 -0
  6. num2words2/currency.py +60 -0
  7. num2words2/lang_AF.py +202 -0
  8. num2words2/lang_AM.py +193 -0
  9. num2words2/lang_AR.py +435 -0
  10. num2words2/lang_AS.py +119 -0
  11. num2words2/lang_AZ.py +208 -0
  12. num2words2/lang_BA.py +119 -0
  13. num2words2/lang_BE.py +356 -0
  14. num2words2/lang_BG.py +393 -0
  15. num2words2/lang_BN.py +242 -0
  16. num2words2/lang_BO.py +122 -0
  17. num2words2/lang_BR.py +135 -0
  18. num2words2/lang_BS.py +189 -0
  19. num2words2/lang_CA.py +476 -0
  20. num2words2/lang_CE.py +546 -0
  21. num2words2/lang_CS.py +260 -0
  22. num2words2/lang_CY.py +574 -0
  23. num2words2/lang_DA.py +170 -0
  24. num2words2/lang_DE.py +180 -0
  25. num2words2/lang_EL.py +338 -0
  26. num2words2/lang_EN.py +118 -0
  27. num2words2/lang_EN_IN.py +26 -0
  28. num2words2/lang_EN_NG.py +45 -0
  29. num2words2/lang_EO.py +130 -0
  30. num2words2/lang_ES.py +399 -0
  31. num2words2/lang_ES_CO.py +37 -0
  32. num2words2/lang_ES_CR.py +38 -0
  33. num2words2/lang_ES_GT.py +37 -0
  34. num2words2/lang_ES_NI.py +35 -0
  35. num2words2/lang_ES_VE.py +43 -0
  36. num2words2/lang_ET.py +393 -0
  37. num2words2/lang_EU.py +158 -0
  38. num2words2/lang_EUR.py +104 -0
  39. num2words2/lang_FA.py +187 -0
  40. num2words2/lang_FI.py +759 -0
  41. num2words2/lang_FO.py +136 -0
  42. num2words2/lang_FR.py +133 -0
  43. num2words2/lang_FR_BE.py +49 -0
  44. num2words2/lang_FR_CH.py +48 -0
  45. num2words2/lang_FR_DZ.py +35 -0
  46. num2words2/lang_GL.py +135 -0
  47. num2words2/lang_GU.py +172 -0
  48. num2words2/lang_HA.py +293 -0
  49. num2words2/lang_HAW.py +144 -0
  50. num2words2/lang_HE.py +314 -0
  51. num2words2/lang_HI.py +243 -0
  52. num2words2/lang_HR.py +304 -0
  53. num2words2/lang_HT.py +136 -0
  54. num2words2/lang_HU.py +189 -0
  55. num2words2/lang_HY.py +364 -0
  56. num2words2/lang_ID.py +242 -0
  57. num2words2/lang_IS.py +208 -0
  58. num2words2/lang_IT.py +265 -0
  59. num2words2/lang_JA.py +615 -0
  60. num2words2/lang_JW.py +136 -0
  61. num2words2/lang_KA.py +169 -0
  62. num2words2/lang_KK.py +136 -0
  63. num2words2/lang_KM.py +173 -0
  64. num2words2/lang_KN.py +182 -0
  65. num2words2/lang_KO.py +175 -0
  66. num2words2/lang_KZ.py +161 -0
  67. num2words2/lang_LA.py +135 -0
  68. num2words2/lang_LB.py +135 -0
  69. num2words2/lang_LN.py +136 -0
  70. num2words2/lang_LO.py +149 -0
  71. num2words2/lang_LT.py +283 -0
  72. num2words2/lang_LV.py +266 -0
  73. num2words2/lang_MG.py +143 -0
  74. num2words2/lang_MI.py +151 -0
  75. num2words2/lang_MK.py +136 -0
  76. num2words2/lang_ML.py +159 -0
  77. num2words2/lang_MN.py +319 -0
  78. num2words2/lang_MR.py +187 -0
  79. num2words2/lang_MS.py +293 -0
  80. num2words2/lang_MT.py +159 -0
  81. num2words2/lang_MY.py +152 -0
  82. num2words2/lang_NE.py +157 -0
  83. num2words2/lang_NL.py +204 -0
  84. num2words2/lang_NN.py +136 -0
  85. num2words2/lang_NO.py +143 -0
  86. num2words2/lang_OC.py +135 -0
  87. num2words2/lang_PA.py +159 -0
  88. num2words2/lang_PL.py +336 -0
  89. num2words2/lang_PS.py +136 -0
  90. num2words2/lang_PT.py +280 -0
  91. num2words2/lang_PT_BR.py +224 -0
  92. num2words2/lang_RO.py +183 -0
  93. num2words2/lang_RU.py +570 -0
  94. num2words2/lang_SA.py +136 -0
  95. num2words2/lang_SD.py +136 -0
  96. num2words2/lang_SI.py +152 -0
  97. num2words2/lang_SK.py +250 -0
  98. num2words2/lang_SL.py +306 -0
  99. num2words2/lang_SN.py +447 -0
  100. num2words2/lang_SO.py +136 -0
  101. num2words2/lang_SQ.py +252 -0
  102. num2words2/lang_SR.py +254 -0
  103. num2words2/lang_SU.py +136 -0
  104. num2words2/lang_SV.py +169 -0
  105. num2words2/lang_SW.py +219 -0
  106. num2words2/lang_TA.py +303 -0
  107. num2words2/lang_TE.py +169 -0
  108. num2words2/lang_TET.py +285 -0
  109. num2words2/lang_TG.py +149 -0
  110. num2words2/lang_TH.py +214 -0
  111. num2words2/lang_TK.py +136 -0
  112. num2words2/lang_TL.py +145 -0
  113. num2words2/lang_TR.py +882 -0
  114. num2words2/lang_TT.py +136 -0
  115. num2words2/lang_UK.py +1101 -0
  116. num2words2/lang_UR.py +168 -0
  117. num2words2/lang_UZ.py +136 -0
  118. num2words2/lang_VI.py +143 -0
  119. num2words2/lang_WO.py +136 -0
  120. num2words2/lang_YI.py +135 -0
  121. num2words2/lang_YO.py +136 -0
  122. num2words2/lang_ZH.py +296 -0
  123. num2words2/lang_ZH_CN.py +85 -0
  124. num2words2/lang_ZH_HK.py +48 -0
  125. num2words2/lang_ZH_TW.py +198 -0
  126. num2words2/utils.py +35 -0
  127. num2words2-0.1.0.dev1.data/scripts/num2words2 +98 -0
  128. num2words2-0.1.0.dev1.dist-info/METADATA +244 -0
  129. num2words2-0.1.0.dev1.dist-info/RECORD +133 -0
  130. num2words2-0.1.0.dev1.dist-info/WHEEL +5 -0
  131. num2words2-0.1.0.dev1.dist-info/entry_points.txt +2 -0
  132. num2words2-0.1.0.dev1.dist-info/licenses/COPYING +145 -0
  133. 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()