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/currency.py ADDED
@@ -0,0 +1,60 @@
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
19
+
20
+ from decimal import ROUND_HALF_UP, Decimal
21
+
22
+
23
+ def parse_currency_parts(value, is_int_with_cents=True, keep_precision=False):
24
+ if isinstance(value, int):
25
+ if is_int_with_cents:
26
+ # assume cents if value is integer
27
+ negative = value < 0
28
+ value = abs(value)
29
+ integer, cents = divmod(value, 100)
30
+ else:
31
+ negative = value < 0
32
+ integer, cents = abs(value), 0
33
+
34
+ else:
35
+ # Convert to string first to avoid float precision issues
36
+ value = Decimal(str(value))
37
+
38
+ if not keep_precision:
39
+ # Round to 2 decimal places
40
+ value = value.quantize(
41
+ Decimal('.01'),
42
+ rounding=ROUND_HALF_UP
43
+ )
44
+
45
+ negative = value < 0
46
+ value = abs(value)
47
+ integer, fraction = divmod(value, 1)
48
+ integer = int(integer)
49
+
50
+ if keep_precision:
51
+ # Keep full precision for cents
52
+ cents = fraction * 100 # Keep as Decimal
53
+ else:
54
+ cents = int(fraction * 100)
55
+
56
+ return integer, cents, negative
57
+
58
+
59
+ def prefix_currency(prefix, base):
60
+ return tuple("%s %s" % (prefix, i) for i in base)
num2words2/lang_AF.py ADDED
@@ -0,0 +1,202 @@
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
+ from .lang_EUR import Num2Word_EUR
21
+
22
+
23
+ class Num2Word_AF(Num2Word_EUR):
24
+ CURRENCY_FORMS = {
25
+ 'ZAR': (('rand', 'rand'), ('sent', 'sent')),
26
+ 'EUR': (('euro', 'euro'), ('sent', 'sent')),
27
+ 'GBP': (('pond', 'pond'), ('penny', 'pence')),
28
+ 'USD': (('dollar', 'dollar'), ('sent', 'sent')),
29
+ 'CNY': (('yuan', 'yuan'), ('jiao', 'fen')),
30
+ }
31
+
32
+ GIGA_SUFFIX = "iljard"
33
+ MEGA_SUFFIX = "iljoen"
34
+
35
+ def setup(self):
36
+ super(Num2Word_AF, self).setup()
37
+
38
+ self.negword = "minus "
39
+ self.pointword = "komma"
40
+
41
+ # Error messages in Afrikaans
42
+ self.errmsg_floatord = (
43
+ "Kan nie die desimale getal %s as 'n ordinale getal behandel nie."
44
+ )
45
+ self.errmsg_nonnum = (
46
+ "Slegs getalle (tipe(%s)) kan na woorde omgeskakel word."
47
+ )
48
+ self.errmsg_negord = (
49
+ "Kan nie die negatiewe getal %s as 'n ordinale getal behandel nie."
50
+ )
51
+ self.errmsg_toobig = "Die getal %s moet minder as %s wees."
52
+ self.exclude_title = []
53
+
54
+ # High number words for very large numbers
55
+ lows = ["non", "okt", "sept", "sext", "kwint", "kwadr", "tr", "b", "m"]
56
+ units = ["", "un", "duo", "tre", "kwattuor", "kwin", "seks", "sept",
57
+ "okto", "novem"]
58
+ tens = ["des", "vigint", "trigint", "kwadragint", "kwinquagint",
59
+ "seksagint", "septuagint", "oktogint", "nonagint"]
60
+
61
+ self.high_numwords = (
62
+ ["send"] + self.gen_high_numwords(units, tens, lows))
63
+
64
+ # Mid-range numbers (thousands, hundreds, tens)
65
+ self.mid_numwords = [(1000, "duisend"), (100, "honderd"),
66
+ (90, "negentig"), (80, "tagtig"),
67
+ (70, "sewentig"), (60, "sestig"),
68
+ (50, "vyftig"), (40, "veertig"),
69
+ (30, "dertig")]
70
+
71
+ # Low numbers (0-20)
72
+ self.low_numwords = ["twintig", "negentien", "agttien", "sewentien",
73
+ "sestien", "vyftien", "veertien", "dertien",
74
+ "twaalf", "elf", "tien", "nege", "agt", "sewe",
75
+ "ses", "vyf", "vier", "drie", "twee", "een",
76
+ "nul"]
77
+
78
+ # Ordinal mappings
79
+ self.ords = {
80
+ "nul": "nulld",
81
+ "een": "eerst",
82
+ "twee": "tweed",
83
+ "drie": "derd",
84
+ "vier": "vierd",
85
+ "vyf": "vyfd",
86
+ "ses": "sesd",
87
+ "sewe": "sewend",
88
+ "agt": "agst",
89
+ "nege": "negend",
90
+ "tien": "tiend",
91
+ "elf": "elfd",
92
+ "twaalf": "twaalfd",
93
+
94
+ # Compound endings
95
+ "ig": "igst",
96
+ "erd": "erdst",
97
+ "end": "endst",
98
+ "joen": "joenst",
99
+ "rd": "rdst"
100
+ }
101
+
102
+ def merge(self, curr, next):
103
+ ctext, cnum, ntext, nnum = curr + next
104
+
105
+ if cnum == 1:
106
+ if nnum == 100 or nnum == 1000:
107
+ return ("een " + ntext, nnum)
108
+ elif nnum < 10 ** 6:
109
+ return next
110
+ ctext = "een"
111
+
112
+ if nnum > cnum:
113
+ if nnum >= 10 ** 6:
114
+ ctext += " "
115
+ elif nnum == 100 or nnum == 1000:
116
+ ctext += " "
117
+ val = cnum * nnum
118
+ else:
119
+ if nnum < 10 < cnum < 100:
120
+ if nnum == 1:
121
+ ntext = "een"
122
+
123
+ # Afrikaans compound formation: vier-en-dertig
124
+ ntext = ntext + "-en-" + ctext
125
+ ctext = ""
126
+ elif cnum >= 10 ** 6:
127
+ ctext += " "
128
+ elif cnum >= 100:
129
+ ctext += " "
130
+ val = cnum + nnum
131
+
132
+ word = ctext + ntext
133
+ return word, val
134
+
135
+ def to_ordinal(self, value):
136
+ self.verify_ordinal(value)
137
+ outword = self.to_cardinal(value)
138
+
139
+ # Handle special compound ordinals
140
+ for key in self.ords:
141
+ if outword.endswith(key):
142
+ outword = outword[:len(outword) - len(key)] + self.ords[key]
143
+ break
144
+
145
+ return outword + "e"
146
+
147
+ def to_ordinal_num(self, value):
148
+ self.verify_ordinal(value)
149
+ # Afrikaans uses "de" for some ordinal numbers, "ste" for most
150
+ if value in [2, 3, 4, 5, 6, 7, 8]:
151
+ return str(value) + "de"
152
+ else:
153
+ return str(value) + "ste"
154
+
155
+ def pluralize(self, n, forms):
156
+ """
157
+ Afrikaans pluralization rules - most currencies don't change form
158
+ :param n: number
159
+ :param forms: tuple of (singular, plural) forms
160
+ :return: appropriate form
161
+ """
162
+ # Most Afrikaans currencies use the same form for singular and plural
163
+ return forms[0]
164
+
165
+ def to_currency(self, val, currency='ZAR', cents=True, separator=' en',
166
+ adjective=False):
167
+ return super(Num2Word_AF, self).to_currency(
168
+ val, currency=currency, cents=cents, separator=separator,
169
+ adjective=adjective)
170
+
171
+ def to_year(self, val, longval=True):
172
+ # Handle special year cases
173
+ if val >= 2000:
174
+ if val == 2000:
175
+ return self.to_cardinal(val)
176
+ elif val < 2010:
177
+ # 2001-2009: "twee duisend een", etc.
178
+ return self.to_cardinal(2000) + " " + self.to_cardinal(val - 2000)
179
+
180
+ else:
181
+ # 2010+: "twintig tien", "twintig elf", etc.
182
+ century = val // 100
183
+ year_part = val % 100
184
+ if year_part == 0:
185
+ return self.to_cardinal(century) + " honderd"
186
+ else:
187
+ return self.to_cardinal(century) + " " + self.to_cardinal(year_part)
188
+ else:
189
+ # Pre-2000 years: "negentien nege-en-negentig" not "negentien honderd nege-en-negentig"
190
+
191
+ if val < 1000:
192
+ return self.to_cardinal(val)
193
+ elif not (val // 100) % 10:
194
+ return self.to_cardinal(val)
195
+ else:
196
+ # Split as century + year
197
+ century = val // 100
198
+ year_part = val % 100
199
+ if year_part == 0:
200
+ return self.to_cardinal(century) + " honderd"
201
+ else:
202
+ return self.to_cardinal(century) + " " + self.to_cardinal(year_part)
num2words2/lang_AM.py ADDED
@@ -0,0 +1,193 @@
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 . import lang_EUR
21
+
22
+
23
+ class Num2Word_AM(lang_EUR.Num2Word_EUR):
24
+ CURRENCY_FORMS = {'ETB': (('ብር', 'ብር'), ('ሳንቲም', 'ሳንቲም'), ' ከ'),
25
+ 'USD': (('ዶላር', 'ዶላር'), ('ሳንቲም', 'ሳንቲም'), ' ከ'),
26
+ 'JPY': (('የን', 'የን'), ('ሴን', 'ሴን'), ' ከ')}
27
+
28
+ GIGA_SUFFIX = 'ቢሊዮን'
29
+ MEGA_SUFFIX = 'ሚሊዮን'
30
+
31
+ def set_high_numwords(self, high):
32
+ cap = 3 * (len(high) + 1)
33
+
34
+ for word, n in zip(high, range(cap, 5, -3)):
35
+ if n == 9:
36
+ self.cards[10 ** n] = word + self.GIGA_SUFFIX
37
+ else:
38
+ self.cards[10 ** n] = word + self.MEGA_SUFFIX
39
+
40
+ def setup(self):
41
+ super(Num2Word_AM, self).setup()
42
+
43
+ self.negword = 'ሰልቢ '
44
+ self.pointword = 'ነጥብ'
45
+ self.exclude_title = ['እና', 'ነጥብ', 'አሉታዊ']
46
+
47
+ self.mid_numwords = [(1000, 'ሺህ'), (100, 'መቶ'), (90, 'ዘጠና'),
48
+ (80, 'ሰማንያ'), (70, 'ሰባ'), (60, 'ስድሳ'),
49
+ (50, 'አምሳ'), (40, 'አርባ'), (30, 'ሠላሳ')]
50
+ self.low_numwords = ['ሃያ', 'አሥራ ዘጠኝ', 'አሥራ ስምንት', 'አሥራ ሰባት',
51
+ 'አስራ ስድስት', 'አሥራ አምስት', 'አሥራ አራት', 'አሥራ ሦስት',
52
+ 'አሥራ ሁለት', 'አሥራ አንድ', 'አሥር', 'ዘጠኝ', 'ስምንት',
53
+ 'ሰባት', 'ስድስት', 'አምስት', 'አራት', 'ሦስት', 'ሁለት',
54
+ 'አንድ', 'ዜሮ']
55
+ self.ords = {'አንድ': 'አንደኛ',
56
+ 'ሁለት': 'ሁለተኛ',
57
+ 'ሦስት': 'ሦስተኛ',
58
+ 'አራት': 'አራተኛ',
59
+ 'አምስት': 'አምስተኛ',
60
+ 'ስድስት': 'ስድስተኛ',
61
+ 'ሰባት': 'ሰባተኛ',
62
+ 'ስምንት': 'ስምንተኛ',
63
+ 'ዘጠኝ': 'ዘጠነኛ',
64
+ 'አሥር': 'አሥረኛ',
65
+ 'አሥራ አንድ': 'አሥራ አንደኛ',
66
+ 'አሥራ ሁለት': 'አሥራ ሁለተኛ',
67
+ 'አሥራ ሦስት': 'አሥራ ሦስተኛ',
68
+ 'አሥራ አራት': 'አሥራ አራተኛ',
69
+ 'አሥራ አምስት': 'አሥራ አምስተኛ',
70
+ 'አሥራ ስድስት': 'አሥራ ስድስተኛ',
71
+ 'አሥራ ሰባት': 'አሥራ ሰባተኛ',
72
+ 'አሥራ ስምንት': 'አሥራ ስምንተኛ',
73
+ 'አሥራ ዘጠኝ': 'አሥራ ዘጠነኛ'}
74
+
75
+ def to_cardinal(self, value):
76
+ try:
77
+ assert int(value) == value
78
+ except (ValueError, TypeError, AssertionError):
79
+ return self.to_cardinal_float(value)
80
+
81
+ # Handle negative integers
82
+ if value < 0:
83
+ return self.negword + self.to_cardinal(-value)
84
+
85
+ out = ''
86
+ if value >= self.MAXVAL:
87
+ raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL))
88
+
89
+ if value == 100:
90
+ return self.title(out + 'መቶ')
91
+ else:
92
+ val = self.splitnum(value)
93
+ words, num = self.clean(val)
94
+ return self.title(out + words)
95
+
96
+ def merge(self, lpair, rpair):
97
+ ltext, lnum = lpair
98
+ rtext, rnum = rpair
99
+ if lnum == 1 and rnum < 100:
100
+ return rtext, rnum
101
+ elif 100 > lnum > rnum:
102
+ return '%s %s' % (ltext, rtext), lnum + rnum
103
+ elif lnum >= 100 > rnum:
104
+ return '%s %s' % (ltext, rtext), lnum + rnum
105
+ elif rnum > lnum:
106
+ return '%s %s' % (ltext, rtext), lnum * rnum
107
+ else:
108
+ # Default case: lnum > rnum, both could be >= 100
109
+ return '%s %s' % (ltext, rtext), lnum + rnum
110
+
111
+ def to_ordinal(self, value):
112
+ self.verify_ordinal(value)
113
+ outwords = self.to_cardinal(value).split(' ')
114
+ lastwords = outwords[-1].split('-')
115
+ lastword = lastwords[-1].lower()
116
+ try:
117
+ lastword = self.ords[lastword]
118
+ except KeyError:
119
+ lastword += 'ኛ'
120
+ lastwords[-1] = self.title(lastword)
121
+ outwords[-1] = ' '.join(lastwords)
122
+ return ' '.join(outwords)
123
+
124
+ def to_ordinal_num(self, value):
125
+ self.verify_ordinal(value)
126
+ return '%s%s' % (value, self.to_ordinal(value)[-1:])
127
+
128
+ def to_currency(self, val, currency='ETB', cents=True, separator=',',
129
+ adjective=False):
130
+ # Track if input was originally an integer
131
+ is_integer_input = isinstance(val, int)
132
+
133
+ if is_integer_input:
134
+ left = abs(val)
135
+ right = 0
136
+ is_negative = val < 0
137
+ else:
138
+ from decimal import Decimal
139
+
140
+ from .currency import parse_currency_parts
141
+
142
+ # Check if value has fractional cents
143
+ decimal_val = Decimal(str(val))
144
+ has_fractional_cents = (decimal_val * 100) % 1 != 0
145
+
146
+ left, right, is_negative = parse_currency_parts(val, is_int_with_cents=False,
147
+ keep_precision=has_fractional_cents)
148
+
149
+ try:
150
+ cr1, cr2, default_separator = self.CURRENCY_FORMS[currency]
151
+ if separator == ',': # Use default separator if not overridden
152
+ separator = default_separator
153
+ except KeyError:
154
+ raise NotImplementedError(
155
+ 'Currency code "%s" not implemented for "%s"' %
156
+ (currency, self.__class__.__name__))
157
+
158
+ minus_str = "%s " % self.negword.strip() if is_negative else ""
159
+ money_str = self.to_cardinal(left)
160
+
161
+ # For floats, always show cents (even if zero)
162
+ # For integers, don't show cents at all
163
+ if not is_integer_input:
164
+ if cents:
165
+ # Handle fractional cents
166
+ from decimal import Decimal
167
+ if isinstance(right, Decimal):
168
+ # Convert fractional cents (e.g., 65.3 cents)
169
+ cents_str = self.to_cardinal_float(float(right)) if right > 0 else 'ዜሮ'
170
+ else:
171
+ cents_str = self.to_cardinal(right) if right > 0 else 'ዜሮ'
172
+ else:
173
+ cents_str = str(float(right) if isinstance(right, Decimal) else right)
174
+ return u'%s%s %s%s %s %s' % (
175
+ minus_str,
176
+ money_str,
177
+ self.pluralize(left, cr1),
178
+ separator,
179
+ cents_str,
180
+ self.pluralize(right, cr2)
181
+ )
182
+ else:
183
+ # Integer: no cents
184
+ return u'%s%s %s' % (
185
+ minus_str,
186
+ money_str,
187
+ self.pluralize(left, cr1)
188
+ )
189
+
190
+ def to_year(self, val, longval=True):
191
+ if not (val // 100) % 10:
192
+ return self.to_cardinal(val)
193
+ return self.to_splitnum(val, hightxt='መቶ', longval=longval)