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_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
|