mirror of
https://github.com/bblaz/num2words.git
synced 2025-12-06 14:52:25 +00:00
Merge branch 'master' of https://github.com/savoirfairelinux/num2words
Conflicts: num2words/__init__.py
This commit is contained in:
@@ -15,7 +15,11 @@
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import math
|
||||
|
||||
from .orderedmapping import OrderedMapping
|
||||
from .compat import to_s
|
||||
|
||||
|
||||
class Num2Word_Base(object):
|
||||
@@ -36,7 +40,7 @@ class Num2Word_Base(object):
|
||||
self.set_numwords()
|
||||
|
||||
self.MAXVAL = 1000 * self.cards.order[0]
|
||||
|
||||
|
||||
|
||||
def set_numwords(self):
|
||||
self.set_high_numwords(self.high_numwords)
|
||||
@@ -64,7 +68,7 @@ class Num2Word_Base(object):
|
||||
for elem in self.cards:
|
||||
if elem > value:
|
||||
continue
|
||||
|
||||
|
||||
out = []
|
||||
if value == 0:
|
||||
div, mod = 1, 0
|
||||
@@ -75,7 +79,7 @@ class Num2Word_Base(object):
|
||||
out.append((self.cards[1], 1))
|
||||
else:
|
||||
if div == value: # The system tallies, eg Roman Numerals
|
||||
return [(div * self.cards[elem], div*elem)]
|
||||
return [(div * self.cards[elem], div*elem)]
|
||||
out.append(self.splitnum(div))
|
||||
|
||||
out.append((self.cards[elem], elem))
|
||||
@@ -88,7 +92,7 @@ class Num2Word_Base(object):
|
||||
|
||||
def to_cardinal(self, value):
|
||||
try:
|
||||
assert long(value) == value
|
||||
assert int(value) == value
|
||||
except (ValueError, TypeError, AssertionError):
|
||||
return self.to_cardinal_float(value)
|
||||
|
||||
@@ -101,31 +105,44 @@ class Num2Word_Base(object):
|
||||
|
||||
if value >= self.MAXVAL:
|
||||
raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL))
|
||||
|
||||
|
||||
val = self.splitnum(value)
|
||||
words, num = self.clean(val)
|
||||
return self.title(out + words)
|
||||
|
||||
|
||||
def float2tuple(self, value):
|
||||
pre = int(value)
|
||||
post = abs(value - pre) * 10**self.precision
|
||||
if abs(round(post) - post) < 0.01:
|
||||
# We generally floor all values beyond our precision (rather than rounding), but in
|
||||
# cases where we have something like 1.239999999, which is probably due to python's
|
||||
# handling of floats, we actually want to consider it as 1.24 instead of 1.23
|
||||
post = int(round(post))
|
||||
else:
|
||||
post = int(math.floor(post))
|
||||
|
||||
return pre, post
|
||||
|
||||
|
||||
def to_cardinal_float(self, value):
|
||||
try:
|
||||
float(value) == value
|
||||
except (ValueError, TypeError, AssertionError):
|
||||
raise TypeError(self.errmsg_nonnum % value)
|
||||
|
||||
pre = int(value)
|
||||
post = abs(value - pre)
|
||||
pre, post = self.float2tuple(float(value))
|
||||
|
||||
post = str(post)
|
||||
post = '0' * (self.precision - len(post)) + post
|
||||
|
||||
out = [self.to_cardinal(pre)]
|
||||
if self.precision:
|
||||
out.append(self.title(self.pointword))
|
||||
|
||||
for i in range(self.precision):
|
||||
post *= 10
|
||||
curr = int(post)
|
||||
out.append(str(self.to_cardinal(curr)))
|
||||
post -= curr
|
||||
curr = int(post[i])
|
||||
out.append(to_s(self.to_cardinal(curr)))
|
||||
|
||||
return " ".join(out)
|
||||
|
||||
@@ -170,10 +187,10 @@ class Num2Word_Base(object):
|
||||
|
||||
|
||||
def verify_ordinal(self, value):
|
||||
if not value == long(value):
|
||||
raise TypeError, self.errmsg_floatord %(value)
|
||||
if not value == int(value):
|
||||
raise TypeError(self.errmsg_floatord % value)
|
||||
if not abs(value) == value:
|
||||
raise TypeError, self.errmsg_negord %(value)
|
||||
raise TypeError(self.errmsg_negord % value)
|
||||
|
||||
|
||||
def verify_num(self, value):
|
||||
@@ -183,8 +200,8 @@ class Num2Word_Base(object):
|
||||
def set_wordnums(self):
|
||||
pass
|
||||
|
||||
|
||||
def to_ordinal(value):
|
||||
|
||||
def to_ordinal(self, value):
|
||||
return self.to_cardinal(value)
|
||||
|
||||
|
||||
@@ -202,12 +219,17 @@ class Num2Word_Base(object):
|
||||
|
||||
#//CHECK: generalise? Any others like pounds/shillings/pence?
|
||||
def to_splitnum(self, val, hightxt="", lowtxt="", jointxt="",
|
||||
divisor=100, longval=True, cents = True):
|
||||
divisor=100, longval=True, cents=True):
|
||||
out = []
|
||||
try:
|
||||
high, low = val
|
||||
except TypeError:
|
||||
high, low = divmod(val, divisor)
|
||||
|
||||
if isinstance(val, float):
|
||||
high, low = self.float2tuple(val)
|
||||
else:
|
||||
try:
|
||||
high, low = val
|
||||
except TypeError:
|
||||
high, low = divmod(val, divisor)
|
||||
|
||||
if high:
|
||||
hightxt = self.title(self.inflect(high, hightxt))
|
||||
out.append(self.to_cardinal(high))
|
||||
@@ -219,6 +241,7 @@ class Num2Word_Base(object):
|
||||
out.append(self.title(jointxt))
|
||||
elif hightxt:
|
||||
out.append(hightxt)
|
||||
|
||||
if low:
|
||||
if cents:
|
||||
out.append(self.to_cardinal(low))
|
||||
@@ -226,6 +249,7 @@ class Num2Word_Base(object):
|
||||
out.append("%02d" % low)
|
||||
if lowtxt and longval:
|
||||
out.append(self.title(self.inflect(low, lowtxt)))
|
||||
|
||||
return " ".join(out)
|
||||
|
||||
|
||||
@@ -260,6 +284,6 @@ class Num2Word_Base(object):
|
||||
_ordnum = self.to_ordinal_num(value)
|
||||
except:
|
||||
_ordnum = "invalid"
|
||||
|
||||
|
||||
print ("For %s, card is %s;\n\tord is %s; and\n\tordnum is %s." %
|
||||
(value, _card, _ord, _ordnum))
|
||||
|
||||
26
num2words/compat.py
Normal file
26
num2words/compat.py
Normal file
@@ -0,0 +1,26 @@
|
||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
# Copyright (c) 2016, Savoir-faire Linux inc. All Rights Reserved.
|
||||
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
import sys
|
||||
|
||||
PY3 = sys.version_info[0] == 3
|
||||
|
||||
def to_s(val):
|
||||
if PY3:
|
||||
return str(val)
|
||||
else:
|
||||
return unicode(val)
|
||||
|
||||
121
num2words/lang_AR.py
Normal file
121
num2words/lang_AR.py
Normal file
@@ -0,0 +1,121 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
||||
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import division, unicode_literals, print_function
|
||||
from . import lang_EU
|
||||
|
||||
class Num2Word_AR(lang_EU.Num2Word_EU):
|
||||
def set_high_numwords(self, high):
|
||||
max = 3 + 3*len(high)
|
||||
for word, n in zip(high, range(max, 3, -3)):
|
||||
self.cards[10**n] = word + "illion"
|
||||
|
||||
def setup(self):
|
||||
self.negword = "سالب "
|
||||
self.pointword = "فاصلة"
|
||||
self.errmsg_nornum = "Only numbers may be converted to words."
|
||||
self.exclude_title = ["و", "فاصلة", "سالب"]
|
||||
|
||||
self.mid_numwords = [(1000000, "مليون"),(1000, "ألف"), (100, "مئة"),
|
||||
(90, "تسعين"), (80, "ثمانين"), (70, "سبعين"),
|
||||
(60, "ستين"), (50, "خمسين"), (40, "أربعين"),
|
||||
(30, "ثلاثين")]
|
||||
self.low_numwords = ["عشرين", "تسعة عشر", "ثمانية عشر", "سبعة عشر",
|
||||
"ستة عشر", "خمسة عشر", "أربعة عشر", "ثلاثة عشر",
|
||||
"اثناعشر", "أحد عشر", "عشرة", "تسعة", "ثمانية",
|
||||
"سبعة", "ستة", "خمسة", "أربعة", "ثلاثة", "اثنين",
|
||||
"واحد", "صفر"]
|
||||
self.ords = { "واحد" : "أول",
|
||||
"اثنين" : "ثاني",
|
||||
"ثلاثة" : "ثالث",
|
||||
"أربعة": "رابع",
|
||||
"خمسة" : "خامس",
|
||||
"ثمانية" : "ثامن",
|
||||
"تسعة" : "تاسع",
|
||||
"اثناعشر" : "ثاني عشر" }
|
||||
|
||||
|
||||
def merge(self, lpair, rpair):
|
||||
ltext, lnum = lpair
|
||||
rtext, rnum = rpair
|
||||
if lnum == 1 and rnum < 100:
|
||||
return (rtext, rnum)
|
||||
elif 100 > lnum > rnum :
|
||||
return ("%s و%s"%(rtext, ltext), rnum + lnum)
|
||||
elif lnum >= 100 > rnum:
|
||||
return ("%s و %s"%(ltext, rtext), lnum + rnum)
|
||||
elif rnum > lnum:
|
||||
if lnum == 1 and rnum in [100, 1000, 1000000]:
|
||||
return ("%s"%(rtext), rnum * lnum)
|
||||
if lnum == 2 and rnum == 100:
|
||||
return ("مئتين", rnum * lnum)
|
||||
if lnum == 2 and rnum in [100, 1000]:
|
||||
return ("%sين"%(rtext), rnum * lnum)
|
||||
return ("%s %s"%(ltext, rtext), lnum * rnum)
|
||||
return ("%s، %s"%(ltext, rtext), lnum + rnum)
|
||||
|
||||
|
||||
def to_ordinal(self, value):
|
||||
self.verify_ordinal(value)
|
||||
outwords = self.to_cardinal(value).split(" ")
|
||||
lastwords = outwords[-1].split("-")
|
||||
lastword = lastwords[-1].lower()
|
||||
try:
|
||||
lastword = self.ords[lastword]
|
||||
except KeyError:
|
||||
lastword += ""
|
||||
lastwords[-1] = self.title(lastword)
|
||||
outwords[-1] = "،".join(lastwords)
|
||||
return " ".join(outwords)
|
||||
|
||||
|
||||
def to_ordinal_num(self, value):
|
||||
self.verify_ordinal(value)
|
||||
return "%s%s"%(value, self.to_ordinal(value)[-2:])
|
||||
|
||||
|
||||
def to_year(self, val, longval=True):
|
||||
if not (val//100)%10:
|
||||
return self.to_cardinal(val)
|
||||
return self.to_splitnum(val, hightxt="مئة", jointxt="و",
|
||||
longval=longval)
|
||||
|
||||
def to_currency(self, val, longval=True):
|
||||
return self.to_splitnum(val, hightxt="ريال", lowtxt="هللة",
|
||||
jointxt="و", longval=longval, cents = True)
|
||||
|
||||
|
||||
n2w = Num2Word_AR()
|
||||
to_card = n2w.to_cardinal
|
||||
to_ord = n2w.to_ordinal
|
||||
to_ordnum = n2w.to_ordinal_num
|
||||
to_year = n2w.to_year
|
||||
|
||||
def main():
|
||||
for val in [ 1, 11, 12, 21, 31, 33, 71, 80, 81, 91, 99, 100, 101, 102, 155,
|
||||
180, 300, 308, 832, 1000, 1001, 1061, 1100, 1500, 1701, 3000,
|
||||
8280, 8291, 150000, 500000, 1000000, 2000000, 2000001,
|
||||
-21212121211221211111, -2.121212, -1.0000100]:
|
||||
n2w.test(val)
|
||||
n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
|
||||
for val in [1,120,1000,1120,1800, 1976,2000,2010,2099,2171]:
|
||||
print(val, "is", n2w.to_currency(val))
|
||||
print(val, "is", n2w.to_year(val))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
||||
|
||||
@@ -14,10 +15,9 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import unicode_literals
|
||||
from __future__ import unicode_literals, print_function
|
||||
from .lang_EU import Num2Word_EU
|
||||
|
||||
#//TODO: Use German error messages
|
||||
class Num2Word_DE(Num2Word_EU):
|
||||
def set_high_numwords(self, high):
|
||||
max = 3 + 6*len(high)
|
||||
@@ -26,12 +26,13 @@ class Num2Word_DE(Num2Word_EU):
|
||||
self.cards[10**n] = word + "illiarde"
|
||||
self.cards[10**(n-3)] = word + "illion"
|
||||
|
||||
|
||||
def setup(self):
|
||||
self.negword = "minus "
|
||||
self.pointword = "Komma"
|
||||
self.errmsg_nonnum = "Only numbers may be converted to words."
|
||||
self.errmsg_toobig = "Number is too large to convert to words."
|
||||
self.errmsg_floatord = "Die Gleitkommazahl %s kann nicht in eine Ordnungszahl konvertiert werden." # "Cannot treat float %s as ordinal."
|
||||
self.errmsg_nonnum = "Nur Zahlen (type(%s)) können in Wörter konvertiert werden." # "type(((type(%s)) ) not in [long, int, float]"
|
||||
self.errmsg_negord = "Die negative Zahl %s kann nicht in eine Ordnungszahl konvertiert werden." # "Cannot treat negative num %s as ordinal."
|
||||
self.errmsg_toobig = "Die Zahl %s muss kleiner als %s sein." # "abs(%s) must be less than %s."
|
||||
self.exclude_title = []
|
||||
|
||||
lows = ["non", "okt", "sept", "sext", "quint", "quadr", "tr", "b", "m"]
|
||||
@@ -44,66 +45,64 @@ class Num2Word_DE(Num2Word_EU):
|
||||
(90, "neunzig"), (80, "achtzig"), (70, "siebzig"),
|
||||
(60, "sechzig"), (50, "f\xFCnfzig"), (40, "vierzig"),
|
||||
(30, "drei\xDFig")]
|
||||
self.low_numwords = ["zwanzig", "neunzehn", "achtzen", "siebzehn",
|
||||
self.low_numwords = ["zwanzig", "neunzehn", "achtzehn", "siebzehn",
|
||||
"sechzehn", "f\xFCnfzehn", "vierzehn", "dreizehn",
|
||||
"zw\xF6lf", "elf", "zehn", "neun", "acht", "sieben",
|
||||
"sechs", "f\xFCnf", "vier", "drei", "zwei", "eins",
|
||||
"null"]
|
||||
self.ords = { "eins" : "ers",
|
||||
"drei" : "drit",
|
||||
"acht" : "ach",
|
||||
"sieben" : "sieb",
|
||||
"ig" : "igs" }
|
||||
self.ordflag = False
|
||||
|
||||
self.ords = {"eins": "ers",
|
||||
"drei": "drit",
|
||||
"acht": "ach",
|
||||
"sieben": "sieb",
|
||||
"ig": "igs",
|
||||
"ert": "erts",
|
||||
"end": "ends",
|
||||
"ion": "ions",
|
||||
"nen": "nens",
|
||||
"rde": "rdes",
|
||||
"rden": "rdens"}
|
||||
|
||||
def merge(self, curr, next):
|
||||
ctext, cnum, ntext, nnum = curr + next
|
||||
|
||||
if cnum == 1:
|
||||
if nnum < 10**6 or self.ordflag:
|
||||
if nnum < 10**6:
|
||||
return next
|
||||
ctext = "eine"
|
||||
|
||||
if nnum > cnum:
|
||||
if nnum >= 10**6:
|
||||
if cnum > 1:
|
||||
if ntext.endswith("e") or self.ordflag:
|
||||
ntext += "s"
|
||||
if ntext.endswith("e"):
|
||||
ntext += "n"
|
||||
else:
|
||||
ntext += "es"
|
||||
ntext += "en"
|
||||
ctext += " "
|
||||
val = cnum * nnum
|
||||
else:
|
||||
if nnum < 10 < cnum < 100:
|
||||
if nnum == 1:
|
||||
ntext = "ein"
|
||||
ntext, ctext = ctext, ntext + "und"
|
||||
ntext, ctext = ctext, ntext + "und"
|
||||
elif cnum >= 10**6:
|
||||
ctext += " "
|
||||
val = cnum + nnum
|
||||
|
||||
word = ctext + ntext
|
||||
return (word, val)
|
||||
|
||||
|
||||
def to_ordinal(self, value):
|
||||
self.verify_ordinal(value)
|
||||
self.ordflag = True
|
||||
outword = self.to_cardinal(value)
|
||||
self.ordflag = False
|
||||
for key in self.ords:
|
||||
if outword.endswith(key):
|
||||
outword = outword[:len(outword) - len(key)] + self.ords[key]
|
||||
break
|
||||
return outword + "te"
|
||||
|
||||
|
||||
# Is this correct??
|
||||
def to_ordinal_num(self, value):
|
||||
self.verify_ordinal(value)
|
||||
return str(value) + "te"
|
||||
|
||||
return str(value) + "."
|
||||
|
||||
def to_currency(self, val, longval=True, old=False):
|
||||
if old:
|
||||
@@ -117,8 +116,6 @@ class Num2Word_DE(Num2Word_EU):
|
||||
return self.to_cardinal(val)
|
||||
return self.to_splitnum(val, hightxt="hundert", longval=longval)
|
||||
|
||||
|
||||
|
||||
n2w = Num2Word_DE()
|
||||
to_card = n2w.to_cardinal
|
||||
to_ord = n2w.to_ordinal
|
||||
@@ -126,15 +123,20 @@ to_ordnum = n2w.to_ordinal_num
|
||||
|
||||
|
||||
def main():
|
||||
for val in [ 1, 11, 12, 21, 31, 33, 71, 80, 81, 91, 99, 100, 101, 102, 155,
|
||||
for val in [1, 7, 8, 12, 17, 81, 91, 99, 100, 101, 102, 155,
|
||||
180, 300, 308, 832, 1000, 1001, 1061, 1100, 1500, 1701, 3000,
|
||||
8280, 8291, 150000, 500000, 1000000, 2000000, 2000001,
|
||||
8280, 8291, 150000, 500000, 3000000, 1000000, 2000001, 1000000000, 2000000000,
|
||||
-21212121211221211111, -2.121212, -1.0000100]:
|
||||
n2w.test(val)
|
||||
|
||||
n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
|
||||
print n2w.to_currency(112121)
|
||||
print n2w.to_year(2000)
|
||||
# n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
|
||||
n2w.test(3000000)
|
||||
n2w.test(3000000000001)
|
||||
n2w.test(3000000324566)
|
||||
print(n2w.to_currency(112121))
|
||||
print(n2w.to_year(2000))
|
||||
print(n2w.to_year(1820))
|
||||
print(n2w.to_year(2001))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
154
num2words/lang_DK.py
Normal file
154
num2words/lang_DK.py
Normal file
@@ -0,0 +1,154 @@
|
||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
||||
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import division, unicode_literals, print_function
|
||||
from num2words import lang_EU
|
||||
|
||||
class Num2Word_DK(lang_EU.Num2Word_EU):
|
||||
def set_high_numwords(self, high):
|
||||
max = 3 + 6*len(high)
|
||||
for word, n in zip(high, range(max, 3, -6)):
|
||||
self.cards[10**n] = word + "illarder"
|
||||
self.cards[10**(n-3)] = word + "illioner"
|
||||
|
||||
def setup(self):
|
||||
self.negword = "minus "
|
||||
self.pointword = "komma"
|
||||
self.errmsg_nornum = "Kun tal kan blive konverteret til ord."
|
||||
self.exclude_title = ["og", "komma", "minus"]
|
||||
|
||||
self.mid_numwords = [(1000, "tusind"), (100, "hundrede"),
|
||||
(90, "halvfems"), (80, "firs"), (70, "halvfjerds"),
|
||||
(60, "treds"), (50, "halvtreds"), (40, "fyrre"),
|
||||
(30, "tredive")]
|
||||
self.low_numwords = ["tyve", "nitten", "atten", "sytten",
|
||||
"seksten", "femten", "fjorten", "tretten",
|
||||
"tolv", "elleve", "ti", "ni", "otte",
|
||||
"syv", "seks", "fem", "fire", "tre", "to",
|
||||
"et", "nul"]
|
||||
self.ords = { "nul" : "nul",
|
||||
"et" : "f\xf8rste",
|
||||
"to" : "anden",
|
||||
"tre" : "tredje",
|
||||
"fire" : "fjerde",
|
||||
"fem" : "femte",
|
||||
"seks" : "sjette",
|
||||
"syv" : "syvende",
|
||||
"otte" : "ottende",
|
||||
"ni" : "niende",
|
||||
"ti" : "tiende",
|
||||
"elleve" : "ellevte",
|
||||
"tolv" : "tolvte",
|
||||
"tretten" : "trett",
|
||||
"fjorten" : "fjort",
|
||||
"femten" : "femt",
|
||||
"seksten" : "sekst",
|
||||
"sytten" : "sytt",
|
||||
"atten" : "att",
|
||||
"nitten" : "nitt",
|
||||
"tyve" : "tyv"}
|
||||
|
||||
def merge(self, curr, next):
|
||||
ctext, cnum, ntext, nnum = curr + next
|
||||
if next[1] == 100 or next[1] == 1000:
|
||||
lst = list(next)
|
||||
lst[0] = 'et' + lst[0]
|
||||
next = tuple(lst)
|
||||
|
||||
if cnum == 1:
|
||||
if nnum < 10**6 or self.ordflag:
|
||||
return next
|
||||
ctext = "en"
|
||||
if nnum > cnum:
|
||||
if nnum >= 10**6:
|
||||
ctext += " "
|
||||
val = cnum * nnum
|
||||
else:
|
||||
if cnum >= 100 and cnum < 1000:
|
||||
ctext += " og "
|
||||
elif cnum >= 1000 and cnum <= 100000:
|
||||
ctext += "e og "
|
||||
if nnum < 10 < cnum < 100:
|
||||
if nnum == 1:
|
||||
ntext = "en"
|
||||
ntext, ctext = ctext, ntext + "og"
|
||||
elif cnum >= 10**6:
|
||||
ctext += " "
|
||||
val = cnum + nnum
|
||||
word = ctext + ntext
|
||||
return (word, val)
|
||||
|
||||
|
||||
def to_ordinal(self, value):
|
||||
self.verify_ordinal(value)
|
||||
self.ordflag = True
|
||||
outword = self.to_cardinal(value)
|
||||
self.ordflag = False
|
||||
for key in self.ords:
|
||||
if outword.endswith(key):
|
||||
outword = outword[:len(outword) - len(key)] + self.ords[key]
|
||||
break
|
||||
if value %100 >= 30 and value %100 <= 39 or value %100 == 0:
|
||||
outword += "te"
|
||||
elif value % 100 > 12 or value %100 == 0:
|
||||
outword += "ende"
|
||||
return outword
|
||||
|
||||
def to_ordinal_num(self, value):
|
||||
self.verify_ordinal(value)
|
||||
vaerdte = (0,1,5,6,11,12)
|
||||
if value %100 >= 30 and value %100 <= 39 or value % 100 in vaerdte:
|
||||
return str(value) + "te"
|
||||
elif value % 100 == 2:
|
||||
return str(value) + "en"
|
||||
return str(value) + "ende"
|
||||
|
||||
|
||||
def to_currency(self, val, longval=True):
|
||||
if val//100 == 1 or val == 1:
|
||||
ret = self.to_splitnum(val, hightxt="kr", lowtxt="\xf8re",
|
||||
jointxt="og",longval=longval)
|
||||
return "en " + ret[3:]
|
||||
return self.to_splitnum(val, hightxt="kr", lowtxt="\xf8re",
|
||||
jointxt="og",longval=longval)
|
||||
|
||||
def to_year(self, val, longval=True):
|
||||
if val == 1:
|
||||
return 'en'
|
||||
if not (val//100)%10:
|
||||
return self.to_cardinal(val)
|
||||
return self.to_splitnum(val, hightxt="hundrede", longval=longval)
|
||||
|
||||
n2w = Num2Word_DK()
|
||||
to_card = n2w.to_cardinal
|
||||
to_ord = n2w.to_ordinal
|
||||
to_ordnum = n2w.to_ordinal_num
|
||||
to_year = n2w.to_year
|
||||
|
||||
def main():
|
||||
for val in [ 1, 11, 12, 21, 31, 33, 71, 80, 81, 91, 99, 100, 101, 102, 155,
|
||||
180, 300, 308, 832, 1000, 1001, 1061, 1100, 1500, 1701, 3000,
|
||||
8280, 8291, 150000, 500000, 1000000, 2000000, 2000001,
|
||||
-21212121211221211111, -2.121212, -1.0000100]:
|
||||
n2w.test(val)
|
||||
n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
|
||||
for val in [1,120, 160, 1000,1120,1800, 1976,2000,2010,2099,2171]:
|
||||
print(val, "er", n2w.to_currency(val))
|
||||
print(val, "er", n2w.to_year(val))
|
||||
n2w.test(65132)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -14,7 +14,7 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import division, unicode_literals
|
||||
from __future__ import division, unicode_literals, print_function
|
||||
from . import lang_EU
|
||||
|
||||
class Num2Word_EN(lang_EU.Num2Word_EU):
|
||||
@@ -47,7 +47,9 @@ class Num2Word_EN(lang_EU.Num2Word_EU):
|
||||
"twelve" : "twelfth" }
|
||||
|
||||
|
||||
def merge(self, (ltext, lnum), (rtext, rnum)):
|
||||
def merge(self, lpair, rpair):
|
||||
ltext, lnum = lpair
|
||||
rtext, rnum = rpair
|
||||
if lnum == 1 and rnum < 100:
|
||||
return (rtext, rnum)
|
||||
elif 100 > lnum > rnum :
|
||||
@@ -68,9 +70,9 @@ class Num2Word_EN(lang_EU.Num2Word_EU):
|
||||
lastword = self.ords[lastword]
|
||||
except KeyError:
|
||||
if lastword[-1] == "y":
|
||||
lastword = lastword[:-1] + "ie"
|
||||
lastword = lastword[:-1] + "ie"
|
||||
lastword += "th"
|
||||
lastwords[-1] = self.title(lastword)
|
||||
lastwords[-1] = self.title(lastword)
|
||||
outwords[-1] = "-".join(lastwords)
|
||||
return " ".join(outwords)
|
||||
|
||||
@@ -105,9 +107,9 @@ def main():
|
||||
n2w.test(val)
|
||||
n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
|
||||
for val in [1,120,1000,1120,1800, 1976,2000,2010,2099,2171]:
|
||||
print val, "is", n2w.to_currency(val)
|
||||
print val, "is", n2w.to_year(val)
|
||||
|
||||
print(val, "is", n2w.to_currency(val))
|
||||
print(val, "is", n2w.to_year(val))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@@ -14,10 +14,10 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import unicode_literals
|
||||
from __future__ import unicode_literals, print_function
|
||||
from .lang_EN import Num2Word_EN
|
||||
|
||||
|
||||
|
||||
class Num2Word_EN_GB(Num2Word_EN):
|
||||
def to_currency(self, val, longval=True):
|
||||
return self.to_splitnum(val, hightxt="pound/s", lowtxt="pence",
|
||||
@@ -38,9 +38,9 @@ def main():
|
||||
n2w.test(val)
|
||||
n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
|
||||
for val in [1,120,1000,1120,1800, 1976,2000,2010,2099,2171]:
|
||||
print val, "is", n2w.to_currency(val)
|
||||
print val, "is", n2w.to_year(val)
|
||||
|
||||
print(val, "is", n2w.to_currency(val))
|
||||
print(val, "is", n2w.to_year(val))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#encoding: UTF-8
|
||||
# encoding: UTF-8
|
||||
|
||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
||||
@@ -16,19 +16,19 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import unicode_literals
|
||||
from __future__ import unicode_literals, print_function
|
||||
from .lang_EU import Num2Word_EU
|
||||
|
||||
|
||||
class Num2Word_ES(Num2Word_EU):
|
||||
|
||||
#//CHECK: Is this sufficient??
|
||||
# //CHECK: Is this sufficient??
|
||||
def set_high_numwords(self, high):
|
||||
max = 3 + 6*len(high)
|
||||
|
||||
for word, n in zip(high, range(max, 3, -6)):
|
||||
self.cards[10**(n-3)] = word + "illón"
|
||||
|
||||
|
||||
def setup(self):
|
||||
lows = ["cuatr", "tr", "b", "m"]
|
||||
self.high_numwords = self.gen_high_numwords([], [], lows)
|
||||
@@ -81,7 +81,6 @@ class Num2Word_ES(Num2Word_EU):
|
||||
1e12 : "trillonésim",
|
||||
1e15 : "cuadrillonésim" }
|
||||
|
||||
|
||||
def merge(self, curr, next):
|
||||
ctext, cnum, ntext, nnum = curr + next
|
||||
|
||||
@@ -94,8 +93,8 @@ class Num2Word_ES(Num2Word_EU):
|
||||
|
||||
if nnum < cnum:
|
||||
if cnum < 100:
|
||||
return ("%s y %s"%(ctext, ntext), cnum + nnum)
|
||||
return ("%s %s"%(ctext, ntext), cnum + nnum)
|
||||
return "%s y %s"%(ctext, ntext), cnum + nnum
|
||||
return "%s %s"%(ctext, ntext), cnum + nnum
|
||||
elif (not nnum % 1000000) and cnum > 1:
|
||||
ntext = ntext[:-3] + "lones"
|
||||
|
||||
@@ -113,7 +112,6 @@ class Num2Word_ES(Num2Word_EU):
|
||||
|
||||
return (ctext + ntext, cnum * nnum)
|
||||
|
||||
|
||||
def to_ordinal(self, value):
|
||||
self.verify_ordinal(value)
|
||||
text = ""
|
||||
@@ -125,10 +123,10 @@ class Num2Word_ES(Num2Word_EU):
|
||||
elif value <= 12:
|
||||
text = "%s%s%s" % (self.ords[10], self.gender_stem, self.to_ordinal(value - 10))
|
||||
elif value <= 100:
|
||||
dec = (value / 10) * 10
|
||||
dec = (value // 10) * 10
|
||||
text = "%s%s %s" % (self.ords[dec], self.gender_stem, self.to_ordinal(value - dec))
|
||||
elif value <= 1e3:
|
||||
cen = (value / 100) * 100
|
||||
cen = (value // 100) * 100
|
||||
text = "%s%s %s" % (self.ords[cen], self.gender_stem, self.to_ordinal(value - cen))
|
||||
elif value < 1e18:
|
||||
# dec contains the following:
|
||||
@@ -151,7 +149,6 @@ class Num2Word_ES(Num2Word_EU):
|
||||
self.verify_ordinal(value)
|
||||
return "%s%s" % (value, "º" if self.gender_stem == 'o' else "ª")
|
||||
|
||||
|
||||
def to_currency(self, val, longval=True, old=False):
|
||||
if old:
|
||||
return self.to_splitnum(val, hightxt="peso/s", lowtxt="peseta/s",
|
||||
@@ -165,17 +162,18 @@ to_card = n2w.to_cardinal
|
||||
to_ord = n2w.to_ordinal
|
||||
to_ordnum = n2w.to_ordinal_num
|
||||
|
||||
|
||||
def main():
|
||||
for val in [ 1, 11, 12, 21, 31, 33, 71, 80, 81, 91, 99, 100, 101, 102, 155,
|
||||
180, 300, 308, 832, 1000, 1001, 1061, 1100, 1500, 1701, 3000,
|
||||
8280, 8291, 150000, 500000, 1000000, 2000000, 2000001,
|
||||
-21212121211221211111, -2.121212, -1.0000100]:
|
||||
for val in [1, 11, 12, 21, 31, 33, 71, 80, 81, 91, 99, 100, 101, 102, 155,
|
||||
180, 300, 308, 832, 1000, 1001, 1061, 1100, 1500, 1701, 3000,
|
||||
8280, 8291, 150000, 500000, 1000000, 2000000, 2000001,
|
||||
-21212121211221211111, -2.121212, -1.0000100]:
|
||||
n2w.test(val)
|
||||
|
||||
n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
|
||||
print n2w.to_currency(1222)
|
||||
print n2w.to_currency(1222, old=True)
|
||||
print n2w.to_year(1222)
|
||||
print(n2w.to_currency(1222))
|
||||
print(n2w.to_currency(1222, old=True))
|
||||
print(n2w.to_year(1222))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
50
num2words/lang_ES_CO.py
Normal file
50
num2words/lang_ES_CO.py
Normal file
@@ -0,0 +1,50 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
||||
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import unicode_literals, print_function
|
||||
from .lang_ES import Num2Word_ES
|
||||
|
||||
|
||||
class Num2Word_ES_CO(Num2Word_ES):
|
||||
|
||||
def to_currency(self, val, longval=True, old=False):
|
||||
return self.to_splitnum(val, hightxt="peso/s", lowtxt="peso/s",
|
||||
divisor=1000, jointxt="y", longval=longval)
|
||||
|
||||
|
||||
n2w = Num2Word_ES_CO()
|
||||
to_card = n2w.to_cardinal
|
||||
to_ord = n2w.to_ordinal
|
||||
to_ordnum = n2w.to_ordinal_num
|
||||
|
||||
|
||||
def main():
|
||||
for val in [1, 11, 12, 21, 31, 33, 71, 80, 81, 91, 99, 100, 101, 102, 155,
|
||||
180, 300, 308, 832, 1000, 1001, 1061, 1100, 1500, 1701, 3000,
|
||||
8280, 8291, 150000, 500000, 1000000, 2000000, 2000001,
|
||||
-21212121211221211111, -2.121212, -1.0000100]:
|
||||
n2w.test(val)
|
||||
|
||||
n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
|
||||
print(n2w.to_currency(1222))
|
||||
print(n2w.to_currency(1222, old=True))
|
||||
print(n2w.to_year(1222))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
49
num2words/lang_ES_VE.py
Normal file
49
num2words/lang_ES_VE.py
Normal file
@@ -0,0 +1,49 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
||||
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import unicode_literals, print_function
|
||||
from .lang_ES import Num2Word_ES
|
||||
|
||||
|
||||
class Num2Word_ES_VE(Num2Word_ES):
|
||||
|
||||
def to_currency(self, val, longval=True, old=False):
|
||||
return self.to_splitnum(val, hightxt="bolívar/es Fuerte/s", lowtxt="bolívar/es fuerte/s",
|
||||
divisor=1000, jointxt="y", longval=longval)
|
||||
|
||||
n2w = Num2Word_ES_VE()
|
||||
to_card = n2w.to_cardinal
|
||||
to_ord = n2w.to_ordinal
|
||||
to_ordnum = n2w.to_ordinal_num
|
||||
|
||||
|
||||
def main():
|
||||
for val in [1, 11, 12, 21, 31, 33, 71, 80, 81, 91, 99, 100, 101, 102, 155,
|
||||
180, 300, 308, 832, 1000, 1001, 1061, 1100, 1500, 1701, 3000,
|
||||
8280, 8291, 150000, 500000, 1000000, 2000000, 2000001,
|
||||
-21212121211221211111, -2.121212, -1.0000100]:
|
||||
n2w.test(val)
|
||||
|
||||
n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
|
||||
print(n2w.to_currency(1222))
|
||||
print(n2w.to_currency(1222, old=True))
|
||||
print(n2w.to_year(1222))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -15,16 +15,18 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import unicode_literals
|
||||
from __future__ import unicode_literals, print_function
|
||||
from .lang_EU import Num2Word_EU
|
||||
|
||||
#//TODO: error messages in French
|
||||
|
||||
class Num2Word_FR(Num2Word_EU):
|
||||
def setup(self):
|
||||
Num2Word_EU.setup(self)
|
||||
|
||||
self.negword = "moins "
|
||||
self.pointword = "virgule"
|
||||
self.errmsg_nonnum = "Only numbers may be converted to words."
|
||||
self.errmsg_toobig = "Number is too large to convert to words."
|
||||
self.errmsg_nonnum = u"Seulement des nombres peuvent être convertis en mots."
|
||||
self.errmsg_toobig = u"Nombre trop grand pour être converti en mots."
|
||||
self.exclude_title = ["et", "virgule", "moins"]
|
||||
self.mid_numwords = [(1000, "mille"), (100, "cent"),
|
||||
(80, "quatre-vingts"), (60, "soixante"),
|
||||
@@ -49,15 +51,14 @@ class Num2Word_FR(Num2Word_EU):
|
||||
else:
|
||||
if (not (cnum - 80)%100 or not cnum%100) and ctext[-1] == "s":
|
||||
ctext = ctext[:-1]
|
||||
if (cnum<1000 and nnum != 1000 and ntext[-1] != "s"
|
||||
and not nnum%100):
|
||||
if cnum < 1000 and nnum != 1000 and ntext[-1] != "s" and not nnum % 100:
|
||||
ntext += "s"
|
||||
|
||||
if nnum < cnum < 100:
|
||||
if nnum % 10 == 1 and cnum != 80:
|
||||
return ("%s et %s"%(ctext, ntext), cnum + nnum)
|
||||
return ("%s-%s"%(ctext, ntext), cnum + nnum)
|
||||
elif nnum > cnum:
|
||||
if nnum > cnum:
|
||||
return ("%s %s"%(ctext, ntext), cnum * nnum)
|
||||
return ("%s %s"%(ctext, ntext), cnum + nnum)
|
||||
|
||||
@@ -83,15 +84,15 @@ class Num2Word_FR(Num2Word_EU):
|
||||
def to_ordinal_num(self, value):
|
||||
self.verify_ordinal(value)
|
||||
out = str(value)
|
||||
out += {"1" : "er" }.get(out[-1], "me")
|
||||
out += {"1" : "er"}.get(out[-1], "me")
|
||||
return out
|
||||
|
||||
def to_currency(self, val, longval=True, old=False):
|
||||
hightxt = "Euro/s"
|
||||
if old:
|
||||
hightxt="franc/s"
|
||||
hightxt = "franc/s"
|
||||
return self.to_splitnum(val, hightxt=hightxt, lowtxt="centime/s",
|
||||
jointxt="et",longval=longval)
|
||||
jointxt="et", longval=longval)
|
||||
|
||||
n2w = Num2Word_FR()
|
||||
to_card = n2w.to_cardinal
|
||||
@@ -99,15 +100,15 @@ to_ord = n2w.to_ordinal
|
||||
to_ordnum = n2w.to_ordinal_num
|
||||
|
||||
def main():
|
||||
for val in [ 1, 11, 12, 21, 31, 33, 71, 80, 81, 91, 99, 100, 101, 102, 155,
|
||||
180, 300, 308, 832, 1000, 1001, 1061, 1100, 1500, 1701, 3000,
|
||||
8280, 8291, 150000, 500000, 1000000, 2000000, 2000001,
|
||||
-21212121211221211111, -2.121212, -1.0000100]:
|
||||
for val in [1, 11, 12, 21, 31, 33, 71, 80, 81, 91, 99, 100, 101, 102, 155,
|
||||
180, 300, 308, 832, 1000, 1001, 1061, 1100, 1500, 1701, 3000,
|
||||
8280, 8291, 150000, 500000, 1000000, 2000000, 2000001,
|
||||
-21212121211221211111, -2.121212, -1.0000100]:
|
||||
n2w.test(val)
|
||||
|
||||
n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
|
||||
print n2w.to_currency(112121)
|
||||
print n2w.to_year(1996)
|
||||
print(n2w.to_currency(112121))
|
||||
print(n2w.to_year(1996))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
69
num2words/lang_FR_CH.py
Normal file
69
num2words/lang_FR_CH.py
Normal file
@@ -0,0 +1,69 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
||||
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import unicode_literals, print_function
|
||||
from .lang_FR import Num2Word_FR
|
||||
|
||||
|
||||
class Num2Word_FR_CH(Num2Word_FR):
|
||||
def setup(self):
|
||||
Num2Word_FR.setup(self)
|
||||
|
||||
self.mid_numwords = [(1000, "mille"), (100, "cent"), (90, "nonante"),
|
||||
(80, "huitante"), (70, "septante"), (60, "soixante"),
|
||||
(50, "cinquante"), (40, "quarante"),
|
||||
(30, "trente")]
|
||||
|
||||
|
||||
def merge(self, curr, next):
|
||||
ctext, cnum, ntext, nnum = curr + next
|
||||
|
||||
if cnum == 1:
|
||||
if nnum < 1000000:
|
||||
return next
|
||||
|
||||
if cnum < 1000 and nnum != 1000 and ntext[-1] != "s" and not nnum % 100:
|
||||
ntext += "s"
|
||||
|
||||
if nnum < cnum < 100:
|
||||
if nnum % 10 == 1:
|
||||
return ("%s et %s"%(ctext, ntext), cnum + nnum)
|
||||
return ("%s-%s"%(ctext, ntext), cnum + nnum)
|
||||
if nnum > cnum:
|
||||
return ("%s %s"%(ctext, ntext), cnum * nnum)
|
||||
return ("%s %s"%(ctext, ntext), cnum + nnum)
|
||||
|
||||
|
||||
n2w = Num2Word_FR_CH()
|
||||
to_card = n2w.to_cardinal
|
||||
to_ord = n2w.to_ordinal
|
||||
to_ordnum = n2w.to_ordinal_num
|
||||
|
||||
def main():
|
||||
for val in [1, 11, 12, 21, 31, 33, 71, 80, 81, 91, 99, 100, 101, 102, 155,
|
||||
180, 300, 308, 832, 1000, 1001, 1061, 1100, 1500, 1701, 3000,
|
||||
8280, 8291, 150000, 500000, 1000000, 2000000, 2000001,
|
||||
-21212121211221211111, -2.121212, -1.0000100]:
|
||||
n2w.test(val)
|
||||
|
||||
n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
|
||||
print(n2w.to_currency(112121))
|
||||
print(n2w.to_year(1996))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
48
num2words/lang_FR_DZ.py
Normal file
48
num2words/lang_FR_DZ.py
Normal file
@@ -0,0 +1,48 @@
|
||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
||||
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import unicode_literals
|
||||
from .lang_FR import Num2Word_FR
|
||||
|
||||
|
||||
class Num2Word_FR_DZ(Num2Word_FR):
|
||||
def to_currency(self, val, longval=True, cents=True, jointxt="virgule"):
|
||||
return self.to_splitnum(val, hightxt="dinard/s", lowtxt="centime/s",
|
||||
jointxt=jointxt, longval=longval, cents=cents)
|
||||
|
||||
|
||||
n2w = Num2Word_FR_DZ()
|
||||
to_card = n2w.to_cardinal
|
||||
to_ord = n2w.to_ordinal
|
||||
to_ordnum = n2w.to_ordinal_num
|
||||
to_year = n2w.to_year
|
||||
to_currency = n2w.to_currency
|
||||
|
||||
def main():
|
||||
for val in [1, 11, 12, 21, 31, 33, 71, 80, 81, 91, 99, 100, 101, 102, 155,
|
||||
180, 300, 308, 832, 1000, 1001, 1061, 1100, 1500, 1701, 3000,
|
||||
8280, 8291, 150000, 500000, 1000000, 2000000, 2000001,
|
||||
-21212121211221211111, -2.121212, -1.0000100]:
|
||||
n2w.test(val)
|
||||
|
||||
n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
|
||||
for val in [1, 120, 1000, 1120, 1800, 1976, 2000, 2010, 2099, 2171]:
|
||||
print(val, "is", n2w.to_currency(val))
|
||||
print(val, "is", n2w.to_year(val))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
162
num2words/lang_HE.py
Normal file
162
num2words/lang_HE.py
Normal file
@@ -0,0 +1,162 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
||||
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
|
||||
from __future__ import unicode_literals, print_function
|
||||
|
||||
ZERO = (u'אפס',)
|
||||
|
||||
ONES = {
|
||||
1: (u'אחד',),
|
||||
2: (u'שנים',),
|
||||
3: (u'שלש',),
|
||||
4: (u'ארבע',),
|
||||
5: (u'חמש',),
|
||||
6: (u'שש',),
|
||||
7: (u'שבע',),
|
||||
8: (u'שמנה',),
|
||||
9: (u'תשע',),
|
||||
}
|
||||
|
||||
TENS = {
|
||||
0: (u'עשר',),
|
||||
1: (u'אחד עשרה',),
|
||||
2: (u'שנים עשרה',),
|
||||
3: (u'שלש עשרה',),
|
||||
4: (u'ארבע עשרה',),
|
||||
5: (u'חמש עשרה',),
|
||||
6: (u'שש עשרה',),
|
||||
7: (u'שבע עשרה',),
|
||||
8: (u'שמנה עשרה',),
|
||||
9: (u'תשע עשרה',),
|
||||
}
|
||||
|
||||
TWENTIES = {
|
||||
2: (u'עשרים',),
|
||||
3: (u'שלשים',),
|
||||
4: (u'ארבעים',),
|
||||
5: (u'חמישים',),
|
||||
6: (u'ששים',),
|
||||
7: (u'שבעים',),
|
||||
8: (u'שמנים',),
|
||||
9: (u'תשעים',),
|
||||
}
|
||||
|
||||
HUNDRED = {
|
||||
1: (u'מאה',),
|
||||
2: (u'מאתיים',),
|
||||
3: (u'מאות',)
|
||||
}
|
||||
|
||||
THOUSANDS = {
|
||||
1: (u'אלף',),
|
||||
2: (u'אלפיים',),
|
||||
}
|
||||
|
||||
AND = u'ו'
|
||||
|
||||
def splitby3(n):
|
||||
length = len(n)
|
||||
if length > 3:
|
||||
start = length % 3
|
||||
if start > 0:
|
||||
yield int(n[:start])
|
||||
for i in range(start, length, 3):
|
||||
yield int(n[i:i+3])
|
||||
else:
|
||||
yield int(n)
|
||||
|
||||
|
||||
def get_digits(n):
|
||||
return [int(x) for x in reversed(list(('%03d' % n)[-3:]))]
|
||||
|
||||
|
||||
def pluralize(n, forms):
|
||||
# gettext implementation:
|
||||
# (n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2)
|
||||
|
||||
form = 0 if (n % 10 == 1 and n % 100 != 11) else 1 if n != 0 else 2
|
||||
|
||||
return forms[form]
|
||||
|
||||
|
||||
def int2word(n):
|
||||
if n > 9999: #doesn't yet work for numbers this big
|
||||
raise NotImplementedError()
|
||||
|
||||
if n == 0:
|
||||
return ZERO[0]
|
||||
|
||||
words = []
|
||||
|
||||
chunks = list(splitby3(str(n)))
|
||||
i = len(chunks)
|
||||
for x in chunks:
|
||||
i -= 1
|
||||
n1, n2, n3 = get_digits(x)
|
||||
|
||||
# print str(n3) + str(n2) + str(n1)
|
||||
|
||||
if n3 > 0:
|
||||
if n3 <= 2:
|
||||
words.append(HUNDRED[n3][0])
|
||||
else:
|
||||
words.append(ONES[n3][0])
|
||||
words.append(HUNDRED[3][0])
|
||||
|
||||
if n2 > 1:
|
||||
words.append(TWENTIES[n2][0])
|
||||
|
||||
if n2 == 1:
|
||||
words.append(TENS[n1][0])
|
||||
elif n1 > 0 and not (i > 0 and x == 1):
|
||||
words.append(ONES[n1][0])
|
||||
|
||||
if i > 0:
|
||||
if i <= 2:
|
||||
words.append(THOUSANDS[i][0])
|
||||
else:
|
||||
words.append(ONES[i][0])
|
||||
words.append(THOUSANDS[1][0])
|
||||
|
||||
if len(words) > 1:
|
||||
words[-1] = AND + words[-1]
|
||||
return ' '.join(words)
|
||||
|
||||
|
||||
def n2w(n):
|
||||
return int2word(int(n))
|
||||
|
||||
|
||||
def to_currency(n, currency='EUR', cents=True, seperator=','):
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
class Num2Word_HE(object):
|
||||
def to_cardinal(self, number):
|
||||
return n2w(number)
|
||||
|
||||
def to_ordinal(self, number):
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
yo = Num2Word_HE()
|
||||
nums = [1, 11, 21, 24, 99, 100, 101, 200, 211, 345, 1000, 1011]
|
||||
for num in nums:
|
||||
print(num, yo.to_cardinal(num))
|
||||
|
||||
196
num2words/lang_ID.py
Normal file
196
num2words/lang_ID.py
Normal file
@@ -0,0 +1,196 @@
|
||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
||||
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import unicode_literals, print_function
|
||||
|
||||
class Num2Word_ID():
|
||||
|
||||
BASE = {0: [],
|
||||
1: ["satu"],
|
||||
2: ["dua"],
|
||||
3: ["tiga"],
|
||||
4: ["empat"],
|
||||
5: ["lima"],
|
||||
6: ["enam"],
|
||||
7: ["tujuh"],
|
||||
8: ["delapan"],
|
||||
9: ["sembilan"]}
|
||||
|
||||
TENS_TO = {3: "ribu",
|
||||
6: "juta",
|
||||
9: "miliar",
|
||||
12: "triliun",
|
||||
15: "kuadriliun",
|
||||
18: "kuantiliun",
|
||||
21: "sekstiliun",
|
||||
24: "septiliun",
|
||||
27: "oktiliun",
|
||||
30: "noniliun",
|
||||
33: "desiliun"}
|
||||
|
||||
errmsg_floatord = "Cannot treat float number as ordinal"
|
||||
errmsg_negord = "Cannot treat negative number as ordinal"
|
||||
errmsg_toobig = "Too large"
|
||||
max_num = 10**36
|
||||
|
||||
def split_by_koma(self, number):
|
||||
return str(number).split('.')
|
||||
|
||||
def split_by_3(self, number):
|
||||
"""
|
||||
starting here, it groups the number by three from the tail
|
||||
'1234567' -> (('1',),('234',),('567',))
|
||||
:param number:str
|
||||
:rtype:tuple
|
||||
"""
|
||||
blocks = ()
|
||||
length = len(number)
|
||||
|
||||
if length < 3:
|
||||
blocks += ((number,),)
|
||||
else:
|
||||
len_of_first_block = length % 3
|
||||
|
||||
if len_of_first_block > 0:
|
||||
first_block = number[0:len_of_first_block],
|
||||
blocks += first_block,
|
||||
|
||||
for i in range(len_of_first_block, length, 3):
|
||||
next_block = (number[i:i+3],),
|
||||
blocks += next_block
|
||||
|
||||
return blocks
|
||||
|
||||
def spell(self, blocks):
|
||||
"""
|
||||
it adds the list of spelling to the blocks
|
||||
(('1',),('034',)) -> (('1',['satu']),('234',['tiga', 'puluh', 'empat']))
|
||||
:param blocks: tuple
|
||||
:rtype: tuple
|
||||
"""
|
||||
word_blocks = ()
|
||||
first_block = blocks[0]
|
||||
if len(first_block[0]) == 1:
|
||||
if first_block[0] == '0':
|
||||
spelling = ['nol']
|
||||
else:
|
||||
spelling = self.BASE[int(first_block[0])]
|
||||
elif len(first_block[0]) == 2:
|
||||
spelling = self.puluh(first_block[0])
|
||||
else:
|
||||
spelling = self.ratus(first_block[0][0]) + self.puluh(first_block[0][1:3])
|
||||
|
||||
word_blocks += (first_block[0], spelling),
|
||||
|
||||
for block in blocks[1:]:
|
||||
spelling = self.ratus(block[0][0]) + self.puluh(block[0][1:3])
|
||||
block += spelling,
|
||||
word_blocks += block,
|
||||
|
||||
return word_blocks
|
||||
|
||||
def ratus(self, number):
|
||||
# it is used to spell
|
||||
if number == '1':
|
||||
return ['seratus']
|
||||
elif number == '0':
|
||||
return []
|
||||
else:
|
||||
return self.BASE[int(number)]+['ratus']
|
||||
|
||||
def puluh(self, number):
|
||||
# it is used to spell
|
||||
if number[0] == '1':
|
||||
if number[1]== '0':
|
||||
return ['sepuluh']
|
||||
elif number[1] == '1':
|
||||
return ['sebelas']
|
||||
else:
|
||||
return self.BASE[int(number[1])]+['belas']
|
||||
elif number[0] == '0':
|
||||
return self.BASE[int(number[1])]
|
||||
else:
|
||||
return self.BASE[int(number[0])]+['puluh']+ self.BASE[int(number[1])]
|
||||
|
||||
def spell_float(self, float_part):
|
||||
# spell the float number
|
||||
word_list = []
|
||||
for n in float_part:
|
||||
if n == '0':
|
||||
word_list += ['nol']
|
||||
continue
|
||||
word_list += self.BASE[int(n)]
|
||||
return ' '.join(['','koma']+word_list)
|
||||
|
||||
def join(self, word_blocks, float_part):
|
||||
"""
|
||||
join the words by first join lists in the tuple
|
||||
:param word_blocks: tuple
|
||||
:rtype: str
|
||||
"""
|
||||
word_list = []
|
||||
length = len(word_blocks)-1
|
||||
first_block = word_blocks[0],
|
||||
start = 0
|
||||
|
||||
if length == 1 and first_block[0][0] == '1':
|
||||
word_list += ['seribu']
|
||||
start = 1
|
||||
|
||||
for i in range(start, length+1, 1):
|
||||
word_list += word_blocks[i][1]
|
||||
if not word_blocks[i][1]:
|
||||
continue
|
||||
if i == length:
|
||||
break
|
||||
word_list += [self.TENS_TO[(length-i)*3]]
|
||||
|
||||
return ' '.join(word_list)+float_part
|
||||
|
||||
def to_cardinal(self, number):
|
||||
if number >= self.max_num:
|
||||
raise OverflowError(self.errmsg_toobig % (number, self.maxnum))
|
||||
minus = ''
|
||||
if number < 0:
|
||||
minus = 'min '
|
||||
float_word = ''
|
||||
n = self.split_by_koma(abs(number))
|
||||
if len(n)==2:
|
||||
float_word = self.spell_float(n[1])
|
||||
return minus + self.join(self.spell(self.split_by_3(n[0])), float_word)
|
||||
|
||||
def to_ordinal(self, number):
|
||||
self.verify_ordinal(number)
|
||||
out_word = self.to_cardinal(number)
|
||||
if out_word == "satu":
|
||||
return "pertama"
|
||||
return "ke" + out_word
|
||||
|
||||
def to_ordinal_num(self, number):
|
||||
self.verify_ordinal(number)
|
||||
return "ke-" + str(number)
|
||||
|
||||
def to_currency(self, value):
|
||||
return self.to_cardinal(value)+" rupiah"
|
||||
|
||||
def to_year(self, value):
|
||||
return self.to_cardinal(value)
|
||||
|
||||
def verify_ordinal(self, value):
|
||||
if not value == int(value):
|
||||
raise TypeError(self.errmsg_floatord % value)
|
||||
if not abs(value) == value:
|
||||
raise TypeError(self.errmsg_negord % value)
|
||||
202
num2words/lang_IT.py
Normal file
202
num2words/lang_IT.py
Normal file
@@ -0,0 +1,202 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import unicode_literals
|
||||
from .lang_EU import Num2Word_EU
|
||||
|
||||
# Globals
|
||||
# -------
|
||||
|
||||
ZERO = "zero"
|
||||
|
||||
CARDINAL_WORDS = [
|
||||
ZERO, "uno", "due", "tre", "quattro", "cinque", "sei", "sette", "otto",
|
||||
"nove", "dieci", "undici", "dodici", "tredici", "quattordici", "quindici",
|
||||
"sedici", "diciassette", "diciotto", "diciannove"
|
||||
]
|
||||
|
||||
ORDINAL_WORDS = [
|
||||
ZERO, "primo", "secondo", "terzo", "quarto", "quinto", "sesto", "settimo",
|
||||
"ottavo", "nono", "decimo", "undicesimo", "dodicesimo", "tredicesimo",
|
||||
"quattordicesimo", "quindicesimo", "sedicesimo", "diciassettesimo",
|
||||
"diciottesimo", "diciannovesimo"
|
||||
]
|
||||
|
||||
# The script can extrapolate the missing numbers from the base forms.
|
||||
STR_TENS = {2: "venti", 3: "trenta", 4: "quaranta", 6: "sessanta"}
|
||||
|
||||
# These prefixes are used for extremely big numbers.
|
||||
EXPONENT_PREFIXES = [
|
||||
ZERO, "m", "b", "tr", "quadr", "quint", "sest", "sett", "ott", "nov", "dec"
|
||||
]
|
||||
|
||||
# Utils
|
||||
# =====
|
||||
|
||||
def phonetic_contraction(string):
|
||||
return (string
|
||||
.replace("oo", "o") # ex. "centootto"
|
||||
.replace("ao", "o") # ex. "settantaotto"
|
||||
.replace("io", "o") # ex. "ventiotto"
|
||||
.replace("au", "u") # ex. "trentauno"
|
||||
)
|
||||
|
||||
def exponent_length_to_string(exponent_length):
|
||||
# We always assume `exponent` to be a multiple of 3. If it's not true, then
|
||||
# Num2Word_IT.big_number_to_cardinal did something wrong.
|
||||
prefix = EXPONENT_PREFIXES[exponent_length // 6]
|
||||
if exponent_length % 6 == 0:
|
||||
return prefix + "ilione"
|
||||
else:
|
||||
return prefix + "iliardo"
|
||||
|
||||
def accentuate(string):
|
||||
# This is inefficient: it may do several rewritings when deleting
|
||||
# half-sentence accents. However, it is the easiest method and speed is
|
||||
# not crucial (duh), so...
|
||||
return " ".join(
|
||||
# Deletes half-sentence accents and accentuates the last "tre"
|
||||
[w.replace("tré", "tre")[:-3] + "tré"
|
||||
# We shouldn't accentuate a single "tre": is has to be a composite
|
||||
# word. ~~~~~~~~~~
|
||||
if w[-3:] == "tre" and len(w) > 3
|
||||
# Deletes half-sentence accents anyway
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~
|
||||
else w.replace("tré", "tre")
|
||||
for w in string.split()
|
||||
])
|
||||
|
||||
def omitt_if_zero(number_to_string):
|
||||
return "" if number_to_string == ZERO else number_to_string
|
||||
|
||||
# Main class
|
||||
# ==========
|
||||
|
||||
class Num2Word_IT:
|
||||
|
||||
MINUS_PREFIX_WORD = "meno "
|
||||
FLOAT_INFIX_WORD = " virgola "
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def float_to_words(self, float_number, ordinal=False):
|
||||
if ordinal:
|
||||
prefix = self.to_ordinal(int(float_number))
|
||||
else:
|
||||
prefix = self.to_cardinal(int(float_number))
|
||||
postfix = " ".join(
|
||||
# Drops the trailing zero and comma ~~~~
|
||||
[self.to_cardinal(int(c)) for c in str(float_number % 1)[2:]]
|
||||
)
|
||||
return prefix + Num2Word_IT.FLOAT_INFIX_WORD + postfix
|
||||
|
||||
def tens_to_cardinal(self, number):
|
||||
tens = number // 10
|
||||
units = number % 10
|
||||
if tens in STR_TENS:
|
||||
prefix = STR_TENS[tens]
|
||||
else:
|
||||
prefix = CARDINAL_WORDS[tens][:-1] + "anta"
|
||||
postfix = omitt_if_zero(CARDINAL_WORDS[units])
|
||||
return phonetic_contraction(prefix + postfix)
|
||||
|
||||
def hundreds_to_cardinal(self, number):
|
||||
hundreds = number // 100
|
||||
prefix = "cento"
|
||||
if hundreds != 1:
|
||||
prefix = CARDINAL_WORDS[hundreds] + prefix
|
||||
postfix = omitt_if_zero(self.to_cardinal(number % 100))
|
||||
return phonetic_contraction(prefix + postfix)
|
||||
|
||||
def thousands_to_cardinal(self, number):
|
||||
thousands = number // 1000
|
||||
if thousands == 1:
|
||||
prefix = "mille"
|
||||
else:
|
||||
prefix = self.to_cardinal(thousands) + "mila"
|
||||
postfix = omitt_if_zero(self.to_cardinal(number % 1000))
|
||||
# "mille" and "mila" don't need any phonetic contractions
|
||||
return prefix + postfix
|
||||
|
||||
def big_number_to_cardinal(self, number):
|
||||
digits = [c for c in str(number)]
|
||||
length = len(digits)
|
||||
if length >= 66:
|
||||
raise NotImplementedError("The given number is too large.")
|
||||
# This is how many digits come before the "illion" term.
|
||||
# cento miliardi => 3
|
||||
# dieci milioni => 2
|
||||
# un miliardo => 1
|
||||
predigits = length % 3 or 3
|
||||
multiplier = digits[:predigits]
|
||||
exponent = digits[predigits:]
|
||||
# Default infix string: "milione", "biliardo", "sestilione", ecc.
|
||||
infix = exponent_length_to_string(len(exponent))
|
||||
if multiplier == ["1"]:
|
||||
prefix = "un "
|
||||
else:
|
||||
prefix = self.to_cardinal(int("".join(multiplier)))
|
||||
# Plural form ~~~~~~~~~~~
|
||||
infix = " " + infix[:-1] + "i"
|
||||
# Read as: Does the value of exponent equal 0?
|
||||
if set(exponent) != set("0"):
|
||||
postfix = self.to_cardinal(int("".join(exponent)))
|
||||
if " e " in postfix:
|
||||
infix += ", "
|
||||
else:
|
||||
infix += " e "
|
||||
else:
|
||||
postfix = ""
|
||||
return prefix + infix + postfix
|
||||
|
||||
def to_cardinal(self, number):
|
||||
if number < 0:
|
||||
string = Num2Word_IT.MINUS_PREFIX_WORD + self.to_cardinal(-number)
|
||||
elif number % 1 != 0:
|
||||
string = self.float_to_words(number)
|
||||
elif number < 20:
|
||||
string = CARDINAL_WORDS[number]
|
||||
elif number < 100:
|
||||
string = self.tens_to_cardinal(number)
|
||||
elif number < 1000:
|
||||
string = self.hundreds_to_cardinal(number)
|
||||
elif number < 1000000:
|
||||
string = self.thousands_to_cardinal(number)
|
||||
else:
|
||||
string = self.big_number_to_cardinal(number)
|
||||
return accentuate(string)
|
||||
|
||||
def to_ordinal(self, number):
|
||||
tens = number % 100
|
||||
# Italian grammar is poorly defined here ¯\_(ツ)_/¯:
|
||||
# centodecimo VS centodieciesimo VS centesimo decimo?
|
||||
is_outside_teens = not 10 < tens < 20
|
||||
if number < 0:
|
||||
return Num2Word_IT.MINUS_PREFIX_WORD + self.to_ordinal(-number)
|
||||
elif number % 1 != 0:
|
||||
return self.float_to_words(number, ordinal=True)
|
||||
elif number < 20:
|
||||
return ORDINAL_WORDS[number]
|
||||
elif is_outside_teens and tens % 10 == 3:
|
||||
# Gets ride of the accent ~~~~~~~~~~
|
||||
return self.to_cardinal(number)[:-1] + "eesimo"
|
||||
elif is_outside_teens and tens % 10 == 6:
|
||||
return self.to_cardinal(number) + "esimo"
|
||||
else:
|
||||
string = self.to_cardinal(number)[:-1]
|
||||
if string[-3:] == "mil":
|
||||
string += "l"
|
||||
return string + "esimo"
|
||||
@@ -85,7 +85,13 @@ vienas litas, nulis centų
|
||||
vienas tūkstantis du šimtai trisdešimt keturi litai, penkiasdešimt šeši centai
|
||||
|
||||
>>> print(to_currency(-1251985, cents = False))
|
||||
minus dvylika tūkstančių penki šimtai devyniolika litų, 85 centai
|
||||
minus dvylika tūkstančių penki šimtai devyniolika eurų, 85 centai
|
||||
|
||||
>>> print(to_currency(1.0, 'EUR'))
|
||||
vienas euras, nulis centų
|
||||
|
||||
>>> print(to_currency(1234.56, 'EUR'))
|
||||
vienas tūkstantis du šimtai trisdešimt keturi eurai, penkiasdešimt šeši centai
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
|
||||
@@ -144,6 +150,7 @@ THOUSANDS = {
|
||||
|
||||
CURRENCIES = {
|
||||
'LTL': ((u'litas', u'litai', u'litų'), (u'centas', u'centai', u'centų')),
|
||||
'EUR': ((u'euras', u'eurai', u'eurų'), (u'centas', u'centai', u'centų')),
|
||||
}
|
||||
|
||||
def splitby3(n):
|
||||
@@ -210,7 +217,7 @@ def n2w(n):
|
||||
else:
|
||||
return int2word(int(n))
|
||||
|
||||
def to_currency(n, currency='LTL', cents = True):
|
||||
def to_currency(n, currency='EUR', cents = True):
|
||||
if type(n) == int:
|
||||
if n < 0:
|
||||
minus = True
|
||||
|
||||
154
num2words/lang_NL.py
Normal file
154
num2words/lang_NL.py
Normal file
@@ -0,0 +1,154 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
||||
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import unicode_literals, print_function
|
||||
from .lang_EU import Num2Word_EU
|
||||
|
||||
class Num2Word_NL(Num2Word_EU):
|
||||
def set_high_numwords(self, high):
|
||||
max = 3 + 6*len(high)
|
||||
|
||||
for word, n in zip(high, range(max, 3, -6)):
|
||||
self.cards[10**n] = word + "iljard"
|
||||
self.cards[10**(n-3)] = word + "iljoen"
|
||||
|
||||
def setup(self):
|
||||
self.negword = "min "
|
||||
self.pointword = "komma"
|
||||
self.errmsg_floatord = "Het zwevende puntnummer %s kan niet omgezet worden naar een ordernummer." # "Cannot treat float %s as ordinal."
|
||||
self.errmsg_nonnum = "Alleen nummers (type (%s)) kunnen naar woorden omgezet worden." # "type(((type(%s)) ) not in [long, int, float]"
|
||||
self.errmsg_negord = "Het negatieve getal %s kan niet omgezet worden naar een ordernummer." # "Cannot treat negative num %s as ordinal."
|
||||
self.errmsg_toobig = "Het getal %s moet minder zijn dan %s." # "abs(%s) must be less than %s."
|
||||
self.exclude_title = []
|
||||
|
||||
lows = ["non", "okt", "sept", "sext", "quint", "quadr", "tr", "b", "m"]
|
||||
units = ["", "un", "duo", "tre", "quattuor", "quin", "sex", "sept",
|
||||
"okto", "novem"]
|
||||
tens = ["dez", "vigint", "trigint", "quadragint", "quinquagint",
|
||||
"sexagint", "septuagint", "oktogint", "nonagint"]
|
||||
|
||||
|
||||
|
||||
|
||||
self.high_numwords = ["zend"]+self.gen_high_numwords(units, tens, lows)
|
||||
self.mid_numwords = [(1000, "duizend"), (100, "honderd"),
|
||||
(90, "negentig"), (80, "tachtig"), (70, "zeventig"),
|
||||
(60, "zestig"), (50, "vijftig"), (40, "veertig"),
|
||||
(30, "dertig")]
|
||||
self.low_numwords = ["twintig", "negentien", "achttien", "zeventien",
|
||||
"zestien", "vijftien", "veertien", "dertien",
|
||||
"twaalf", "elf", "tien", "negen", "acht", "zeven",
|
||||
"zes", "vijf", "vier", "drie", "twee", "één",
|
||||
"nul"]
|
||||
|
||||
self.ords = {"één": "eerst",
|
||||
"twee": "tweed",
|
||||
"drie": "derd",
|
||||
"vier": "vierd",
|
||||
"vijf": "vijfd",
|
||||
"zes": "zesd",
|
||||
"zeven": "zevend",
|
||||
"acht": "achtst",
|
||||
"negen": "negend",
|
||||
"tien":"tiend",
|
||||
"elf":"elfd",
|
||||
"twaalf":"twaalfd",
|
||||
|
||||
"ig": "igst",
|
||||
"erd": "erdst",
|
||||
"end": "endst",
|
||||
"joen": "joenst",
|
||||
"rd": "rdst"}
|
||||
|
||||
def merge(self, curr, next):
|
||||
ctext, cnum, ntext, nnum = curr + next
|
||||
|
||||
if cnum == 1:
|
||||
if nnum < 10**6:
|
||||
return next
|
||||
ctext = "een"
|
||||
|
||||
if nnum > cnum:
|
||||
if nnum >= 10**6:
|
||||
ctext += " "
|
||||
val = cnum * nnum
|
||||
else:
|
||||
if nnum < 10 < cnum < 100:
|
||||
if nnum == 1:
|
||||
ntext = "een"
|
||||
|
||||
if ntext.endswith("e"):
|
||||
ntext += "ën"#"n"
|
||||
else:
|
||||
ntext += "en"
|
||||
ntext, ctext = ctext, ntext #+ "en"
|
||||
elif cnum >= 10**6:
|
||||
ctext += " "
|
||||
val = cnum + nnum
|
||||
|
||||
word = ctext + ntext
|
||||
return (word, val)
|
||||
|
||||
def to_ordinal(self, value):
|
||||
self.verify_ordinal(value)
|
||||
outword = self.to_cardinal(value)
|
||||
for key in self.ords:
|
||||
if outword.endswith(key):
|
||||
outword = outword[:len(outword) - len(key)] + self.ords[key]
|
||||
break
|
||||
return outword + "e"
|
||||
|
||||
def to_ordinal_num(self, value):
|
||||
self.verify_ordinal(value)
|
||||
return str(value) + "."
|
||||
|
||||
def to_currency(self, val, longval=True, old=False):
|
||||
if old:
|
||||
return self.to_splitnum(val, hightxt="euro/s", lowtxt="cent/s",
|
||||
jointxt="en",longval=longval)
|
||||
return super(Num2Word_NL, self).to_currency(val, jointxt="en",
|
||||
longval=longval)
|
||||
|
||||
def to_year(self, val, longval=True):
|
||||
if not (val//100)%10:
|
||||
return self.to_cardinal(val)
|
||||
return self.to_splitnum(val, hightxt="honderd", longval=longval)
|
||||
|
||||
n2w = Num2Word_NL()
|
||||
to_card = n2w.to_cardinal
|
||||
to_ord = n2w.to_ordinal
|
||||
to_ordnum = n2w.to_ordinal_num
|
||||
|
||||
|
||||
def main():
|
||||
for val in [1, 7, 8, 12, 17, 62,81, 91, 99, 100, 101, 102, 155,
|
||||
180, 300, 308, 832, 1000, 1001, 1061,1062, 1100, 1500, 1701, 3000,
|
||||
8280, 8291, 150000, 500000, 3000000, 1000000, 2000001, 1000000000, 2000000000,
|
||||
-21212121211221211111, -2.121212, -1.0000100]:
|
||||
n2w.test(val)
|
||||
|
||||
n2w.test(3000000)
|
||||
n2w.test(3000000000001)
|
||||
n2w.test(3000000324566)
|
||||
print(n2w.to_currency(112121))
|
||||
print(n2w.to_year(2000))
|
||||
print(n2w.to_year(1820))
|
||||
print(n2w.to_year(2001))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
123
num2words/lang_NO.py
Normal file
123
num2words/lang_NO.py
Normal file
@@ -0,0 +1,123 @@
|
||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
||||
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import division, unicode_literals, print_function
|
||||
from . import lang_EU
|
||||
|
||||
class Num2Word_NO(lang_EU.Num2Word_EU):
|
||||
def set_high_numwords(self, high):
|
||||
max = 3 + 6*len(high)
|
||||
for word, n in zip(high, range(max, 3, -6)):
|
||||
self.cards[10**n] = word + "illard"
|
||||
self.cards[10**(n-3)] = word + "illion"
|
||||
|
||||
def setup(self):
|
||||
self.negword = "minus "
|
||||
self.pointword = "komma"
|
||||
self.errmsg_nornum = "Bare tall kan bli konvertert til ord."
|
||||
self.exclude_title = ["og", "komma", "minus"]
|
||||
|
||||
self.mid_numwords = [(1000, "tusen"), (100, "hundre"),
|
||||
(90, "nitti"), (80, "\xe5tti"), (70, "sytti"),
|
||||
(60, "seksti"), (50, "femti"), (40, "f\xf8rti"),
|
||||
(30, "tretti")]
|
||||
self.low_numwords = ["tjue", "nitten", "atten", "sytten",
|
||||
"seksten", "femten", "fjorten", "tretten",
|
||||
"tolv", "elleve", "ti", "ni", "\xe5tte",
|
||||
"syv", "seks", "fem", "fire", "tre", "to",
|
||||
"en", "null"]
|
||||
self.ords = { "en" : "f\xf8rste",
|
||||
"to" : "andre",
|
||||
"tre" : "tredje",
|
||||
"fire" : "fjerde",
|
||||
"fem" : "femte",
|
||||
"seks" : "sjette",
|
||||
"syv" : "syvende",
|
||||
"\xe5tte" : "\xe5ttende",
|
||||
"ni" : "niende",
|
||||
"ti" : "tiende",
|
||||
"elleve" : "ellevte",
|
||||
"tolv" : "tolvte",
|
||||
"tjue" : "tjuende" }
|
||||
|
||||
|
||||
def merge(self, lpair, rpair):
|
||||
ltext, lnum = lpair
|
||||
rtext, rnum = rpair
|
||||
if lnum == 1 and rnum < 100:
|
||||
return (rtext, rnum)
|
||||
elif 100 > lnum > rnum :
|
||||
return ("%s-%s"%(ltext, rtext), lnum + rnum)
|
||||
elif lnum >= 100 > rnum:
|
||||
return ("%s og %s"%(ltext, rtext), lnum + rnum)
|
||||
elif rnum > lnum:
|
||||
return ("%s %s"%(ltext, rtext), lnum * rnum)
|
||||
return ("%s, %s"%(ltext, rtext), lnum + rnum)
|
||||
|
||||
|
||||
def to_ordinal(self, value):
|
||||
self.verify_ordinal(value)
|
||||
outwords = self.to_cardinal(value).split(" ")
|
||||
lastwords = outwords[-1].split("-")
|
||||
lastword = lastwords[-1].lower()
|
||||
try:
|
||||
lastword = self.ords[lastword]
|
||||
except KeyError:
|
||||
if lastword[-2:] == "ti":
|
||||
lastword = lastword + "ende"
|
||||
else:
|
||||
lastword += "de"
|
||||
lastwords[-1] = self.title(lastword)
|
||||
outwords[-1] = "".join(lastwords)
|
||||
return " ".join(outwords)
|
||||
|
||||
|
||||
def to_ordinal_num(self, value):
|
||||
self.verify_ordinal(value)
|
||||
return "%s%s"%(value, self.to_ordinal(value)[-2:])
|
||||
|
||||
|
||||
def to_year(self, val, longval=True):
|
||||
if not (val//100)%10:
|
||||
return self.to_cardinal(val)
|
||||
return self.to_splitnum(val, hightxt="hundre", jointxt="og",
|
||||
longval=longval)
|
||||
|
||||
def to_currency(self, val, longval=True):
|
||||
return self.to_splitnum(val, hightxt="krone/r", lowtxt="\xf8re/r",
|
||||
jointxt="og", longval=longval, cents = True)
|
||||
|
||||
|
||||
n2w = Num2Word_NO()
|
||||
to_card = n2w.to_cardinal
|
||||
to_ord = n2w.to_ordinal
|
||||
to_ordnum = n2w.to_ordinal_num
|
||||
to_year = n2w.to_year
|
||||
|
||||
def main():
|
||||
for val in [ 1, 11, 12, 21, 31, 33, 71, 80, 81, 91, 99, 100, 101, 102, 155,
|
||||
180, 300, 308, 832, 1000, 1001, 1061, 1100, 1500, 1701, 3000,
|
||||
8280, 8291, 150000, 500000, 1000000, 2000000, 2000001,
|
||||
-21212121211221211111, -2.121212, -1.0000100]:
|
||||
n2w.test(val)
|
||||
n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
|
||||
for val in [1,120,1000,1120,1800, 1976,2000,2010,2099,2171]:
|
||||
print(val, "er", n2w.to_currency(val))
|
||||
print(val, "er", n2w.to_year(val))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
290
num2words/lang_PL.py
Normal file
290
num2words/lang_PL.py
Normal file
@@ -0,0 +1,290 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
||||
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
u"""
|
||||
>>> from textwrap import fill
|
||||
|
||||
>>> ' '.join([str(i) for i in splitby3('1')])
|
||||
u'1'
|
||||
>>> ' '.join([str(i) for i in splitby3('1123')])
|
||||
u'1 123'
|
||||
>>> ' '.join([str(i) for i in splitby3('1234567890')])
|
||||
u'1 234 567 890'
|
||||
|
||||
>>> print(' '.join([n2w(i) for i in range(10)]))
|
||||
zero jeden dwa trzy cztery pięć sześć siedem osiem dziewięć
|
||||
|
||||
>>> print(fill(' '.join([n2w(i+10) for i in range(10)])))
|
||||
dziesięć jedenaście dwanaście trzynaście czternaście piętnaście
|
||||
szesnaście siedemnaście osiemnaście dziewiętnaście
|
||||
|
||||
>>> print(fill(' '.join([n2w(i*10) for i in range(10)])))
|
||||
zero dziesięć dwadzieścia trzydzieści czterdzieści pięćdziesiąt
|
||||
sześćdziesiąt siedemdziesiąt osiemdziesiąt dziewięćdzisiąt
|
||||
|
||||
>>> print(n2w(100))
|
||||
sto
|
||||
>>> print(n2w(101))
|
||||
sto jeden
|
||||
>>> print(n2w(110))
|
||||
sto dziesięć
|
||||
>>> print(n2w(115))
|
||||
sto piętnaście
|
||||
>>> print(n2w(123))
|
||||
sto dwadzieścia trzy
|
||||
>>> print(n2w(1000))
|
||||
tysiąc
|
||||
>>> print(n2w(1001))
|
||||
tysiąc jeden
|
||||
>>> print(n2w(2012))
|
||||
dwa tysiące dwanaście
|
||||
|
||||
>>> print(n2w(12519.85))
|
||||
dwanaście tysięcy pięćset dziewiętnaście przecinek osiemdziesiąt pięć
|
||||
|
||||
>>> print(n2w(123.50))
|
||||
sto dwadzieścia trzy przecinek pięć
|
||||
|
||||
>>> print(fill(n2w(1234567890)))
|
||||
miliard dwieście trzydzieści cztery miliony pięćset sześćdziesiąt
|
||||
siedem tysięcy osiemset dziewięćdzisiąt
|
||||
|
||||
>>> print(fill(n2w(215461407892039002157189883901676)))
|
||||
dwieście piętnaście kwintylionów czterysta sześćdziesiąt jeden
|
||||
kwadryliardów czterysta siedem kwadrylionów osiemset dziewięćdzisiąt
|
||||
dwa tryliardy trzydzieści dziewięć trylionów dwa biliardy sto
|
||||
pięćdziesiąt siedem bilionów sto osiemdziesiąt dziewięć miliardów
|
||||
osiemset osiemdziesiąt trzy miliony dziewęćset jeden tysięcy sześćset
|
||||
siedemdziesiąt sześć
|
||||
|
||||
>>> print(fill(n2w(719094234693663034822824384220291)))
|
||||
siedemset dziewiętnaście kwintylionów dziewięćdzisiąt cztery
|
||||
kwadryliardy dwieście trzydzieści cztery kwadryliony sześćset
|
||||
dziewięćdzisiąt trzy tryliardy sześćset sześćdziesiąt trzy tryliony
|
||||
trzydzieści cztery biliardy osiemset dwadzieścia dwa biliony osiemset
|
||||
dwadzieścia cztery miliardy trzysta osiemdziesiąt cztery miliony
|
||||
dwieście dwadzieścia tysięcy dwieście dziewięćdzisiąt jeden
|
||||
|
||||
>>> print(to_currency(1.0, 'EUR'))
|
||||
jeden euro, zero centów
|
||||
|
||||
>>> print(to_currency(1.0, 'PLN'))
|
||||
jeden złoty, zero groszy
|
||||
|
||||
>>> print(to_currency(1234.56, 'EUR'))
|
||||
tysiąc dwieście trzydzieści cztery euro, pięćdziesiąt sześć centów
|
||||
|
||||
>>> print(to_currency(1234.56, 'PLN'))
|
||||
tysiąc dwieście trzydzieści cztery złote, pięćdziesiąt sześć groszy
|
||||
|
||||
>>> print(to_currency(10111, 'EUR', seperator=' i'))
|
||||
sto jeden euro i jedenaście centów
|
||||
|
||||
>>> print(to_currency(10121, 'PLN', seperator=' i'))
|
||||
sto jeden złotych i dwadzieścia jeden groszy
|
||||
|
||||
>>> print(to_currency(-1251985, cents = False))
|
||||
minus dwanaście tysięcy pięćset dziewiętnaście euro, 85 centów
|
||||
|
||||
>>> print(to_currency(123.50, 'PLN', seperator=' i'))
|
||||
sto dwadzieścia trzy złote i pięćdziesiąt groszy
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
|
||||
ZERO = (u'zero',)
|
||||
|
||||
ONES = {
|
||||
1: (u'jeden',),
|
||||
2: (u'dwa',),
|
||||
3: (u'trzy',),
|
||||
4: (u'cztery',),
|
||||
5: (u'pięć',),
|
||||
6: (u'sześć',),
|
||||
7: (u'siedem',),
|
||||
8: (u'osiem',),
|
||||
9: (u'dziewięć',),
|
||||
}
|
||||
|
||||
TENS = {
|
||||
0: (u'dziesięć',),
|
||||
1: (u'jedenaście',),
|
||||
2: (u'dwanaście',),
|
||||
3: (u'trzynaście',),
|
||||
4: (u'czternaście',),
|
||||
5: (u'piętnaście',),
|
||||
6: (u'szesnaście',),
|
||||
7: (u'siedemnaście',),
|
||||
8: (u'osiemnaście',),
|
||||
9: (u'dziewiętnaście',),
|
||||
}
|
||||
|
||||
TWENTIES = {
|
||||
2: (u'dwadzieścia',),
|
||||
3: (u'trzydzieści',),
|
||||
4: (u'czterdzieści',),
|
||||
5: (u'pięćdziesiąt',),
|
||||
6: (u'sześćdziesiąt',),
|
||||
7: (u'siedemdziesiąt',),
|
||||
8: (u'osiemdziesiąt',),
|
||||
9: (u'dziewięćdzisiąt',),
|
||||
}
|
||||
|
||||
HUNDREDS = {
|
||||
1: (u'sto',),
|
||||
2: (u'dwieście',),
|
||||
3: (u'trzysta',),
|
||||
4: (u'czterysta',),
|
||||
5: (u'pięćset',),
|
||||
6: (u'sześćset',),
|
||||
7: (u'siedemset',),
|
||||
8: (u'osiemset',),
|
||||
9: (u'dziewęćset',),
|
||||
}
|
||||
|
||||
THOUSANDS = {
|
||||
1: (u'tysiąc', u'tysiące', u'tysięcy'), # 10^3
|
||||
2: (u'milion', u'miliony', u'milionów'), # 10^6
|
||||
3: (u'miliard', u'miliardy', u'miliardów'), # 10^9
|
||||
4: (u'bilion', u'biliony', u'bilionów'), # 10^12
|
||||
5: (u'biliard', u'biliardy', u'biliardów'), # 10^15
|
||||
6: (u'trylion', u'tryliony', u'trylionów'), # 10^18
|
||||
7: (u'tryliard', u'tryliardy', u'tryliardów'), # 10^21
|
||||
8: (u'kwadrylion', u'kwadryliony', u'kwadrylionów'), # 10^24
|
||||
9: (u'kwaryliard', u'kwadryliardy', u'kwadryliardów'), #10^27
|
||||
10: (u'kwintylion', u'kwintyliony', u'kwintylionów'), # 10^30
|
||||
}
|
||||
|
||||
CURRENCIES = {
|
||||
'PLN': (
|
||||
(u'złoty', u'złote', u'złotych'), (u'grosz', u'grosze', u'groszy')
|
||||
),
|
||||
'EUR': (
|
||||
(u'euro', u'euro', u'euro'), (u'cent', u'centy', u'centów')
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def splitby3(n):
|
||||
length = len(n)
|
||||
if length > 3:
|
||||
start = length % 3
|
||||
if start > 0:
|
||||
yield int(n[:start])
|
||||
for i in range(start, length, 3):
|
||||
yield int(n[i:i + 3])
|
||||
else:
|
||||
yield int(n)
|
||||
|
||||
|
||||
def get_digits(n):
|
||||
return [int(x) for x in reversed(list(('%03d' % n)[-3:]))]
|
||||
|
||||
|
||||
def pluralize(n, forms):
|
||||
form = 0 if n == 1 else 1 if (n % 10 > 1 and n % 10 < 5 and (n % 100 < 10 or n % 100 > 20)) else 2
|
||||
return forms[form]
|
||||
|
||||
|
||||
def int2word(n):
|
||||
if n == 0:
|
||||
return ZERO[0]
|
||||
|
||||
words = []
|
||||
chunks = list(splitby3(str(n)))
|
||||
i = len(chunks)
|
||||
for x in chunks:
|
||||
i -= 1
|
||||
n1, n2, n3 = get_digits(x)
|
||||
|
||||
if n3 > 0:
|
||||
words.append(HUNDREDS[n3][0])
|
||||
|
||||
if n2 > 1:
|
||||
words.append(TWENTIES[n2][0])
|
||||
|
||||
if n2 == 1:
|
||||
words.append(TENS[n1][0])
|
||||
elif n1 > 0 and not (i > 0 and x == 1):
|
||||
words.append(ONES[n1][0])
|
||||
|
||||
if i > 0:
|
||||
words.append(pluralize(x, THOUSANDS[i]))
|
||||
|
||||
return ' '.join(words)
|
||||
|
||||
|
||||
def n2w(n):
|
||||
n = str(n).replace(',', '.')
|
||||
if '.' in n:
|
||||
left, right = n.split('.')
|
||||
return u'%s przecinek %s' % (int2word(int(left)), int2word(int(right)))
|
||||
else:
|
||||
return int2word(int(n))
|
||||
|
||||
|
||||
def to_currency(n, currency = 'EUR', cents = True, seperator = ','):
|
||||
if type(n) == int:
|
||||
if n < 0:
|
||||
minus = True
|
||||
else:
|
||||
minus = False
|
||||
|
||||
n = abs(n)
|
||||
left = n // 100
|
||||
right = n % 100
|
||||
else:
|
||||
n = str(n).replace(',', '.')
|
||||
if '.' in n:
|
||||
left, right = n.split('.')
|
||||
if len(right) == 1:
|
||||
right = right + '0'
|
||||
else:
|
||||
left, right = n, 0
|
||||
left, right = int(left), int(right)
|
||||
minus = False
|
||||
cr1, cr2 = CURRENCIES[currency]
|
||||
|
||||
if minus:
|
||||
minus_str = "minus "
|
||||
else:
|
||||
minus_str = ""
|
||||
|
||||
if cents:
|
||||
cents_str = int2word(right)
|
||||
else:
|
||||
cents_str = "%02d" % right
|
||||
|
||||
return u'%s%s %s%s %s %s' % (
|
||||
minus_str,
|
||||
int2word(left),
|
||||
pluralize(left, cr1),
|
||||
seperator,
|
||||
cents_str,
|
||||
pluralize(right, cr2)
|
||||
)
|
||||
|
||||
|
||||
class Num2Word_PL(object):
|
||||
def to_cardinal(self, number):
|
||||
return n2w(number)
|
||||
|
||||
def to_ordinal(self, number):
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import doctest
|
||||
doctest.testmod()
|
||||
209
num2words/lang_PT_BR.py
Normal file
209
num2words/lang_PT_BR.py
Normal file
@@ -0,0 +1,209 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
||||
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import division, unicode_literals
|
||||
import re
|
||||
|
||||
from . import lang_EU
|
||||
|
||||
|
||||
class Num2Word_PT_BR(lang_EU.Num2Word_EU):
|
||||
def set_high_numwords(self, high):
|
||||
max = 3 + 3*len(high)
|
||||
for word, n in zip(high, range(max, 3, -3)):
|
||||
self.cards[10**n] = word + "ilhão"
|
||||
|
||||
def setup(self):
|
||||
self.negword = "menos "
|
||||
self.pointword = "vírgula"
|
||||
self.errmsg_nornum = "Somente números podem ser convertidos para palavras"
|
||||
self.exclude_title = ["e", "vírgula", "menos"]
|
||||
|
||||
self.mid_numwords = [
|
||||
(1000, "mil"), (100, "cem"), (90, "noventa"),
|
||||
(80, "oitenta"), (70, "setenta"), (60, "sessenta"), (50, "cinquenta"),
|
||||
(40, "quarenta"), (30, "trinta")
|
||||
]
|
||||
self.low_numwords = [
|
||||
"vinte", "dezenove", "dezoito", "dezessete", "dezesseis",
|
||||
"quinze", "catorze", "treze", "doze", "onze", "dez",
|
||||
"nove", "oito", "sete", "seis", "cinco", "quatro", "três", "dois",
|
||||
"um", "zero"
|
||||
]
|
||||
self.ords = [
|
||||
{
|
||||
0: "",
|
||||
1: "primeiro",
|
||||
2: "segundo",
|
||||
3: "terceiro",
|
||||
4: "quarto",
|
||||
5: "quinto",
|
||||
6: "sexto",
|
||||
7: "sétimo",
|
||||
8: "oitavo",
|
||||
9: "nono",
|
||||
},
|
||||
{
|
||||
0: "",
|
||||
1: "décimo",
|
||||
2: "vigésimo",
|
||||
3: "trigésimo",
|
||||
4: "quadragésimo",
|
||||
5: "quinquagésimo",
|
||||
6: "sexagésimo",
|
||||
7: "septuagésimo",
|
||||
8: "octogésimo",
|
||||
9: "nonagésimo",
|
||||
},
|
||||
{
|
||||
0: "",
|
||||
1: "centésimo",
|
||||
2: "ducentésimo",
|
||||
3: "tricentésimo",
|
||||
4: "quadrigentésimo",
|
||||
5: "quingentésimo",
|
||||
6: "seiscentésimo",
|
||||
7: "septigentésimo",
|
||||
8: "octigentésimo",
|
||||
9: "nongentésimo",
|
||||
},
|
||||
]
|
||||
self.thousand_separators = {
|
||||
3: "milésimo",
|
||||
6: "milionésimo",
|
||||
9: "bilionésimo",
|
||||
12: "trilionésimo",
|
||||
15: "quadrilionésimo"
|
||||
}
|
||||
self.hundreds = {
|
||||
1: "cento",
|
||||
2: "duzentos",
|
||||
3: "trezentos",
|
||||
4: "quatrocentos",
|
||||
5: "quinhentos",
|
||||
6: "seiscentos",
|
||||
7: "setecentos",
|
||||
8: "oitocentos",
|
||||
9: "novecentos",
|
||||
}
|
||||
|
||||
def merge(self, curr, next):
|
||||
ctext, cnum, ntext, nnum = curr + next
|
||||
|
||||
if cnum == 1:
|
||||
if nnum < 1000000:
|
||||
return next
|
||||
ctext = "um"
|
||||
elif cnum == 100 and not nnum == 1000:
|
||||
ctext = "cento"
|
||||
|
||||
if nnum < cnum:
|
||||
if cnum < 100:
|
||||
return ("%s e %s" % (ctext, ntext), cnum + nnum)
|
||||
return ("%s e %s" % (ctext, ntext), cnum + nnum)
|
||||
|
||||
elif (not nnum % 1000000) and cnum > 1:
|
||||
ntext = ntext[:-4] + "lhões"
|
||||
|
||||
if nnum == 100:
|
||||
ctext = self.hundreds[cnum]
|
||||
ntext = ""
|
||||
|
||||
else:
|
||||
ntext = " " + ntext
|
||||
|
||||
return (ctext + ntext, cnum * nnum)
|
||||
|
||||
def to_cardinal(self, value):
|
||||
result = super(Num2Word_PT_BR, self).to_cardinal(value)
|
||||
|
||||
# Transforms "mil E cento e catorze reais" into "mil, cento e catorze reais"
|
||||
for ext in (
|
||||
'mil', 'milhão', 'milhões', 'bilhão', 'bilhões',
|
||||
'trilhão', 'trilhões', 'quatrilhão', 'quatrilhões'):
|
||||
if re.match('.*{} e \w*ento'.format(ext), result):
|
||||
result = result.replace('{} e'.format(ext), '{},'.format(ext), 1)
|
||||
|
||||
return result
|
||||
|
||||
def to_ordinal(self, value):
|
||||
self.verify_ordinal(value)
|
||||
|
||||
result = []
|
||||
value = str(value)
|
||||
thousand_separator = ''
|
||||
|
||||
for idx, char in enumerate(value[::-1]):
|
||||
if idx and idx % 3 == 0:
|
||||
thousand_separator = self.thousand_separators[idx]
|
||||
|
||||
if char != '0' and thousand_separator:
|
||||
# avoiding "segundo milionésimo milésimo" for 6000000, for instance
|
||||
result.append(thousand_separator)
|
||||
thousand_separator = ''
|
||||
|
||||
result.append(self.ords[idx % 3][int(char)])
|
||||
|
||||
result = ' '.join(result[::-1])
|
||||
result = result.strip()
|
||||
result = re.sub('\s+', ' ', result)
|
||||
|
||||
if result.startswith('primeiro') and value != '1':
|
||||
# avoiding "primeiro milésimo", "primeiro milionésimo" and so on
|
||||
result = result[9:]
|
||||
|
||||
return result
|
||||
|
||||
def to_ordinal_num(self, value):
|
||||
self.verify_ordinal(value)
|
||||
return "%sº" % (value)
|
||||
|
||||
def to_year(self, val, longval=True):
|
||||
if val < 0:
|
||||
return self.to_cardinal(abs(val)) + ' antes de Cristo'
|
||||
return self.to_cardinal(val)
|
||||
|
||||
def to_currency(self, val, longval=True):
|
||||
integer_part, decimal_part = ('%.2f' % val).split('.')
|
||||
|
||||
result = self.to_cardinal(int(integer_part))
|
||||
|
||||
appended_currency = False
|
||||
for ext in (
|
||||
'milhão', 'milhões', 'bilhão', 'bilhões',
|
||||
'trilhão', 'trilhões', 'quatrilhão', 'quatrilhões'):
|
||||
if result.endswith(ext):
|
||||
result += ' de reais'
|
||||
appended_currency = True
|
||||
|
||||
if result in ['um', 'menos um']:
|
||||
result += ' real'
|
||||
appended_currency = True
|
||||
if not appended_currency:
|
||||
result += ' reais'
|
||||
|
||||
if int(decimal_part):
|
||||
cents = self.to_cardinal(int(decimal_part))
|
||||
result += ' e ' + cents
|
||||
|
||||
if cents == 'um':
|
||||
result += ' centavo'
|
||||
else:
|
||||
result += ' centavos'
|
||||
|
||||
return result
|
||||
312
num2words/lang_RU.py
Normal file
312
num2words/lang_RU.py
Normal file
@@ -0,0 +1,312 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
||||
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
u"""
|
||||
>>> from textwrap import fill
|
||||
|
||||
>>> ' '.join([str(i) for i in splitby3('1')])
|
||||
u'1'
|
||||
>>> ' '.join([str(i) for i in splitby3('1123')])
|
||||
u'1 123'
|
||||
>>> ' '.join([str(i) for i in splitby3('1234567890')])
|
||||
u'1 234 567 890'
|
||||
|
||||
>>> print(' '.join([n2w(i) for i in range(10)]))
|
||||
ноль один два три четыре пять шесть семь восемь девять
|
||||
|
||||
>>> print(fill(' '.join([n2w(i+10) for i in range(10)])))
|
||||
десять одиннадцать двенадцать тринадцать четырнадцать пятнадцать
|
||||
шестнадцать семнадцать восемнадцать девятнадцать
|
||||
|
||||
>>> print(fill(' '.join([n2w(i*10) for i in range(10)])))
|
||||
ноль десять двадцать тридцать сорок пятьдесят шестьдесят семьдесят
|
||||
восемьдесят девяносто
|
||||
|
||||
>>> print(n2w(100))
|
||||
сто
|
||||
>>> print(n2w(101))
|
||||
сто один
|
||||
>>> print(n2w(110))
|
||||
сто десять
|
||||
>>> print(n2w(115))
|
||||
сто пятнадцать
|
||||
>>> print(n2w(123))
|
||||
сто двадцать три
|
||||
>>> print(n2w(1000))
|
||||
тысяча
|
||||
>>> print(n2w(1001))
|
||||
тысяча один
|
||||
>>> print(n2w(2012))
|
||||
две тысячи двенадцать
|
||||
|
||||
>>> print(n2w(12519.85))
|
||||
двенадцать тысяч пятьсот девятнадцать запятая восемьдесят пять
|
||||
|
||||
>>> print(fill(n2w(1234567890)))
|
||||
миллиард двести тридцать четыре миллиона пятьсот шестьдесят семь тысяч
|
||||
восемьсот девяносто
|
||||
|
||||
>>> print(fill(n2w(215461407892039002157189883901676)))
|
||||
двести пятнадцать нониллионов четыреста шестьдесят один октиллион
|
||||
четыреста семь септиллионов восемьсот девяносто два секстиллиона
|
||||
тридцать девять квинтиллионов два квадриллиона сто пятьдесят семь
|
||||
триллионов сто восемьдесят девять миллиардов восемьсот восемьдесят три
|
||||
миллиона девятьсот одна тысяча шестьсот семьдесят шесть
|
||||
|
||||
>>> print(fill(n2w(719094234693663034822824384220291)))
|
||||
семьсот девятнадцать нониллионов девяносто четыре октиллиона двести
|
||||
тридцать четыре септиллиона шестьсот девяносто три секстиллиона
|
||||
шестьсот шестьдесят три квинтиллиона тридцать четыре квадриллиона
|
||||
восемьсот двадцать два триллиона восемьсот двадцать четыре миллиарда
|
||||
триста восемьдесят четыре миллиона двести двадцать тысяч двести
|
||||
девяносто один
|
||||
|
||||
>>> print(to_currency(1.0, 'EUR'))
|
||||
один евро, ноль центов
|
||||
|
||||
>>> print(to_currency(1.0, 'RUB'))
|
||||
один рубль, ноль копеек
|
||||
|
||||
>>> print(to_currency(1234.56, 'EUR'))
|
||||
тысяча двести тридцать четыре евро, пятьдесят шесть центов
|
||||
|
||||
>>> print(to_currency(1234.56, 'RUB'))
|
||||
тысяча двести тридцать четыре рубля, пятьдесят шесть копеек
|
||||
|
||||
>>> print(to_currency(10111, 'EUR', seperator=u' и'))
|
||||
сто один евро и одиннадцать центов
|
||||
|
||||
>>> print(to_currency(10121, 'RUB', seperator=u' и'))
|
||||
сто один рубль и двадцать одна копейка
|
||||
|
||||
>>> print(to_currency(10122, 'RUB', seperator=u' и'))
|
||||
сто один рубль и двадцать две копейки
|
||||
|
||||
>>> print(to_currency(10121, 'EUR', seperator=u' и'))
|
||||
сто один евро и двадцать один цент
|
||||
|
||||
>>> print(to_currency(-1251985, cents = False))
|
||||
минус двенадцать тысяч пятьсот девятнадцать евро, 85 центов
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
|
||||
ZERO = (u'ноль',)
|
||||
|
||||
ONES_FEMININE = {
|
||||
1: (u'одна',),
|
||||
2: (u'две',),
|
||||
3: (u'три',),
|
||||
4: (u'четыре',),
|
||||
5: (u'пять',),
|
||||
6: (u'шесть',),
|
||||
7: (u'семь',),
|
||||
8: (u'восемь',),
|
||||
9: (u'девять',),
|
||||
}
|
||||
|
||||
ONES = {
|
||||
1: (u'один',),
|
||||
2: (u'два',),
|
||||
3: (u'три',),
|
||||
4: (u'четыре',),
|
||||
5: (u'пять',),
|
||||
6: (u'шесть',),
|
||||
7: (u'семь',),
|
||||
8: (u'восемь',),
|
||||
9: (u'девять',),
|
||||
}
|
||||
|
||||
TENS = {
|
||||
0: (u'десять',),
|
||||
1: (u'одиннадцать',),
|
||||
2: (u'двенадцать',),
|
||||
3: (u'тринадцать',),
|
||||
4: (u'четырнадцать',),
|
||||
5: (u'пятнадцать',),
|
||||
6: (u'шестнадцать',),
|
||||
7: (u'семнадцать',),
|
||||
8: (u'восемнадцать',),
|
||||
9: (u'девятнадцать',),
|
||||
}
|
||||
|
||||
TWENTIES = {
|
||||
2: (u'двадцать',),
|
||||
3: (u'тридцать',),
|
||||
4: (u'сорок',),
|
||||
5: (u'пятьдесят',),
|
||||
6: (u'шестьдесят',),
|
||||
7: (u'семьдесят',),
|
||||
8: (u'восемьдесят',),
|
||||
9: (u'девяносто',),
|
||||
}
|
||||
|
||||
HUNDREDS = {
|
||||
1: (u'сто',),
|
||||
2: (u'двести',),
|
||||
3: (u'триста',),
|
||||
4: (u'четыреста',),
|
||||
5: (u'пятьсот',),
|
||||
6: (u'шестьсот',),
|
||||
7: (u'семьсот',),
|
||||
8: (u'восемьсот',),
|
||||
9: (u'девятьсот',),
|
||||
}
|
||||
|
||||
THOUSANDS = {
|
||||
1: (u'тысяча', u'тысячи', u'тысяч'), # 10^3
|
||||
2: (u'миллион', u'миллиона', u'миллионов'), # 10^6
|
||||
3: (u'миллиард', u'миллиарда', u'миллиардов'), # 10^9
|
||||
4: (u'триллион', u'триллиона', u'триллионов'), # 10^12
|
||||
5: (u'квадриллион', u'квадриллиона', u'квадриллионов'), # 10^15
|
||||
6: (u'квинтиллион', u'квинтиллиона', u'квинтиллионов'), # 10^18
|
||||
7: (u'секстиллион', u'секстиллиона', u'секстиллионов'), # 10^21
|
||||
8: (u'септиллион', u'септиллиона', u'септиллионов'), # 10^24
|
||||
9: (u'октиллион', u'октиллиона', u'октиллионов'), #10^27
|
||||
10: (u'нониллион', u'нониллиона', u'нониллионов'), # 10^30
|
||||
}
|
||||
|
||||
CURRENCIES = {
|
||||
'RUB': (
|
||||
(u'рубль', u'рубля', u'рублей'), (u'копейка', u'копейки', u'копеек')
|
||||
),
|
||||
'EUR': (
|
||||
(u'евро', u'евро', u'евро'), (u'цент', u'цента', u'центов')
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def splitby3(n):
|
||||
length = len(n)
|
||||
if length > 3:
|
||||
start = length % 3
|
||||
if start > 0:
|
||||
yield int(n[:start])
|
||||
for i in range(start, length, 3):
|
||||
yield int(n[i:i+3])
|
||||
else:
|
||||
yield int(n)
|
||||
|
||||
|
||||
def get_digits(n):
|
||||
return [int(x) for x in reversed(list(('%03d' % n)[-3:]))]
|
||||
|
||||
|
||||
def pluralize(n, forms):
|
||||
if (n % 100 < 10 or n % 100 > 20):
|
||||
if n % 10 == 1:
|
||||
form = 0
|
||||
elif (n % 10 > 1 and n % 10 < 5):
|
||||
form = 1
|
||||
else:
|
||||
form = 2
|
||||
else:
|
||||
form = 2
|
||||
return forms[form]
|
||||
|
||||
|
||||
def int2word(n, feminine=False):
|
||||
if n < 0:
|
||||
return ' '.join([u'минус', int2word(abs(n))])
|
||||
|
||||
if n == 0:
|
||||
return ZERO[0]
|
||||
|
||||
words = []
|
||||
chunks = list(splitby3(str(n)))
|
||||
i = len(chunks)
|
||||
for x in chunks:
|
||||
i -= 1
|
||||
n1, n2, n3 = get_digits(x)
|
||||
|
||||
if n3 > 0:
|
||||
words.append(HUNDREDS[n3][0])
|
||||
|
||||
if n2 > 1:
|
||||
words.append(TWENTIES[n2][0])
|
||||
|
||||
if n2 == 1:
|
||||
words.append(TENS[n1][0])
|
||||
elif n1 > 0:
|
||||
ones = ONES_FEMININE if i == 1 or feminine and i == 0 else ONES
|
||||
words.append(ones[n1][0])
|
||||
|
||||
if i > 0 and x != 0:
|
||||
words.append(pluralize(x, THOUSANDS[i]))
|
||||
|
||||
return ' '.join(words)
|
||||
|
||||
|
||||
def n2w(n):
|
||||
n = str(n).replace(',', '.')
|
||||
if '.' in n:
|
||||
left, right = n.split('.')
|
||||
return u'%s запятая %s' % (int2word(int(left)), int2word(int(right)))
|
||||
else:
|
||||
return int2word(int(n))
|
||||
|
||||
|
||||
def to_currency(n, currency='EUR', cents=True, seperator=','):
|
||||
if type(n) == int:
|
||||
if n < 0:
|
||||
minus = True
|
||||
else:
|
||||
minus = False
|
||||
|
||||
n = abs(n)
|
||||
left = n / 100
|
||||
right = n % 100
|
||||
else:
|
||||
n = str(n).replace(',', '.')
|
||||
if '.' in n:
|
||||
left, right = n.split('.')
|
||||
else:
|
||||
left, right = n, 0
|
||||
left, right = int(left), int(right)
|
||||
minus = False
|
||||
cr1, cr2 = CURRENCIES[currency]
|
||||
|
||||
if minus:
|
||||
minus_str = "минус "
|
||||
else:
|
||||
minus_str = ""
|
||||
|
||||
if cents:
|
||||
cents_feminine = currency == 'RUB'
|
||||
cents_str = int2word(right, cents_feminine)
|
||||
else:
|
||||
cents_str = "%02d" % right
|
||||
|
||||
return u'%s%s %s%s %s %s' % (
|
||||
minus_str,
|
||||
int2word(left),
|
||||
pluralize(left, cr1),
|
||||
seperator,
|
||||
cents_str,
|
||||
pluralize(right, cr2)
|
||||
)
|
||||
|
||||
|
||||
class Num2Word_RU(object):
|
||||
def to_cardinal(self, number):
|
||||
return n2w(number)
|
||||
|
||||
def to_ordinal(self, number):
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import doctest
|
||||
doctest.testmod()
|
||||
565
num2words/lang_TR.py
Normal file
565
num2words/lang_TR.py
Normal file
@@ -0,0 +1,565 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
||||
# Copyright (c) 2017, Tufan Kaynak, Framras. All Rights Reserved.
|
||||
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
|
||||
class Num2Word_TR(object):
|
||||
def __init__(self):
|
||||
self.precision = 2
|
||||
self.negword = u"eksi"
|
||||
self.pointword = u"virgül"
|
||||
self.CURRENCY_UNIT = (u"lira",)
|
||||
self.CURRENCY_SUBUNIT = (u"kuruş",)
|
||||
self.errmsg_nonnum = u"Sadece sayılar yazıya çevrilebilir."
|
||||
self.errmsg_floatord = u"Tam sayı olmayan {} sıralamada kullanılamaz."
|
||||
self.errmsg_negord = u"Pozitif olmayan {} sıralamada kullanılamaz."
|
||||
self.errmsg_toobig = u"abs({}) sayı yazıya çevirmek için çok büyük. Yazıya çevrilebilecek en büyük rakam {}."
|
||||
self.exclude_title = []
|
||||
self.DECIMAL_SIGN = (",",)
|
||||
self.ORDINAL_SIGN = (".",)
|
||||
self.ZERO = (u"sıfır",)
|
||||
self.CARDINAL_ONES = {
|
||||
"1": u"bir",
|
||||
"2": u"iki",
|
||||
"3": u"üç",
|
||||
"4": u"dört",
|
||||
"5": u"beş",
|
||||
"6": u"altı",
|
||||
"7": u"yedi",
|
||||
"8": u"sekiz",
|
||||
"9": u"dokuz"
|
||||
}
|
||||
self.ORDINAL_ONES = {
|
||||
"1": u"birinci",
|
||||
"2": u"ikinci",
|
||||
"3": u"üçüncü",
|
||||
"4": u"dördüncü",
|
||||
"5": u"beşinci",
|
||||
"6": u"altıncı",
|
||||
"7": u"yedinci",
|
||||
"8": u"sekizinci",
|
||||
"9": u"dokuzuncu"
|
||||
}
|
||||
self.CARDINAL_TENS = {
|
||||
"1": u"on",
|
||||
"2": u"yirmi",
|
||||
"3": u"otuz",
|
||||
"4": u"kırk",
|
||||
"5": u"elli",
|
||||
"6": u"altmış",
|
||||
"7": u"yetmiş",
|
||||
"8": u"seksen",
|
||||
"9": u"doksan"
|
||||
}
|
||||
self.ORDINAL_TENS = {
|
||||
"1": u"onuncu",
|
||||
"2": u"yirminci",
|
||||
"3": u"otuzuncu",
|
||||
"4": u"kırkıncı",
|
||||
"5": u"ellinci",
|
||||
"6": u"altmışıncı",
|
||||
"7": u"yetmişinci",
|
||||
"8": u"sekseninci",
|
||||
"9": u"doksanıncı"
|
||||
}
|
||||
self.HUNDREDS = {
|
||||
"2": u"iki",
|
||||
"3": u"üç",
|
||||
"4": u"dört",
|
||||
"5": u"beş",
|
||||
"6": u"altı",
|
||||
"7": u"yedi",
|
||||
"8": u"sekiz",
|
||||
"9": u"dokuz"
|
||||
}
|
||||
self.CARDINAL_HUNDRED = (u"yüz",)
|
||||
self.ORDINAL_HUNDRED = (u"yüzüncü",)
|
||||
self.CARDINAL_TRIPLETS = {
|
||||
1: u"bin",
|
||||
2: u"milyon",
|
||||
3: u"milyar",
|
||||
4: u"trilyon",
|
||||
5: u"katrilyon",
|
||||
6: u"kentilyon"
|
||||
}
|
||||
self.ORDINAL_TRIPLETS = {
|
||||
1: u"bininci",
|
||||
2: u"milyonuncu",
|
||||
3: u"milyarıncı",
|
||||
4: u"trilyonuncu",
|
||||
5: u"katrilyonuncu",
|
||||
6: u"kentilyon"
|
||||
}
|
||||
self.MAXVAL = (10 ** ((len(self.CARDINAL_TRIPLETS) + 1) * 3)) - 1
|
||||
|
||||
self.integers_to_read = []
|
||||
self.total_triplets_to_read = 0
|
||||
self.total_digits_outside_triplets = 0
|
||||
self.order_of_last_zero_digit = 0
|
||||
|
||||
def to_cardinal(self, value):
|
||||
wrd = ""
|
||||
is_cardinal = self.verify_cardinal(value)
|
||||
if is_cardinal:
|
||||
if not int(value) == value:
|
||||
return self.to_cardinal_float(value)
|
||||
self.to_splitnum(value)
|
||||
|
||||
if self.order_of_last_zero_digit >= len(self.integers_to_read[0]):
|
||||
# number like 00 and all 0s and even more, raise error
|
||||
return wrd
|
||||
|
||||
if self.total_triplets_to_read == 1:
|
||||
if self.total_digits_outside_triplets == 2:
|
||||
if self.order_of_last_zero_digit == 1:
|
||||
# number like x0, read cardinal x0 and return
|
||||
wrd += self.CARDINAL_TENS.get(self.integers_to_read[0][0], "")
|
||||
return wrd
|
||||
if self.order_of_last_zero_digit == 0:
|
||||
# number like xy, read cardinal xy and return
|
||||
wrd += self.CARDINAL_TENS.get(self.integers_to_read[0][0], "")
|
||||
wrd += self.CARDINAL_ONES.get(self.integers_to_read[0][1], "")
|
||||
return wrd
|
||||
|
||||
if self.total_digits_outside_triplets == 1:
|
||||
if self.order_of_last_zero_digit == 0:
|
||||
# number like x, read cardinal x and return
|
||||
wrd += self.CARDINAL_ONES.get(self.integers_to_read[0][0], "")
|
||||
return wrd
|
||||
|
||||
if self.total_digits_outside_triplets == 0:
|
||||
if self.order_of_last_zero_digit == 2:
|
||||
# number like x00, read cardinal x00 and return
|
||||
wrd += self.HUNDREDS.get(self.integers_to_read[0][0], "")
|
||||
wrd += self.CARDINAL_HUNDRED[0]
|
||||
return wrd
|
||||
if self.order_of_last_zero_digit == 1:
|
||||
# number like xy0, read cardinal xy0 and return
|
||||
wrd += self.HUNDREDS.get(self.integers_to_read[0][0], "")
|
||||
wrd += self.CARDINAL_HUNDRED[0]
|
||||
wrd += self.CARDINAL_TENS.get(self.integers_to_read[0][1], "")
|
||||
return wrd
|
||||
if self.order_of_last_zero_digit == 0:
|
||||
# number like xyz, read cardinal xyz and return
|
||||
wrd += self.HUNDREDS.get(self.integers_to_read[0][0], "")
|
||||
wrd += self.CARDINAL_HUNDRED[0]
|
||||
wrd += self.CARDINAL_TENS.get(self.integers_to_read[0][1], "")
|
||||
wrd += self.CARDINAL_ONES.get(self.integers_to_read[0][2], "")
|
||||
return wrd
|
||||
|
||||
if self.total_triplets_to_read >= 2:
|
||||
if self.total_digits_outside_triplets == 2:
|
||||
if self.order_of_last_zero_digit == len(self.integers_to_read[0]) - 1:
|
||||
# number like x0 and all 0s, read cardinal x0 0..0 and return
|
||||
wrd += self.CARDINAL_TENS.get(self.integers_to_read[0][0], "")
|
||||
wrd += self.CARDINAL_TRIPLETS[self.total_triplets_to_read - 1]
|
||||
return wrd
|
||||
if self.order_of_last_zero_digit == len(self.integers_to_read[0]) - 2:
|
||||
# number like xy and all 0s, read cardinal xy 0..0 and return
|
||||
wrd += self.CARDINAL_TENS.get(self.integers_to_read[0][0], "")
|
||||
wrd += self.CARDINAL_ONES.get(self.integers_to_read[0][1], "")
|
||||
wrd += self.CARDINAL_TRIPLETS[self.total_triplets_to_read - 1]
|
||||
return wrd
|
||||
if self.order_of_last_zero_digit < len(self.integers_to_read[0]) - 2:
|
||||
# number like xy and others, read cardinal xy n..n and return
|
||||
wrd += self.CARDINAL_TENS.get(self.integers_to_read[0][0], "")
|
||||
wrd += self.CARDINAL_ONES.get(self.integers_to_read[0][1], "")
|
||||
wrd += self.CARDINAL_TRIPLETS[self.total_triplets_to_read - 1]
|
||||
|
||||
if self.total_digits_outside_triplets == 1:
|
||||
if self.order_of_last_zero_digit == len(self.integers_to_read[0]) - 1:
|
||||
# number like x and all 0s, read cardinal x 0..0 and return
|
||||
if not (self.total_triplets_to_read == 2 and self.integers_to_read[0][0] == "1"):
|
||||
wrd += self.CARDINAL_ONES.get(self.integers_to_read[0][0], "")
|
||||
wrd += self.CARDINAL_TRIPLETS[self.total_triplets_to_read - 1]
|
||||
return wrd
|
||||
if self.order_of_last_zero_digit < len(self.integers_to_read[0]) - 1:
|
||||
# number like x and others, read cardinal x n..n and return
|
||||
if not (self.total_triplets_to_read == 2 and self.integers_to_read[0][0] == "1"):
|
||||
wrd += self.CARDINAL_ONES.get(self.integers_to_read[0][0], "")
|
||||
wrd += self.CARDINAL_TRIPLETS[self.total_triplets_to_read - 1]
|
||||
|
||||
if self.total_digits_outside_triplets == 0:
|
||||
if self.order_of_last_zero_digit == len(self.integers_to_read[0]) - 1:
|
||||
# number like x00 and all 0s, read cardinal x00 0..0 and return
|
||||
wrd += self.HUNDREDS.get(self.integers_to_read[0][0], "")
|
||||
wrd += self.CARDINAL_HUNDRED[0]
|
||||
wrd += self.CARDINAL_TRIPLETS[self.total_triplets_to_read - 1]
|
||||
return wrd
|
||||
if self.order_of_last_zero_digit == len(self.integers_to_read[0]) - 2:
|
||||
# number like xy0 and all 0s, read cardinal xy0 0..0 and return
|
||||
wrd += self.HUNDREDS.get(self.integers_to_read[0][0], "")
|
||||
wrd += self.CARDINAL_HUNDRED[0]
|
||||
wrd += self.CARDINAL_TENS.get(self.integers_to_read[0][1], "")
|
||||
wrd += self.CARDINAL_TRIPLETS[self.total_triplets_to_read - 1]
|
||||
return wrd
|
||||
if self.order_of_last_zero_digit == len(self.integers_to_read[0]) - 3:
|
||||
# number like xyz and all 0s, read cardinal xyz 0..0 and return
|
||||
wrd += self.HUNDREDS.get(self.integers_to_read[0][0], "")
|
||||
wrd += self.CARDINAL_HUNDRED[0]
|
||||
wrd += self.CARDINAL_TENS.get(self.integers_to_read[0][1], "")
|
||||
wrd += self.CARDINAL_ONES.get(self.integers_to_read[0][2], "")
|
||||
wrd += self.CARDINAL_TRIPLETS[self.total_triplets_to_read - 1]
|
||||
return wrd
|
||||
if self.order_of_last_zero_digit < len(self.integers_to_read[0]) - 3:
|
||||
# number like xyz and all others, read cardinal xyz n..n
|
||||
wrd += self.HUNDREDS.get(self.integers_to_read[0][0], "")
|
||||
wrd += self.CARDINAL_HUNDRED[0]
|
||||
wrd += self.CARDINAL_TENS.get(self.integers_to_read[0][1], "")
|
||||
if not (self.total_triplets_to_read == 2 and self.integers_to_read[0][2] == "1"):
|
||||
wrd += self.CARDINAL_ONES.get(self.integers_to_read[0][2], "")
|
||||
wrd += self.CARDINAL_TRIPLETS[self.total_triplets_to_read - 1]
|
||||
|
||||
for i in list(range(self.total_triplets_to_read - 1, 0, -1)):
|
||||
reading_triplet_order = self.total_triplets_to_read - i
|
||||
if self.total_digits_outside_triplets == 0:
|
||||
last_read_digit_order = reading_triplet_order * 3
|
||||
else:
|
||||
last_read_digit_order = (reading_triplet_order - 1) * 3 + self.total_digits_outside_triplets
|
||||
|
||||
if not self.integers_to_read[0][last_read_digit_order: last_read_digit_order + 3] == "000":
|
||||
if not self.integers_to_read[0][last_read_digit_order] == "0":
|
||||
wrd += self.HUNDREDS.get(self.integers_to_read[0][last_read_digit_order], "")
|
||||
if self.order_of_last_zero_digit == len(self.integers_to_read[0]) - (
|
||||
last_read_digit_order) - 1:
|
||||
if i == 1:
|
||||
wrd += self.CARDINAL_HUNDRED[0]
|
||||
return wrd
|
||||
elif i > 1:
|
||||
wrd += self.CARDINAL_HUNDRED[0]
|
||||
wrd += self.CARDINAL_TRIPLETS[i - 1]
|
||||
return wrd
|
||||
else:
|
||||
wrd += self.CARDINAL_HUNDRED[0]
|
||||
|
||||
if not self.integers_to_read[0][last_read_digit_order + 1] == "0":
|
||||
if self.order_of_last_zero_digit == len(self.integers_to_read[0]) - (
|
||||
last_read_digit_order) - 2:
|
||||
if i == 1:
|
||||
wrd += self.CARDINAL_TENS.get(
|
||||
self.integers_to_read[0][last_read_digit_order + 1], "")
|
||||
return wrd
|
||||
elif i > 1:
|
||||
wrd += self.CARDINAL_TENS.get(
|
||||
self.integers_to_read[0][last_read_digit_order + 1], "")
|
||||
wrd += self.CARDINAL_TRIPLETS[i - 1]
|
||||
return wrd
|
||||
else:
|
||||
wrd += self.CARDINAL_TENS.get(self.integers_to_read[0][last_read_digit_order + 1],
|
||||
"")
|
||||
|
||||
if not self.integers_to_read[0][last_read_digit_order + 2] == "0":
|
||||
if self.order_of_last_zero_digit == len(self.integers_to_read[0]) - (
|
||||
last_read_digit_order) - 3:
|
||||
if i == 1:
|
||||
wrd += self.CARDINAL_ONES.get(
|
||||
self.integers_to_read[0][last_read_digit_order + 2], "")
|
||||
return wrd
|
||||
if i == 2:
|
||||
if not self.integers_to_read[0][
|
||||
last_read_digit_order: last_read_digit_order + 2] == "00":
|
||||
wrd += self.CARDINAL_ONES.get(
|
||||
self.integers_to_read[0][last_read_digit_order + 2], "")
|
||||
elif not self.integers_to_read[0][last_read_digit_order + 2] == "1":
|
||||
wrd += self.CARDINAL_ONES.get(
|
||||
self.integers_to_read[0][last_read_digit_order + 2], "")
|
||||
wrd += self.CARDINAL_TRIPLETS[i - 1]
|
||||
return wrd
|
||||
if i > 2:
|
||||
wrd += self.CARDINAL_ONES.get(
|
||||
self.integers_to_read[0][last_read_digit_order + 2], "")
|
||||
wrd += self.CARDINAL_TRIPLETS[i - 1]
|
||||
return wrd
|
||||
else:
|
||||
if not self.integers_to_read[0][
|
||||
last_read_digit_order: last_read_digit_order + 2] == "00":
|
||||
wrd += self.CARDINAL_ONES.get(
|
||||
self.integers_to_read[0][last_read_digit_order + 2], "")
|
||||
else:
|
||||
if i == 2:
|
||||
if not self.integers_to_read[0][
|
||||
last_read_digit_order: last_read_digit_order + 2] == "00":
|
||||
wrd += self.CARDINAL_ONES.get(
|
||||
self.integers_to_read[0][last_read_digit_order + 2], "")
|
||||
elif not self.integers_to_read[0][last_read_digit_order + 2] == "1":
|
||||
wrd += self.CARDINAL_ONES.get(
|
||||
self.integers_to_read[0][last_read_digit_order + 2], "")
|
||||
|
||||
wrd += self.CARDINAL_TRIPLETS[i - 1]
|
||||
|
||||
return wrd
|
||||
|
||||
def to_cardinal_float(self, value):
|
||||
self.to_splitnum(value)
|
||||
wrd = ""
|
||||
wrd += self.pointword
|
||||
if len(self.integers_to_read[1]) >= 1:
|
||||
wrd += self.CARDINAL_TENS.get(self.integers_to_read[1][0], "")
|
||||
|
||||
if len(self.integers_to_read[1]) == 2:
|
||||
wrd += self.CARDINAL_ONES.get(self.integers_to_read[1][1], "")
|
||||
|
||||
if self.integers_to_read[0] == "0":
|
||||
wrd = self.ZERO[0] + wrd
|
||||
else:
|
||||
wrd = self.to_cardinal(int(self.integers_to_read[0])) + wrd
|
||||
return wrd
|
||||
|
||||
def verify_cardinal(self, value):
|
||||
iscardinal = True
|
||||
try:
|
||||
if not float(value) == value:
|
||||
iscardinal = False
|
||||
except (ValueError, TypeError):
|
||||
raise TypeError(self.errmsg_nonnum)
|
||||
if abs(value) >= self.MAXVAL:
|
||||
raise OverflowError(self.errmsg_toobig.format(value, self.MAXVAL))
|
||||
return iscardinal
|
||||
|
||||
def verify_ordinal(self, value):
|
||||
isordinal = True
|
||||
try:
|
||||
if not int(value) == value:
|
||||
isordinal = False
|
||||
if not abs(value) == value:
|
||||
raise TypeError(self.errmsg_negord.format(value))
|
||||
except (ValueError, TypeError):
|
||||
raise TypeError(self.errmsg_nonnum)
|
||||
if abs(value) >= self.MAXVAL:
|
||||
raise OverflowError(self.errmsg_toobig.format(value, self.MAXVAL))
|
||||
return isordinal
|
||||
|
||||
def to_ordinal(self, value):
|
||||
wrd = ""
|
||||
isordinal = self.verify_ordinal(value)
|
||||
if isordinal:
|
||||
self.to_splitnum(value)
|
||||
|
||||
if self.order_of_last_zero_digit >= len(self.integers_to_read[0]):
|
||||
# number like 00 and all 0s and even more, raise error
|
||||
return wrd
|
||||
|
||||
if self.total_triplets_to_read == 1:
|
||||
if self.total_digits_outside_triplets == 2:
|
||||
if self.order_of_last_zero_digit == 1:
|
||||
# number like x0, read ordinal x0 and return
|
||||
wrd += self.ORDINAL_TENS.get(self.integers_to_read[0][0], "")
|
||||
return wrd
|
||||
if self.order_of_last_zero_digit == 0:
|
||||
# number like xy, read ordinal xy and return
|
||||
wrd += self.CARDINAL_TENS.get(self.integers_to_read[0][0], "")
|
||||
wrd += self.ORDINAL_ONES.get(self.integers_to_read[0][1], "")
|
||||
return wrd
|
||||
|
||||
if self.total_digits_outside_triplets == 1:
|
||||
if self.order_of_last_zero_digit == 0:
|
||||
# number like x, read ordinal x and return
|
||||
wrd += self.ORDINAL_ONES.get(self.integers_to_read[0][0], "")
|
||||
return wrd
|
||||
|
||||
if self.total_digits_outside_triplets == 0:
|
||||
if self.order_of_last_zero_digit == 2:
|
||||
# number like x00, read ordinal x00 and return
|
||||
wrd += self.HUNDREDS.get(self.integers_to_read[0][0], "")
|
||||
wrd += self.ORDINAL_HUNDRED[0]
|
||||
return wrd
|
||||
if self.order_of_last_zero_digit == 1:
|
||||
# number like xy0, read ordinal xy0 and return
|
||||
wrd += self.HUNDREDS.get(self.integers_to_read[0][0], "")
|
||||
wrd += self.CARDINAL_HUNDRED[0]
|
||||
wrd += self.ORDINAL_TENS.get(self.integers_to_read[0][1], "")
|
||||
return wrd
|
||||
if self.order_of_last_zero_digit == 0:
|
||||
# number like xyz, read ordinal xyz and return
|
||||
wrd += self.HUNDREDS.get(self.integers_to_read[0][0], "")
|
||||
wrd += self.CARDINAL_HUNDRED[0]
|
||||
wrd += self.CARDINAL_TENS.get(self.integers_to_read[0][1], "")
|
||||
if not self.integers_to_read[0][2] == "0":
|
||||
wrd += self.ORDINAL_ONES.get(self.integers_to_read[0][2], "")
|
||||
return wrd
|
||||
|
||||
if self.total_triplets_to_read >= 2:
|
||||
if self.total_digits_outside_triplets == 2:
|
||||
if self.order_of_last_zero_digit == len(self.integers_to_read[0]) - 1:
|
||||
# number like x0 and all 0s, read ordinal x0 0..0 and return
|
||||
wrd += self.CARDINAL_TENS.get(self.integers_to_read[0][0], "")
|
||||
wrd += self.ORDINAL_TRIPLETS[self.total_triplets_to_read - 1]
|
||||
return wrd
|
||||
if self.order_of_last_zero_digit == len(self.integers_to_read[0]) - 2:
|
||||
# number like xy and all 0s, read ordinal xy 0..0 and return
|
||||
wrd += self.CARDINAL_TENS.get(self.integers_to_read[0][0], "")
|
||||
wrd += self.CARDINAL_ONES.get(self.integers_to_read[0][1], "")
|
||||
wrd += self.ORDINAL_TRIPLETS[self.total_triplets_to_read - 1]
|
||||
return wrd
|
||||
if self.order_of_last_zero_digit < len(self.integers_to_read[0]) - 2:
|
||||
# number like xy and others, read cardinal xy n..n and return
|
||||
wrd += self.CARDINAL_TENS.get(self.integers_to_read[0][0], "")
|
||||
wrd += self.CARDINAL_ONES.get(self.integers_to_read[0][1], "")
|
||||
wrd += self.CARDINAL_TRIPLETS[self.total_triplets_to_read - 1]
|
||||
|
||||
if self.total_digits_outside_triplets == 1:
|
||||
if self.order_of_last_zero_digit == len(self.integers_to_read[0]) - 1:
|
||||
# number like x and all 0s, read ordinal x 0..0 and return
|
||||
if not (self.total_triplets_to_read == 2 and self.integers_to_read[0][0] == "1"):
|
||||
wrd += self.CARDINAL_ONES.get(self.integers_to_read[0][0], "")
|
||||
wrd += self.ORDINAL_TRIPLETS[self.total_triplets_to_read - 1]
|
||||
return wrd
|
||||
if self.order_of_last_zero_digit < len(self.integers_to_read[0]) - 1:
|
||||
# number like x and others, read cardinal x n..n and return
|
||||
if not (self.total_triplets_to_read == 2 and self.integers_to_read[0][0] == "1"):
|
||||
wrd += self.CARDINAL_ONES.get(self.integers_to_read[0][0], "")
|
||||
wrd += self.CARDINAL_TRIPLETS[self.total_triplets_to_read - 1]
|
||||
|
||||
if self.total_digits_outside_triplets == 0:
|
||||
if self.order_of_last_zero_digit == len(self.integers_to_read[0]) - 1:
|
||||
# number like x00 and all 0s, read ordinal x00 0..0 and return
|
||||
wrd += self.HUNDREDS.get(self.integers_to_read[0][0], "")
|
||||
wrd += self.CARDINAL_HUNDRED[0]
|
||||
wrd += self.ORDINAL_TRIPLETS[self.total_triplets_to_read - 1]
|
||||
return wrd
|
||||
if self.order_of_last_zero_digit == len(self.integers_to_read[0]) - 2:
|
||||
# number like xy0 and all 0s, read ordinal xy0 0..0 and return
|
||||
wrd += self.HUNDREDS.get(self.integers_to_read[0][0], "")
|
||||
wrd += self.CARDINAL_HUNDRED[0]
|
||||
wrd += self.CARDINAL_TENS.get(self.integers_to_read[0][1], "")
|
||||
wrd += self.ORDINAL_TRIPLETS[self.total_triplets_to_read - 1]
|
||||
return wrd
|
||||
if self.order_of_last_zero_digit == len(self.integers_to_read[0]) - 3:
|
||||
# number like xyz and all 0s, read ordinal xyz 0..0 and return
|
||||
wrd += self.HUNDREDS.get(self.integers_to_read[0][0], "")
|
||||
wrd += self.CARDINAL_HUNDRED[0]
|
||||
wrd += self.CARDINAL_TENS.get(self.integers_to_read[0][1], "")
|
||||
wrd += self.CARDINAL_ONES.get(self.integers_to_read[0][2], "")
|
||||
wrd += self.ORDINAL_TRIPLETS[self.total_triplets_to_read - 1]
|
||||
return wrd
|
||||
if self.order_of_last_zero_digit < len(self.integers_to_read[0]) - 3:
|
||||
# number like xyz and all others, read cardinal xyz n..n
|
||||
wrd += self.HUNDREDS.get(self.integers_to_read[0][0], "")
|
||||
wrd += self.CARDINAL_HUNDRED[0]
|
||||
wrd += self.CARDINAL_TENS.get(self.integers_to_read[0][1], "")
|
||||
if not (self.total_triplets_to_read == 2 and self.integers_to_read[0][2] == "1"):
|
||||
wrd += self.CARDINAL_ONES.get(self.integers_to_read[0][2], "")
|
||||
wrd += self.CARDINAL_TRIPLETS[self.total_triplets_to_read - 1]
|
||||
|
||||
for i in list(range(self.total_triplets_to_read - 1, 0, -1)):
|
||||
reading_triplet_order = self.total_triplets_to_read - i
|
||||
if self.total_digits_outside_triplets == 0:
|
||||
last_read_digit_order = reading_triplet_order * 3
|
||||
else:
|
||||
last_read_digit_order = (reading_triplet_order - 1) * 3 + self.total_digits_outside_triplets
|
||||
|
||||
if not self.integers_to_read[0][last_read_digit_order: last_read_digit_order + 3] == "000":
|
||||
if not self.integers_to_read[0][last_read_digit_order] == "0":
|
||||
if not self.integers_to_read[0][last_read_digit_order] == "1":
|
||||
wrd += self.CARDINAL_ONES.get(self.integers_to_read[0][last_read_digit_order], "")
|
||||
if self.order_of_last_zero_digit == len(self.integers_to_read[0]) - (
|
||||
last_read_digit_order) - 1:
|
||||
if i == 1:
|
||||
wrd += self.ORDINAL_HUNDRED[0]
|
||||
return wrd
|
||||
elif i > 1:
|
||||
wrd += self.CARDINAL_HUNDRED[0]
|
||||
wrd += self.ORDINAL_TRIPLETS[i - 1]
|
||||
return wrd
|
||||
else:
|
||||
wrd += self.CARDINAL_HUNDRED[0]
|
||||
|
||||
if not self.integers_to_read[0][last_read_digit_order + 1] == "0":
|
||||
if self.order_of_last_zero_digit == len(self.integers_to_read[0]) - (
|
||||
last_read_digit_order) - 2:
|
||||
if i == 1:
|
||||
wrd += self.ORDINAL_TENS.get(
|
||||
self.integers_to_read[0][last_read_digit_order + 1], "")
|
||||
return wrd
|
||||
elif i > 1:
|
||||
wrd += self.CARDINAL_TENS.get(
|
||||
self.integers_to_read[0][last_read_digit_order + 1], "")
|
||||
wrd += self.ORDINAL_TRIPLETS[i - 1]
|
||||
return wrd
|
||||
else:
|
||||
wrd += self.CARDINAL_TENS.get(self.integers_to_read[0][last_read_digit_order + 1],
|
||||
"")
|
||||
|
||||
if not self.integers_to_read[0][last_read_digit_order + 2] == "0":
|
||||
if self.order_of_last_zero_digit == len(self.integers_to_read[0]) - (
|
||||
last_read_digit_order) - 3:
|
||||
if i == 1:
|
||||
wrd += self.ORDINAL_ONES.get(
|
||||
self.integers_to_read[0][last_read_digit_order + 2], "")
|
||||
return wrd
|
||||
if i == 2:
|
||||
if not self.integers_to_read[0][
|
||||
last_read_digit_order: last_read_digit_order + 2] == "00":
|
||||
wrd += self.CARDINAL_ONES.get(
|
||||
self.integers_to_read[0][last_read_digit_order + 2], "")
|
||||
elif not self.integers_to_read[0][last_read_digit_order + 2] == "1":
|
||||
wrd += self.CARDINAL_ONES.get(
|
||||
self.integers_to_read[0][last_read_digit_order + 2], "")
|
||||
wrd += self.ORDINAL_TRIPLETS[i - 1]
|
||||
return wrd
|
||||
if i > 2:
|
||||
wrd += self.CARDINAL_ONES.get(
|
||||
self.integers_to_read[0][last_read_digit_order + 2], "")
|
||||
wrd += self.ORDINAL_TRIPLETS[i - 1]
|
||||
return wrd
|
||||
else:
|
||||
if not self.integers_to_read[0][
|
||||
last_read_digit_order: last_read_digit_order + 2] == "00":
|
||||
wrd += self.CARDINAL_ONES.get(
|
||||
self.integers_to_read[0][last_read_digit_order + 2], "")
|
||||
else:
|
||||
if not self.integers_to_read[0][
|
||||
last_read_digit_order: last_read_digit_order + 2] == "00":
|
||||
wrd += self.CARDINAL_ONES.get(
|
||||
self.integers_to_read[0][last_read_digit_order + 2], "")
|
||||
elif not self.integers_to_read[0][last_read_digit_order + 2] == "1":
|
||||
wrd += self.CARDINAL_ONES.get(
|
||||
self.integers_to_read[0][last_read_digit_order + 2], "")
|
||||
|
||||
wrd += self.CARDINAL_TRIPLETS[i - 1]
|
||||
|
||||
return wrd
|
||||
|
||||
def to_splitnum(self, val):
|
||||
float_digits = str(int(val * 10 ** self.precision))
|
||||
if not int(val) == 0:
|
||||
self.integers_to_read = [str(int(val)), float_digits[len(float_digits) - self.precision:]]
|
||||
else:
|
||||
self.integers_to_read = ["0", "0" * (self.precision - len(float_digits)) + float_digits[len(float_digits) - self.precision:]]
|
||||
if len(self.integers_to_read[0]) % 3 > 0:
|
||||
self.total_triplets_to_read = (len(self.integers_to_read[0]) // 3) + 1
|
||||
elif len(self.integers_to_read[0]) % 3 == 0:
|
||||
self.total_triplets_to_read = len(self.integers_to_read[0]) // 3
|
||||
self.total_digits_outside_triplets = len(self.integers_to_read[0]) % 3
|
||||
|
||||
okunacak = list(self.integers_to_read[0][::-1])
|
||||
self.order_of_last_zero_digit = 0
|
||||
found = 0
|
||||
for i in range(len(okunacak) - 1):
|
||||
if int(okunacak[i]) == 0 and found == 0:
|
||||
self.order_of_last_zero_digit = i + 1
|
||||
else:
|
||||
found = 1
|
||||
|
||||
def to_currency(self, value, **kwargs):
|
||||
valueparts = self.to_cardinal(value).split(self.pointword)
|
||||
if len(valueparts) == 1:
|
||||
return valueparts[0] + self.CURRENCY_UNIT[0]
|
||||
if len(valueparts) == 2:
|
||||
return self.CURRENCY_UNIT[0].join(valueparts) + self.CURRENCY_SUBUNIT[0]
|
||||
316
num2words/lang_UK.py
Normal file
316
num2words/lang_UK.py
Normal file
@@ -0,0 +1,316 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
||||
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
u"""
|
||||
>>> from textwrap import fill
|
||||
|
||||
>>> ' '.join([str(i) for i in splitby3('1')])
|
||||
u'1'
|
||||
>>> ' '.join([str(i) for i in splitby3('1123')])
|
||||
u'1 123'
|
||||
>>> ' '.join([str(i) for i in splitby3('1234567890')])
|
||||
u'1 234 567 890'
|
||||
|
||||
>>> print(' '.join([n2w(i) for i in range(10)]))
|
||||
нуль один два три чотири п'ять шiсть сiмь вiсiм дев'ять
|
||||
|
||||
>>> print(fill(' '.join([n2w(i+10) for i in range(10)])))
|
||||
десять одинадцять дванадцять тринадцять чотирнадцять п'ятнадцять
|
||||
шiстнадцять сiмнадцять вiсiмнадцять дев'ятнадцять
|
||||
|
||||
>>> print(fill(' '.join([n2w(i*10) for i in range(10)])))
|
||||
нуль десять двадцять тридцять сорок п'ятдесят шiстдесят сiмдесят
|
||||
вiсiмдесят дев'яносто
|
||||
|
||||
>>> print(n2w(100))
|
||||
сто
|
||||
>>> print(n2w(101))
|
||||
сто один
|
||||
>>> print(n2w(110))
|
||||
сто десять
|
||||
>>> print(n2w(115))
|
||||
сто п'ятнадцять
|
||||
>>> print(n2w(123))
|
||||
сто двадцять три
|
||||
>>> print(n2w(1000))
|
||||
тисяча
|
||||
>>> print(n2w(1001))
|
||||
тисяча один
|
||||
>>> print(n2w(2012))
|
||||
двi тисячi дванадцять
|
||||
|
||||
>>> print(n2w(12519.85))
|
||||
дванадцять тисяч п'ятсот дев'ятнадцять кома вiсiмдесят п'ять
|
||||
|
||||
>>> print(fill(n2w(1234567890)))
|
||||
мiльярд двiстi тридцать чотири мiльйона п'ятсот шiстдесят сiмь тисяч
|
||||
вiсiмсот дев'яносто
|
||||
|
||||
>>> print(fill(n2w(215461407892039002157189883901676)))
|
||||
двiстi п'ятнадцять нонiльйонiв чотириста шiстдесят один октильйон
|
||||
чотириста сiм септильйонiв вiсiмсот дев'яносто два секстильйони
|
||||
тридцять дев'ять квiнтильйонiв два квадрильйони сто п'ятдесят сiм
|
||||
трильйонiв сто вiсiмдесят дев'ять мiльярдiв вiсiмсот вiсiмдесят три
|
||||
мiльйона дев'ятсот одна тисяча шiстсот сiмдесят шiсть
|
||||
|
||||
>>> print(fill(n2w(719094234693663034822824384220291)))
|
||||
сiмсот дев'ятнадцять нонiльйонiв дев'яносто чотири октильйони двiстi
|
||||
тридцять чотири септильйони шiстсот дев'яносто три секстильйони
|
||||
шiстсот шiстдесят три квiнтильйони тридцять чотири квадрильйони
|
||||
вiсiмсот двадцять два трильйони вiсiмсот двадцять чотири мiльярди
|
||||
триста вiсiмдесят чотири мiльйона двiстi двадцять тисяч двiстi
|
||||
дев'яносто один
|
||||
|
||||
>>> print(to_currency(1.0, 'EUR'))
|
||||
один євро, нуль центiв
|
||||
|
||||
>>> print(to_currency(1.0, 'UAH'))
|
||||
одна гривня, нуль копiйок
|
||||
|
||||
>>> print(to_currency(1234.56, 'EUR'))
|
||||
тисяча двiстi тридцять чотири євро, п'ятдесят шiсть центiв
|
||||
|
||||
>>> print(to_currency(1234.56, 'UAH'))
|
||||
тисяча двiстi тридцять чотири гривнi, п'ятдесят шiсть копiйок
|
||||
|
||||
>>> print(to_currency(10111, 'EUR', seperator=u' та'))
|
||||
сто один євро та одинадцять центiв
|
||||
|
||||
>>> print(to_currency(10121, 'UAH', seperator=u' та'))
|
||||
сто одна гривня та двадцять одна копiйка
|
||||
|
||||
>>> print(to_currency(10122, 'UAH', seperator=u' та'))
|
||||
сто одна гривня та двадцять одна копiйка
|
||||
|
||||
>>> print(to_currency(10121, 'EUR', seperator=u' та'))
|
||||
сто один євро та двадцять один цент
|
||||
|
||||
>>> print(to_currency(-1251985, cents = False))
|
||||
мiнус дванадцять тисяч п'ятьсот дев'ятнадцять євро, 85 центiв
|
||||
"""
|
||||
from __future__ import unicode_literals
|
||||
|
||||
ZERO = (u'нуль',)
|
||||
|
||||
ONES_FEMININE = {
|
||||
1: (u'одна',),
|
||||
2: (u'двi',),
|
||||
3: (u'три',),
|
||||
4: (u'чотири',),
|
||||
5: (u'п\'ять',),
|
||||
6: (u'шiсть',),
|
||||
7: (u'сiм',),
|
||||
8: (u'вiсiм',),
|
||||
9: (u'дев\'ять',),
|
||||
}
|
||||
|
||||
ONES = {
|
||||
1: (u'один',),
|
||||
2: (u'два',),
|
||||
3: (u'три',),
|
||||
4: (u'чотири',),
|
||||
5: (u'п\'ять',),
|
||||
6: (u'шiсть',),
|
||||
7: (u'сiм',),
|
||||
8: (u'вiсiм',),
|
||||
9: (u'дев\'ять',),
|
||||
}
|
||||
|
||||
TENS = {
|
||||
0: (u'десять',),
|
||||
1: (u'одинадцять',),
|
||||
2: (u'дванадцять',),
|
||||
3: (u'тринадцять',),
|
||||
4: (u'чотирнадцять',),
|
||||
5: (u'п\'ятнадцять',),
|
||||
6: (u'шiстнадцять',),
|
||||
7: (u'сiмнадцять',),
|
||||
8: (u'вiсiмнадцять',),
|
||||
9: (u'дев\'ятнадцять',),
|
||||
}
|
||||
|
||||
TWENTIES = {
|
||||
2: (u'двадцять',),
|
||||
3: (u'тридцять',),
|
||||
4: (u'сорок',),
|
||||
5: (u'п\'ятдесят',),
|
||||
6: (u'шiстдесят',),
|
||||
7: (u'сiмдесят',),
|
||||
8: (u'вiсiмдесят',),
|
||||
9: (u'дев\'яносто',),
|
||||
}
|
||||
|
||||
HUNDREDS = {
|
||||
1: (u'сто',),
|
||||
2: (u'двiстi',),
|
||||
3: (u'триста',),
|
||||
4: (u'чотириста',),
|
||||
5: (u'п\'ятсот',),
|
||||
6: (u'шiстсот',),
|
||||
7: (u'сiмсот',),
|
||||
8: (u'вiсiмсот',),
|
||||
9: (u'дев\'ятсот',),
|
||||
}
|
||||
|
||||
THOUSANDS = {
|
||||
1: (u'тисяча', u'тисячi', u'тисяч'), # 10^3
|
||||
2: (u'мiльйон', u'мiльйони', u'мiльйонiв'), # 10^6
|
||||
3: (u'мiльярд', u'мiльярди', u'мiльярдiв'), # 10^9
|
||||
4: (u'трильйон', u'трильйони', u'трильйонiв'), # 10^12
|
||||
5: (u'квадрильйон', u'квадрильйони', u'квадрильйонiв'), # 10^15
|
||||
6: (u'квiнтильйон', u'квiнтильйони', u'квiнтильйонiв'), # 10^18
|
||||
7: (u'секстильйон', u'секстильйони', u'секстильйонiв'), # 10^21
|
||||
8: (u'септильйон', u'септильйони', u'септильйонiв'), # 10^24
|
||||
9: (u'октильйон', u'октильйони', u'октильйонiв'), #10^27
|
||||
10: (u'нонiльйон', u'нонiльйони', u'нонiльйонiв'), # 10^30
|
||||
}
|
||||
|
||||
CURRENCIES = {
|
||||
'UAH': (
|
||||
(u'гривня', u'гривнi', u'гривень'), (u'копiйка', u'копiйки', u'копiйок')
|
||||
),
|
||||
'EUR': (
|
||||
(u'евро', u'евро', u'евро'), (u'цент', u'центи', u'центiв')
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def splitby3(n):
|
||||
length = len(n)
|
||||
if length > 3:
|
||||
start = length % 3
|
||||
if start > 0:
|
||||
yield int(n[:start])
|
||||
for i in range(start, length, 3):
|
||||
yield int(n[i:i+3])
|
||||
else:
|
||||
yield int(n)
|
||||
|
||||
|
||||
def get_digits(n):
|
||||
return [int(x) for x in reversed(list(('%03d' % n)[-3:]))]
|
||||
|
||||
|
||||
def pluralize(n, forms):
|
||||
#form = 0 if n==1 else 1 if (n % 10 > 1 and n % 10 < 5 and (n % 100 < 10 or n % 100 > 20)) else 2
|
||||
if (n % 100 < 10 or n % 100 > 20):
|
||||
if n % 10 == 1:
|
||||
form = 0
|
||||
elif (n % 10 > 1 and n % 10 < 5):
|
||||
form = 1
|
||||
else:
|
||||
form = 2
|
||||
else:
|
||||
form = 2
|
||||
|
||||
return forms[form]
|
||||
|
||||
|
||||
def int2word(n, feminine=True):
|
||||
if n < 0:
|
||||
return ' '.join([u'мiнус', int2word(abs(n))])
|
||||
|
||||
if n == 0:
|
||||
return ZERO[0]
|
||||
|
||||
words = []
|
||||
chunks = list(splitby3(str(n)))
|
||||
i = len(chunks)
|
||||
for x in chunks:
|
||||
i -= 1
|
||||
n1, n2, n3 = get_digits(x)
|
||||
|
||||
if n3 > 0:
|
||||
words.append(HUNDREDS[n3][0])
|
||||
|
||||
if n2 > 1:
|
||||
words.append(TWENTIES[n2][0])
|
||||
|
||||
if n2 == 1:
|
||||
words.append(TENS[n1][0])
|
||||
#elif n1 > 0 and not (i > 0 and x == 1):
|
||||
elif n1 > 0:
|
||||
ones = ONES_FEMININE if i == 1 or feminine and i == 0 else ONES
|
||||
words.append(ones[n1][0])
|
||||
|
||||
|
||||
if i > 0 and ((n1+n2+n3) > 0):
|
||||
words.append(pluralize(x, THOUSANDS[i]))
|
||||
|
||||
return ' '.join(words)
|
||||
|
||||
|
||||
def n2w(n):
|
||||
n = str(n).replace(',', '.')
|
||||
if '.' in n:
|
||||
left, right = n.split('.')
|
||||
return u'%s кома %s' % (int2word(int(left)), int2word(int(right)))
|
||||
else:
|
||||
return int2word(int(n))
|
||||
|
||||
|
||||
def to_currency(n, currency='EUR', cents=True, seperator=','):
|
||||
if type(n) == int:
|
||||
if n < 0:
|
||||
minus = True
|
||||
else:
|
||||
minus = False
|
||||
|
||||
n = abs(n)
|
||||
left = n / 100
|
||||
right = n % 100
|
||||
else:
|
||||
n = str(n).replace(',', '.')
|
||||
if '.' in n:
|
||||
left, right = n.split('.')
|
||||
else:
|
||||
left, right = n, 0
|
||||
left, right = int(left), int(right)
|
||||
minus = False
|
||||
cr1, cr2 = CURRENCIES[currency]
|
||||
|
||||
if minus:
|
||||
minus_str = "мiнус "
|
||||
else:
|
||||
minus_str = ""
|
||||
|
||||
if cents:
|
||||
cents_feminine = currency == 'UAH'
|
||||
cents_str = int2word(right, cents_feminine)
|
||||
else:
|
||||
cents_str = "%02d" % right
|
||||
|
||||
return u'%s%s %s%s %s %s' % (
|
||||
minus_str,
|
||||
int2word(left),
|
||||
pluralize(left, cr1),
|
||||
seperator,
|
||||
cents_str,
|
||||
pluralize(right, cr2)
|
||||
)
|
||||
|
||||
|
||||
class Num2Word_UK(object):
|
||||
def to_cardinal(self, number):
|
||||
return n2w(number)
|
||||
|
||||
def to_ordinal(self, number):
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import doctest
|
||||
doctest.testmod()
|
||||
102
num2words/lang_VN.py
Normal file
102
num2words/lang_VN.py
Normal file
@@ -0,0 +1,102 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
||||
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
|
||||
to_19 = (u'không', u'một', u'hai', u'ba', u'bốn', u'năm', u'sáu',
|
||||
u'bảy', u'tám', u'chín', u'mười', u'mười một', u'mười hai',
|
||||
u'mười ba', u'mười bốn', u'mười lăm', u'mười sáu', u'mười bảy',
|
||||
u'mười tám', u'mười chín')
|
||||
tens = (u'hai mươi', u'ba mươi', u'bốn mươi', u'năm mươi',
|
||||
u'sáu mươi', u'bảy mươi', u'tám mươi', u'chín mươi')
|
||||
denom = ('',
|
||||
u'nghìn', u'triệu', u'tỷ', u'nghìn tỷ', u'trăm nghìn tỷ',
|
||||
'Quintillion', 'Sextillion', 'Septillion', 'Octillion', 'Nonillion',
|
||||
'Decillion', 'Undecillion', 'Duodecillion', 'Tredecillion',
|
||||
'Quattuordecillion', 'Sexdecillion', 'Septendecillion',
|
||||
'Octodecillion', 'Novemdecillion', 'Vigintillion')
|
||||
|
||||
|
||||
class Num2Word_VN(object):
|
||||
|
||||
def _convert_nn(self, val):
|
||||
if val < 20:
|
||||
return to_19[val]
|
||||
for (dcap, dval) in ((k, 20 + (10 * v)) for (v, k) in enumerate(tens)):
|
||||
if dval + 10 > val:
|
||||
if val % 10:
|
||||
a = u'lăm'
|
||||
if to_19[val % 10] == u'một':
|
||||
a = u'mốt'
|
||||
else:
|
||||
a = to_19[val % 10]
|
||||
if to_19[val % 10] == u'năm':
|
||||
a = u'lăm'
|
||||
return dcap + ' ' + a
|
||||
return dcap
|
||||
|
||||
def _convert_nnn(self, val):
|
||||
word = ''
|
||||
(mod, rem) = (val % 100, val // 100)
|
||||
if rem > 0:
|
||||
word = to_19[rem] + u' trăm'
|
||||
if mod > 0:
|
||||
word = word + ' '
|
||||
if mod > 0 and mod < 10:
|
||||
if mod == 5:
|
||||
word = word != '' and word + u'lẻ năm' or word + u'năm'
|
||||
else:
|
||||
word = word != '' and word + u'lẻ ' \
|
||||
+ self._convert_nn(mod) or word + self._convert_nn(mod)
|
||||
if mod >= 10:
|
||||
word = word + self._convert_nn(mod)
|
||||
return word
|
||||
|
||||
def vietnam_number(self, val):
|
||||
if val < 100:
|
||||
return self._convert_nn(val)
|
||||
if val < 1000:
|
||||
return self._convert_nnn(val)
|
||||
for (didx, dval) in ((v - 1, 1000 ** v) for v in range(len(denom))):
|
||||
if dval > val:
|
||||
mod = 1000 ** didx
|
||||
l = val // mod
|
||||
r = val - (l * mod)
|
||||
|
||||
ret = self._convert_nnn(l) + u' ' + denom[didx]
|
||||
if r > 0 and r <= 99:
|
||||
ret = self._convert_nnn(l) + u' ' + denom[didx] + u' lẻ'
|
||||
if r > 0:
|
||||
ret = ret + ' ' + self.vietnam_number(r)
|
||||
return ret
|
||||
|
||||
def number_to_text(self, number):
|
||||
number = '%.2f' % number
|
||||
the_list = str(number).split('.')
|
||||
start_word = self.vietnam_number(int(the_list[0]))
|
||||
final_result = start_word
|
||||
if len(the_list) > 1 and int(the_list[1]) > 0:
|
||||
end_word = self.vietnam_number(int(the_list[1]))
|
||||
final_result = final_result + ' phẩy ' + end_word
|
||||
return final_result
|
||||
|
||||
def to_cardinal(self, number):
|
||||
return self.number_to_text(number)
|
||||
|
||||
def to_ordinal(self, number):
|
||||
return self.to_cardinal(number)
|
||||
Reference in New Issue
Block a user