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_NE.py ADDED
@@ -0,0 +1,157 @@
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
+ # Nepali language support
24
+ class Num2Word_NE(Num2Word_Base):
25
+ CURRENCY_FORMS = {
26
+ 'NPR': (('रुपैयाँ', 'रुपैयाँ'), ('पैसा', 'पैसा')),
27
+ 'USD': (('dollar', 'dollars'), ('cent', 'cents')),
28
+ 'EUR': (('euro', 'euros'), ('cent', 'cents')),
29
+ }
30
+
31
+ def setup(self):
32
+ self.negword = "ऋण "
33
+ self.pointword = "दशमलव"
34
+ self.ones = ['', 'एक', 'दुई', 'तीन', 'चार', 'पाँच', 'छ', 'सात', 'आठ', 'नौ']
35
+ self.tens = ['', 'दस', 'बीस', 'तीस', 'चालीस', 'पचास', 'साठी', 'सत्तरी', 'असी', 'नब्बे']
36
+ self.teens = ['दस', 'एघार', 'बाह्र', 'तेह्र', 'चौध', 'पन्ध्र', 'सोह्र', 'सत्र', 'अठार', 'उन्नाइस']
37
+ self.hundred = "सय"
38
+ self.thousand = "हजार"
39
+ self.lakh = "लाख"
40
+ self.crore = "करोड"
41
+ self.zero = "शून्य"
42
+
43
+ def to_cardinal(self, number):
44
+ """Convert a number to its word representation in Nepali."""
45
+ n = str(number).strip()
46
+
47
+ if n.startswith('-'):
48
+ n = n[1:]
49
+ ret = self.negword
50
+ else:
51
+ ret = ""
52
+
53
+ if '.' in n:
54
+ left, right = n.split('.', 1)
55
+ ret += self._int_to_word(int(left)) + " " + self.pointword + " "
56
+ ret += " ".join(self._int_to_word(int(d)) for d in right)
57
+ return ret.strip()
58
+ else:
59
+ return (ret + self._int_to_word(int(n))).strip()
60
+
61
+ def _int_to_word(self, number):
62
+ """Convert an integer to its word representation in Nepali."""
63
+ if number == 0:
64
+ return self.zero
65
+
66
+ if number < 0:
67
+ return self.negword + self._int_to_word(abs(number))
68
+ elif number < 10:
69
+ return self.ones[number]
70
+ elif number < 20:
71
+ return self.teens[number - 10]
72
+ elif number < 100:
73
+ result = self.tens[number // 10]
74
+ if number % 10:
75
+ result += " " + self.ones[number % 10]
76
+ return result
77
+ elif number < 1000:
78
+ result = self.ones[number // 100] + " " + self.hundred
79
+ remainder = number % 100
80
+ if remainder:
81
+ result += " " + self._int_to_word(remainder)
82
+ return result
83
+ elif number < 100000: # Lakh
84
+ result = self._int_to_word(number // 1000) + " " + self.thousand
85
+ remainder = number % 1000
86
+ if remainder:
87
+ result += " " + self._int_to_word(remainder)
88
+ return result
89
+ elif number < 10000000: # Crore
90
+ result = self._int_to_word(number // 100000) + " " + self.lakh
91
+ remainder = number % 100000
92
+ if remainder:
93
+ result += " " + self._int_to_word(remainder)
94
+ return result
95
+ elif number < 1000000000:
96
+ result = self._int_to_word(number // 10000000) + " " + self.crore
97
+ remainder = number % 10000000
98
+ if remainder:
99
+ result += " " + self._int_to_word(remainder)
100
+ return result
101
+ else:
102
+ return str(number) # Fallback for very large numbers
103
+
104
+ def to_ordinal(self, number):
105
+ """Convert to ordinal in Nepali.
106
+
107
+ Nepali ordinals use 'औं' suffix for most numbers.
108
+ Special forms exist for first few ordinals.
109
+ """
110
+ if number == 1:
111
+ return "पहिलो" # first
112
+ elif number == 2:
113
+ return "दोस्रो" # second
114
+ elif number == 3:
115
+ return "तेस्रो" # third
116
+ elif number == 4:
117
+ return "चौथो" # fourth
118
+ else:
119
+ # For other numbers, add औं suffix
120
+ cardinal = self.to_cardinal(number)
121
+ return cardinal + "औं"
122
+
123
+ def to_ordinal_num(self, number):
124
+ """Convert to abbreviated ordinal."""
125
+ return str(number) + "."
126
+
127
+ def to_year(self, val, longval=True):
128
+ """Convert to year in Nepali."""
129
+ if val < 0:
130
+ return "BC " + self.to_cardinal(abs(val))
131
+ else:
132
+ return "" + self.to_cardinal(val)
133
+
134
+ def to_currency(self, val, currency='NPR', cents=True, separator=' ', adjective=False):
135
+ """Convert to currency in Nepali."""
136
+ is_negative = False
137
+ if val < 0:
138
+ is_negative = True
139
+ val = abs(val)
140
+
141
+ parts = str(val).split('.')
142
+ left = int(parts[0]) if parts[0] else 0
143
+ right = int(parts[1][:2].ljust(2, '0')) if len(parts) > 1 and parts[1] else 0
144
+
145
+ cr1, cr2 = self.CURRENCY_FORMS.get(currency, self.CURRENCY_FORMS['NPR'])
146
+
147
+ left_str = self._int_to_word(left)
148
+ result = left_str + " " + (cr1[1] if left != 1 else cr1[0])
149
+
150
+ if cents and right:
151
+ cents_str = self._int_to_word(right)
152
+ result += separator + cents_str + " " + (cr2[1] if right != 1 else cr2[0])
153
+
154
+ if is_negative:
155
+ result = self.negword + result
156
+
157
+ return result.strip()
num2words2/lang_NL.py ADDED
@@ -0,0 +1,204 @@
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_NL(Num2Word_EUR):
24
+ CURRENCY_FORMS = {
25
+ 'EUR': (('euro', 'euro'), ('cent', 'cent')),
26
+ 'GBP': (('pond', 'pond'), ('penny', 'pence')),
27
+ 'USD': (('dollar', 'dollar'), ('cent', 'cent')),
28
+ 'CNY': (('yuan', 'yuan'), ('jiao', 'fen')),
29
+ }
30
+
31
+ GIGA_SUFFIX = "iljard"
32
+ MEGA_SUFFIX = "iljoen"
33
+
34
+ def setup(self):
35
+ super(Num2Word_NL, self).setup()
36
+
37
+ self.negword = "min "
38
+ self.pointword = "komma"
39
+ # "Cannot treat float %s as ordinal."
40
+ self.errmsg_floatord = (
41
+ "Het zwevende puntnummer %s kan niet omgezet worden " +
42
+ "naar een ordernummer."
43
+ )
44
+ # "type(((type(%s)) ) not in [long, int, float]"
45
+ self.errmsg_nonnum = (
46
+ "Alleen nummers (type (%s)) kunnen naar " +
47
+ "woorden omgezet worden."
48
+ )
49
+ # "Cannot treat negative num %s as ordinal."
50
+ self.errmsg_negord = (
51
+ "Het negatieve getal %s kan niet omgezet " +
52
+ "worden naar een ordernummer."
53
+ )
54
+ # "abs(%s) must be less than %s."
55
+ self.errmsg_toobig = "Het getal %s moet minder zijn dan %s."
56
+ self.exclude_title = []
57
+
58
+ lows = ["non", "okt", "sept", "sext", "quint", "quadr", "tr", "b", "m"]
59
+ units = ["", "un", "duo", "tre", "quattuor", "quin", "sex", "sept",
60
+ "okto", "novem"]
61
+ tens = ["dez", "vigint", "trigint", "quadragint", "quinquagint",
62
+ "sexagint", "septuagint", "oktogint", "nonagint"]
63
+
64
+ self.high_numwords = (
65
+ ["zend"] + self.gen_high_numwords(units, tens, lows))
66
+
67
+ self.mid_numwords = [(1000, "duizend"), (100, "honderd"),
68
+ (90, "negentig"), (80, "tachtig"),
69
+ (70, "zeventig"), (60, "zestig"),
70
+ (50, "vijftig"), (40, "veertig"),
71
+ (30, "dertig")]
72
+
73
+ self.low_numwords = ["twintig", "negentien", "achttien", "zeventien",
74
+ "zestien", "vijftien", "veertien", "dertien",
75
+ "twaalf", "elf", "tien", "negen", "acht", "zeven",
76
+ "zes", "vijf", "vier", "drie", "twee", "één",
77
+ "nul"]
78
+
79
+ # Wiktionary says it is "nulde", not "nulte" or "nule"
80
+ # https://en.wiktionary.org/wiki/nulde
81
+ self.ords = {"nul": "nuld",
82
+ "één": "eerst",
83
+ "twee": "tweed",
84
+ "drie": "derd",
85
+ "vier": "vierd",
86
+ "vijf": "vijfd",
87
+ "zes": "zesd",
88
+ "zeven": "zevend",
89
+ "acht": "achtst",
90
+ "negen": "negend",
91
+ "tien": "tiend",
92
+ "elf": "elfd",
93
+ "twaalf": "twaalfd",
94
+
95
+ "ig": "igst",
96
+ "erd": "erdst",
97
+ "end": "endst",
98
+ "joen": "joenst",
99
+ "rd": "rdst"}
100
+
101
+ def merge(self, curr, next):
102
+ ctext, cnum, ntext, nnum = curr + next
103
+
104
+ if cnum == 1:
105
+ if nnum < 10 ** 6:
106
+ return next
107
+ ctext = "een"
108
+
109
+ if nnum > cnum:
110
+ if nnum >= 10 ** 6:
111
+ ctext += " "
112
+ val = cnum * nnum
113
+ else:
114
+ if nnum < 10 < cnum < 100:
115
+ if nnum == 1:
116
+ ntext = "een"
117
+
118
+ if ntext.endswith("e"):
119
+ ntext += "ën" # "n"
120
+ else:
121
+ ntext += "en"
122
+ ntext, ctext = ctext, ntext # + "en"
123
+ elif cnum >= 10 ** 6:
124
+ ctext += " "
125
+ val = cnum + nnum
126
+
127
+ word = ctext + ntext
128
+ return word, val
129
+
130
+ def to_currency(self, val, currency='EUR', cents=True, separator=' en',
131
+ adjective=False):
132
+ # Handle integers specially - just add currency name without cents
133
+ if isinstance(val, int):
134
+ try:
135
+ cr1, cr2 = self.CURRENCY_FORMS[currency]
136
+ except (KeyError, AttributeError):
137
+ # Fallback to base implementation for unknown currency
138
+ return super(Num2Word_NL, self).to_currency(
139
+ val, currency=currency, cents=cents, separator=separator,
140
+ adjective=adjective)
141
+
142
+ minus_str = self.negword if val < 0 else ""
143
+ abs_val = abs(val)
144
+ money_str = self.to_cardinal(abs_val)
145
+
146
+ # Proper pluralization for currency
147
+ if abs_val == 1:
148
+ currency_str = cr1[0] if isinstance(cr1, tuple) else cr1
149
+ else:
150
+ currency_str = cr1[1] if isinstance(cr1, tuple) and len(cr1) > 1 else (cr1[0] if isinstance(cr1, tuple) else cr1)
151
+
152
+ return (u'%s %s %s' % (minus_str, money_str, currency_str)).strip()
153
+
154
+ # For floats, use the parent class implementation
155
+ return super(Num2Word_NL, self).to_currency(
156
+ val, currency=currency, cents=cents, separator=separator,
157
+ adjective=adjective)
158
+
159
+ def to_ordinal(self, value):
160
+ self.verify_ordinal(value)
161
+ outword = self.to_cardinal(value)
162
+ for key in self.ords:
163
+ if outword.endswith(key):
164
+ outword = outword[:len(outword) - len(key)] + self.ords[key]
165
+ break
166
+ return outword + "e"
167
+
168
+ def to_ordinal_num(self, value):
169
+ self.verify_ordinal(value)
170
+ return str(value) + "e"
171
+
172
+ def pluralize(self, n, forms):
173
+ """
174
+ :param n:
175
+ :param forms:
176
+ :return:
177
+
178
+ gettext form is nplurals=2; plural=(n != 1);
179
+ but this claims https://onzetaal.nl/taaladvies/euro-euros/
180
+ not sure if it's applied only to euro
181
+ """
182
+ return forms[0]
183
+
184
+ def to_year(self, val, longval=True):
185
+ # For years 1100-1999, use the "[number]honderd" form
186
+ # e.g. 1600 -> "zestienhonderd" not "duizendzeshonderd"
187
+ if 1100 <= val <= 1999:
188
+ hundreds = val // 100
189
+ remainder = val % 100
190
+
191
+ # Convert the hundreds part (11-19)
192
+ result = self.to_cardinal(hundreds) + "honderd"
193
+
194
+ # Add remainder if any
195
+ if remainder:
196
+ remainder_text = self.to_cardinal(remainder)
197
+ result = result + remainder_text
198
+
199
+ return result
200
+
201
+ # For other years, use standard logic
202
+ if not (val // 100) % 10:
203
+ return self.to_cardinal(val)
204
+ return self.to_splitnum(val, hightxt="honderd", longval=longval)
num2words2/lang_NN.py ADDED
@@ -0,0 +1,136 @@
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
+ # Norwegian Nynorsk language support
24
+ class Num2Word_NN(Num2Word_Base):
25
+ CURRENCY_FORMS = {
26
+ 'NOK': (('krone', 'kroner'), ('øre', 'øre')),
27
+ 'USD': (('dollar', 'dollars'), ('cent', 'cents')),
28
+ 'EUR': (('euro', 'euros'), ('cent', 'cents'))
29
+ }
30
+
31
+ def setup(self):
32
+ self.negword = "minus "
33
+ self.pointword = "point"
34
+ self.ones = ['', 'ein', 'to', 'tre', 'fire', 'fem', 'seks', 'sju', 'åtte', 'ni']
35
+ self.tens = ['', 'ti', 'tjue', 'tretti', 'førti', 'femti', 'seksti', 'sytti', 'åtti', 'nitti']
36
+ self.hundred = "hundre"
37
+ self.thousand = "tusen"
38
+ self.million = "million"
39
+
40
+ def to_cardinal(self, number):
41
+ """Convert a number to its word representation in Norwegian Nynorsk."""
42
+ n = str(number).strip()
43
+
44
+ if n.startswith('-'):
45
+ n = n[1:]
46
+ ret = self.negword
47
+ else:
48
+ ret = ""
49
+
50
+ if '.' in n:
51
+ left, right = n.split('.', 1)
52
+ ret += self._int_to_word(int(left)) + " " + self.pointword + " "
53
+ for digit in right:
54
+ ret += self._int_to_word(int(digit)) + " "
55
+ return ret.strip()
56
+ else:
57
+ return (ret + self._int_to_word(int(n))).strip()
58
+
59
+ def _int_to_word(self, number):
60
+ """Convert an integer to its word representation in Norwegian Nynorsk."""
61
+ if number == 0:
62
+ return self.ones[0] if self.ones[0] else "zero"
63
+
64
+ if number < 0:
65
+ return self.negword + self._int_to_word(abs(number))
66
+ elif number < 10:
67
+ return self.ones[number]
68
+ elif number < 100:
69
+ tens_val = number // 10
70
+ ones_val = number % 10
71
+ if ones_val == 0:
72
+ return self.tens[tens_val]
73
+ else:
74
+ return self.tens[tens_val] + " " + self.ones[ones_val]
75
+ elif number < 1000:
76
+ hundreds_val = number // 100
77
+ remainder = number % 100
78
+ result = self.ones[hundreds_val] + " " + self.hundred
79
+ if remainder:
80
+ result += " " + self._int_to_word(remainder)
81
+ return result
82
+ elif number < 1000000:
83
+ thousands_val = number // 1000
84
+ remainder = number % 1000
85
+ result = self._int_to_word(thousands_val) + " " + self.thousand
86
+ if remainder:
87
+ result += " " + self._int_to_word(remainder)
88
+ return result
89
+ elif number < 1000000000:
90
+ millions_val = number // 1000000
91
+ remainder = number % 1000000
92
+ result = self._int_to_word(millions_val) + " " + self.million
93
+ if remainder:
94
+ result += " " + self._int_to_word(remainder)
95
+ return result
96
+ else:
97
+ return str(number) # Fallback for very large numbers
98
+
99
+ def to_ordinal(self, number):
100
+ """Convert to ordinal in Norwegian Nynorsk."""
101
+ cardinal = self.to_cardinal(number)
102
+ # Language-specific ordinal suffix
103
+ return cardinal + "-de"
104
+
105
+ def to_ordinal_num(self, number):
106
+ """Convert to abbreviated ordinal."""
107
+ return str(number) + "."
108
+
109
+ def to_year(self, val, longval=True):
110
+ """Convert to year in Norwegian Nynorsk."""
111
+ return self.to_cardinal(val)
112
+
113
+ def to_currency(self, val, currency='NOK', cents=True, separator=' ', adjective=False):
114
+ """Convert to currency in Norwegian Nynorsk."""
115
+ is_negative = False
116
+ if val < 0:
117
+ is_negative = True
118
+ val = abs(val)
119
+
120
+ parts = str(val).split('.')
121
+ left = int(parts[0]) if parts[0] else 0
122
+ right = int(parts[1][:2].ljust(2, '0')) if len(parts) > 1 and parts[1] else 0
123
+
124
+ cr1, cr2 = self.CURRENCY_FORMS.get(currency, list(self.CURRENCY_FORMS.values())[0])
125
+
126
+ left_str = self._int_to_word(left)
127
+ result = left_str + " " + (cr1[1] if left != 1 else cr1[0])
128
+
129
+ if cents and right:
130
+ cents_str = self._int_to_word(right)
131
+ result += separator + cents_str + " " + (cr2[1] if right != 1 else cr2[0])
132
+
133
+ if is_negative:
134
+ result = self.negword + result
135
+
136
+ return result.strip()
num2words2/lang_NO.py ADDED
@@ -0,0 +1,143 @@
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_NO(lang_EUR.Num2Word_EUR):
24
+ GIGA_SUFFIX = "illiard"
25
+ MEGA_SUFFIX = "illion"
26
+ CURRENCY_FORMS = {
27
+ 'NOK': (('krone', 'kroner'), ('øre', 'øre')),
28
+ 'EUR': (('euro', 'euro'), ('cent', 'cent')),
29
+ 'USD': (('dollar', 'dollar'), ('cent', 'cent')),
30
+ }
31
+
32
+ def set_high_numwords(self, high):
33
+ cap = 3 + 6 * len(high)
34
+
35
+ for word, n in zip(high, range(cap, 3, -6)):
36
+ if self.GIGA_SUFFIX:
37
+ self.cards[10 ** n] = word + self.GIGA_SUFFIX
38
+
39
+ if self.MEGA_SUFFIX:
40
+ self.cards[10 ** (n - 3)] = word + self.MEGA_SUFFIX
41
+
42
+ def setup(self):
43
+ super(Num2Word_NO, self).setup()
44
+
45
+ self.negword = "minus "
46
+ self.pointword = "komma"
47
+ self.exclude_title = ["og", "komma", "minus"]
48
+
49
+ self.mid_numwords = [(1000, "tusen"), (100, "hundre"),
50
+ (90, "nitti"), (80, "\xe5tti"), (70, "sytti"),
51
+ (60, "seksti"), (50, "femti"), (40, "f\xf8rti"),
52
+ (30, "tretti")]
53
+ self.low_numwords = ["tjue", "nitten", "atten", "sytten",
54
+ "seksten", "femten", "fjorten", "tretten",
55
+ "tolv", "elleve", "ti", "ni", "\xe5tte",
56
+ "syv", "seks", "fem", "fire", "tre", "to",
57
+ "en", "null"]
58
+ self.ords_pl = {"to": "andre",
59
+ "tre": "tredje",
60
+ "fire": "fjerde",
61
+ "fem": "femte",
62
+ "seks": "sjette",
63
+ "syv": "syvende",
64
+ "\xe5tte": "\xe5ttende",
65
+ "ni": "niende",
66
+ "ti": "tiende",
67
+ "elleve": "ellevte",
68
+ "tolv": "tolvte",
69
+ "fjorten": "fjortende",
70
+ "femten": "femtende",
71
+ "seksten": "sekstende",
72
+ "sytten": "syttende",
73
+ "atten": "attende",
74
+ "nitten": "nittende",
75
+ "tjue": "tjuende",
76
+ "hundre": "hundrede",
77
+ "tusen": "tusende",
78
+ "million": "millionte"}
79
+ # this needs to be done separately to not block 13-19 to_ordinal
80
+ self.ords_sg = {"en": "f\xf8rste"}
81
+
82
+ def merge(self, lpair, rpair):
83
+ ltext, lnum = lpair
84
+ rtext, rnum = rpair
85
+ if lnum == 1 and rnum < 100:
86
+ return (rtext, rnum)
87
+ elif 100 > lnum > rnum:
88
+ return ("%s%s" % (ltext, rtext), lnum + rnum)
89
+ elif lnum >= 100 > rnum:
90
+ return ("%s og %s" % (ltext, rtext), lnum + rnum)
91
+ elif rnum > lnum:
92
+ # Special case for Norwegian: use "ett" before "tusen" but not "en" before "hundre"
93
+ if lnum == 1 and rnum == 1000:
94
+ return ("ett %s" % rtext, lnum * rnum)
95
+ elif lnum == 100 and rnum == 1000:
96
+ # 100000 should be "hundre tusen" not "en hundre tusen"
97
+ return ("hundre tusen", 100000)
98
+ # Handle Norwegian plural forms for million and milliard
99
+ if rnum == 10**6:
100
+ if lnum == 1:
101
+ return ("en million", lnum * rnum)
102
+ else:
103
+ return ("%s millioner" % ltext, lnum * rnum)
104
+ elif rnum == 10**9:
105
+ if lnum == 1:
106
+ return ("en milliard", lnum * rnum)
107
+ else:
108
+ return ("%s milliarder" % ltext, lnum * rnum)
109
+ return ("%s %s" % (ltext, rtext), lnum * rnum)
110
+ return ("%s %s" % (ltext, rtext), lnum + rnum)
111
+
112
+ def to_ordinal(self, value):
113
+ self.verify_ordinal(value)
114
+ outword = self.to_cardinal(value)
115
+ for key in self.ords_pl:
116
+ if outword.endswith(key):
117
+ outword = outword[:len(outword) - len(key)] + self.ords_pl[key]
118
+ break
119
+ for key in self.ords_sg:
120
+ if outword.endswith(key):
121
+ outword = outword[:len(outword) - len(key)] + self.ords_sg[key]
122
+ break
123
+ return outword
124
+
125
+ def to_ordinal_num(self, value):
126
+ self.verify_ordinal(value)
127
+ return str(value) + "."
128
+
129
+ def to_year(self, val, longval=True):
130
+ if not (val // 100) % 10:
131
+ return self.to_cardinal(val)
132
+ return self.to_splitnum(val, hightxt="hundre", jointxt="og",
133
+ longval=longval)
134
+
135
+ def to_currency(self, val, currency='NOK', cents=True, separator=' og',
136
+ adjective=False):
137
+ result = super(Num2Word_NO, self).to_currency(
138
+ val, currency=currency, cents=cents, separator=separator,
139
+ adjective=adjective)
140
+
141
+ # do not print "og null øre"
142
+ result = result.replace(' og null øre', '')
143
+ return result