mirror of
https://github.com/bblaz/num2words.git
synced 2025-12-06 06:42:25 +00:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,3 +2,4 @@
|
|||||||
build
|
build
|
||||||
dist
|
dist
|
||||||
*.egg-info
|
*.egg-info
|
||||||
|
/.tox
|
||||||
|
|||||||
9
.travis.yml
Normal file
9
.travis.yml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
sudo: false
|
||||||
|
language: python
|
||||||
|
python:
|
||||||
|
- "2.7"
|
||||||
|
- "3.4"
|
||||||
|
- "3.5"
|
||||||
|
- "3.6"
|
||||||
|
install: pip install tox-travis
|
||||||
|
script: tox
|
||||||
15
CHANGES.rst
15
CHANGES.rst
@@ -1,6 +1,21 @@
|
|||||||
Changelog
|
Changelog
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
Version 0.5.4 -- 2016/10/18
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
* Tons of new languages!
|
||||||
|
* Add Polish localization. (#23)
|
||||||
|
* Add Swiss-French localization. (#38)
|
||||||
|
* Add Russian localization. (#28, #46, #48)
|
||||||
|
* Add Indonesian localization. (#29)
|
||||||
|
* Add Norwegian localization. (#33)
|
||||||
|
* Add Danish localization. (#40)
|
||||||
|
* Add Brazilian localization. (#37, #47)
|
||||||
|
* Improve German localization. (#25, #27, #49)
|
||||||
|
* Improve Lithuanian localization. (#52)
|
||||||
|
* Improve floating point spelling. (#24)
|
||||||
|
|
||||||
Version 0.5.3 -- 2015/06/09
|
Version 0.5.3 -- 2015/06/09
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
|
|||||||
11
README.rst
11
README.rst
@@ -1,6 +1,8 @@
|
|||||||
num2words - Convert numbers to words in multiple languages
|
num2words - Convert numbers to words in multiple languages
|
||||||
==========================================================
|
==========================================================
|
||||||
|
|
||||||
|
.. image:: https://travis-ci.org/savoirfairelinux/num2words.svg?branch=master :target: https://travis-ci.org/savoirfairelinux/num2words
|
||||||
|
|
||||||
``num2words`` is a library that converts numbers like ``42`` to words like ``forty-two``. It
|
``num2words`` is a library that converts numbers like ``42`` to words like ``forty-two``. It
|
||||||
supports multiple languages (English, French, Spanish, German and Lithuanian) and can even generate
|
supports multiple languages (English, French, Spanish, German and Lithuanian) and can even generate
|
||||||
ordinal numbers like ``forty-second`` (altough this last feature is a bit buggy at the moment).
|
ordinal numbers like ``forty-second`` (altough this last feature is a bit buggy at the moment).
|
||||||
@@ -49,6 +51,13 @@ Besides the numerical argument, there's two optional arguments.
|
|||||||
* ``lv`` (Latvian)
|
* ``lv`` (Latvian)
|
||||||
* ``en_GB`` (British English)
|
* ``en_GB`` (British English)
|
||||||
* ``en_IN`` (Indian English)
|
* ``en_IN`` (Indian English)
|
||||||
|
* ``no`` (Norwegian)
|
||||||
|
* ``pl`` (Polish)
|
||||||
|
* ``ru`` (Russian)
|
||||||
|
* ``dk`` (Danish)
|
||||||
|
* ``pt_BR`` (Brazilian Portuguese)
|
||||||
|
* ``he`` (Hebrew)
|
||||||
|
* ``it`` (Italian)
|
||||||
|
|
||||||
You can supply values like ``fr_FR``, the code will be
|
You can supply values like ``fr_FR``, the code will be
|
||||||
correctly interpreted. If you supply an unsupported language, ``NotImplementedError`` is raised.
|
correctly interpreted. If you supply an unsupported language, ``NotImplementedError`` is raised.
|
||||||
@@ -62,7 +71,7 @@ Therefore, if you want to call ``num2words`` with a fallback, you can do::
|
|||||||
History
|
History
|
||||||
-------
|
-------
|
||||||
|
|
||||||
``num2words`` is based on an old library , ``pynum2word`` created by Taro Ogawa in 2003.
|
``num2words`` is based on an old library, ``pynum2word`` created by Taro Ogawa in 2003.
|
||||||
Unfortunately, the library stopped being maintained and the author can't be reached. There was
|
Unfortunately, the library stopped being maintained and the author can't be reached. There was
|
||||||
another developer, Marius Grigaitis, who in 2011 added Lithuanian support, but didn't take over
|
another developer, Marius Grigaitis, who in 2011 added Lithuanian support, but didn't take over
|
||||||
maintenance of the project.
|
maintenance of the project.
|
||||||
|
|||||||
@@ -20,22 +20,38 @@ from . import lang_EN
|
|||||||
from . import lang_EN_GB
|
from . import lang_EN_GB
|
||||||
from . import lang_EN_IN
|
from . import lang_EN_IN
|
||||||
from . import lang_FR
|
from . import lang_FR
|
||||||
|
from . import lang_FR_CH
|
||||||
from . import lang_DE
|
from . import lang_DE
|
||||||
from . import lang_ES
|
from . import lang_ES
|
||||||
from . import lang_LT
|
from . import lang_LT
|
||||||
from . import lang_LV
|
from . import lang_LV
|
||||||
from . import lang_PL
|
from . import lang_PL
|
||||||
|
from . import lang_RU
|
||||||
|
from . import lang_ID
|
||||||
|
from . import lang_NO
|
||||||
|
from . import lang_DK
|
||||||
|
from . import lang_PT_BR
|
||||||
|
from . import lang_HE
|
||||||
|
from . import lang_IT
|
||||||
|
|
||||||
CONVERTER_CLASSES = {
|
CONVERTER_CLASSES = {
|
||||||
'en': lang_EN.Num2Word_EN(),
|
'en': lang_EN.Num2Word_EN(),
|
||||||
'en_GB': lang_EN_GB.Num2Word_EN_GB(),
|
'en_GB': lang_EN_GB.Num2Word_EN_GB(),
|
||||||
'en_IN': lang_EN_IN.Num2Word_EN_IN(),
|
'en_IN': lang_EN_IN.Num2Word_EN_IN(),
|
||||||
'fr': lang_FR.Num2Word_FR(),
|
'fr': lang_FR.Num2Word_FR(),
|
||||||
|
'fr_CH': lang_FR_CH.Num2Word_FR_CH(),
|
||||||
'de': lang_DE.Num2Word_DE(),
|
'de': lang_DE.Num2Word_DE(),
|
||||||
'es': lang_ES.Num2Word_ES(),
|
'es': lang_ES.Num2Word_ES(),
|
||||||
|
'id': lang_ID.Num2Word_ID(),
|
||||||
'lt': lang_LT.Num2Word_LT(),
|
'lt': lang_LT.Num2Word_LT(),
|
||||||
'lv': lang_LV.Num2Word_LV(),
|
'lv': lang_LV.Num2Word_LV(),
|
||||||
'pl': lang_PL.Num2Word_PL(),
|
'pl': lang_PL.Num2Word_PL(),
|
||||||
|
'ru': lang_RU.Num2Word_RU(),
|
||||||
|
'no': lang_NO.Num2Word_NO(),
|
||||||
|
'dk': lang_DK.Num2Word_DK(),
|
||||||
|
'pt_BR': lang_PT_BR.Num2Word_PT_BR(),
|
||||||
|
'he': lang_HE.Num2Word_HE(),
|
||||||
|
'it': lang_IT.Num2Word_IT()
|
||||||
}
|
}
|
||||||
|
|
||||||
def num2words(number, ordinal=False, lang='en'):
|
def num2words(number, ordinal=False, lang='en'):
|
||||||
|
|||||||
@@ -15,7 +15,11 @@
|
|||||||
# MA 02110-1301 USA
|
# MA 02110-1301 USA
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import math
|
||||||
|
|
||||||
from .orderedmapping import OrderedMapping
|
from .orderedmapping import OrderedMapping
|
||||||
|
from .compat import to_s
|
||||||
|
|
||||||
|
|
||||||
class Num2Word_Base(object):
|
class Num2Word_Base(object):
|
||||||
@@ -88,7 +92,7 @@ class Num2Word_Base(object):
|
|||||||
|
|
||||||
def to_cardinal(self, value):
|
def to_cardinal(self, value):
|
||||||
try:
|
try:
|
||||||
assert long(value) == value
|
assert int(value) == value
|
||||||
except (ValueError, TypeError, AssertionError):
|
except (ValueError, TypeError, AssertionError):
|
||||||
return self.to_cardinal_float(value)
|
return self.to_cardinal_float(value)
|
||||||
|
|
||||||
@@ -102,7 +106,6 @@ class Num2Word_Base(object):
|
|||||||
if value >= self.MAXVAL:
|
if value >= self.MAXVAL:
|
||||||
raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL))
|
raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL))
|
||||||
|
|
||||||
|
|
||||||
val = self.splitnum(value)
|
val = self.splitnum(value)
|
||||||
words, num = self.clean(val)
|
words, num = self.clean(val)
|
||||||
return self.title(out + words)
|
return self.title(out + words)
|
||||||
@@ -114,18 +117,26 @@ class Num2Word_Base(object):
|
|||||||
except (ValueError, TypeError, AssertionError):
|
except (ValueError, TypeError, AssertionError):
|
||||||
raise TypeError(self.errmsg_nonnum % value)
|
raise TypeError(self.errmsg_nonnum % value)
|
||||||
|
|
||||||
|
value = float(value)
|
||||||
pre = int(value)
|
pre = int(value)
|
||||||
post = abs(value - pre)
|
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))
|
||||||
|
post = str(post)
|
||||||
|
post = '0' * (self.precision - len(post)) + post
|
||||||
|
|
||||||
out = [self.to_cardinal(pre)]
|
out = [self.to_cardinal(pre)]
|
||||||
if self.precision:
|
if self.precision:
|
||||||
out.append(self.title(self.pointword))
|
out.append(self.title(self.pointword))
|
||||||
|
|
||||||
for i in range(self.precision):
|
for i in range(self.precision):
|
||||||
post *= 10
|
curr = int(post[i])
|
||||||
curr = int(post)
|
out.append(to_s(self.to_cardinal(curr)))
|
||||||
out.append(str(self.to_cardinal(curr)))
|
|
||||||
post -= curr
|
|
||||||
|
|
||||||
return " ".join(out)
|
return " ".join(out)
|
||||||
|
|
||||||
@@ -170,10 +181,10 @@ class Num2Word_Base(object):
|
|||||||
|
|
||||||
|
|
||||||
def verify_ordinal(self, value):
|
def verify_ordinal(self, value):
|
||||||
if not value == long(value):
|
if not value == int(value):
|
||||||
raise TypeError, self.errmsg_floatord %(value)
|
raise TypeError(self.errmsg_floatord % value)
|
||||||
if not abs(value) == value:
|
if not abs(value) == value:
|
||||||
raise TypeError, self.errmsg_negord %(value)
|
raise TypeError(self.errmsg_negord % value)
|
||||||
|
|
||||||
|
|
||||||
def verify_num(self, value):
|
def verify_num(self, value):
|
||||||
@@ -184,7 +195,7 @@ class Num2Word_Base(object):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def to_ordinal(value):
|
def to_ordinal(self, value):
|
||||||
return self.to_cardinal(value)
|
return self.to_cardinal(value)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
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)
|
||||||
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||||
# Copyright (c) 2013, Savoir-faire Linux inc. 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,
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
# MA 02110-1301 USA
|
# MA 02110-1301 USA
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals, print_function
|
||||||
from .lang_EU import Num2Word_EU
|
from .lang_EU import Num2Word_EU
|
||||||
|
|
||||||
#//TODO: Use German error messages
|
|
||||||
class Num2Word_DE(Num2Word_EU):
|
class Num2Word_DE(Num2Word_EU):
|
||||||
def set_high_numwords(self, high):
|
def set_high_numwords(self, high):
|
||||||
max = 3 + 6*len(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] = word + "illiarde"
|
||||||
self.cards[10**(n-3)] = word + "illion"
|
self.cards[10**(n-3)] = word + "illion"
|
||||||
|
|
||||||
|
|
||||||
def setup(self):
|
def setup(self):
|
||||||
self.negword = "minus "
|
self.negword = "minus "
|
||||||
self.pointword = "Komma"
|
self.pointword = "Komma"
|
||||||
self.errmsg_nonnum = "Only numbers may be converted to words."
|
self.errmsg_floatord = "Die Gleitkommazahl %s kann nicht in eine Ordnungszahl konvertiert werden." # "Cannot treat float %s as ordinal."
|
||||||
self.errmsg_toobig = "Number is too large to convert to words."
|
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 = []
|
self.exclude_title = []
|
||||||
|
|
||||||
lows = ["non", "okt", "sept", "sext", "quint", "quadr", "tr", "b", "m"]
|
lows = ["non", "okt", "sept", "sext", "quint", "quadr", "tr", "b", "m"]
|
||||||
@@ -44,41 +45,45 @@ class Num2Word_DE(Num2Word_EU):
|
|||||||
(90, "neunzig"), (80, "achtzig"), (70, "siebzig"),
|
(90, "neunzig"), (80, "achtzig"), (70, "siebzig"),
|
||||||
(60, "sechzig"), (50, "f\xFCnfzig"), (40, "vierzig"),
|
(60, "sechzig"), (50, "f\xFCnfzig"), (40, "vierzig"),
|
||||||
(30, "drei\xDFig")]
|
(30, "drei\xDFig")]
|
||||||
self.low_numwords = ["zwanzig", "neunzehn", "achtzen", "siebzehn",
|
self.low_numwords = ["zwanzig", "neunzehn", "achtzehn", "siebzehn",
|
||||||
"sechzehn", "f\xFCnfzehn", "vierzehn", "dreizehn",
|
"sechzehn", "f\xFCnfzehn", "vierzehn", "dreizehn",
|
||||||
"zw\xF6lf", "elf", "zehn", "neun", "acht", "sieben",
|
"zw\xF6lf", "elf", "zehn", "neun", "acht", "sieben",
|
||||||
"sechs", "f\xFCnf", "vier", "drei", "zwei", "eins",
|
"sechs", "f\xFCnf", "vier", "drei", "zwei", "eins",
|
||||||
"null"]
|
"null"]
|
||||||
self.ords = { "eins" : "ers",
|
self.ords = {"eins": "ers",
|
||||||
"drei" : "drit",
|
"drei": "drit",
|
||||||
"acht" : "ach",
|
"acht": "ach",
|
||||||
"sieben" : "sieb",
|
"sieben": "sieb",
|
||||||
"ig" : "igs" }
|
"ig": "igs",
|
||||||
self.ordflag = False
|
"ert": "erts",
|
||||||
|
"end": "ends",
|
||||||
|
"ion": "ions",
|
||||||
|
"nen": "nens",
|
||||||
|
"rde": "rdes",
|
||||||
|
"rden": "rdens"}
|
||||||
|
|
||||||
def merge(self, curr, next):
|
def merge(self, curr, next):
|
||||||
ctext, cnum, ntext, nnum = curr + next
|
ctext, cnum, ntext, nnum = curr + next
|
||||||
|
|
||||||
if cnum == 1:
|
if cnum == 1:
|
||||||
if nnum < 10**6 or self.ordflag:
|
if nnum < 10**6:
|
||||||
return next
|
return next
|
||||||
ctext = "eine"
|
ctext = "eine"
|
||||||
|
|
||||||
if nnum > cnum:
|
if nnum > cnum:
|
||||||
if nnum >= 10**6:
|
if nnum >= 10**6:
|
||||||
if cnum > 1:
|
if cnum > 1:
|
||||||
if ntext.endswith("e") or self.ordflag:
|
if ntext.endswith("e"):
|
||||||
ntext += "s"
|
ntext += "n"
|
||||||
else:
|
else:
|
||||||
ntext += "es"
|
ntext += "en"
|
||||||
ctext += " "
|
ctext += " "
|
||||||
val = cnum * nnum
|
val = cnum * nnum
|
||||||
else:
|
else:
|
||||||
if nnum < 10 < cnum < 100:
|
if nnum < 10 < cnum < 100:
|
||||||
if nnum == 1:
|
if nnum == 1:
|
||||||
ntext = "ein"
|
ntext = "ein"
|
||||||
ntext, ctext = ctext, ntext + "und"
|
ntext, ctext = ctext, ntext + "und"
|
||||||
elif cnum >= 10**6:
|
elif cnum >= 10**6:
|
||||||
ctext += " "
|
ctext += " "
|
||||||
val = cnum + nnum
|
val = cnum + nnum
|
||||||
@@ -86,24 +91,18 @@ class Num2Word_DE(Num2Word_EU):
|
|||||||
word = ctext + ntext
|
word = ctext + ntext
|
||||||
return (word, val)
|
return (word, val)
|
||||||
|
|
||||||
|
|
||||||
def to_ordinal(self, value):
|
def to_ordinal(self, value):
|
||||||
self.verify_ordinal(value)
|
self.verify_ordinal(value)
|
||||||
self.ordflag = True
|
|
||||||
outword = self.to_cardinal(value)
|
outword = self.to_cardinal(value)
|
||||||
self.ordflag = False
|
|
||||||
for key in self.ords:
|
for key in self.ords:
|
||||||
if outword.endswith(key):
|
if outword.endswith(key):
|
||||||
outword = outword[:len(outword) - len(key)] + self.ords[key]
|
outword = outword[:len(outword) - len(key)] + self.ords[key]
|
||||||
break
|
break
|
||||||
return outword + "te"
|
return outword + "te"
|
||||||
|
|
||||||
|
|
||||||
# Is this correct??
|
|
||||||
def to_ordinal_num(self, value):
|
def to_ordinal_num(self, value):
|
||||||
self.verify_ordinal(value)
|
self.verify_ordinal(value)
|
||||||
return str(value) + "te"
|
return str(value) + "."
|
||||||
|
|
||||||
|
|
||||||
def to_currency(self, val, longval=True, old=False):
|
def to_currency(self, val, longval=True, old=False):
|
||||||
if old:
|
if old:
|
||||||
@@ -117,8 +116,6 @@ class Num2Word_DE(Num2Word_EU):
|
|||||||
return self.to_cardinal(val)
|
return self.to_cardinal(val)
|
||||||
return self.to_splitnum(val, hightxt="hundert", longval=longval)
|
return self.to_splitnum(val, hightxt="hundert", longval=longval)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
n2w = Num2Word_DE()
|
n2w = Num2Word_DE()
|
||||||
to_card = n2w.to_cardinal
|
to_card = n2w.to_cardinal
|
||||||
to_ord = n2w.to_ordinal
|
to_ord = n2w.to_ordinal
|
||||||
@@ -126,15 +123,20 @@ to_ordnum = n2w.to_ordinal_num
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
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,
|
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]:
|
-21212121211221211111, -2.121212, -1.0000100]:
|
||||||
n2w.test(val)
|
n2w.test(val)
|
||||||
|
|
||||||
n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
|
# n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
|
||||||
print n2w.to_currency(112121)
|
n2w.test(3000000)
|
||||||
print n2w.to_year(2000)
|
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__":
|
if __name__ == "__main__":
|
||||||
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,
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
# MA 02110-1301 USA
|
# MA 02110-1301 USA
|
||||||
|
|
||||||
from __future__ import division, unicode_literals
|
from __future__ import division, unicode_literals, print_function
|
||||||
from . import lang_EU
|
from . import lang_EU
|
||||||
|
|
||||||
class Num2Word_EN(lang_EU.Num2Word_EU):
|
class Num2Word_EN(lang_EU.Num2Word_EU):
|
||||||
@@ -47,7 +47,9 @@ class Num2Word_EN(lang_EU.Num2Word_EU):
|
|||||||
"twelve" : "twelfth" }
|
"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:
|
if lnum == 1 and rnum < 100:
|
||||||
return (rtext, rnum)
|
return (rtext, rnum)
|
||||||
elif 100 > lnum > rnum :
|
elif 100 > lnum > rnum :
|
||||||
@@ -105,8 +107,8 @@ def main():
|
|||||||
n2w.test(val)
|
n2w.test(val)
|
||||||
n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
|
n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
|
||||||
for val in [1,120,1000,1120,1800, 1976,2000,2010,2099,2171]:
|
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_currency(val))
|
||||||
print val, "is", n2w.to_year(val)
|
print(val, "is", n2w.to_year(val))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
# MA 02110-1301 USA
|
# MA 02110-1301 USA
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals, print_function
|
||||||
from .lang_EN import Num2Word_EN
|
from .lang_EN import Num2Word_EN
|
||||||
|
|
||||||
|
|
||||||
@@ -38,8 +38,8 @@ def main():
|
|||||||
n2w.test(val)
|
n2w.test(val)
|
||||||
n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
|
n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
|
||||||
for val in [1,120,1000,1120,1800, 1976,2000,2010,2099,2171]:
|
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_currency(val))
|
||||||
print val, "is", n2w.to_year(val)
|
print(val, "is", n2w.to_year(val))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
# MA 02110-1301 USA
|
# MA 02110-1301 USA
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals, print_function
|
||||||
from .lang_EU import Num2Word_EU
|
from .lang_EU import Num2Word_EU
|
||||||
|
|
||||||
class Num2Word_ES(Num2Word_EU):
|
class Num2Word_ES(Num2Word_EU):
|
||||||
@@ -173,9 +173,9 @@ def main():
|
|||||||
n2w.test(val)
|
n2w.test(val)
|
||||||
|
|
||||||
n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
|
n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
|
||||||
print n2w.to_currency(1222)
|
print(n2w.to_currency(1222))
|
||||||
print n2w.to_currency(1222, old=True)
|
print(n2w.to_currency(1222, old=True))
|
||||||
print n2w.to_year(1222)
|
print(n2w.to_year(1222))
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
@@ -15,16 +15,16 @@
|
|||||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
# MA 02110-1301 USA
|
# MA 02110-1301 USA
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals, print_function
|
||||||
from .lang_EU import Num2Word_EU
|
from .lang_EU import Num2Word_EU
|
||||||
|
|
||||||
#//TODO: error messages in French
|
|
||||||
class Num2Word_FR(Num2Word_EU):
|
class Num2Word_FR(Num2Word_EU):
|
||||||
def setup(self):
|
def setup(self):
|
||||||
self.negword = "moins "
|
self.negword = "moins "
|
||||||
self.pointword = "virgule"
|
self.pointword = "virgule"
|
||||||
self.errmsg_nonnum = "Only numbers may be converted to words."
|
self.errmsg_nonnum = u"Seulement des nombres peuvent être convertis en mots."
|
||||||
self.errmsg_toobig = "Number is too large to convert to words."
|
self.errmsg_toobig = u"Nombre trop grand pour être converti en mots."
|
||||||
self.exclude_title = ["et", "virgule", "moins"]
|
self.exclude_title = ["et", "virgule", "moins"]
|
||||||
self.mid_numwords = [(1000, "mille"), (100, "cent"),
|
self.mid_numwords = [(1000, "mille"), (100, "cent"),
|
||||||
(80, "quatre-vingts"), (60, "soixante"),
|
(80, "quatre-vingts"), (60, "soixante"),
|
||||||
@@ -106,8 +106,8 @@ def main():
|
|||||||
n2w.test(val)
|
n2w.test(val)
|
||||||
|
|
||||||
n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
|
n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
|
||||||
print n2w.to_currency(112121)
|
print(n2w.to_currency(112121))
|
||||||
print n2w.to_year(1996)
|
print(n2w.to_year(1996))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
109
num2words/lang_FR_CH.py
Normal file
109
num2words/lang_FR_CH.py
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
# -*- 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_EU import Num2Word_EU
|
||||||
|
|
||||||
|
class Num2Word_FR_CH(Num2Word_EU):
|
||||||
|
def setup(self):
|
||||||
|
self.negword = "moins "
|
||||||
|
self.pointword = "virgule"
|
||||||
|
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"), (90, "nonante"),
|
||||||
|
(80, "huitante"), (70, "septante"), (60, "soixante"),
|
||||||
|
(50, "cinquante"), (40, "quarante"),
|
||||||
|
(30, "trente")]
|
||||||
|
self.low_numwords = ["vingt", "dix-neuf", "dix-huit", "dix-sept",
|
||||||
|
"seize", "quinze", "quatorze", "treize", "douze",
|
||||||
|
"onze", "dix", "neuf", "huit", "sept", "six",
|
||||||
|
"cinq", "quatre", "trois", "deux", "un", "zéro"]
|
||||||
|
self.ords = {
|
||||||
|
"cinq": "cinquième",
|
||||||
|
"neuf": "neuvième",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
||||||
|
elif nnum > cnum:
|
||||||
|
return ("%s %s"%(ctext, ntext), cnum * nnum)
|
||||||
|
return ("%s %s"%(ctext, ntext), cnum + nnum)
|
||||||
|
|
||||||
|
|
||||||
|
# Is this right for such things as 1001 - "mille unième" instead of
|
||||||
|
# "mille premier"?? "millième"??
|
||||||
|
|
||||||
|
def to_ordinal(self,value):
|
||||||
|
self.verify_ordinal(value)
|
||||||
|
if value == 1:
|
||||||
|
return "premier"
|
||||||
|
word = self.to_cardinal(value)
|
||||||
|
for src, repl in self.ords.items():
|
||||||
|
if word.endswith(src):
|
||||||
|
word = word[:-len(src)] + repl
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
if word[-1] == "e":
|
||||||
|
word = word[:-1]
|
||||||
|
word = word + "ième"
|
||||||
|
return word
|
||||||
|
|
||||||
|
def to_ordinal_num(self, value):
|
||||||
|
self.verify_ordinal(value)
|
||||||
|
out = str(value)
|
||||||
|
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"
|
||||||
|
return self.to_splitnum(val, hightxt=hightxt, lowtxt="centime/s",
|
||||||
|
jointxt="et",longval=longval)
|
||||||
|
|
||||||
|
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()
|
||||||
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)
|
||||||
217
num2words/lang_IT.py
Normal file
217
num2words/lang_IT.py
Normal file
@@ -0,0 +1,217 @@
|
|||||||
|
# -*- 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
|
||||||
|
|
||||||
|
import re
|
||||||
|
import math
|
||||||
|
|
||||||
|
class Num2Word_IT(object):
|
||||||
|
def __init__(self):
|
||||||
|
self._minus = "meno "
|
||||||
|
|
||||||
|
self._exponent = {
|
||||||
|
0 : ('',''),
|
||||||
|
3 : ('mille','mila'),
|
||||||
|
6 : ('milione','miloni'),
|
||||||
|
12 : ('miliardo','miliardi'),
|
||||||
|
18 : ('trillone','trilloni'),
|
||||||
|
24 : ('quadrilione','quadrilioni')}
|
||||||
|
|
||||||
|
self._digits = ['zero', 'uno', 'due', 'tre', 'quattro', 'cinque', 'sei', 'sette', 'otto', 'nove']
|
||||||
|
|
||||||
|
self._sep = ''
|
||||||
|
|
||||||
|
def _toWords(self, num, power=0):
|
||||||
|
str_num = str(num)
|
||||||
|
# The return string;
|
||||||
|
ret = ''
|
||||||
|
|
||||||
|
# add a the word for the minus sign if necessary
|
||||||
|
if num < 0:
|
||||||
|
ret = self._sep + self._minus
|
||||||
|
|
||||||
|
if len(str_num) > 6:
|
||||||
|
current_power = 6
|
||||||
|
# check for highest power
|
||||||
|
if power in self._exponent:
|
||||||
|
# convert the number above the first 6 digits
|
||||||
|
# with it's corresponding $power.
|
||||||
|
snum = str_num[0:-6]
|
||||||
|
if snum != '':
|
||||||
|
ret = ret + self._toWords(int(snum), power + 6)
|
||||||
|
|
||||||
|
num = int(str_num[-6:])
|
||||||
|
if num == 0:
|
||||||
|
return ret
|
||||||
|
|
||||||
|
elif num == 0 or str_num == '':
|
||||||
|
return ' ' + self._digits[0] + ' '
|
||||||
|
else:
|
||||||
|
current_power = len(str_num)
|
||||||
|
|
||||||
|
# See if we need "thousands"
|
||||||
|
thousands = math.floor(num / 1000)
|
||||||
|
if thousands == 1:
|
||||||
|
ret = ret + self._sep + 'mille' + self._sep
|
||||||
|
elif thousands > 1:
|
||||||
|
ret = ret + self._toWords(int(thousands), 3) + self._sep
|
||||||
|
|
||||||
|
# values for digits, tens and hundreds
|
||||||
|
h = int(math.floor((num / 100) % 10))
|
||||||
|
t = int(math.floor((num / 10) % 10))
|
||||||
|
d = int(math.floor(num % 10))
|
||||||
|
|
||||||
|
# centinaia: duecento, trecento, etc...
|
||||||
|
if h == 1:
|
||||||
|
if ((d==0) and (t == 0)):# is it's '100' use 'cien'
|
||||||
|
ret = ret + self._sep + 'cento'
|
||||||
|
else:
|
||||||
|
ret = ret + self._sep + 'cento'
|
||||||
|
elif h == 2 or h == 3 or h == 4 or h == 6 or h == 8:
|
||||||
|
ret = ret + self._sep + self._digits[h] + 'cento'
|
||||||
|
elif h == 5:
|
||||||
|
ret = ret + self._sep + 'cinquecento'
|
||||||
|
elif h == 7:
|
||||||
|
ret = ret + self._sep + 'settecento'
|
||||||
|
elif h == 9:
|
||||||
|
ret = ret + self._sep + 'novecento'
|
||||||
|
|
||||||
|
# decine: venti trenta, etc...
|
||||||
|
if t == 9:
|
||||||
|
if d == 1 or d == 8:
|
||||||
|
ret = ret + self._sep + 'novant'
|
||||||
|
else:
|
||||||
|
ret = ret + self._sep + 'novanta'
|
||||||
|
if t == 8:
|
||||||
|
if d == 1 or d == 8:
|
||||||
|
ret = ret + self._sep + 'ottant'
|
||||||
|
else:
|
||||||
|
ret = ret + self._sep + 'ottanta'
|
||||||
|
if t == 7:
|
||||||
|
if d == 1 or d == 8:
|
||||||
|
ret = ret + self._sep + 'settant'
|
||||||
|
else:
|
||||||
|
ret = ret + self._sep + 'settanta'
|
||||||
|
if t == 6:
|
||||||
|
if d == 1 or d == 8:
|
||||||
|
ret = ret + self._sep + 'sessant'
|
||||||
|
else:
|
||||||
|
ret = ret + self._sep + 'sessanta'
|
||||||
|
if t == 5:
|
||||||
|
if d == 1 or d == 8:
|
||||||
|
ret = ret + self._sep + 'cinquant'
|
||||||
|
else:
|
||||||
|
ret = ret + self._sep + 'cinquanta'
|
||||||
|
if t == 4:
|
||||||
|
if d == 1 or d == 8:
|
||||||
|
ret = ret + self._sep + 'quarant'
|
||||||
|
else:
|
||||||
|
ret = ret + self._sep + 'quaranta'
|
||||||
|
if t == 3:
|
||||||
|
if d == 1 or d == 8:
|
||||||
|
ret = ret + self._sep + 'trent'
|
||||||
|
else:
|
||||||
|
ret = ret + self._sep + 'trenta'
|
||||||
|
if t == 2:
|
||||||
|
if d == 0:
|
||||||
|
ret = ret + self._sep + 'venti'
|
||||||
|
elif (d == 1 or d == 8):
|
||||||
|
ret = ret + self._sep + 'vent' + self._digits[d]
|
||||||
|
else:
|
||||||
|
ret = ret + self._sep + 'venti' + self._digits[d]
|
||||||
|
if t == 1:
|
||||||
|
if d == 0:
|
||||||
|
ret = ret + self._sep + 'dieci'
|
||||||
|
elif d == 1:
|
||||||
|
ret = ret + self._sep + 'undici'
|
||||||
|
elif d == 2:
|
||||||
|
ret = ret + self._sep + 'dodici'
|
||||||
|
elif d == 3:
|
||||||
|
ret = ret + self._sep + 'tredici'
|
||||||
|
elif d == 4:
|
||||||
|
ret = ret + self._sep + 'quattordici'
|
||||||
|
elif d == 5:
|
||||||
|
ret = ret + self._sep + 'quindici'
|
||||||
|
elif d == 6:
|
||||||
|
ret = ret + self._sep + 'sedici'
|
||||||
|
elif d == 7:
|
||||||
|
ret = ret + self._sep + 'diciassette'
|
||||||
|
elif d == 8:
|
||||||
|
ret = ret + self._sep + 'diciotto'
|
||||||
|
elif d == 9:
|
||||||
|
ret = ret + self._sep + 'diciannove'
|
||||||
|
|
||||||
|
# add digits only if it is a multiple of 10 and not 1x or 2x
|
||||||
|
if t != 1 and t != 2 and d > 0:
|
||||||
|
# don't add 'e' for numbers below 10
|
||||||
|
if t != 0:
|
||||||
|
# use 'un' instead of 'uno' when there is a suffix ('mila', 'milloni', etc...)
|
||||||
|
if (power > 0) and ( d == 1):
|
||||||
|
ret = ret + self._sep + 'e un'
|
||||||
|
else:
|
||||||
|
ret = ret + self._sep + '' + self._digits[d]
|
||||||
|
else:
|
||||||
|
if power > 0 and d == 1:
|
||||||
|
ret = ret + self._sep + 'un '
|
||||||
|
else:
|
||||||
|
ret = ret + self._sep + self._digits[d]
|
||||||
|
|
||||||
|
if power > 0:
|
||||||
|
if power in self._exponent:
|
||||||
|
lev = self._exponent[power]
|
||||||
|
|
||||||
|
if lev is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# if it's only one use the singular suffix
|
||||||
|
if d == 1 and t == 0 and h == 0:
|
||||||
|
suffix = lev[0]
|
||||||
|
else:
|
||||||
|
suffix = lev[1]
|
||||||
|
|
||||||
|
if num != 0:
|
||||||
|
ret = ret + self._sep + suffix
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
def to_cardinal(self, number):
|
||||||
|
return self._toWords(number)
|
||||||
|
|
||||||
|
def to_ordinal_num(self, number):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def to_ordinal(self,value):
|
||||||
|
if 0 <= value <= 10:
|
||||||
|
return ["primo", "secondo", "terzo", "quarto", "quinto", "sesto", "settimo", "ottavo", "nono", "decimo"][value - 1]
|
||||||
|
else:
|
||||||
|
as_word = self._toWords(value)
|
||||||
|
if as_word.endswith("dici"):
|
||||||
|
return re.sub("dici$", "dicesimo", as_word)
|
||||||
|
elif as_word.endswith("to"):
|
||||||
|
return re.sub("to$", "tesimo", as_word)
|
||||||
|
elif as_word.endswith("ta"):
|
||||||
|
return re.sub("ta$", "tesimo", as_word)
|
||||||
|
else:
|
||||||
|
return as_word + "simo"
|
||||||
|
|
||||||
|
|
||||||
|
n2w = Num2Word_IT()
|
||||||
|
to_card = n2w.to_cardinal
|
||||||
|
to_ord = n2w.to_ordinal
|
||||||
|
to_ordnum = n2w.to_ordinal_num
|
||||||
|
|
||||||
@@ -85,7 +85,13 @@ vienas litas, nulis centų
|
|||||||
vienas tūkstantis du šimtai trisdešimt keturi litai, penkiasdešimt šeši centai
|
vienas tūkstantis du šimtai trisdešimt keturi litai, penkiasdešimt šeši centai
|
||||||
|
|
||||||
>>> print(to_currency(-1251985, cents = False))
|
>>> 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
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
@@ -144,6 +150,7 @@ THOUSANDS = {
|
|||||||
|
|
||||||
CURRENCIES = {
|
CURRENCIES = {
|
||||||
'LTL': ((u'litas', u'litai', u'litų'), (u'centas', u'centai', u'centų')),
|
'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):
|
def splitby3(n):
|
||||||
@@ -210,7 +217,7 @@ def n2w(n):
|
|||||||
else:
|
else:
|
||||||
return int2word(int(n))
|
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 type(n) == int:
|
||||||
if n < 0:
|
if n < 0:
|
||||||
minus = True
|
minus = True
|
||||||
|
|||||||
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()
|
||||||
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 and not (i > 0 and x == 1):
|
||||||
|
ones = ONES_FEMININE if i == 1 or feminine and i == 0 else ONES
|
||||||
|
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 запятая %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()
|
||||||
3
setup.py
3
setup.py
@@ -17,7 +17,7 @@ LONG_DESC = open('README.rst', 'rt').read() + '\n\n' + open('CHANGES.rst', 'rt')
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='num2words',
|
name='num2words',
|
||||||
version='0.5.3',
|
version='0.5.4',
|
||||||
description='Modules to convert numbers to words. Easily extensible.',
|
description='Modules to convert numbers to words. Easily extensible.',
|
||||||
long_description=LONG_DESC,
|
long_description=LONG_DESC,
|
||||||
license='LGPL',
|
license='LGPL',
|
||||||
@@ -29,5 +29,4 @@ setup(
|
|||||||
url='https://github.com/savoirfairelinux/num2words',
|
url='https://github.com/savoirfairelinux/num2words',
|
||||||
packages=find_packages(exclude=['tests']),
|
packages=find_packages(exclude=['tests']),
|
||||||
test_suite='tests',
|
test_suite='tests',
|
||||||
use_2to3=True,
|
|
||||||
)
|
)
|
||||||
|
|||||||
51
tests/test_de.py
Normal file
51
tests/test_de.py
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
# Copyright (c) 2015, 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 unittest import TestCase
|
||||||
|
|
||||||
|
from num2words import num2words
|
||||||
|
|
||||||
|
class Num2WordsDETest(TestCase):
|
||||||
|
def test_ordinal_less_than_twenty(self):
|
||||||
|
self.assertEqual(num2words(7, ordinal=True, lang='de'), "siebte")
|
||||||
|
self.assertEqual(num2words(8, ordinal=True, lang='de'), "achte")
|
||||||
|
self.assertEqual(num2words(12, ordinal=True, lang='de'), "zwölfte")
|
||||||
|
self.assertEqual(num2words(17, ordinal=True, lang='de'), "siebzehnte")
|
||||||
|
|
||||||
|
def test_ordinal_more_than_twenty(self):
|
||||||
|
self.assertEqual(num2words(81, ordinal=True, lang='de'), "einundachtzigste")
|
||||||
|
|
||||||
|
def test_ordinal_at_crucial_number(self):
|
||||||
|
self.assertEqual(num2words(100, ordinal=True, lang='de'), "hundertste")
|
||||||
|
self.assertEqual(num2words(1000, ordinal=True, lang='de'), "tausendste")
|
||||||
|
self.assertEqual(num2words(4000, ordinal=True, lang='de'), "viertausendste")
|
||||||
|
self.assertEqual(num2words(2000000, ordinal=True, lang='de'), "zwei millionenste")
|
||||||
|
self.assertEqual(num2words(5000000000, ordinal=True, lang='de'), "fünf milliardenste")
|
||||||
|
|
||||||
|
def test_cardinal_at_some_numbers(self):
|
||||||
|
self.assertEqual(num2words(2000000, lang='de'), "zwei millionen")
|
||||||
|
self.assertEqual(num2words(4000000000, lang='de'), "vier milliarden")
|
||||||
|
|
||||||
|
def test_cardinal_for_decimal_number(self):
|
||||||
|
self.assertEqual(num2words(3.486, lang='de'), "drei Komma vier acht")
|
||||||
|
|
||||||
|
def test_ordinal_for_negative_numbers(self):
|
||||||
|
self.assertRaises(TypeError, num2words, -12, ordinal=True, lang='de')
|
||||||
|
|
||||||
|
def test_ordinal_for_floating_numbers(self):
|
||||||
|
self.assertRaises(TypeError, num2words, 2.453, ordinal=True, lang='de')
|
||||||
@@ -21,3 +21,10 @@ class Num2WordsENTest(TestCase):
|
|||||||
def test_and_join_199(self):
|
def test_and_join_199(self):
|
||||||
# ref https://github.com/savoirfairelinux/num2words/issues/8
|
# ref https://github.com/savoirfairelinux/num2words/issues/8
|
||||||
self.assertEqual(num2words(199), "one hundred and ninety-nine")
|
self.assertEqual(num2words(199), "one hundred and ninety-nine")
|
||||||
|
|
||||||
|
def test_cardinal_for_float_number(self):
|
||||||
|
# issue 24
|
||||||
|
self.assertEqual(num2words(12.50), "twelve point five zero")
|
||||||
|
self.assertEqual(num2words(12.51), "twelve point five one")
|
||||||
|
self.assertEqual(num2words(12.53), "twelve point five three")
|
||||||
|
self.assertEqual(num2words(12.59), "twelve point five nine")
|
||||||
36
tests/test_fr_ch.py
Normal file
36
tests/test_fr_ch.py
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
# Copyright (c) 2015, 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 unittest import TestCase
|
||||||
|
|
||||||
|
from num2words import num2words
|
||||||
|
|
||||||
|
class Num2WordsENTest(TestCase):
|
||||||
|
def test_ordinal_special_joins(self):
|
||||||
|
self.assertEqual(num2words(5, ordinal=True, lang='fr_CH'), "cinquième")
|
||||||
|
self.assertEqual(num2words(6, ordinal=True, lang='fr_CH'), "sixième")
|
||||||
|
self.assertEqual(num2words(35, ordinal=True, lang='fr_CH'), "trente-cinquième")
|
||||||
|
self.assertEqual(num2words(9, ordinal=True, lang='fr_CH'), "neuvième")
|
||||||
|
self.assertEqual(num2words(49, ordinal=True, lang='fr_CH'), "quarante-neuvième")
|
||||||
|
self.assertEqual(num2words(71, lang='fr_CH'), "septante et un")
|
||||||
|
self.assertEqual(num2words(81, lang='fr_CH'), "huitante et un")
|
||||||
|
self.assertEqual(num2words(80, lang='fr_CH'), "huitante")
|
||||||
|
self.assertEqual(num2words(880, lang='fr_CH'), "huit cents huitante")
|
||||||
|
self.assertEqual(num2words(91, ordinal=True, lang='fr_CH'), "nonante et unième")
|
||||||
|
self.assertEqual(num2words(53, lang='fr_CH'), "cinquante-trois")
|
||||||
|
|
||||||
49
tests/test_id.py
Normal file
49
tests/test_id.py
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
# 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 unittest import TestCase
|
||||||
|
|
||||||
|
from num2words import num2words
|
||||||
|
|
||||||
|
class Num2WordsIDTest(TestCase):
|
||||||
|
def test_cardinal_for_natural_number(self):
|
||||||
|
self.assertEqual(num2words(10, lang='id'), "sepuluh")
|
||||||
|
self.assertEqual(num2words(11, lang='id'), "sebelas")
|
||||||
|
self.assertEqual(num2words(108, lang='id'), "seratus delapan")
|
||||||
|
self.assertEqual(num2words(1075, lang='id'), "seribu tujuh puluh lima")
|
||||||
|
self.assertEqual(num2words(1087231, lang='id'), "satu juta delapan puluh tujuh ribu dua ratus tiga puluh satu")
|
||||||
|
self.assertEqual(num2words(1000000408, lang='id'), "satu miliar empat ratus delapan")
|
||||||
|
|
||||||
|
def test_cardinal_for_decimal_number(self):
|
||||||
|
self.assertEqual(num2words(12.234, lang='id'), "dua belas koma dua tiga empat")
|
||||||
|
self.assertEqual(num2words(9.076, lang='id'), "sembilan koma nol tujuh enam")
|
||||||
|
|
||||||
|
def test_cardinal_for_negative_number(self):
|
||||||
|
self.assertEqual(num2words(-923, lang='id'), "min sembilan ratus dua puluh tiga")
|
||||||
|
self.assertEqual(num2words(-0.234, lang='id'), "min nol koma dua tiga empat")
|
||||||
|
|
||||||
|
def test_ordinal_for_natural_number(self):
|
||||||
|
self.assertEqual(num2words(1, ordinal=True, lang='id'), "pertama")
|
||||||
|
self.assertEqual(num2words(10, ordinal=True, lang='id'), "kesepuluh")
|
||||||
|
|
||||||
|
#def test_ordinal_numeric_for_natural_number(self):
|
||||||
|
# self.assertEqual(num2words(1, ordinal=True, lang='id'), "ke-1")
|
||||||
|
# self.assertEqual(num2words(10, ordinal=True, lang='id'), "ke-10")
|
||||||
|
|
||||||
|
def test_ordinal_for_negative_number(self):
|
||||||
|
self.assertRaises(TypeError, num2words, -12, ordinal=True, lang='id')
|
||||||
|
|
||||||
|
def test_ordinal_for_floating_number(self):
|
||||||
|
self.assertRaises(TypeError, num2words, 3.243, ordinal=True, lang='id')
|
||||||
96
tests/test_it.py
Normal file
96
tests/test_it.py
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
# Copyright (c) 2015, 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 unittest import TestCase
|
||||||
|
|
||||||
|
from num2words import num2words
|
||||||
|
|
||||||
|
class Num2WordsITTest(TestCase):
|
||||||
|
|
||||||
|
def test_number(self):
|
||||||
|
|
||||||
|
test_cases = (
|
||||||
|
(1,'uno'),
|
||||||
|
(2,'due'),
|
||||||
|
(3,'tre'),
|
||||||
|
(11,'undici'),
|
||||||
|
(12,'dodici'),
|
||||||
|
(16,'sedici'),
|
||||||
|
(19,'diciannove'),
|
||||||
|
(20,'venti'),
|
||||||
|
(21,'ventuno'),
|
||||||
|
(26,'ventisei'),
|
||||||
|
(28,'ventotto'),
|
||||||
|
(30,'trenta'),
|
||||||
|
(31,'trentuno'),
|
||||||
|
(40,'quaranta'),
|
||||||
|
(43,'quarantatre'),
|
||||||
|
(50,'cinquanta'),
|
||||||
|
(55,'cinquantacinque'),
|
||||||
|
(60,'sessanta'),
|
||||||
|
(67,'sessantasette'),
|
||||||
|
(70,'settanta'),
|
||||||
|
(79,'settantanove'),
|
||||||
|
(100,'cento'),
|
||||||
|
(101,'centouno'),
|
||||||
|
(199,'centonovantanove'),
|
||||||
|
(203,'duecentotre'),
|
||||||
|
(287,'duecentoottantasette'),
|
||||||
|
(300,'trecento'),
|
||||||
|
(356,'trecentocinquantasei'),
|
||||||
|
(410,'quattrocentodieci'),
|
||||||
|
(434,'quattrocentotrentaquattro'),
|
||||||
|
(578,'cinquecentosettantotto'),
|
||||||
|
(689,'seicentoottantanove'),
|
||||||
|
(729,'settecentoventinove'),
|
||||||
|
(894,'ottocentonovantaquattro'),
|
||||||
|
(999,'novecentonovantanove'),
|
||||||
|
(1000,'mille'),
|
||||||
|
(1001,'milleuno'),
|
||||||
|
(1097,'millenovantasette'),
|
||||||
|
(1104,'millecentoquattro'),
|
||||||
|
(1243,'milleduecentoquarantatre'),
|
||||||
|
(2385,'duemilatrecentoottantacinque'),
|
||||||
|
(3766,'tremilasettecentosessantasei'),
|
||||||
|
(4196,'quattromilacentonovantasei'),
|
||||||
|
(5846,'cinquemilaottocentoquarantasei'),
|
||||||
|
(6459,'seimilaquattrocentocinquantanove'),
|
||||||
|
(7232,'settemiladuecentotrentadue'),
|
||||||
|
(8569,'ottomilacinquecentosessantanove'),
|
||||||
|
(9539,'novemilacinquecentotrentanove'),
|
||||||
|
(1000000,'un milione'),
|
||||||
|
(1000001,'un milioneuno'),
|
||||||
|
# (1000000100,'un miliardocento'), # DOES NOT WORK TODO: FIX
|
||||||
|
)
|
||||||
|
|
||||||
|
for test in test_cases:
|
||||||
|
self.assertEqual(num2words(test[0], lang='it'), test[1])
|
||||||
|
|
||||||
|
def test_ordinal(self):
|
||||||
|
|
||||||
|
test_cases = (
|
||||||
|
(1,'primo'),
|
||||||
|
(8,'ottavo'),
|
||||||
|
(12,'dodicesimo'),
|
||||||
|
(14,'quattordicesimo'),
|
||||||
|
(28,'ventottesimo'),
|
||||||
|
(100,'centesimo'),
|
||||||
|
)
|
||||||
|
|
||||||
|
for test in test_cases:
|
||||||
|
self.assertEqual(num2words(test[0], lang='it', ordinal=True), test[1])
|
||||||
219
tests/test_pt_BR.py
Normal file
219
tests/test_pt_BR.py
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
# Copyright (c) 2015, 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 decimal import Decimal
|
||||||
|
from unittest import TestCase
|
||||||
|
|
||||||
|
from num2words import num2words
|
||||||
|
from num2words.lang_PT_BR import Num2Word_PT_BR
|
||||||
|
|
||||||
|
|
||||||
|
class Num2WordsPTBRTest(TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
super(Num2WordsPTBRTest, self).setUp()
|
||||||
|
self.n2w = Num2Word_PT_BR()
|
||||||
|
|
||||||
|
def test_cardinal_integer(self):
|
||||||
|
self.assertEqual(num2words(1, lang='pt_BR'), 'um')
|
||||||
|
self.assertEqual(num2words(2, lang='pt_BR'), 'dois')
|
||||||
|
self.assertEqual(num2words(3, lang='pt_BR'), 'três')
|
||||||
|
self.assertEqual(num2words(4, lang='pt_BR'), 'quatro')
|
||||||
|
self.assertEqual(num2words(5, lang='pt_BR'), 'cinco')
|
||||||
|
self.assertEqual(num2words(6, lang='pt_BR'), 'seis')
|
||||||
|
self.assertEqual(num2words(7, lang='pt_BR'), 'sete')
|
||||||
|
self.assertEqual(num2words(8, lang='pt_BR'), 'oito')
|
||||||
|
self.assertEqual(num2words(9, lang='pt_BR'), 'nove')
|
||||||
|
self.assertEqual(num2words(10, lang='pt_BR'), 'dez')
|
||||||
|
self.assertEqual(num2words(11, lang='pt_BR'), 'onze')
|
||||||
|
self.assertEqual(num2words(12, lang='pt_BR'), 'doze')
|
||||||
|
self.assertEqual(num2words(13, lang='pt_BR'), 'treze')
|
||||||
|
self.assertEqual(num2words(14, lang='pt_BR'), 'catorze')
|
||||||
|
self.assertEqual(num2words(15, lang='pt_BR'), 'quinze')
|
||||||
|
self.assertEqual(num2words(16, lang='pt_BR'), 'dezesseis')
|
||||||
|
self.assertEqual(num2words(17, lang='pt_BR'), 'dezessete')
|
||||||
|
self.assertEqual(num2words(18, lang='pt_BR'), 'dezoito')
|
||||||
|
self.assertEqual(num2words(19, lang='pt_BR'), 'dezenove')
|
||||||
|
self.assertEqual(num2words(20, lang='pt_BR'), 'vinte')
|
||||||
|
|
||||||
|
self.assertEqual(num2words(21, lang='pt_BR'), 'vinte e um')
|
||||||
|
self.assertEqual(num2words(22, lang='pt_BR'), 'vinte e dois')
|
||||||
|
self.assertEqual(num2words(35, lang='pt_BR'), 'trinta e cinco')
|
||||||
|
self.assertEqual(num2words(99, lang='pt_BR'), 'noventa e nove')
|
||||||
|
|
||||||
|
self.assertEqual(num2words(100, lang='pt_BR'), 'cem')
|
||||||
|
self.assertEqual(num2words(101, lang='pt_BR'), 'cento e um')
|
||||||
|
self.assertEqual(num2words(128, lang='pt_BR'), 'cento e vinte e oito')
|
||||||
|
self.assertEqual(num2words(713, lang='pt_BR'), 'setecentos e treze')
|
||||||
|
|
||||||
|
self.assertEqual(num2words(1000, lang='pt_BR'), 'mil')
|
||||||
|
self.assertEqual(num2words(1001, lang='pt_BR'), 'mil e um')
|
||||||
|
self.assertEqual(num2words(1111, lang='pt_BR'), 'mil, cento e onze')
|
||||||
|
self.assertEqual(num2words(2114, lang='pt_BR'), 'dois mil, cento e catorze')
|
||||||
|
self.assertEqual(num2words(73421, lang='pt_BR'), 'setenta e três mil, quatrocentos e vinte e um')
|
||||||
|
|
||||||
|
self.assertEqual(num2words(100000, lang='pt_BR'), 'cem mil')
|
||||||
|
self.assertEqual(num2words(250050, lang='pt_BR'), 'duzentos e cinquenta mil e cinquenta')
|
||||||
|
self.assertEqual(num2words(6000000, lang='pt_BR'), 'seis milhões')
|
||||||
|
self.assertEqual(num2words(19000000000, lang='pt_BR'), 'dezenove bilhões')
|
||||||
|
self.assertEqual(num2words(145000000002, lang='pt_BR'), 'cento e quarenta e cinco bilhões e dois')
|
||||||
|
|
||||||
|
def test_cardinal_integer_negative(self):
|
||||||
|
self.assertEqual(num2words(-1, lang='pt_BR'), 'menos um')
|
||||||
|
self.assertEqual(num2words(-256, lang='pt_BR'), 'menos duzentos e cinquenta e seis')
|
||||||
|
self.assertEqual(num2words(-1000, lang='pt_BR'), 'menos mil')
|
||||||
|
self.assertEqual(num2words(-1000000, lang='pt_BR'), 'menos um milhão')
|
||||||
|
self.assertEqual(num2words(-1234567, lang='pt_BR'), 'menos um milhão, duzentos e trinta e quatro mil, quinhentos e sessenta e sete')
|
||||||
|
|
||||||
|
def test_cardinal_float(self):
|
||||||
|
self.assertEqual(num2words(Decimal('1.00'), lang='pt_BR'), 'um')
|
||||||
|
self.assertEqual(num2words(Decimal('1.01'), lang='pt_BR'), 'um vírgula zero um')
|
||||||
|
self.assertEqual(num2words(Decimal('1.035'), lang='pt_BR'), 'um vírgula zero três')
|
||||||
|
self.assertEqual(num2words(Decimal('1.35'), lang='pt_BR'), 'um vírgula três cinco')
|
||||||
|
self.assertEqual(num2words(Decimal('3.14159'), lang='pt_BR'), 'três vírgula um quatro')
|
||||||
|
self.assertEqual(num2words(Decimal('101.22'), lang='pt_BR'), 'cento e um vírgula dois dois')
|
||||||
|
self.assertEqual(num2words(Decimal('2345.75'), lang='pt_BR'), 'dois mil, trezentos e quarenta e cinco vírgula sete cinco')
|
||||||
|
|
||||||
|
def test_cardinal_float_negative(self):
|
||||||
|
self.assertEqual(num2words(Decimal('-2.34'), lang='pt_BR'), 'menos dois vírgula três quatro')
|
||||||
|
self.assertEqual(num2words(Decimal('-9.99'), lang='pt_BR'), 'menos nove vírgula nove nove')
|
||||||
|
self.assertEqual(num2words(Decimal('-7.01'), lang='pt_BR'), 'menos sete vírgula zero um')
|
||||||
|
self.assertEqual(num2words(Decimal('-222.22'), lang='pt_BR'), 'menos duzentos e vinte e dois vírgula dois dois')
|
||||||
|
|
||||||
|
def test_ordinal(self):
|
||||||
|
self.assertEqual(num2words(1, lang='pt_BR', ordinal=True), 'primeiro')
|
||||||
|
self.assertEqual(num2words(2, lang='pt_BR', ordinal=True), 'segundo')
|
||||||
|
self.assertEqual(num2words(3, lang='pt_BR', ordinal=True), 'terceiro')
|
||||||
|
self.assertEqual(num2words(4, lang='pt_BR', ordinal=True), 'quarto')
|
||||||
|
self.assertEqual(num2words(5, lang='pt_BR', ordinal=True), 'quinto')
|
||||||
|
self.assertEqual(num2words(6, lang='pt_BR', ordinal=True), 'sexto')
|
||||||
|
self.assertEqual(num2words(7, lang='pt_BR', ordinal=True), 'sétimo')
|
||||||
|
self.assertEqual(num2words(8, lang='pt_BR', ordinal=True), 'oitavo')
|
||||||
|
self.assertEqual(num2words(9, lang='pt_BR', ordinal=True), 'nono')
|
||||||
|
self.assertEqual(num2words(10, lang='pt_BR', ordinal=True), 'décimo')
|
||||||
|
self.assertEqual(num2words(11, lang='pt_BR', ordinal=True), 'décimo primeiro')
|
||||||
|
self.assertEqual(num2words(12, lang='pt_BR', ordinal=True), 'décimo segundo')
|
||||||
|
self.assertEqual(num2words(13, lang='pt_BR', ordinal=True), 'décimo terceiro')
|
||||||
|
self.assertEqual(num2words(14, lang='pt_BR', ordinal=True), 'décimo quarto')
|
||||||
|
self.assertEqual(num2words(15, lang='pt_BR', ordinal=True), 'décimo quinto')
|
||||||
|
self.assertEqual(num2words(16, lang='pt_BR', ordinal=True), 'décimo sexto')
|
||||||
|
self.assertEqual(num2words(17, lang='pt_BR', ordinal=True), 'décimo sétimo')
|
||||||
|
self.assertEqual(num2words(18, lang='pt_BR', ordinal=True), 'décimo oitavo')
|
||||||
|
self.assertEqual(num2words(19, lang='pt_BR', ordinal=True), 'décimo nono')
|
||||||
|
self.assertEqual(num2words(20, lang='pt_BR', ordinal=True), 'vigésimo')
|
||||||
|
|
||||||
|
self.assertEqual(num2words(21, lang='pt_BR', ordinal=True), 'vigésimo primeiro')
|
||||||
|
self.assertEqual(num2words(22, lang='pt_BR', ordinal=True), 'vigésimo segundo')
|
||||||
|
self.assertEqual(num2words(35, lang='pt_BR', ordinal=True), 'trigésimo quinto')
|
||||||
|
self.assertEqual(num2words(99, lang='pt_BR', ordinal=True), 'nonagésimo nono')
|
||||||
|
|
||||||
|
self.assertEqual(num2words(100, lang='pt_BR', ordinal=True), 'centésimo')
|
||||||
|
self.assertEqual(num2words(101, lang='pt_BR', ordinal=True), 'centésimo primeiro')
|
||||||
|
self.assertEqual(num2words(128, lang='pt_BR', ordinal=True), 'centésimo vigésimo oitavo')
|
||||||
|
self.assertEqual(num2words(713, lang='pt_BR', ordinal=True), 'septigentésimo décimo terceiro')
|
||||||
|
|
||||||
|
self.assertEqual(num2words(1000, lang='pt_BR', ordinal=True), 'milésimo')
|
||||||
|
self.assertEqual(num2words(1001, lang='pt_BR', ordinal=True), 'milésimo primeiro')
|
||||||
|
self.assertEqual(num2words(1111, lang='pt_BR', ordinal=True), 'milésimo centésimo décimo primeiro')
|
||||||
|
self.assertEqual(num2words(2114, lang='pt_BR', ordinal=True), 'segundo milésimo centésimo décimo quarto')
|
||||||
|
self.assertEqual(num2words(73421, lang='pt_BR', ordinal=True), 'septuagésimo terceiro milésimo quadrigentésimo vigésimo primeiro')
|
||||||
|
|
||||||
|
self.assertEqual(num2words(100000, lang='pt_BR', ordinal=True), 'centésimo milésimo')
|
||||||
|
self.assertEqual(num2words(250050, lang='pt_BR', ordinal=True), 'ducentésimo quinquagésimo milésimo quinquagésimo')
|
||||||
|
self.assertEqual(num2words(6000000, lang='pt_BR', ordinal=True), 'sexto milionésimo')
|
||||||
|
self.assertEqual(num2words(19000000000, lang='pt_BR', ordinal=True), 'décimo nono bilionésimo')
|
||||||
|
self.assertEqual(num2words(145000000002, lang='pt_BR', ordinal=True), 'centésimo quadragésimo quinto bilionésimo segundo')
|
||||||
|
|
||||||
|
def test_currency_integer(self):
|
||||||
|
self.assertEqual(self.n2w.to_currency(1), 'um real')
|
||||||
|
self.assertEqual(self.n2w.to_currency(2), 'dois reais')
|
||||||
|
self.assertEqual(self.n2w.to_currency(3), 'três reais')
|
||||||
|
self.assertEqual(self.n2w.to_currency(4), 'quatro reais')
|
||||||
|
self.assertEqual(self.n2w.to_currency(5), 'cinco reais')
|
||||||
|
self.assertEqual(self.n2w.to_currency(6), 'seis reais')
|
||||||
|
self.assertEqual(self.n2w.to_currency(7), 'sete reais')
|
||||||
|
self.assertEqual(self.n2w.to_currency(8), 'oito reais')
|
||||||
|
self.assertEqual(self.n2w.to_currency(9), 'nove reais')
|
||||||
|
self.assertEqual(self.n2w.to_currency(10), 'dez reais')
|
||||||
|
self.assertEqual(self.n2w.to_currency(11), 'onze reais')
|
||||||
|
self.assertEqual(self.n2w.to_currency(12), 'doze reais')
|
||||||
|
self.assertEqual(self.n2w.to_currency(13), 'treze reais')
|
||||||
|
self.assertEqual(self.n2w.to_currency(14), 'catorze reais')
|
||||||
|
self.assertEqual(self.n2w.to_currency(15), 'quinze reais')
|
||||||
|
self.assertEqual(self.n2w.to_currency(16), 'dezesseis reais')
|
||||||
|
self.assertEqual(self.n2w.to_currency(17), 'dezessete reais')
|
||||||
|
self.assertEqual(self.n2w.to_currency(18), 'dezoito reais')
|
||||||
|
self.assertEqual(self.n2w.to_currency(19), 'dezenove reais')
|
||||||
|
self.assertEqual(self.n2w.to_currency(20), 'vinte reais')
|
||||||
|
|
||||||
|
self.assertEqual(self.n2w.to_currency(21), 'vinte e um reais')
|
||||||
|
self.assertEqual(self.n2w.to_currency(22), 'vinte e dois reais')
|
||||||
|
self.assertEqual(self.n2w.to_currency(35), 'trinta e cinco reais')
|
||||||
|
self.assertEqual(self.n2w.to_currency(99), 'noventa e nove reais')
|
||||||
|
|
||||||
|
self.assertEqual(self.n2w.to_currency(100), 'cem reais')
|
||||||
|
self.assertEqual(self.n2w.to_currency(101), 'cento e um reais')
|
||||||
|
self.assertEqual(self.n2w.to_currency(128), 'cento e vinte e oito reais')
|
||||||
|
self.assertEqual(self.n2w.to_currency(713), 'setecentos e treze reais')
|
||||||
|
|
||||||
|
self.assertEqual(self.n2w.to_currency(1000), 'mil reais')
|
||||||
|
self.assertEqual(self.n2w.to_currency(1001), 'mil e um reais')
|
||||||
|
self.assertEqual(self.n2w.to_currency(1111), 'mil, cento e onze reais')
|
||||||
|
self.assertEqual(self.n2w.to_currency(2114), 'dois mil, cento e catorze reais')
|
||||||
|
self.assertEqual(self.n2w.to_currency(73421), 'setenta e três mil, quatrocentos e vinte e um reais')
|
||||||
|
|
||||||
|
self.assertEqual(self.n2w.to_currency(100000), 'cem mil reais')
|
||||||
|
self.assertEqual(self.n2w.to_currency(250050), 'duzentos e cinquenta mil e cinquenta reais')
|
||||||
|
self.assertEqual(self.n2w.to_currency(6000000), 'seis milhões de reais')
|
||||||
|
self.assertEqual(self.n2w.to_currency(19000000000), 'dezenove bilhões de reais')
|
||||||
|
self.assertEqual(self.n2w.to_currency(145000000002), 'cento e quarenta e cinco bilhões e dois reais')
|
||||||
|
|
||||||
|
def test_currency_integer_negative(self):
|
||||||
|
self.assertEqual(self.n2w.to_currency(-1), 'menos um real')
|
||||||
|
self.assertEqual(self.n2w.to_currency(-256), 'menos duzentos e cinquenta e seis reais')
|
||||||
|
self.assertEqual(self.n2w.to_currency(-1000), 'menos mil reais')
|
||||||
|
self.assertEqual(self.n2w.to_currency(-1000000), 'menos um milhão de reais')
|
||||||
|
self.assertEqual(self.n2w.to_currency(-1234567), 'menos um milhão, duzentos e trinta e quatro mil, quinhentos e sessenta e sete reais')
|
||||||
|
|
||||||
|
def test_currency_float(self):
|
||||||
|
self.assertEqual(self.n2w.to_currency(Decimal('1.00')), 'um real')
|
||||||
|
self.assertEqual(self.n2w.to_currency(Decimal('1.01')), 'um real e um centavo')
|
||||||
|
self.assertEqual(self.n2w.to_currency(Decimal('1.035')), 'um real e três centavos')
|
||||||
|
self.assertEqual(self.n2w.to_currency(Decimal('1.35')), 'um real e trinta e cinco centavos')
|
||||||
|
self.assertEqual(self.n2w.to_currency(Decimal('3.14159')), 'três reais e catorze centavos')
|
||||||
|
self.assertEqual(self.n2w.to_currency(Decimal('101.22')), 'cento e um reais e vinte e dois centavos')
|
||||||
|
self.assertEqual(self.n2w.to_currency(Decimal('2345.75')), 'dois mil, trezentos e quarenta e cinco reais e setenta e cinco centavos')
|
||||||
|
|
||||||
|
def test_currency_float_negative(self):
|
||||||
|
self.assertEqual(self.n2w.to_currency(Decimal('-2.34')), 'menos dois reais e trinta e quatro centavos')
|
||||||
|
self.assertEqual(self.n2w.to_currency(Decimal('-9.99')), 'menos nove reais e noventa e nove centavos')
|
||||||
|
self.assertEqual(self.n2w.to_currency(Decimal('-7.01')), 'menos sete reais e um centavo')
|
||||||
|
self.assertEqual(self.n2w.to_currency(Decimal('-222.22')), 'menos duzentos e vinte e dois reais e vinte e dois centavos')
|
||||||
|
|
||||||
|
def test_year(self):
|
||||||
|
self.assertEqual(self.n2w.to_year(1001), 'mil e um')
|
||||||
|
self.assertEqual(self.n2w.to_year(1789), 'mil, setecentos e oitenta e nove')
|
||||||
|
self.assertEqual(self.n2w.to_year(1942), 'mil, novecentos e quarenta e dois')
|
||||||
|
self.assertEqual(self.n2w.to_year(1984), 'mil, novecentos e oitenta e quatro')
|
||||||
|
self.assertEqual(self.n2w.to_year(2000), 'dois mil')
|
||||||
|
self.assertEqual(self.n2w.to_year(2001), 'dois mil e um')
|
||||||
|
self.assertEqual(self.n2w.to_year(2016), 'dois mil e dezesseis')
|
||||||
|
|
||||||
|
def test_year_negative(self):
|
||||||
|
self.assertEqual(self.n2w.to_year(-30), 'trinta antes de Cristo')
|
||||||
|
self.assertEqual(self.n2w.to_year(-744), 'setecentos e quarenta e quatro antes de Cristo')
|
||||||
|
self.assertEqual(self.n2w.to_year(-10000), 'dez mil antes de Cristo')
|
||||||
31
tests/test_ru.py
Normal file
31
tests/test_ru.py
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
# 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 unittest import TestCase
|
||||||
|
|
||||||
|
from num2words import num2words
|
||||||
|
|
||||||
|
class Num2WordsRUTest(TestCase):
|
||||||
|
|
||||||
|
def test_cardinal(self):
|
||||||
|
self.assertEqual(num2words(5, lang='ru'), u"пять")
|
||||||
|
self.assertEqual(num2words(15, lang='ru'), u"пятнадцать")
|
||||||
|
self.assertEqual(num2words(154, lang='ru'), u"сто пятьдесят четыре")
|
||||||
|
self.assertEqual(num2words(418531, lang='ru'), u"четыреста восемнадцать тысяч пятьсот тридцать один")
|
||||||
|
|
||||||
|
def test_floating_point(self):
|
||||||
|
self.assertEqual(num2words(5.2, lang='ru'), u"пять запятая два")
|
||||||
|
self.assertEqual(num2words(561.42, lang='ru'), u"пятьсот шестьдесят один запятая сорок два")
|
||||||
Reference in New Issue
Block a user