Initial commit (Clean history)
This commit is contained in:
111
path/to/venv/lib/python3.12/site-packages/num2words/__init__.py
Normal file
111
path/to/venv/lib/python3.12/site-packages/num2words/__init__.py
Normal file
@@ -0,0 +1,111 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
||||
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from . import (lang_AM, lang_AR, lang_AZ, lang_BE, lang_BN, lang_CA, lang_CE,
|
||||
lang_CS, lang_CY, lang_DA, lang_DE, lang_EN, lang_EN_IN,
|
||||
lang_EN_NG, lang_EO, lang_ES, lang_ES_CO, lang_ES_CR,
|
||||
lang_ES_GT, lang_ES_NI, lang_ES_VE, lang_FA, lang_FI, lang_FR,
|
||||
lang_FR_BE, lang_FR_CH, lang_FR_DZ, lang_HE, lang_HU, lang_ID,
|
||||
lang_IS, lang_IT, lang_JA, lang_KN, lang_KO, lang_KZ, lang_LT,
|
||||
lang_LV, lang_NL, lang_NO, lang_PL, lang_PT, lang_PT_BR,
|
||||
lang_RO, lang_RU, lang_SK, lang_SL, lang_SR, lang_SV, lang_TE,
|
||||
lang_TET, lang_TG, lang_TH, lang_TR, lang_UK, lang_VI)
|
||||
|
||||
CONVERTER_CLASSES = {
|
||||
'am': lang_AM.Num2Word_AM(),
|
||||
'ar': lang_AR.Num2Word_AR(),
|
||||
'az': lang_AZ.Num2Word_AZ(),
|
||||
'be': lang_BE.Num2Word_BE(),
|
||||
'bn': lang_BN.Num2Word_BN(),
|
||||
'ca': lang_CA.Num2Word_CA(),
|
||||
'ce': lang_CE.Num2Word_CE(),
|
||||
'cs': lang_CS.Num2Word_CS(),
|
||||
'cy': lang_CY.Num2Word_CY(),
|
||||
'en': lang_EN.Num2Word_EN(),
|
||||
'en_IN': lang_EN_IN.Num2Word_EN_IN(),
|
||||
'en_NG': lang_EN_NG.Num2Word_EN_NG(),
|
||||
'fa': lang_FA.Num2Word_FA(),
|
||||
'fr': lang_FR.Num2Word_FR(),
|
||||
'fr_CH': lang_FR_CH.Num2Word_FR_CH(),
|
||||
'fr_BE': lang_FR_BE.Num2Word_FR_BE(),
|
||||
'fr_DZ': lang_FR_DZ.Num2Word_FR_DZ(),
|
||||
'de': lang_DE.Num2Word_DE(),
|
||||
'fi': lang_FI.Num2Word_FI(),
|
||||
'eo': lang_EO.Num2Word_EO(),
|
||||
'es': lang_ES.Num2Word_ES(),
|
||||
'es_CO': lang_ES_CO.Num2Word_ES_CO(),
|
||||
'es_CR': lang_ES_CR.Num2Word_ES_CR(),
|
||||
'es_GT': lang_ES_GT.Num2Word_ES_GT(),
|
||||
'es_NI': lang_ES_NI.Num2Word_ES_NI(),
|
||||
'es_VE': lang_ES_VE.Num2Word_ES_VE(),
|
||||
'id': lang_ID.Num2Word_ID(),
|
||||
'ja': lang_JA.Num2Word_JA(),
|
||||
'kn': lang_KN.Num2Word_KN(),
|
||||
'ko': lang_KO.Num2Word_KO(),
|
||||
'kz': lang_KZ.Num2Word_KZ(),
|
||||
'lt': lang_LT.Num2Word_LT(),
|
||||
'lv': lang_LV.Num2Word_LV(),
|
||||
'pl': lang_PL.Num2Word_PL(),
|
||||
'ro': lang_RO.Num2Word_RO(),
|
||||
'ru': lang_RU.Num2Word_RU(),
|
||||
'sk': lang_SK.Num2Word_SK(),
|
||||
'sl': lang_SL.Num2Word_SL(),
|
||||
'sr': lang_SR.Num2Word_SR(),
|
||||
'sv': lang_SV.Num2Word_SV(),
|
||||
'no': lang_NO.Num2Word_NO(),
|
||||
'da': lang_DA.Num2Word_DA(),
|
||||
'pt': lang_PT.Num2Word_PT(),
|
||||
'pt_BR': lang_PT_BR.Num2Word_PT_BR(),
|
||||
'he': lang_HE.Num2Word_HE(),
|
||||
'it': lang_IT.Num2Word_IT(),
|
||||
'vi': lang_VI.Num2Word_VI(),
|
||||
'tg': lang_TG.Num2Word_TG(),
|
||||
'th': lang_TH.Num2Word_TH(),
|
||||
'tr': lang_TR.Num2Word_TR(),
|
||||
'nl': lang_NL.Num2Word_NL(),
|
||||
'uk': lang_UK.Num2Word_UK(),
|
||||
'te': lang_TE.Num2Word_TE(),
|
||||
'tet': lang_TET.Num2Word_TET(),
|
||||
'hu': lang_HU.Num2Word_HU(),
|
||||
'is': lang_IS.Num2Word_IS(),
|
||||
}
|
||||
|
||||
CONVERTES_TYPES = ['cardinal', 'ordinal', 'ordinal_num', 'year', 'currency']
|
||||
|
||||
|
||||
def num2words(number, ordinal=False, lang='en', to='cardinal', **kwargs):
|
||||
# We try the full language first
|
||||
if lang not in CONVERTER_CLASSES:
|
||||
# ... and then try only the first 2 letters
|
||||
lang = lang[:2]
|
||||
if lang not in CONVERTER_CLASSES:
|
||||
raise NotImplementedError()
|
||||
converter = CONVERTER_CLASSES[lang]
|
||||
|
||||
if isinstance(number, str):
|
||||
number = converter.str_to_number(number)
|
||||
|
||||
# backwards compatible
|
||||
if ordinal:
|
||||
to = 'ordinal'
|
||||
|
||||
if to not in CONVERTES_TYPES:
|
||||
raise NotImplementedError()
|
||||
|
||||
return getattr(converter, 'to_{}'.format(to))(number, **kwargs)
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
310
path/to/venv/lib/python3.12/site-packages/num2words/base.py
Normal file
310
path/to/venv/lib/python3.12/site-packages/num2words/base.py
Normal file
@@ -0,0 +1,310 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
||||
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import math
|
||||
from collections import OrderedDict
|
||||
from decimal import Decimal
|
||||
|
||||
from .compat import to_s
|
||||
from .currency import parse_currency_parts, prefix_currency
|
||||
|
||||
|
||||
class Num2Word_Base(object):
|
||||
CURRENCY_FORMS = {}
|
||||
CURRENCY_ADJECTIVES = {}
|
||||
|
||||
def __init__(self):
|
||||
self.is_title = False
|
||||
self.precision = 2
|
||||
self.exclude_title = []
|
||||
self.negword = "(-) "
|
||||
self.pointword = "(.)"
|
||||
self.errmsg_nonnum = "type(%s) not in [long, int, float]"
|
||||
self.errmsg_floatord = "Cannot treat float %s as ordinal."
|
||||
self.errmsg_negord = "Cannot treat negative num %s as ordinal."
|
||||
self.errmsg_toobig = "abs(%s) must be less than %s."
|
||||
|
||||
self.setup()
|
||||
|
||||
# uses cards
|
||||
if any(hasattr(self, field) for field in
|
||||
['high_numwords', 'mid_numwords', 'low_numwords']):
|
||||
self.cards = OrderedDict()
|
||||
self.set_numwords()
|
||||
self.MAXVAL = 1000 * list(self.cards.keys())[0]
|
||||
|
||||
def set_numwords(self):
|
||||
self.set_high_numwords(self.high_numwords)
|
||||
self.set_mid_numwords(self.mid_numwords)
|
||||
self.set_low_numwords(self.low_numwords)
|
||||
|
||||
def set_high_numwords(self, *args):
|
||||
raise NotImplementedError
|
||||
|
||||
def set_mid_numwords(self, mid):
|
||||
for key, val in mid:
|
||||
self.cards[key] = val
|
||||
|
||||
def set_low_numwords(self, numwords):
|
||||
for word, n in zip(numwords, range(len(numwords) - 1, -1, -1)):
|
||||
self.cards[n] = word
|
||||
|
||||
def splitnum(self, value):
|
||||
for elem in self.cards:
|
||||
if elem > value:
|
||||
continue
|
||||
|
||||
out = []
|
||||
if value == 0:
|
||||
div, mod = 1, 0
|
||||
else:
|
||||
div, mod = divmod(value, elem)
|
||||
|
||||
if div == 1:
|
||||
out.append((self.cards[1], 1))
|
||||
else:
|
||||
if div == value: # The system tallies, eg Roman Numerals
|
||||
return [(div * self.cards[elem], div*elem)]
|
||||
out.append(self.splitnum(div))
|
||||
|
||||
out.append((self.cards[elem], elem))
|
||||
|
||||
if mod:
|
||||
out.append(self.splitnum(mod))
|
||||
|
||||
return out
|
||||
|
||||
def parse_minus(self, num_str):
|
||||
"""Detach minus and return it as symbol with new num_str."""
|
||||
if num_str.startswith('-'):
|
||||
# Extra spacing to compensate if there is no minus.
|
||||
return '%s ' % self.negword.strip(), num_str[1:]
|
||||
return '', num_str
|
||||
|
||||
def str_to_number(self, value):
|
||||
return Decimal(value)
|
||||
|
||||
def to_cardinal(self, value):
|
||||
try:
|
||||
assert int(value) == value
|
||||
except (ValueError, TypeError, AssertionError):
|
||||
return self.to_cardinal_float(value)
|
||||
|
||||
out = ""
|
||||
if value < 0:
|
||||
value = abs(value)
|
||||
out = "%s " % self.negword.strip()
|
||||
|
||||
if value >= self.MAXVAL:
|
||||
raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL))
|
||||
|
||||
val = self.splitnum(value)
|
||||
words, num = self.clean(val)
|
||||
return self.title(out + words)
|
||||
|
||||
def float2tuple(self, value):
|
||||
pre = int(value)
|
||||
|
||||
# Simple way of finding decimal places to update the precision
|
||||
self.precision = abs(Decimal(str(value)).as_tuple().exponent)
|
||||
|
||||
post = abs(value - pre) * 10**self.precision
|
||||
if abs(round(post) - post) < 0.01:
|
||||
# We generally floor all values beyond our precision (rather than
|
||||
# rounding), but in cases where we have something like 1.239999999,
|
||||
# which is probably due to python's handling of floats, we actually
|
||||
# want to consider it as 1.24 instead of 1.23
|
||||
post = int(round(post))
|
||||
else:
|
||||
post = int(math.floor(post))
|
||||
|
||||
return pre, post
|
||||
|
||||
def to_cardinal_float(self, value):
|
||||
try:
|
||||
float(value) == value
|
||||
except (ValueError, TypeError, AssertionError, AttributeError):
|
||||
raise TypeError(self.errmsg_nonnum % value)
|
||||
|
||||
pre, post = self.float2tuple(float(value))
|
||||
|
||||
post = str(post)
|
||||
post = '0' * (self.precision - len(post)) + post
|
||||
|
||||
out = [self.to_cardinal(pre)]
|
||||
if self.precision:
|
||||
out.append(self.title(self.pointword))
|
||||
|
||||
for i in range(self.precision):
|
||||
curr = int(post[i])
|
||||
out.append(to_s(self.to_cardinal(curr)))
|
||||
|
||||
return " ".join(out)
|
||||
|
||||
def merge(self, curr, next):
|
||||
raise NotImplementedError
|
||||
|
||||
def clean(self, val):
|
||||
out = val
|
||||
while len(val) != 1:
|
||||
out = []
|
||||
left, right = val[:2]
|
||||
if isinstance(left, tuple) and isinstance(right, tuple):
|
||||
out.append(self.merge(left, right))
|
||||
if val[2:]:
|
||||
out.append(val[2:])
|
||||
else:
|
||||
for elem in val:
|
||||
if isinstance(elem, list):
|
||||
if len(elem) == 1:
|
||||
out.append(elem[0])
|
||||
else:
|
||||
out.append(self.clean(elem))
|
||||
else:
|
||||
out.append(elem)
|
||||
val = out
|
||||
return out[0]
|
||||
|
||||
def title(self, value):
|
||||
if self.is_title:
|
||||
out = []
|
||||
value = value.split()
|
||||
for word in value:
|
||||
if word in self.exclude_title:
|
||||
out.append(word)
|
||||
else:
|
||||
out.append(word[0].upper() + word[1:])
|
||||
value = " ".join(out)
|
||||
return 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)
|
||||
|
||||
def to_ordinal(self, value):
|
||||
return self.to_cardinal(value)
|
||||
|
||||
def to_ordinal_num(self, value):
|
||||
return value
|
||||
|
||||
# Trivial version
|
||||
def inflect(self, value, text):
|
||||
text = text.split("/")
|
||||
if value == 1:
|
||||
return text[0]
|
||||
return "".join(text)
|
||||
|
||||
# //CHECK: generalise? Any others like pounds/shillings/pence?
|
||||
def to_splitnum(self, val, hightxt="", lowtxt="", jointxt="",
|
||||
divisor=100, longval=True, cents=True):
|
||||
out = []
|
||||
|
||||
if isinstance(val, float):
|
||||
high, low = self.float2tuple(val)
|
||||
else:
|
||||
try:
|
||||
high, low = val
|
||||
except TypeError:
|
||||
high, low = divmod(val, divisor)
|
||||
|
||||
if high:
|
||||
hightxt = self.title(self.inflect(high, hightxt))
|
||||
out.append(self.to_cardinal(high))
|
||||
if low:
|
||||
if longval:
|
||||
if hightxt:
|
||||
out.append(hightxt)
|
||||
if jointxt:
|
||||
out.append(self.title(jointxt))
|
||||
elif hightxt:
|
||||
out.append(hightxt)
|
||||
|
||||
if low:
|
||||
if cents:
|
||||
out.append(self.to_cardinal(low))
|
||||
else:
|
||||
out.append("%02d" % low)
|
||||
if lowtxt and longval:
|
||||
out.append(self.title(self.inflect(low, lowtxt)))
|
||||
|
||||
return " ".join(out)
|
||||
|
||||
def to_year(self, value, **kwargs):
|
||||
return self.to_cardinal(value)
|
||||
|
||||
def pluralize(self, n, forms):
|
||||
"""
|
||||
Should resolve gettext form:
|
||||
http://docs.translatehouse.org/projects/localization-guide/en/latest/l10n/pluralforms.html
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def _money_verbose(self, number, currency):
|
||||
return self.to_cardinal(number)
|
||||
|
||||
def _cents_verbose(self, number, currency):
|
||||
return self.to_cardinal(number)
|
||||
|
||||
def _cents_terse(self, number, currency):
|
||||
return "%02d" % number
|
||||
|
||||
def to_currency(self, val, currency='EUR', cents=True, separator=',',
|
||||
adjective=False):
|
||||
"""
|
||||
Args:
|
||||
val: Numeric value
|
||||
currency (str): Currency code
|
||||
cents (bool): Verbose cents
|
||||
separator (str): Cent separator
|
||||
adjective (bool): Prefix currency name with adjective
|
||||
Returns:
|
||||
str: Formatted string
|
||||
|
||||
"""
|
||||
left, right, is_negative = parse_currency_parts(val)
|
||||
|
||||
try:
|
||||
cr1, cr2 = self.CURRENCY_FORMS[currency]
|
||||
|
||||
except KeyError:
|
||||
raise NotImplementedError(
|
||||
'Currency code "%s" not implemented for "%s"' %
|
||||
(currency, self.__class__.__name__))
|
||||
|
||||
if adjective and currency in self.CURRENCY_ADJECTIVES:
|
||||
cr1 = prefix_currency(self.CURRENCY_ADJECTIVES[currency], cr1)
|
||||
|
||||
minus_str = "%s " % self.negword.strip() if is_negative else ""
|
||||
money_str = self._money_verbose(left, currency)
|
||||
cents_str = self._cents_verbose(right, currency) \
|
||||
if cents else self._cents_terse(right, currency)
|
||||
|
||||
return u'%s%s %s%s %s %s' % (
|
||||
minus_str,
|
||||
money_str,
|
||||
self.pluralize(left, cr1),
|
||||
separator,
|
||||
cents_str,
|
||||
self.pluralize(right, cr2)
|
||||
)
|
||||
|
||||
def setup(self):
|
||||
pass
|
||||
@@ -0,0 +1,29 @@
|
||||
# -*- 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
|
||||
|
||||
|
||||
try:
|
||||
strtype = basestring
|
||||
except NameError:
|
||||
strtype = str
|
||||
|
||||
|
||||
def to_s(val):
|
||||
try:
|
||||
return unicode(val)
|
||||
except NameError:
|
||||
return str(val)
|
||||
@@ -0,0 +1,50 @@
|
||||
# -*- 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
|
||||
|
||||
from decimal import ROUND_HALF_UP, Decimal
|
||||
|
||||
|
||||
def parse_currency_parts(value, is_int_with_cents=True):
|
||||
if isinstance(value, int):
|
||||
if is_int_with_cents:
|
||||
# assume cents if value is integer
|
||||
negative = value < 0
|
||||
value = abs(value)
|
||||
integer, cents = divmod(value, 100)
|
||||
else:
|
||||
negative = value < 0
|
||||
integer, cents = abs(value), 0
|
||||
|
||||
else:
|
||||
value = Decimal(value)
|
||||
value = value.quantize(
|
||||
Decimal('.01'),
|
||||
rounding=ROUND_HALF_UP
|
||||
)
|
||||
negative = value < 0
|
||||
value = abs(value)
|
||||
integer, fraction = divmod(value, 1)
|
||||
integer = int(integer)
|
||||
cents = int(fraction * 100)
|
||||
|
||||
return integer, cents, negative
|
||||
|
||||
|
||||
def prefix_currency(prefix, base):
|
||||
return tuple("%s %s" % (prefix, i) for i in base)
|
||||
129
path/to/venv/lib/python3.12/site-packages/num2words/lang_AM.py
Normal file
129
path/to/venv/lib/python3.12/site-packages/num2words/lang_AM.py
Normal file
@@ -0,0 +1,129 @@
|
||||
# -*- 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, print_function, unicode_literals
|
||||
|
||||
from . import lang_EU
|
||||
|
||||
|
||||
class Num2Word_AM(lang_EU.Num2Word_EU):
|
||||
CURRENCY_FORMS = {'ETB': (('ብር', 'ብር'), ('ሳንቲም', 'ሳንቲም'))}
|
||||
|
||||
GIGA_SUFFIX = 'ቢሊዮን'
|
||||
MEGA_SUFFIX = 'ሚሊዮን'
|
||||
|
||||
def set_high_numwords(self, high):
|
||||
cap = 3 * (len(high) + 1)
|
||||
|
||||
for word, n in zip(high, range(cap, 5, -3)):
|
||||
if n == 9:
|
||||
self.cards[10 ** n] = word + self.GIGA_SUFFIX
|
||||
else:
|
||||
self.cards[10 ** n] = word + self.MEGA_SUFFIX
|
||||
|
||||
def setup(self):
|
||||
super(Num2Word_AM, self).setup()
|
||||
|
||||
self.negword = 'አሉታዊ '
|
||||
self.pointword = 'ነጥብ'
|
||||
self.exclude_title = ['እና', 'ነጥብ', 'አሉታዊ']
|
||||
|
||||
self.mid_numwords = [(1000, 'ሺህ'), (100, 'መቶ'), (90, 'ዘጠና'),
|
||||
(80, 'ሰማኒያ'), (70, 'ሰባ'), (60, 'ስድሳ'),
|
||||
(50, 'አምሳ'), (40, 'አርባ'), (30, 'ሠላሳ')]
|
||||
self.low_numwords = ['ሃያ', 'አሥራ ዘጠኝ', 'አሥራ ስምንት', 'አሥራ ሰባት',
|
||||
'አስራ ስድስት', 'አሥራ አምስት', 'አሥራ አራት', 'አሥራ ሦስት',
|
||||
'አሥራ ሁለት', 'አሥራ አንድ', 'አሥር', 'ዘጠኝ', 'ስምንት',
|
||||
'ሰባት', 'ስድስት', 'አምስት', 'አራት', 'ሦስት', 'ሁለት',
|
||||
'አንድ', 'ዜሮ']
|
||||
self.ords = {'አንድ': 'አንደኛ',
|
||||
'ሁለት': 'ሁለተኛ',
|
||||
'ሦስት': 'ሦስተኛ',
|
||||
'አራት': 'አራተኛ',
|
||||
'አምስት': 'አምስተኛ',
|
||||
'ስድስት': 'ስድስተኛ',
|
||||
'ሰባት': 'ሰባተኛ',
|
||||
'ስምንት': 'ስምንተኛ',
|
||||
'ዘጠኝ': 'ዘጠነኛ',
|
||||
'አሥር': 'አሥረኛ',
|
||||
'አሥራ አንድ': 'አሥራ አንደኛ',
|
||||
'አሥራ ሁለት': 'አሥራ ሁለተኛ',
|
||||
'አሥራ ሦስት': 'አሥራ ሦስተኛ',
|
||||
'አሥራ አራት': 'አሥራ አራተኛ',
|
||||
'አሥራ አምስት': 'አሥራ አምስተኛ',
|
||||
'አሥራ ስድስት': 'አሥራ ስድስተኛ',
|
||||
'አሥራ ሰባት': 'አሥራ ሰባተኛ',
|
||||
'አሥራ ስምንት': 'አሥራ ስምንተኛ',
|
||||
'አሥራ ዘጠኝ': 'አሥራ ዘጠነኛ'}
|
||||
|
||||
def to_cardinal(self, value):
|
||||
try:
|
||||
assert int(value) == value
|
||||
except (ValueError, TypeError, AssertionError):
|
||||
return self.to_cardinal_float(value)
|
||||
|
||||
out = ''
|
||||
if value >= self.MAXVAL:
|
||||
raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL))
|
||||
|
||||
if value == 100:
|
||||
return self.title(out + 'መቶ')
|
||||
else:
|
||||
val = self.splitnum(value)
|
||||
words, num = self.clean(val)
|
||||
return self.title(out + words)
|
||||
|
||||
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 %s' % (ltext, rtext), lnum + rnum
|
||||
elif rnum > lnum:
|
||||
return '%s %s' % (ltext, rtext), lnum * rnum
|
||||
|
||||
def to_ordinal(self, value):
|
||||
self.verify_ordinal(value)
|
||||
outwords = self.to_cardinal(value).split(' ')
|
||||
lastwords = outwords[-1].split('-')
|
||||
lastword = lastwords[-1].lower()
|
||||
try:
|
||||
lastword = self.ords[lastword]
|
||||
except KeyError:
|
||||
lastword += 'ኛ'
|
||||
lastwords[-1] = self.title(lastword)
|
||||
outwords[-1] = ' '.join(lastwords)
|
||||
return ' '.join(outwords)
|
||||
|
||||
def to_ordinal_num(self, value):
|
||||
self.verify_ordinal(value)
|
||||
return '%s%s' % (value, self.to_ordinal(value)[-1:])
|
||||
|
||||
def to_currency(self, val, currency='ብር', cents=True, separator=' ከ',
|
||||
adjective=True):
|
||||
result = super(Num2Word_AM, self).to_currency(
|
||||
val, currency=currency, cents=cents, separator=separator,
|
||||
adjective=adjective)
|
||||
return result
|
||||
|
||||
def to_year(self, val, longval=True):
|
||||
if not (val // 100) % 10:
|
||||
return self.to_cardinal(val)
|
||||
return self.to_splitnum(val, hightxt='መቶ', longval=longval)
|
||||
415
path/to/venv/lib/python3.12/site-packages/num2words/lang_AR.py
Normal file
415
path/to/venv/lib/python3.12/site-packages/num2words/lang_AR.py
Normal file
@@ -0,0 +1,415 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
||||
# Copyright (c) 2018, Abdullah Alhazmy, Alhazmy13. 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 decimal
|
||||
import math
|
||||
import re
|
||||
from decimal import Decimal
|
||||
from math import floor
|
||||
|
||||
from .base import Num2Word_Base
|
||||
|
||||
CURRENCY_SR = [("ريال", "ريالان", "ريالات", "ريالاً"),
|
||||
("هللة", "هللتان", "هللات", "هللة")]
|
||||
CURRENCY_EGP = [("جنيه", "جنيهان", "جنيهات", "جنيهاً"),
|
||||
("قرش", "قرشان", "قروش", "قرش")]
|
||||
CURRENCY_KWD = [("دينار", "ديناران", "دينارات", "ديناراً"),
|
||||
("فلس", "فلسان", "فلس", "فلس")]
|
||||
CURRENCY_TND = [("دينار", "ديناران", "دينارات", "ديناراً"),
|
||||
("مليماً", "ميلمان", "مليمات", "مليم")]
|
||||
|
||||
ARABIC_ONES = [
|
||||
"", "واحد", "اثنان", "ثلاثة", "أربعة", "خمسة", "ستة", "سبعة", "ثمانية",
|
||||
"تسعة",
|
||||
"عشرة", "أحد عشر", "اثنا عشر", "ثلاثة عشر", "أربعة عشر", "خمسة عشر",
|
||||
"ستة عشر", "سبعة عشر", "ثمانية عشر",
|
||||
"تسعة عشر"
|
||||
]
|
||||
|
||||
|
||||
class Num2Word_AR(Num2Word_Base):
|
||||
errmsg_toobig = "abs(%s) must be less than %s."
|
||||
MAXVAL = 10**51
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
self.number = 0
|
||||
self.arabicPrefixText = ""
|
||||
self.arabicSuffixText = ""
|
||||
self.integer_value = 0
|
||||
self._decimalValue = ""
|
||||
self.partPrecision = 2
|
||||
self.currency_unit = CURRENCY_SR[0]
|
||||
self.currency_subunit = CURRENCY_SR[1]
|
||||
self.isCurrencyPartNameFeminine = True
|
||||
self.isCurrencyNameFeminine = False
|
||||
self.separator = 'و'
|
||||
|
||||
self.arabicOnes = ARABIC_ONES
|
||||
self.arabicFeminineOnes = [
|
||||
"", "إحدى", "اثنتان", "ثلاث", "أربع", "خمس", "ست", "سبع", "ثمان",
|
||||
"تسع",
|
||||
"عشر", "إحدى عشرة", "اثنتا عشرة", "ثلاث عشرة", "أربع عشرة",
|
||||
"خمس عشرة", "ست عشرة", "سبع عشرة", "ثماني عشرة",
|
||||
"تسع عشرة"
|
||||
]
|
||||
self.arabicOrdinal = [
|
||||
"", "اول", "ثاني", "ثالث", "رابع", "خامس", "سادس", "سابع", "ثامن",
|
||||
"تاسع", "عاشر", "حادي عشر", "ثاني عشر", "ثالث عشر", "رابع عشر",
|
||||
"خامس عشر", "سادس عشر", "سابع عشر", "ثامن عشر", "تاسع عشر"
|
||||
]
|
||||
self.arabicTens = [
|
||||
"عشرون", "ثلاثون", "أربعون", "خمسون", "ستون", "سبعون", "ثمانون",
|
||||
"تسعون"
|
||||
]
|
||||
self.arabicHundreds = [
|
||||
"", "مائة", "مئتان", "ثلاثمائة", "أربعمائة", "خمسمائة", "ستمائة",
|
||||
"سبعمائة", "ثمانمائة", "تسعمائة"
|
||||
]
|
||||
|
||||
self.arabicAppendedTwos = [
|
||||
"مئتا", "ألفا", "مليونا", "مليارا", "تريليونا", "كوادريليونا",
|
||||
"كوينتليونا", "سكستيليونا", "سبتيليونا", "أوكتيليونا ",
|
||||
"نونيليونا", "ديسيليونا", "أندسيليونا", "دوديسيليونا",
|
||||
"تريديسيليونا", "كوادريسيليونا", "كوينتينيليونا"
|
||||
]
|
||||
self.arabicTwos = [
|
||||
"مئتان", "ألفان", "مليونان", "ملياران", "تريليونان",
|
||||
"كوادريليونان", "كوينتليونان", "سكستيليونان", "سبتيليونان",
|
||||
"أوكتيليونان ", "نونيليونان ", "ديسيليونان", "أندسيليونان",
|
||||
"دوديسيليونان", "تريديسيليونان", "كوادريسيليونان", "كوينتينيليونان"
|
||||
]
|
||||
self.arabicGroup = [
|
||||
"مائة", "ألف", "مليون", "مليار", "تريليون", "كوادريليون",
|
||||
"كوينتليون", "سكستيليون", "سبتيليون", "أوكتيليون", "نونيليون",
|
||||
"ديسيليون", "أندسيليون", "دوديسيليون", "تريديسيليون",
|
||||
"كوادريسيليون", "كوينتينيليون"
|
||||
]
|
||||
self.arabicAppendedGroup = [
|
||||
"", "ألفاً", "مليوناً", "ملياراً", "تريليوناً", "كوادريليوناً",
|
||||
"كوينتليوناً", "سكستيليوناً", "سبتيليوناً", "أوكتيليوناً",
|
||||
"نونيليوناً", "ديسيليوناً", "أندسيليوناً", "دوديسيليوناً",
|
||||
"تريديسيليوناً", "كوادريسيليوناً", "كوينتينيليوناً"
|
||||
]
|
||||
self.arabicPluralGroups = [
|
||||
"", "آلاف", "ملايين", "مليارات", "تريليونات", "كوادريليونات",
|
||||
"كوينتليونات", "سكستيليونات", "سبتيليونات", "أوكتيليونات",
|
||||
"نونيليونات", "ديسيليونات", "أندسيليونات", "دوديسيليونات",
|
||||
"تريديسيليونات", "كوادريسيليونات", "كوينتينيليونات"
|
||||
]
|
||||
assert len(self.arabicAppendedGroup) == len(self.arabicGroup)
|
||||
assert len(self.arabicPluralGroups) == len(self.arabicGroup)
|
||||
assert len(self.arabicAppendedTwos) == len(self.arabicTwos)
|
||||
|
||||
def number_to_arabic(self, arabic_prefix_text, arabic_suffix_text):
|
||||
self.arabicPrefixText = arabic_prefix_text
|
||||
self.arabicSuffixText = arabic_suffix_text
|
||||
self.extract_integer_and_decimal_parts()
|
||||
|
||||
def extract_integer_and_decimal_parts(self):
|
||||
splits = re.split('\\.', str(self.number))
|
||||
|
||||
self.integer_value = int(splits[0])
|
||||
if len(splits) > 1:
|
||||
self._decimalValue = int(self.decimal_value(splits[1]))
|
||||
else:
|
||||
self._decimalValue = 0
|
||||
|
||||
def decimal_value(self, decimal_part):
|
||||
|
||||
if self.partPrecision is not len(decimal_part):
|
||||
decimal_part_length = len(decimal_part)
|
||||
|
||||
decimal_part_builder = decimal_part
|
||||
for i in range(0, self.partPrecision - decimal_part_length):
|
||||
decimal_part_builder += '0'
|
||||
decimal_part = decimal_part_builder
|
||||
|
||||
if len(decimal_part) <= self.partPrecision:
|
||||
dec = len(decimal_part)
|
||||
else:
|
||||
dec = self.partPrecision
|
||||
result = decimal_part[0: dec]
|
||||
else:
|
||||
result = decimal_part
|
||||
|
||||
# The following is useless (never happens)
|
||||
# for i in range(len(result), self.partPrecision):
|
||||
# result += '0'
|
||||
return result
|
||||
|
||||
def digit_feminine_status(self, digit, group_level):
|
||||
if group_level == -1:
|
||||
if self.isCurrencyPartNameFeminine:
|
||||
return self.arabicFeminineOnes[int(digit)]
|
||||
else:
|
||||
# Note: this never happens
|
||||
return self.arabicOnes[int(digit)]
|
||||
elif group_level == 0:
|
||||
if self.isCurrencyNameFeminine:
|
||||
return self.arabicFeminineOnes[int(digit)]
|
||||
else:
|
||||
return self.arabicOnes[int(digit)]
|
||||
else:
|
||||
return self.arabicOnes[int(digit)]
|
||||
|
||||
def process_arabic_group(self, group_number, group_level,
|
||||
remaining_number):
|
||||
tens = Decimal(group_number) % Decimal(100)
|
||||
hundreds = Decimal(group_number) / Decimal(100)
|
||||
ret_val = ""
|
||||
|
||||
if int(hundreds) > 0:
|
||||
if tens == 0 and int(hundreds) == 2:
|
||||
ret_val = "{}".format(self.arabicAppendedTwos[0])
|
||||
else:
|
||||
ret_val = "{}".format(self.arabicHundreds[int(hundreds)])
|
||||
if ret_val != "" and tens != 0:
|
||||
ret_val += " و "
|
||||
|
||||
if tens > 0:
|
||||
if tens < 20:
|
||||
# if int(group_level) >= len(self.arabicTwos):
|
||||
# raise OverflowError(self.errmsg_toobig %
|
||||
# (self.number, self.MAXVAL))
|
||||
assert int(group_level) < len(self.arabicTwos)
|
||||
if tens == 2 and int(hundreds) == 0 and group_level > 0:
|
||||
pow = int(math.log10(self.integer_value))
|
||||
if self.integer_value > 10 and pow % 3 == 0 and \
|
||||
self.integer_value == 2 * (10 ** pow):
|
||||
ret_val = "{}".format(
|
||||
self.arabicAppendedTwos[int(group_level)])
|
||||
else:
|
||||
ret_val = "{}".format(
|
||||
self.arabicTwos[int(group_level)])
|
||||
else:
|
||||
|
||||
if tens == 1 and group_level > 0 and hundreds == 0:
|
||||
# Note: this never happens
|
||||
# (hundreds == 0 only if group_number is 0)
|
||||
ret_val += ""
|
||||
elif (tens == 1 or tens == 2) and (
|
||||
group_level == 0 or group_level == -1) and \
|
||||
hundreds == 0 and remaining_number == 0:
|
||||
# Note: this never happens (idem)
|
||||
ret_val += ""
|
||||
elif tens == 1 and group_level > 0:
|
||||
ret_val += self.arabicGroup[int(group_level)]
|
||||
else:
|
||||
ret_val += self.digit_feminine_status(int(tens),
|
||||
group_level)
|
||||
else:
|
||||
ones = tens % 10
|
||||
tens = (tens / 10) - 2
|
||||
if ones > 0:
|
||||
ret_val += self.digit_feminine_status(ones, group_level)
|
||||
if ret_val != "" and ones != 0:
|
||||
ret_val += " و "
|
||||
|
||||
ret_val += self.arabicTens[int(tens)]
|
||||
|
||||
return ret_val
|
||||
|
||||
# We use this instead of built-in `abs` function,
|
||||
# because `abs` suffers from loss of precision for big numbers
|
||||
def abs(self, number):
|
||||
return number if number >= 0 else -number
|
||||
|
||||
# We use this instead of `"{:09d}".format(number)`,
|
||||
# because the string conversion suffers from loss of
|
||||
# precision for big numbers
|
||||
def to_str(self, number):
|
||||
integer = int(number)
|
||||
if integer == number:
|
||||
return str(integer)
|
||||
decimal = round((number - integer) * 10**9)
|
||||
return str(integer) + "." + "{:09d}".format(decimal).rstrip("0")
|
||||
|
||||
def convert(self, value):
|
||||
self.number = self.to_str(value)
|
||||
self.number_to_arabic(self.arabicPrefixText, self.arabicSuffixText)
|
||||
return self.convert_to_arabic()
|
||||
|
||||
def convert_to_arabic(self):
|
||||
temp_number = Decimal(self.number)
|
||||
|
||||
if temp_number == Decimal(0):
|
||||
return "صفر"
|
||||
|
||||
decimal_string = self.process_arabic_group(self._decimalValue,
|
||||
-1,
|
||||
Decimal(0))
|
||||
ret_val = ""
|
||||
group = 0
|
||||
|
||||
while temp_number > Decimal(0):
|
||||
|
||||
temp_number_dec = Decimal(str(temp_number))
|
||||
try:
|
||||
number_to_process = int(temp_number_dec % Decimal(str(1000)))
|
||||
except decimal.InvalidOperation:
|
||||
decimal.getcontext().prec = len(
|
||||
temp_number_dec.as_tuple().digits
|
||||
)
|
||||
number_to_process = int(temp_number_dec % Decimal(str(1000)))
|
||||
|
||||
temp_number = int(temp_number_dec / Decimal(1000))
|
||||
|
||||
group_description = \
|
||||
self.process_arabic_group(number_to_process,
|
||||
group,
|
||||
Decimal(floor(temp_number)))
|
||||
if group_description != '':
|
||||
if group > 0:
|
||||
if ret_val != "":
|
||||
ret_val = "{}و {}".format("", ret_val)
|
||||
if number_to_process != 2 and number_to_process != 1:
|
||||
# if group >= len(self.arabicGroup):
|
||||
# raise OverflowError(self.errmsg_toobig %
|
||||
# (self.number, self.MAXVAL)
|
||||
# )
|
||||
assert group < len(self.arabicGroup)
|
||||
if number_to_process % 100 != 1:
|
||||
if 3 <= number_to_process <= 10:
|
||||
ret_val = "{} {}".format(
|
||||
self.arabicPluralGroups[group], ret_val)
|
||||
else:
|
||||
if ret_val != "":
|
||||
ret_val = "{} {}".format(
|
||||
self.arabicAppendedGroup[group],
|
||||
ret_val)
|
||||
else:
|
||||
ret_val = "{} {}".format(
|
||||
self.arabicGroup[group], ret_val)
|
||||
|
||||
else:
|
||||
ret_val = "{} {}".format(self.arabicGroup[group],
|
||||
ret_val)
|
||||
ret_val = "{} {}".format(group_description, ret_val)
|
||||
group += 1
|
||||
formatted_number = ""
|
||||
if self.arabicPrefixText != "":
|
||||
formatted_number += "{} ".format(self.arabicPrefixText)
|
||||
formatted_number += ret_val
|
||||
if self.integer_value != 0:
|
||||
remaining100 = int(self.integer_value % 100)
|
||||
|
||||
if remaining100 == 0:
|
||||
formatted_number += self.currency_unit[0]
|
||||
elif remaining100 == 1:
|
||||
formatted_number += self.currency_unit[0]
|
||||
elif remaining100 == 2:
|
||||
if self.integer_value == 2:
|
||||
formatted_number += self.currency_unit[1]
|
||||
else:
|
||||
formatted_number += self.currency_unit[0]
|
||||
elif 3 <= remaining100 <= 10:
|
||||
formatted_number += self.currency_unit[2]
|
||||
elif 11 <= remaining100 <= 99:
|
||||
formatted_number += self.currency_unit[3]
|
||||
if self._decimalValue != 0:
|
||||
formatted_number += " {} ".format(self.separator)
|
||||
formatted_number += decimal_string
|
||||
|
||||
if self._decimalValue != 0:
|
||||
formatted_number += " "
|
||||
remaining100 = int(self._decimalValue % 100)
|
||||
|
||||
if remaining100 == 0:
|
||||
formatted_number += self.currency_subunit[0]
|
||||
elif remaining100 == 1:
|
||||
formatted_number += self.currency_subunit[0]
|
||||
elif remaining100 == 2:
|
||||
formatted_number += self.currency_subunit[1]
|
||||
elif 3 <= remaining100 <= 10:
|
||||
formatted_number += self.currency_subunit[2]
|
||||
elif 11 <= remaining100 <= 99:
|
||||
formatted_number += self.currency_subunit[3]
|
||||
|
||||
if self.arabicSuffixText != "":
|
||||
formatted_number += " {}".format(self.arabicSuffixText)
|
||||
|
||||
return formatted_number
|
||||
|
||||
def validate_number(self, number):
|
||||
if number >= self.MAXVAL:
|
||||
raise OverflowError(self.errmsg_toobig % (number, self.MAXVAL))
|
||||
return number
|
||||
|
||||
def set_currency_prefer(self, currency):
|
||||
if currency == 'TND':
|
||||
self.currency_unit = CURRENCY_TND[0]
|
||||
self.currency_subunit = CURRENCY_TND[1]
|
||||
self.partPrecision = 3
|
||||
elif currency == 'EGP':
|
||||
self.currency_unit = CURRENCY_EGP[0]
|
||||
self.currency_subunit = CURRENCY_EGP[1]
|
||||
self.partPrecision = 2
|
||||
elif currency == 'KWD':
|
||||
self.currency_unit = CURRENCY_KWD[0]
|
||||
self.currency_subunit = CURRENCY_KWD[1]
|
||||
self.partPrecision = 2
|
||||
else:
|
||||
self.currency_unit = CURRENCY_SR[0]
|
||||
self.currency_subunit = CURRENCY_SR[1]
|
||||
self.partPrecision = 2
|
||||
|
||||
def to_currency(self, value, currency='SR', prefix='', suffix=''):
|
||||
self.set_currency_prefer(currency)
|
||||
self.isCurrencyNameFeminine = False
|
||||
self.separator = "و"
|
||||
self.arabicOnes = ARABIC_ONES
|
||||
self.arabicPrefixText = prefix
|
||||
self.arabicSuffixText = suffix
|
||||
return self.convert(value=value)
|
||||
|
||||
def to_ordinal(self, number, prefix=''):
|
||||
if number <= 19:
|
||||
return "{}".format(self.arabicOrdinal[number])
|
||||
if number < 100:
|
||||
self.isCurrencyNameFeminine = True
|
||||
else:
|
||||
self.isCurrencyNameFeminine = False
|
||||
self.currency_subunit = ('', '', '', '')
|
||||
self.currency_unit = ('', '', '', '')
|
||||
self.arabicPrefixText = prefix
|
||||
self.arabicSuffixText = ""
|
||||
return "{}".format(self.convert(self.abs(number)).strip())
|
||||
|
||||
def to_year(self, value):
|
||||
value = self.validate_number(value)
|
||||
return self.to_cardinal(value)
|
||||
|
||||
def to_ordinal_num(self, value):
|
||||
return self.to_ordinal(value).strip()
|
||||
|
||||
def to_cardinal(self, number):
|
||||
self.isCurrencyNameFeminine = False
|
||||
number = self.validate_number(number)
|
||||
minus = ''
|
||||
if number < 0:
|
||||
minus = 'سالب '
|
||||
self.separator = ','
|
||||
self.currency_subunit = ('', '', '', '')
|
||||
self.currency_unit = ('', '', '', '')
|
||||
self.arabicPrefixText = ""
|
||||
self.arabicSuffixText = ""
|
||||
self.arabicOnes = ARABIC_ONES
|
||||
return minus + self.convert(value=self.abs(number)).strip()
|
||||
204
path/to/venv/lib/python3.12/site-packages/num2words/lang_AZ.py
Normal file
204
path/to/venv/lib/python3.12/site-packages/num2words/lang_AZ.py
Normal file
@@ -0,0 +1,204 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
||||
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from .base import Num2Word_Base
|
||||
|
||||
|
||||
class Num2Word_AZ(Num2Word_Base):
|
||||
DIGITS = {
|
||||
0: u"sıfır",
|
||||
1: u"bir",
|
||||
2: u"iki",
|
||||
3: u"üç",
|
||||
4: u"dörd",
|
||||
5: u"beş",
|
||||
6: u"altı",
|
||||
7: u"yeddi",
|
||||
8: u"səkkiz",
|
||||
9: u"doqquz",
|
||||
}
|
||||
|
||||
DECIMALS = {
|
||||
1: u"on",
|
||||
2: u"iyirmi",
|
||||
3: u"otuz",
|
||||
4: u"qırx",
|
||||
5: u"əlli",
|
||||
6: u"altmış",
|
||||
7: u"yetmiş",
|
||||
8: u"səksən",
|
||||
9: u"doxsan",
|
||||
}
|
||||
|
||||
POWERS_OF_TEN = {
|
||||
2: u"yüz",
|
||||
3: u"min",
|
||||
6: u"milyon",
|
||||
9: u"milyard",
|
||||
12: u"trilyon",
|
||||
15: u"katrilyon",
|
||||
18: u"kentilyon",
|
||||
21: u"sekstilyon",
|
||||
24: u"septilyon",
|
||||
27: u"oktilyon",
|
||||
30: u"nonilyon",
|
||||
33: u"desilyon",
|
||||
36: u"undesilyon",
|
||||
39: u"dodesilyon",
|
||||
42: u"tredesilyon",
|
||||
45: u"katordesilyon",
|
||||
48: u"kendesilyon",
|
||||
51: u"seksdesilyon",
|
||||
54: u"septendesilyon",
|
||||
57: u"oktodesilyon",
|
||||
60: u"novemdesilyon",
|
||||
63: u"vigintilyon",
|
||||
}
|
||||
|
||||
VOWELS = u"aıoueəiöü"
|
||||
VOWEL_TO_CARDINAL_SUFFIX_MAP = {
|
||||
**dict.fromkeys(["a", "ı"], "ıncı"),
|
||||
**dict.fromkeys(["e", "ə", "i"], "inci"),
|
||||
**dict.fromkeys(["o", "u"], "uncu"),
|
||||
**dict.fromkeys(["ö", "ü"], "üncü"),
|
||||
}
|
||||
|
||||
VOWEL_TO_CARDINAL_NUM_SUFFIX_MAP = {
|
||||
**dict.fromkeys(["a", "ı"], "cı"),
|
||||
**dict.fromkeys(["e", "ə", "i"], "ci"),
|
||||
**dict.fromkeys(["o", "u"], "cu"),
|
||||
**dict.fromkeys(["ö", "ü"], "cü"),
|
||||
}
|
||||
|
||||
CURRENCY_INTEGRAL = ('manat', 'manat')
|
||||
CURRENCY_FRACTION = ('qəpik', 'qəpik')
|
||||
CURRENCY_FORMS = {'AZN': (CURRENCY_INTEGRAL, CURRENCY_FRACTION)}
|
||||
|
||||
def setup(self):
|
||||
super().setup()
|
||||
|
||||
self.negword = u"mənfi"
|
||||
self.pointword = u"nöqtə"
|
||||
|
||||
def to_cardinal(self, value):
|
||||
value_str = str(value)
|
||||
parts = value_str.split(".")
|
||||
integral_part = parts[0]
|
||||
fraction_part = parts[1] if len(parts) > 1 else ""
|
||||
|
||||
if integral_part.startswith("-"):
|
||||
integral_part = integral_part[1:] # ignore minus sign here
|
||||
|
||||
integral_part_in_words = self.int_to_word(integral_part)
|
||||
fraction_part_in_words = "" if not fraction_part else self.int_to_word(
|
||||
fraction_part, leading_zeros=True)
|
||||
|
||||
value_in_words = integral_part_in_words
|
||||
if fraction_part:
|
||||
value_in_words = " ".join(
|
||||
[
|
||||
integral_part_in_words,
|
||||
self.pointword,
|
||||
fraction_part_in_words
|
||||
]
|
||||
)
|
||||
|
||||
if value < 0:
|
||||
value_in_words = " ".join([self.negword, value_in_words])
|
||||
|
||||
return value_in_words
|
||||
|
||||
def to_ordinal(self, value):
|
||||
assert int(value) == value
|
||||
|
||||
cardinal = self.to_cardinal(value)
|
||||
last_vowel = self._last_vowel(cardinal)
|
||||
assert last_vowel is not None
|
||||
suffix = self.VOWEL_TO_CARDINAL_SUFFIX_MAP[last_vowel]
|
||||
|
||||
if cardinal.endswith(tuple(self.VOWELS)):
|
||||
cardinal = cardinal[:-1]
|
||||
|
||||
ordinal = "".join([cardinal, suffix])
|
||||
|
||||
return ordinal
|
||||
|
||||
def to_ordinal_num(self, value):
|
||||
assert int(value) == value
|
||||
|
||||
cardinal = self.to_cardinal(value)
|
||||
last_vowel = self._last_vowel(cardinal)
|
||||
assert last_vowel is not None
|
||||
suffix = self.VOWEL_TO_CARDINAL_NUM_SUFFIX_MAP[last_vowel]
|
||||
ordinal_num = "-".join([str(value), suffix])
|
||||
|
||||
return ordinal_num
|
||||
|
||||
def to_year(self, value):
|
||||
assert int(value) == value
|
||||
|
||||
year = self.to_cardinal(abs(value))
|
||||
if value < 0:
|
||||
year = " ".join(["e.ə.", year])
|
||||
|
||||
return year
|
||||
|
||||
def pluralize(self, n, forms):
|
||||
form = 0 if n == 1 else 1
|
||||
return forms[form]
|
||||
|
||||
def int_to_word(self, num_str, leading_zeros=False):
|
||||
words = []
|
||||
reversed_str = list(reversed(num_str))
|
||||
|
||||
for index, digit in enumerate(reversed_str):
|
||||
digit_int = int(digit)
|
||||
# calculate remainder after dividing index by 3
|
||||
# because number is parsed by three digit chunks
|
||||
remainder_to_3 = index % 3
|
||||
if remainder_to_3 == 0:
|
||||
if index > 0:
|
||||
if set(reversed_str[index:index+3]) != {'0'}:
|
||||
words.insert(0, self.POWERS_OF_TEN[index])
|
||||
if digit_int > 0:
|
||||
# we say "min" not "bir min"
|
||||
if not (digit_int == 1 and index == 3):
|
||||
words.insert(0, self.DIGITS[digit_int])
|
||||
elif remainder_to_3 == 1:
|
||||
if digit_int != 0:
|
||||
words.insert(0, self.DECIMALS[digit_int])
|
||||
else: # remainder is 2
|
||||
if digit_int > 0:
|
||||
words.insert(0, self.POWERS_OF_TEN[2]) # "yüz"
|
||||
if digit_int > 1:
|
||||
words.insert(0, self.DIGITS[digit_int])
|
||||
|
||||
if num_str == '0':
|
||||
words.append(self.DIGITS[0])
|
||||
|
||||
if leading_zeros:
|
||||
zeros_count = len(num_str) - len(str(int(num_str)))
|
||||
words[:0] = zeros_count * [self.DIGITS[0]]
|
||||
|
||||
return " ".join(words)
|
||||
|
||||
def _last_vowel(self, value):
|
||||
for char in value[::-1]:
|
||||
if char in self.VOWELS:
|
||||
return char
|
||||
351
path/to/venv/lib/python3.12/site-packages/num2words/lang_BE.py
Normal file
351
path/to/venv/lib/python3.12/site-packages/num2words/lang_BE.py
Normal file
@@ -0,0 +1,351 @@
|
||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
||||
# Copyright (c) 2022, Sergei Ruzki. 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 .base import Num2Word_Base
|
||||
from .utils import get_digits, splitbyx
|
||||
|
||||
ZERO = "нуль"
|
||||
|
||||
ONES_FEMININE = {
|
||||
1: "адна",
|
||||
2: "дзве",
|
||||
3: "тры",
|
||||
4: "чатыры",
|
||||
5: "пяць",
|
||||
6: "шэсць",
|
||||
7: "сем",
|
||||
8: "восем",
|
||||
9: "дзевяць",
|
||||
}
|
||||
|
||||
ONES = {
|
||||
"f": {
|
||||
1: "адна",
|
||||
2: "дзве",
|
||||
3: "тры",
|
||||
4: "чатыры",
|
||||
5: "пяць",
|
||||
6: "шэсць",
|
||||
7: "сем",
|
||||
8: "восем",
|
||||
9: "дзевяць",
|
||||
},
|
||||
"m": {
|
||||
1: "адзін",
|
||||
2: "два",
|
||||
3: "тры",
|
||||
4: "чатыры",
|
||||
5: "пяць",
|
||||
6: "шэсць",
|
||||
7: "сем",
|
||||
8: "восем",
|
||||
9: "дзевяць",
|
||||
},
|
||||
"n": {
|
||||
1: "адно",
|
||||
2: "два",
|
||||
3: "тры",
|
||||
4: "чатыры",
|
||||
5: "пяць",
|
||||
6: "шэсць",
|
||||
7: "сем",
|
||||
8: "восем",
|
||||
9: "дзевяць",
|
||||
},
|
||||
}
|
||||
|
||||
TENS = {
|
||||
0: "дзесяць",
|
||||
1: "адзінаццаць",
|
||||
2: "дванаццаць",
|
||||
3: "трынаццаць",
|
||||
4: "чатырнаццаць",
|
||||
5: "пятнаццаць",
|
||||
6: "шаснаццаць",
|
||||
7: "сямнаццаць",
|
||||
8: "васямнаццаць",
|
||||
9: "дзевятнаццаць",
|
||||
}
|
||||
|
||||
TWENTIES = {
|
||||
2: "дваццаць",
|
||||
3: "трыццаць",
|
||||
4: "сорак",
|
||||
5: "пяцьдзясят",
|
||||
6: "шэсцьдзясят",
|
||||
7: "семдзесят",
|
||||
8: "восемдзесят",
|
||||
9: "дзевяноста",
|
||||
}
|
||||
|
||||
TWENTIES_ORD = (
|
||||
("дваццаць", "дваццаці"),
|
||||
("трыццаць", "трыццаці"),
|
||||
("сорак", "сарака"),
|
||||
("пяцьдзясят", "пяцідзясяці"),
|
||||
("шэсцьдзясят", "шaсцідзясяці"),
|
||||
("семдзесят", "сямідзесяці"),
|
||||
("восемдзесят", "васьмідзесяці"),
|
||||
("дзевяноста", "дзевяноста"),
|
||||
)
|
||||
|
||||
HUNDREDS = {
|
||||
1: "сто",
|
||||
2: "дзвесце",
|
||||
3: "трыста",
|
||||
4: "чатырыста",
|
||||
5: "пяцьсот",
|
||||
6: "шэсцьсот",
|
||||
7: "семсот",
|
||||
8: "восемсот",
|
||||
9: "дзевяцьсот",
|
||||
}
|
||||
|
||||
THOUSANDS = {
|
||||
1: ("тысяча", "тысячы", "тысяч"), # 10^3
|
||||
2: ("мільён", "мільёны", "мільёнаў"), # 10^6
|
||||
3: ("мільярд", "мільярды", "мільярдаў"), # 10^9
|
||||
4: ("трыльён", "трыльёны", "трыльёнаў"), # 10^12
|
||||
5: ("квадрыльён", "квадрыльёны", "квадрыльёнаў"), # 10^15
|
||||
6: ("квінтыльён", "квінтыльёны", "квінтыльёнаў"), # 10^18
|
||||
7: ("секстыльён", "секстыльёны", "секстыльёнаў"), # 10^21
|
||||
8: ("сэптыльён", "сэптыльёны", "сэптыльёнаў"), # 10^24
|
||||
9: ("актыльён", "актыльёны", "актыльёнаў"), # 10^27
|
||||
10: ("нанільён", "нанільёны", "нанільёнаў"), # 10^30
|
||||
}
|
||||
|
||||
|
||||
class Num2Word_BE(Num2Word_Base):
|
||||
CURRENCY_FORMS = {
|
||||
"RUB": (
|
||||
("расійскі рубель", "расійскія рублі", "расійскіх рублёў"),
|
||||
("капейка", "капейкі", "капеек"),
|
||||
),
|
||||
"EUR": (("еўра", "еўра", "еўра"), ("цэнт", "цэнты", "цэнтаў")),
|
||||
"USD": (("долар", "долары", "долараў"), ("цэнт", "цэнты", "цэнтаў")),
|
||||
"UAH": (
|
||||
("грыўна", "грыўны", "грыўнаў"),
|
||||
("капейка", "капейкі", "капеек"),
|
||||
),
|
||||
"KZT": (("тэнге", "тэнге", "тэнге"), ("тыйін", "тыйіны", "тыйінаў")),
|
||||
"BYN": (
|
||||
("беларускі рубель", "беларускія рублі", "беларускіх рублёў"),
|
||||
("капейка", "капейкі", "капеек"),
|
||||
),
|
||||
"UZS": (("сум", "сумы", "сумаў"), ("тыйін", "тыйіны", "тыйінаў")),
|
||||
"PLN": (("злоты", "злотых", "злотых"), ("грош", "грошы", "грошаў")),
|
||||
}
|
||||
|
||||
def setup(self):
|
||||
self.negword = "мінус"
|
||||
self.pointword = "коска"
|
||||
self.ords = {
|
||||
"нуль": "нулявы",
|
||||
"адзін": "першы",
|
||||
"два": "другі",
|
||||
"тры": "трэці",
|
||||
"чатыры": "чацвёрты",
|
||||
"пяць": "пяты",
|
||||
"шэсць": "шосты",
|
||||
"сем": "сёмы",
|
||||
"восем": "восьмы",
|
||||
"дзевяць": "дзявяты",
|
||||
"сто": "соты",
|
||||
"тысяча": "тысячны",
|
||||
}
|
||||
|
||||
self.ords_adjective = {
|
||||
"адзін": "адна",
|
||||
"адна": "адна",
|
||||
"дзве": "двух",
|
||||
"тры": "трох",
|
||||
"чатыры": "чатырох",
|
||||
"пяць": "пяці",
|
||||
"шэсць": "шасці",
|
||||
"сем": "сямі",
|
||||
"восем": "васьмі",
|
||||
"дзевяць": "дзевяцi",
|
||||
"сто": "ста",
|
||||
}
|
||||
|
||||
def to_cardinal(self, number, gender="m"):
|
||||
n = str(number).replace(",", ".")
|
||||
if "." in n:
|
||||
left, right = n.split(".")
|
||||
if set(right) == {"0"}:
|
||||
leading_zero_count = 0
|
||||
else:
|
||||
leading_zero_count = len(right) - len(right.lstrip("0"))
|
||||
|
||||
decimal_part = (ZERO + " ") * leading_zero_count + self._int2word(
|
||||
int(right), gender
|
||||
)
|
||||
return "{} {} {}".format(
|
||||
self._int2word(int(left), gender), self.pointword, decimal_part
|
||||
)
|
||||
else:
|
||||
return self._int2word(int(n), gender)
|
||||
|
||||
def pluralize(self, n, forms):
|
||||
if n % 100 < 10 or n % 100 > 20:
|
||||
if n % 10 == 1:
|
||||
form = 0
|
||||
elif 5 > n % 10 > 1:
|
||||
form = 1
|
||||
else:
|
||||
form = 2
|
||||
else:
|
||||
form = 2
|
||||
return forms[form]
|
||||
|
||||
def to_ordinal(self, number, gender="m"):
|
||||
self.verify_ordinal(number)
|
||||
if isinstance(gender, bool) and gender:
|
||||
gender = "f"
|
||||
outwords = self.to_cardinal(number, gender).split(" ")
|
||||
lastword = outwords[-1].lower()
|
||||
try:
|
||||
if len(outwords) > 1:
|
||||
if outwords[-2] in self.ords_adjective:
|
||||
outwords[-2] = self.ords_adjective.get(
|
||||
outwords[-2], outwords[-2]
|
||||
)
|
||||
elif outwords[-2] == "дзесяць":
|
||||
outwords[-2] = outwords[-2][:-1] + "і"
|
||||
if len(outwords) == 3:
|
||||
if outwords[-3] in ["адзін", "адна"]:
|
||||
outwords[-3] = ""
|
||||
lastword = self.ords[lastword]
|
||||
except KeyError:
|
||||
if lastword[:-3] in self.ords_adjective:
|
||||
lastword = (
|
||||
self.ords_adjective.get(lastword[:-3], lastword) + "соты"
|
||||
)
|
||||
elif lastword[-7:] == "дзесяць":
|
||||
lastword = "дзясяты"
|
||||
elif lastword[-9:] == "семдзесят":
|
||||
lastword = "сямідзясяты"
|
||||
elif lastword[-1] == "ь" or lastword[-2] == "ц":
|
||||
lastword = lastword[:-2] + "ты"
|
||||
elif lastword[-1] == "к":
|
||||
lastword = lastword.replace("о", "а") + "авы"
|
||||
|
||||
elif lastword[-2] == "ч" or lastword[-1] == "ч":
|
||||
if lastword[-2] == "ч":
|
||||
lastword = lastword[:-1] + "ны"
|
||||
if lastword[-1] == "ч":
|
||||
lastword = lastword + "ны"
|
||||
|
||||
elif lastword[-1] == "н" or lastword[-2] == "н":
|
||||
lastword = lastword[: lastword.rfind("н") + 1] + "ны"
|
||||
elif lastword[-3:] == "наў":
|
||||
lastword = lastword[: lastword.rfind("н") + 1] + "ны"
|
||||
elif lastword[-1] == "д" or lastword[-2] == "д":
|
||||
lastword = lastword[: lastword.rfind("д") + 1] + "ны"
|
||||
|
||||
if gender == "f":
|
||||
if lastword[-2:] in [
|
||||
"ці",
|
||||
]:
|
||||
lastword = lastword[:-2] + "цяя"
|
||||
else:
|
||||
lastword = lastword[:-1] + "ая"
|
||||
|
||||
if gender == "n":
|
||||
if lastword[-2:] in ["ці", "ца"]:
|
||||
lastword = lastword[:-2] + "цяе"
|
||||
else:
|
||||
lastword = lastword[:-1] + "ае"
|
||||
|
||||
outwords[-1] = self.title(lastword)
|
||||
if len(outwords) == 2 and "адна" in outwords[-2]:
|
||||
outwords[-2] = outwords[-1]
|
||||
del outwords[-1]
|
||||
|
||||
if len(outwords) > 1 and (
|
||||
(any(x[0] in outwords[-1] for x in THOUSANDS.values()))
|
||||
or "тысяч" in outwords[-1]
|
||||
):
|
||||
new_outwords = []
|
||||
for _w in outwords:
|
||||
replacement = next(
|
||||
(x for x in TWENTIES_ORD if x[0] in _w), None
|
||||
)
|
||||
if replacement:
|
||||
_w = _w.replace(replacement[0], replacement[1])
|
||||
new_outwords.append(_w)
|
||||
outwords = ["".join(new_outwords)]
|
||||
|
||||
return " ".join(outwords).strip()
|
||||
|
||||
def _money_verbose(self, number, currency):
|
||||
gender = "m"
|
||||
if currency == "UAH":
|
||||
gender = "f"
|
||||
|
||||
return self._int2word(number, gender)
|
||||
|
||||
def _cents_verbose(self, number, currency):
|
||||
if currency in ("UAH", "RUB", "BYN"):
|
||||
gender = "f"
|
||||
else:
|
||||
gender = "m"
|
||||
|
||||
return self._int2word(number, gender)
|
||||
|
||||
def _int2word(self, n, gender="m"):
|
||||
if n < 0:
|
||||
return " ".join([self.negword, self._int2word(abs(n), gender)])
|
||||
|
||||
if n == 0:
|
||||
return ZERO
|
||||
|
||||
words = []
|
||||
chunks = list(splitbyx(str(n), 3))
|
||||
i = len(chunks)
|
||||
for x in chunks:
|
||||
i -= 1
|
||||
|
||||
if x == 0:
|
||||
continue
|
||||
|
||||
n1, n2, n3 = get_digits(x)
|
||||
|
||||
if n3 > 0:
|
||||
words.append(HUNDREDS[n3])
|
||||
|
||||
if n2 > 1:
|
||||
words.append(TWENTIES[n2])
|
||||
|
||||
if n2 == 1:
|
||||
words.append(TENS[n1])
|
||||
elif n1 > 0:
|
||||
if i == 0:
|
||||
ones = ONES[gender]
|
||||
elif i == 1:
|
||||
ones = ONES["f"] # Thousands are feminine
|
||||
else:
|
||||
ones = ONES["m"]
|
||||
|
||||
words.append(ones[n1])
|
||||
|
||||
if i > 0:
|
||||
words.append(self.pluralize(x, THOUSANDS[i]))
|
||||
|
||||
return " ".join(words)
|
||||
203
path/to/venv/lib/python3.12/site-packages/num2words/lang_BN.py
Normal file
203
path/to/venv/lib/python3.12/site-packages/num2words/lang_BN.py
Normal file
@@ -0,0 +1,203 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Author: Mehedi Hasan Khondoker
|
||||
# Email: mehedihasankhondoker [at] gmail.com
|
||||
# Copyright (c) 2024, Mehedi Hasan Khondoker. All Rights Reserved.
|
||||
|
||||
# This library is build for Bangladesh format Number to Word conversion.
|
||||
# You are welcome as contributor to the library.
|
||||
|
||||
# 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.
|
||||
|
||||
|
||||
from decimal import Decimal
|
||||
|
||||
RANKING = ['', 'প্রথম', 'দ্বিতীয়', 'তৃতীয়', 'চতুর্থ', 'পঞ্চম', 'ষষ্ঠ',
|
||||
'সপ্তম', 'অষ্টম', 'নবম', 'দশম'] # pragma: no cover
|
||||
|
||||
AKOK = ['', 'এক', 'দুই', 'তিন', 'চার', 'পাঁচ', 'ছয়',
|
||||
'সাত', 'আট', 'নয়'] # pragma: no cover
|
||||
|
||||
DOSOK = [
|
||||
'দশ', 'এগারো', 'বারো', 'তেরো', 'চৌদ্দ', 'পনের',
|
||||
'ষোল', 'সতের', 'আঠারো', 'উনিশ',
|
||||
'বিশ', 'একুশ', 'বাইশ', 'তেইশ', 'চব্বিশ', 'পঁচিশ',
|
||||
'ছাব্বিশ', 'সাতাশ', 'আটাশ', 'উনত্রিশ',
|
||||
'ত্রিশ', 'একত্রিশ', 'বত্রিশ', 'তেত্রিশ', 'চৌত্রিশ', 'পঁইত্রিশ',
|
||||
'ছত্রিশ', 'সাতত্রিশ', 'আটত্রিশ', 'উনচল্লিশ', 'চল্লিশ',
|
||||
'একচল্লিশ', 'বিয়াল্লিশ', 'তেতাল্লিশ', 'চৌচল্লিশ',
|
||||
'পঁয়তাল্লিশ', 'ছেচল্লিশ', 'সাতচল্লিশ', 'আটচল্লিশ', 'উনপঞ্চাশ',
|
||||
'পঞ্চাশ', 'একান্ন', 'বাহান্ন', 'তিপ্পান্ন', 'চুয়ান্ন', 'পঞ্চান্ন',
|
||||
'ছাপ্পান্ন', 'সাতান্ন', 'আটান্ন', 'উনষাট', 'ষাট',
|
||||
'একষট্টি', 'বাষট্টি', 'তেষট্টি', 'চৌষট্টি', 'পঁয়ষট্টি',
|
||||
'ছিষট্টি', 'সাতষট্টি', 'আটষট্টি', 'উনসত্তর', 'সত্তর',
|
||||
'একাত্তর ', 'বাহাত্তর', 'তিয়াত্তর', 'চুয়াত্তর', 'পঁচাত্তর',
|
||||
'ছিয়াত্তর', 'সাতাত্তর', 'আটাত্তর', 'উনআশি', 'আশি',
|
||||
'একাশি', 'বিরাশি', 'তিরাশি', 'চুরাশি', 'পঁচাশি',
|
||||
'ছিয়াশি', 'সাতাশি', 'আটাশি', 'উননব্বই', 'নব্বই',
|
||||
'একানব্বই', 'বিরানব্বই', 'তিরানব্বই', 'চুরানব্বই', 'পঁচানব্বই',
|
||||
'ছিয়ানব্বই', 'সাতানব্বই', 'আটানব্বই', 'নিরানব্বই'
|
||||
] # pragma: no cover
|
||||
HAZAR = ' হাজার ' # pragma: no cover
|
||||
LAKH = ' লাখ ' # pragma: no cover
|
||||
KOTI = ' কোটি ' # pragma: no cover
|
||||
MAX_NUMBER = 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 # noqa: E501 # pragma: no cover
|
||||
|
||||
|
||||
class NumberTooLargeError(Exception):
|
||||
"""Custom exception for numbers that are too large."""
|
||||
pass
|
||||
|
||||
|
||||
class Num2Word_BN:
|
||||
|
||||
@staticmethod
|
||||
def str_to_number(number):
|
||||
return abs(Decimal(str(number))) # pragma: no cover
|
||||
|
||||
@staticmethod
|
||||
def parse_number(number: Decimal):
|
||||
dosomik = str(number - int(number)).split('.')[1:]
|
||||
dosomik_str = ''.join(dosomik) if dosomik else 0
|
||||
return int(number), int(dosomik_str)
|
||||
|
||||
@staticmethod
|
||||
def parse_paisa(number: Decimal):
|
||||
# 1-99 for paisa count so two digits are valid.
|
||||
paisa = str(number - int(number)).split('.')[1:]
|
||||
paisa_str = ''.join(paisa) if paisa else 0
|
||||
|
||||
# this is need, when we parse to decimal it removes trailing 0 .
|
||||
if paisa_str:
|
||||
paisa_str = str(int(paisa_str) * 100)[:2]
|
||||
return int(number), int(paisa_str)
|
||||
|
||||
def _is_smaller_than_max_number(self, number):
|
||||
if MAX_NUMBER >= number:
|
||||
return True
|
||||
raise NumberTooLargeError(f'Too Large number maximum '
|
||||
f'value={MAX_NUMBER}')
|
||||
|
||||
def _dosomik_to_bengali_word(self, number):
|
||||
word = ''
|
||||
for i in str(number):
|
||||
word += ' ' + AKOK[int(i)]
|
||||
return word
|
||||
|
||||
def _number_to_bengali_word(self, number):
|
||||
if number == 0:
|
||||
return 'শূন্য'
|
||||
|
||||
words = ''
|
||||
|
||||
if number >= 10 ** 7:
|
||||
words += self._number_to_bengali_word(number // 10 ** 7) + KOTI
|
||||
number %= 10 ** 7
|
||||
|
||||
if number >= 10 ** 5:
|
||||
words += self._number_to_bengali_word(number // 10 ** 5) + LAKH
|
||||
number %= 10 ** 5
|
||||
|
||||
if number >= 1000:
|
||||
words += self._number_to_bengali_word(number // 1000) + HAZAR
|
||||
number %= 1000
|
||||
|
||||
if number >= 100:
|
||||
words += AKOK[number // 100] + 'শত '
|
||||
number %= 100
|
||||
|
||||
if 10 <= number <= 99:
|
||||
words += DOSOK[number - 10] + ' '
|
||||
number = 0
|
||||
|
||||
if 0 < number < 10:
|
||||
words += AKOK[number] + ' '
|
||||
|
||||
return words.strip()
|
||||
|
||||
def to_currency(self, val):
|
||||
"""
|
||||
This function represent a number to word in bangla taka and paisa.
|
||||
example:
|
||||
1 = এক টাকা,
|
||||
101 = একশত এক টাকা,
|
||||
9999.15 = নয় হাজার নয়শত নিরানব্বই টাকা পনের পয়সা
|
||||
and so on.
|
||||
"""
|
||||
|
||||
dosomik_word = None
|
||||
number = self.str_to_number(val)
|
||||
number, decimal_part = self.parse_paisa(number)
|
||||
self._is_smaller_than_max_number(number)
|
||||
|
||||
if decimal_part > 0:
|
||||
dosomik_word = f' {self._number_to_bengali_word(decimal_part)} পয়সা' # noqa: E501
|
||||
|
||||
words = f'{self._number_to_bengali_word(number)} টাকা'
|
||||
|
||||
if dosomik_word:
|
||||
return (words + dosomik_word).strip()
|
||||
return words.strip()
|
||||
|
||||
def to_cardinal(self, number):
|
||||
"""
|
||||
This function represent a number to word in bangla.
|
||||
example:
|
||||
1 = এক,
|
||||
101 = একশত এক,
|
||||
9999 = নয় হাজার নয়শত নিরানব্বই
|
||||
and so on.
|
||||
"""
|
||||
|
||||
dosomik_word = None
|
||||
number = self.str_to_number(number)
|
||||
number, decimal_part = self.parse_number(number)
|
||||
self._is_smaller_than_max_number(number)
|
||||
|
||||
if decimal_part > 0:
|
||||
dosomik_word = f' দশমিক{self._dosomik_to_bengali_word(decimal_part)}' # noqa: E501
|
||||
|
||||
words = self._number_to_bengali_word(number)
|
||||
|
||||
if dosomik_word:
|
||||
return (words + dosomik_word).strip()
|
||||
return words.strip()
|
||||
|
||||
def to_ordinal(self, number):
|
||||
return self.to_cardinal(number)
|
||||
|
||||
def to_ordinal_num(self, number):
|
||||
"""
|
||||
This function represent a number to ranking in bangla.
|
||||
example:
|
||||
1 = প্রথম,
|
||||
2 = দ্বিতীয়,
|
||||
1001 = এক হাজার একতম
|
||||
and so on.
|
||||
"""
|
||||
self._is_smaller_than_max_number(number)
|
||||
|
||||
if number in range(1, 11):
|
||||
return RANKING[number]
|
||||
else:
|
||||
rank = self.to_cardinal(int(abs(number)))
|
||||
if rank.endswith('ত'):
|
||||
return rank + 'ম'
|
||||
return rank + 'তম'
|
||||
|
||||
def to_year(self, number):
|
||||
"""
|
||||
This function represent a number to year in bangla.
|
||||
example:
|
||||
2002 = দুই হাজার দুই সাল,
|
||||
2024 = দুই হাজার চব্বিশ সাল
|
||||
and so on.
|
||||
"""
|
||||
self._is_smaller_than_max_number(number)
|
||||
return self.to_cardinal(int(abs(number))) + ' সাল'
|
||||
476
path/to/venv/lib/python3.12/site-packages/num2words/lang_CA.py
Normal file
476
path/to/venv/lib/python3.12/site-packages/num2words/lang_CA.py
Normal file
@@ -0,0 +1,476 @@
|
||||
from __future__ import division, print_function, unicode_literals
|
||||
|
||||
import math
|
||||
|
||||
from .lang_EU import Num2Word_EU
|
||||
|
||||
GENERIC_DOLLARS = ('dòlar', 'dòlars')
|
||||
GENERIC_CENTS = ('centau', 'centaus')
|
||||
CURRENCIES_UNA = (
|
||||
'SLL',
|
||||
'SEK',
|
||||
'NOK',
|
||||
'CZK',
|
||||
'DKK',
|
||||
'ISK',
|
||||
'SKK',
|
||||
'GBP',
|
||||
'CYP',
|
||||
'EGP',
|
||||
'FKP',
|
||||
'GIP',
|
||||
'LBP',
|
||||
'SDG',
|
||||
'SHP',
|
||||
'SSP',
|
||||
'SYP',
|
||||
'INR',
|
||||
'IDR',
|
||||
'LKR',
|
||||
'MUR',
|
||||
'NPR',
|
||||
'PKR',
|
||||
'SCR',
|
||||
'ESP',
|
||||
'TRY',
|
||||
'ITL',
|
||||
)
|
||||
CENTS_UNA = ('EGP', 'JOD', 'LBP', 'SDG', 'SSP', 'SYP')
|
||||
|
||||
|
||||
class Num2Word_CA(Num2Word_EU):
|
||||
CURRENCY_FORMS = {
|
||||
'EUR': (('euro', 'euros'), ('cèntim', 'cèntims')),
|
||||
'ESP': (('pesseta', 'pessetes'), ('cèntim', 'cèntims')),
|
||||
'USD': (GENERIC_DOLLARS, ('centau', 'centaus')),
|
||||
'PEN': (('sol', 'sols'), ('cèntim', 'cèntims')),
|
||||
'CRC': (('colón', 'colons'), GENERIC_CENTS),
|
||||
'AUD': (GENERIC_DOLLARS, GENERIC_CENTS),
|
||||
'CAD': (GENERIC_DOLLARS, GENERIC_CENTS),
|
||||
'GBP': (('lliura', 'lliures'), ('penic', 'penics')),
|
||||
'RUB': (('ruble', 'rubles'), ('copec', 'copecs')),
|
||||
'SEK': (('corona', 'corones'), ('öre', 'öre')),
|
||||
'NOK': (('corona', 'corones'), ('øre', 'øre')),
|
||||
'PLN': (('zloty', 'zlotys'), ('grosz', 'groszy')),
|
||||
'MXN': (('peso', 'pesos'), GENERIC_CENTS),
|
||||
'RON': (('leu', 'lei'), ('ban', 'bani')),
|
||||
'INR': (('rupia', 'rupies'), ('paisa', 'paise')),
|
||||
'HUF': (('fòrint', 'fòrints'), ('fillér', 'fillérs')),
|
||||
'FRF': (('franc', 'francs'), ('cèntim', 'cèntims')),
|
||||
'CNY': (('iuan', 'iuans'), ('fen', 'jiao')),
|
||||
'CZK': (('corona', 'corones'), ('haléř', 'haléřů')),
|
||||
'NIO': (('córdoba', 'córdobas'), GENERIC_CENTS),
|
||||
'VES': (('bolívar', 'bolívars'), ('cèntim', 'cèntims')),
|
||||
'BRL': (('real', 'reals'), GENERIC_CENTS),
|
||||
'CHF': (('franc', 'francs'), ('cèntim', 'cèntims')),
|
||||
'JPY': (('ien', 'iens'), ('sen', 'sen')),
|
||||
'KRW': (('won', 'wons'), ('jeon', 'jeon')),
|
||||
'KPW': (('won', 'wons'), ('chŏn', 'chŏn')),
|
||||
'TRY': (('lira', 'lires'), ('kuruş', 'kuruş')),
|
||||
'ZAR': (('rand', 'rands'), ('cèntim', 'cèntims')),
|
||||
'KZT': (('tenge', 'tenge'), ('tin', 'tin')),
|
||||
'UAH': (('hrívnia', 'hrívnies'), ('kopiika', 'kopíok')),
|
||||
'THB': (('baht', 'bahts'), ('satang', 'satang')),
|
||||
'AED': (('dirham', 'dirhams'), ('fils', 'fulūs')),
|
||||
'AFN': (('afgani', 'afganis'), ('puli', 'puls')),
|
||||
'ALL': (('lek', 'lekë'), ('qqindarka', 'qindarkë')),
|
||||
'AMD': (('dram', 'drams'), ('luma', 'lumas')),
|
||||
'ANG': (('florí', 'florins'), ('cèntim', 'cèntims')),
|
||||
'AOA': (('kwanza', 'kwanzes'), ('cèntim', 'cèntims')),
|
||||
'ARS': (('peso', 'pesos'), GENERIC_CENTS),
|
||||
'AWG': (('florí', 'florins'), GENERIC_CENTS),
|
||||
'AZN': (('manat', 'manats'), ('qəpik', 'qəpik')),
|
||||
'BBD': (GENERIC_DOLLARS, GENERIC_CENTS),
|
||||
'BDT': (('taka', 'taka'), ('poisha', 'poisha')),
|
||||
'BGN': (('lev', 'leva'), ('stotinka', 'stotinki')),
|
||||
'BHD': (('dinar', 'dinars'), ('fils', 'fulūs')),
|
||||
'BIF': (('franc', 'francs'), ('cèntim', 'cèntims')),
|
||||
'BMD': (GENERIC_DOLLARS, GENERIC_CENTS),
|
||||
'BND': (GENERIC_DOLLARS, GENERIC_CENTS),
|
||||
'BOB': (('boliviano', 'bolivianos'), GENERIC_CENTS),
|
||||
'BSD': (GENERIC_DOLLARS, GENERIC_CENTS),
|
||||
'BTN': (('ngultrum', 'ngultrums'), ('chetrum', 'chetrums')),
|
||||
'BWP': (('pula', 'pula'), ('thebe', 'thebe')),
|
||||
'BYN': (('ruble', 'rubles'), ('copec', 'copecs')),
|
||||
'BYR': (('ruble', 'rubles'), ('copec', 'copecs')),
|
||||
'BZD': (GENERIC_DOLLARS, ('cèntim', 'cèntims')),
|
||||
'CDF': (('franc', 'francs'), ('cèntim', 'cèntims')),
|
||||
'CLP': (('peso', 'pesos'), GENERIC_CENTS),
|
||||
'COP': (('peso', 'pesos'), GENERIC_CENTS),
|
||||
'CUP': (('peso', 'pesos'), GENERIC_CENTS),
|
||||
'CVE': (('escut', 'escuts'), GENERIC_CENTS),
|
||||
'CYP': (('lliura', 'lliures'), ('cèntim', 'cèntims')),
|
||||
'DJF': (('franc', 'francs'), ('cèntim', 'cèntims')),
|
||||
'DKK': (('corona', 'corones'), ('øre', 'øre')),
|
||||
'DOP': (('peso', 'pesos'), GENERIC_CENTS),
|
||||
'DZD': (('dinar', 'dinars'), ('cèntim', 'cèntims')),
|
||||
'ECS': (('sucre', 'sucres'), GENERIC_CENTS),
|
||||
'EGP': (('lliura', 'lliures'), ('piastre', 'piastres')),
|
||||
'ERN': (('nakfa', 'nakfes'), ('cèntim', 'cèntims')),
|
||||
'ETB': (('birr', 'birr'), ('cèntim', 'cèntims')),
|
||||
'FJD': (GENERIC_DOLLARS, GENERIC_CENTS),
|
||||
'FKP': (('lliura', 'lliures'), ('penic', 'penics')),
|
||||
'GEL': (('lari', 'laris'), ('tetri', 'tetri')),
|
||||
'GHS': (('cedi', 'cedis'), ('pesewa', 'pesewas')),
|
||||
'GIP': (('lliura', 'lliures'), ('penic', 'penics')),
|
||||
'GMD': (('dalasi', 'dalasis'), ('butut', 'bututs')),
|
||||
'GNF': (('franc', 'francs'), ('cèntim', 'cèntims')),
|
||||
'GTQ': (('quetzal', 'quetzals'), GENERIC_CENTS),
|
||||
'GYD': (GENERIC_DOLLARS, GENERIC_CENTS),
|
||||
'HKD': (GENERIC_DOLLARS, GENERIC_CENTS),
|
||||
'HNL': (('lempira', 'lempires'), GENERIC_CENTS),
|
||||
'HRK': (('kuna', 'kuna'), ('lipa', 'lipa')),
|
||||
'HTG': (('gourde', 'gourdes'), ('cèntim', 'cèntims')),
|
||||
'IDR': (('rúpia', 'rúpies'), ('cèntim', 'cèntims')),
|
||||
'ILS': (('xéquel', 'xéquels'), ('agorà', 'agorot')),
|
||||
'IQD': (('dinar', 'dinars'), ('fils', 'fils')),
|
||||
'IRR': (('rial', 'rials'), ('dinar', 'dinars')),
|
||||
'ISK': (('corona', 'corones'), ('eyrir', 'aurar')),
|
||||
'ITL': (('lira', 'lires'), ('cèntim', 'cèntims')),
|
||||
'JMD': (GENERIC_DOLLARS, ('cèntim', 'cèntims')),
|
||||
'JOD': (('dinar', 'dinars'), ('piastra', 'piastres')),
|
||||
'KES': (('xiling', 'xílings'), ('cèntim', 'cèntims')),
|
||||
'KGS': (('som', 'som'), ('tyiyn', 'tyiyn')),
|
||||
'KHR': (('riel', 'riels'), ('cèntim', 'cèntims')),
|
||||
'KMF': (('franc', 'francs'), ('cèntim', 'cèntims')),
|
||||
'KWD': (('dinar', 'dinars'), ('fils', 'fils')),
|
||||
'KYD': (GENERIC_DOLLARS, ('cèntim', 'cèntims')),
|
||||
'LAK': (('kip', 'kips'), ('at', 'at')),
|
||||
'LBP': (('lliura', 'lliures'), ('piastra', 'piastres')),
|
||||
'LKR': (('rúpia', 'rúpies'), ('cèntim', 'cèntims')),
|
||||
'LRD': (GENERIC_DOLLARS, ('cèntim', 'cèntims')),
|
||||
'LSL': (('loti', 'maloti'), ('sente', 'lisente')),
|
||||
'LTL': (('lita', 'litai'), ('cèntim', 'cèntims')),
|
||||
'LYD': (('dinar', 'dinars'), ('dírham', 'dírhams')),
|
||||
'MAD': (('dírham', 'dirhams'), ('cèntim', 'cèntims')),
|
||||
'MDL': (('leu', 'lei'), ('ban', 'bani')),
|
||||
'MGA': (('ariary', 'ariary'), ('iraimbilanja', 'iraimbilanja')),
|
||||
'MKD': (('denar', 'denari'), ('deni', 'deni')),
|
||||
'MMK': (('kyat', 'kyats'), ('pya', 'pyas')),
|
||||
'MNT': (('tögrög', 'tögrög'), ('möngö', 'möngö')),
|
||||
'MOP': (('pataca', 'pataques'), ('avo', 'avos')),
|
||||
'MRO': (('ouguiya', 'ouguiya'), ('khoums', 'khoums')),
|
||||
'MRU': (('ouguiya', 'ouguiya'), ('khoums', 'khoums')),
|
||||
'MUR': (('rupia', 'rúpies'), ('cèntim', 'cèntims')),
|
||||
'MVR': (('rufiyaa', 'rufiyaa'), ('laari', 'laari')),
|
||||
'MWK': (('kwacha', 'kwacha'), ('tambala', 'tambala')),
|
||||
'MYR': (('ringgit', 'ringgits'), ('sen', 'sens')),
|
||||
'MZN': (('metical', 'meticals'), GENERIC_CENTS),
|
||||
'NAD': (GENERIC_DOLLARS, ('cèntim', 'cèntims')),
|
||||
'NGN': (('naira', 'naires'), ('kobo', 'kobos')),
|
||||
'NPR': (('rupia', 'rupies'), ('paisa', 'paises')),
|
||||
'NZD': (GENERIC_DOLLARS, GENERIC_CENTS),
|
||||
'OMR': (('rial', 'rials'), ('baisa', 'baisa')),
|
||||
'PAB': (GENERIC_DOLLARS, ('centésimo', 'centésimos')),
|
||||
'PGK': (('kina', 'kina'), ('toea', 'toea')),
|
||||
'PHP': (('peso', 'pesos'), GENERIC_CENTS),
|
||||
'PKR': (('rupia', 'rupies'), ('paisa', 'paise')),
|
||||
'PLZ': (('zloty', 'zlotys'), ('grosz', 'groszy')),
|
||||
'PYG': (('guaraní', 'guaranís'), ('cèntim', 'cèntims')),
|
||||
'QAR': (('rial', 'rials'), ('dírham', 'dírhams')),
|
||||
'QTQ': (('quetzal', 'quetzals'), GENERIC_CENTS),
|
||||
'RSD': (('dinar', 'dinars'), ('para', 'para')),
|
||||
'RUR': (('ruble', 'rubles'), ('copec', 'copecs')),
|
||||
'RWF': (('franc', 'francs'), ('cèntim', 'cèntims')),
|
||||
'SAR': (('riyal', 'riyals'), ('hàl·lala', 'hàl·lalat')),
|
||||
'SBD': (GENERIC_DOLLARS, ('cèntim', 'cèntims')),
|
||||
'SCR': (('rupia', 'rupies'), ('cèntim', 'cèntims')),
|
||||
'SDG': (('lliura', 'lliures'), ('piastre', 'piastres')),
|
||||
'SGD': (GENERIC_DOLLARS, ('cèntim', 'cèntims')),
|
||||
'SHP': (('lliura', 'lliures'), ('penic', 'penics')),
|
||||
'SLL': (('leonE', 'leones'), ('cèntim', 'cèntims')),
|
||||
'SRD': (GENERIC_DOLLARS, ('cèntim', 'cèntims')),
|
||||
'SSP': (('lliura', 'lliures'), ('piastre', 'piastres')),
|
||||
'STD': (('dobra', 'dobrAs'), ('cèntim', 'cèntims')),
|
||||
'SVC': (('colón', 'colons'), GENERIC_CENTS),
|
||||
'SYP': (('lliura', 'lliures'), ('piastre', 'piastres')),
|
||||
'SZL': (('lilangeni', 'emalangeni'), ('cèntim', 'cèntims')),
|
||||
'TJS': (('somoni', 'somoni'), ('diram', 'diram')),
|
||||
'TMT': (('manat', 'manats'), ('teňňesi', 'teňňesi')),
|
||||
'TND': (('dinar', 'dinars'), ('mil·lim', 'mil·limat')),
|
||||
'TOP': (('paanga', 'paangas'), ('seniti', 'seniti')),
|
||||
'TTD': (GENERIC_DOLLARS, ('cèntim', 'cèntims')),
|
||||
'TWD': (('nou dòlar', 'nous dòlars'), ('fen', 'fen')),
|
||||
'TZS': (('xíling', 'xílings'), ('cèntim', 'cèntims')),
|
||||
'UGX': (('xíling', 'xílings'), ('cèntim', 'cèntims')),
|
||||
'UYU': (('peso', 'pesos'), ('centèsim', 'centèsims')),
|
||||
'UZS': (('som', 'som'), ('tiyin', 'tiyin')),
|
||||
'VND': (('dong', 'dongs'), ('xu', 'xu')),
|
||||
'VUV': (('vatu', 'vatus'), ('cèntim', 'cèntims')),
|
||||
'WST': (('tala', 'tala'), ('sene', 'sene')),
|
||||
'XAF': (('franc CFA', 'francs CFA'), ('cèntim', 'cèntims')),
|
||||
'XCD': (GENERIC_DOLLARS, ('cèntim', 'cèntims')),
|
||||
'XOF': (('franc CFA', 'francs CFA'), ('cèntim', 'cèntims')),
|
||||
'XPF': (('franc CFP', 'francs CFP'), ('cèntim', 'cèntims')),
|
||||
'YER': (('rial', 'rials'), ('fils', 'fils')),
|
||||
'YUM': (('dinar', 'dinars'), ('para', 'para')),
|
||||
'ZMW': (('kwacha', 'kwacha'), ('ngwee', 'ngwee')),
|
||||
'ZWL': (GENERIC_DOLLARS, ('cèntim', 'cèntims')),
|
||||
'ZWL': (GENERIC_DOLLARS, ('cèntim', 'cèntims')),
|
||||
}
|
||||
|
||||
GIGA_SUFFIX = None
|
||||
MEGA_SUFFIX = "ilió"
|
||||
|
||||
def setup(self):
|
||||
lows = ["quadr", "tr", "b", "m"]
|
||||
self.high_numwords = self.gen_high_numwords([], [], lows)
|
||||
self.negword = "menys "
|
||||
self.pointword = "punt"
|
||||
self.errmsg_nonnum = "type(%s) no és [long, int, float]"
|
||||
self.errmsg_floatord = "El float %s no pot ser tractat com un" \
|
||||
" ordinal."
|
||||
self.errmsg_negord = "El número negatiu %s no pot ser tractat" \
|
||||
" com un ordinal."
|
||||
self.errmsg_toobig = "abs(%s) ha de ser inferior a %s."
|
||||
self.gender_stem = "è"
|
||||
self.exclude_title = ["i", "menys", "punt"]
|
||||
|
||||
self.mid_numwords = [
|
||||
(1000, "mil"),
|
||||
(100, "cent"),
|
||||
(90, "noranta"),
|
||||
(80, "vuitanta"),
|
||||
(70, "setanta"),
|
||||
(60, "seixanta"),
|
||||
(50, "cinquanta"),
|
||||
(40, "quaranta"),
|
||||
(30, "trenta"),
|
||||
]
|
||||
self.low_numwords = [
|
||||
"vint-i-nou",
|
||||
"vint-i-vuit",
|
||||
"vint-i-set",
|
||||
"vint-i-sis",
|
||||
"vint-i-cinc",
|
||||
"vint-i-quatre",
|
||||
"vint-i-tres",
|
||||
"vint-i-dos",
|
||||
"vint-i-un",
|
||||
"vint",
|
||||
"dinou",
|
||||
"divuit",
|
||||
"disset",
|
||||
"setze",
|
||||
"quinze",
|
||||
"catorze",
|
||||
"tretze",
|
||||
"dotze",
|
||||
"onze",
|
||||
"deu",
|
||||
"nou",
|
||||
"vuit",
|
||||
"set",
|
||||
"sis",
|
||||
"cinc",
|
||||
"quatre",
|
||||
"tres",
|
||||
"dos",
|
||||
"un",
|
||||
"zero",
|
||||
]
|
||||
self.mid_num = {
|
||||
1000: "mil",
|
||||
100: "cent",
|
||||
90: "noranta",
|
||||
80: "vuitanta",
|
||||
70: "setanta",
|
||||
60: "seixanta",
|
||||
50: "cinquanta",
|
||||
40: "quaranta",
|
||||
30: "trenta",
|
||||
20: "vint",
|
||||
10: "deu",
|
||||
}
|
||||
self.low_num = {
|
||||
0: "zero",
|
||||
1: "un",
|
||||
2: "dos",
|
||||
3: "tres",
|
||||
4: "quatre",
|
||||
5: "cinc",
|
||||
6: "sis",
|
||||
7: "set",
|
||||
8: "vuit",
|
||||
9: "nou",
|
||||
10: "deu",
|
||||
11: "onze",
|
||||
12: "dotze",
|
||||
13: "tretze",
|
||||
14: "catorze",
|
||||
15: "quinze",
|
||||
16: "setze",
|
||||
17: "disset",
|
||||
18: "divuit",
|
||||
19: "dinou",
|
||||
20: "vint",
|
||||
21: "vint-i-un",
|
||||
22: "vint-i-dos",
|
||||
23: "vint-i-tres",
|
||||
24: "vint-i-quatre",
|
||||
25: "vint-i-cinc",
|
||||
26: "vint-i-sis",
|
||||
27: "vint-i-set",
|
||||
28: "vint-i-vuit",
|
||||
29: "vint-i-nou",
|
||||
}
|
||||
self.ords = {
|
||||
1: "primer",
|
||||
2: "segon",
|
||||
3: "tercer",
|
||||
4: "quart",
|
||||
5: "cinqu",
|
||||
6: "sis",
|
||||
7: "set",
|
||||
8: "vuit",
|
||||
9: "nov",
|
||||
10: "des",
|
||||
11: "onz",
|
||||
12: "dotz",
|
||||
13: "tretz",
|
||||
14: "catorz",
|
||||
15: "quinz",
|
||||
16: "setz",
|
||||
17: "disset",
|
||||
18: "divuit",
|
||||
19: "dinov",
|
||||
20: "vint",
|
||||
30: "trent",
|
||||
40: "quarant",
|
||||
50: "cinquant",
|
||||
60: "seixant",
|
||||
70: "setant",
|
||||
80: "vuitant",
|
||||
90: "norant",
|
||||
100: "cent",
|
||||
200: "dos-cent",
|
||||
300: "tres-cent",
|
||||
400: "quatre-cent",
|
||||
500: "cinc-cent",
|
||||
600: "sis-cent",
|
||||
700: "set-cent",
|
||||
800: "vuit-cent",
|
||||
900: "nou-cent",
|
||||
1e3: "mil",
|
||||
1e6: "milion",
|
||||
1e9: "mil milion",
|
||||
1e12: "bilion",
|
||||
1e15: "mil bilion",
|
||||
}
|
||||
|
||||
self.ords_2 = {1: "1r", 2: "2n", 3: "3r", 4: "4t"}
|
||||
self.ords_3 = {
|
||||
1: "unè",
|
||||
2: "dosè",
|
||||
3: "tresè",
|
||||
4: "quatrè",
|
||||
5: "cinquè",
|
||||
6: "sisè",
|
||||
7: "setè",
|
||||
8: "vuitè",
|
||||
9: "novè",
|
||||
}
|
||||
|
||||
def merge(self, curr, next):
|
||||
ctext, cnum, ntext, nnum = curr + next
|
||||
if cnum == 1:
|
||||
if nnum < 1000000:
|
||||
return next
|
||||
ctext = "un"
|
||||
|
||||
if nnum < cnum:
|
||||
if cnum < 100:
|
||||
return "%s-%s" % (ctext, ntext), cnum + nnum
|
||||
elif nnum == 1:
|
||||
return "%s %s" % (ctext, ntext), cnum + nnum
|
||||
elif cnum == 100:
|
||||
return "%s %s" % (ctext, ntext), cnum + nnum
|
||||
else:
|
||||
return "%s %s" % (ctext, ntext), cnum + nnum
|
||||
elif (not nnum % 1000000) and cnum > 1:
|
||||
ntext = ntext[:-3] + "lions"
|
||||
if nnum == 100:
|
||||
ntext += "s"
|
||||
ctext += "-"
|
||||
else:
|
||||
ntext = " " + ntext
|
||||
return (ctext + ntext, cnum * nnum)
|
||||
|
||||
def to_ordinal(self, value):
|
||||
self.verify_ordinal(value)
|
||||
if value == 0:
|
||||
text = ""
|
||||
elif value < 5:
|
||||
text = self.ords[value]
|
||||
elif value <= 20:
|
||||
text = "%s%s" % (self.ords[value], self.gender_stem)
|
||||
elif value <= 30:
|
||||
frac = value % 10
|
||||
text = "%s%s%s" % (self.ords[20], "-i-", self.ords_3[frac])
|
||||
elif value < 100:
|
||||
dec = (value // 10) * 10
|
||||
text = "%s%s%s%s" % (self.ords[dec], "a",
|
||||
"-", self.ords_3[value - dec])
|
||||
elif value == 1e2:
|
||||
text = "%s%s" % (self.ords[value], self.gender_stem)
|
||||
elif value < 2e2:
|
||||
cen = (value // 100) * 100
|
||||
text = "%s %s" % (self.ords[cen], self.to_ordinal(value - cen))
|
||||
elif value < 1e3:
|
||||
cen = (value // 100) * 100
|
||||
text = "%s%s %s" % (self.ords[cen], "s",
|
||||
self.to_ordinal(value - cen))
|
||||
elif value == 1e3:
|
||||
text = "%s%s" % (self.ords[value], self.gender_stem)
|
||||
elif value < 1e6:
|
||||
dec = 1000 ** int(math.log(int(value), 1000))
|
||||
high_part, low_part = divmod(value, dec)
|
||||
cardinal = self.to_cardinal(high_part) if high_part != 1 else ""
|
||||
text = "%s %s %s" % (cardinal, self.ords[dec],
|
||||
self.to_ordinal(low_part))
|
||||
elif value < 1e18:
|
||||
dec = 1000 ** int(math.log(int(value), 1000))
|
||||
high_part, low_part = divmod(value, dec)
|
||||
cardinal = self.to_cardinal(high_part) if high_part != 1 else ""
|
||||
text = "%s%s%s %s" % (cardinal, self.ords[dec],
|
||||
self.gender_stem, self.to_ordinal(low_part))
|
||||
else:
|
||||
part1 = self.to_cardinal(value)
|
||||
text = "%s%s" % (part1[:-1], "onè")
|
||||
return text.strip()
|
||||
|
||||
def to_ordinal_num(self, value):
|
||||
self.verify_ordinal(value)
|
||||
if value not in self.ords_2:
|
||||
return "%s%s" % (value, "è" if self.gender_stem == "è" else "a")
|
||||
else:
|
||||
return self.ords_2[value]
|
||||
|
||||
def to_currency(self, val, currency="EUR", cents=True,
|
||||
separator=" amb", adjective=False):
|
||||
result = super(Num2Word_CA, self).to_currency(
|
||||
val, currency=currency, cents=cents,
|
||||
separator=separator, adjective=adjective
|
||||
)
|
||||
list_result = result.split(separator + " ")
|
||||
|
||||
if currency in CURRENCIES_UNA:
|
||||
list_result[0] = list_result[0].replace("un", "una")
|
||||
list_result[0] = list_result[0].replace("dos", "dues")
|
||||
list_result[0] = list_result[0].replace("cents", "centes")
|
||||
|
||||
list_result[0] = list_result[0].replace("vint-i-un", "vint-i-un")
|
||||
list_result[0] = list_result[0].replace(" i un", "-un")
|
||||
list_result[0] = list_result[0].replace("un", "un")
|
||||
|
||||
if currency in CENTS_UNA:
|
||||
list_result[1] = list_result[1].replace("un", "una")
|
||||
list_result[1] = list_result[1].replace("dos", "dues")
|
||||
|
||||
list_result[1] = list_result[1].replace("vint-i-un", "vint-i-una")
|
||||
|
||||
list_result[1] = list_result[1].replace("un", "un")
|
||||
|
||||
result = (separator + " ").join(list_result)
|
||||
|
||||
return result
|
||||
522
path/to/venv/lib/python3.12/site-packages/num2words/lang_CE.py
Normal file
522
path/to/venv/lib/python3.12/site-packages/num2words/lang_CE.py
Normal file
@@ -0,0 +1,522 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2023, Johannes Heinecke. 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 .currency import parse_currency_parts
|
||||
from .lang_EU import Num2Word_EU
|
||||
|
||||
# Chechen numbers inflect in case if without noun or
|
||||
# use a special oblique ending when followed by a counted noun
|
||||
# 4, 14, 40 and composites thereof agree in class (gender) with the
|
||||
# noun. Chechen has 6 classes which are indicated by the initial
|
||||
# letter of 4, 14 and 40. By default it is "д" but
|
||||
# it can also be "б", "й" or "в".
|
||||
# Indicate the needed class prefix as follows
|
||||
# num2words(4, lang='ce', case="abs", clazz="б")
|
||||
|
||||
|
||||
CARDINALS = {
|
||||
"casenames": {
|
||||
"abs": "Им.",
|
||||
"gen": "Род.",
|
||||
"dat": "Дат.",
|
||||
"erg": "Эрг;",
|
||||
"instr": "Твор.",
|
||||
"mat": "Вещ.",
|
||||
"comp": "Сравнит.",
|
||||
"all": "Местн.",
|
||||
},
|
||||
"casesuffix_cons": { # to be added to numerals with final consonant
|
||||
"gen": "аннан",
|
||||
"dat": "анна",
|
||||
"erg": "амма",
|
||||
"instr": "анца",
|
||||
"mat": "аннах",
|
||||
"comp": "аннал",
|
||||
"all": "анга",
|
||||
"obl": "ан",
|
||||
"ORD": "алгӀа",
|
||||
},
|
||||
"casesuffix_voc": { # to be added to numerals with final vowel
|
||||
"gen": "ннан",
|
||||
"dat": "нна",
|
||||
"erg": "мма",
|
||||
"instr": "нца",
|
||||
"mat": "ннах",
|
||||
"comp": "ннал",
|
||||
"all": "нга",
|
||||
"obl": "н",
|
||||
"ORD": "лгӀа",
|
||||
},
|
||||
0: {
|
||||
"attr": "ноль",
|
||||
"abs": "ноль",
|
||||
"gen": "нолан",
|
||||
"dat": "нолана",
|
||||
"erg": "ноло",
|
||||
"instr": "ноланца",
|
||||
"mat": "ноланах",
|
||||
"comp": "ноланал",
|
||||
"all": "ноланга",
|
||||
},
|
||||
1: {
|
||||
"attr": "цхьа", # in front of nouns in ABS
|
||||
"obl": "цхьана", # with nouns in other cases than ABS
|
||||
"abs": "цхьаъ",
|
||||
"gen": "цхьаннан",
|
||||
"dat": "цхьанна",
|
||||
"erg": "цхьамма",
|
||||
"instr": "цхьаьнца",
|
||||
"mat": "цхьаннах",
|
||||
"comp": "цхьаннал",
|
||||
"all": "цхаьнга",
|
||||
"ORD": "цхьалгӀа",
|
||||
},
|
||||
2: {
|
||||
"attr": "ши", # in front of 100, 1000
|
||||
"obl": "шина",
|
||||
"abs": "шиъ",
|
||||
"gen": "шиннан",
|
||||
"dat": "шинна",
|
||||
"erg": "шимма",
|
||||
"instr": "шинца",
|
||||
"mat": "шиннах",
|
||||
"comp": "шиннал",
|
||||
"all": "шинга",
|
||||
"ORD": "шолгӀа",
|
||||
},
|
||||
3: {
|
||||
"attr": "кхо",
|
||||
"obl": "кхона",
|
||||
"abs": "кхоъ",
|
||||
"gen": "кхааннан",
|
||||
"dat": "кхаанна",
|
||||
"erg": "кхаамма",
|
||||
"instr": "кхаанца",
|
||||
"mat": "кхааннах",
|
||||
"comp": "кхааннал",
|
||||
"all": "кхаанга",
|
||||
"ORD": "кхоалгӀа",
|
||||
},
|
||||
4: {
|
||||
"attr": "д*и",
|
||||
"obl": "д*еа",
|
||||
"abs": "д*иъ",
|
||||
"gen": "д*еаннан",
|
||||
"dat": "д*еанна",
|
||||
"erg": "д*еамма",
|
||||
"instr": "д*еанца",
|
||||
"mat": "д*еаннах",
|
||||
"comp": "д*еаннал",
|
||||
"all": "д*еанга",
|
||||
"ORD": "д*оьалгӀа",
|
||||
},
|
||||
5: {
|
||||
"attr": "пхи",
|
||||
"obl": "пхеа",
|
||||
"abs": "пхиъ",
|
||||
"gen": "пхеаннан",
|
||||
"dat": "пхеанна",
|
||||
"erg": "пхеамма",
|
||||
"instr": "нхеанца",
|
||||
"mat": "пхеаннах",
|
||||
"comp": "пхеаннал",
|
||||
"all": "пхеанга",
|
||||
"ORD": "пхоьалгӀа",
|
||||
},
|
||||
6: {
|
||||
"abs": "ялх",
|
||||
"attr": "ялх",
|
||||
"ORD": "йолхалгӀа",
|
||||
},
|
||||
7: {
|
||||
"abs": "ворхӀ",
|
||||
"attr": "ворхӀ",
|
||||
"ORD": "ворхӀалгӀа",
|
||||
},
|
||||
8: {
|
||||
"abs": "бархӀ",
|
||||
"attr": "бархӀ",
|
||||
"ORD": "борхӀалӀа",
|
||||
},
|
||||
9: {
|
||||
"abs": "исс",
|
||||
"attr": "исс",
|
||||
"ORD": "уьссалгӀа",
|
||||
},
|
||||
10: {
|
||||
"attr": "итт",
|
||||
"abs": "итт",
|
||||
"gen": "иттаннан",
|
||||
"dat": "иттанна",
|
||||
"erg": "иттамма",
|
||||
"instr": "иттанца",
|
||||
"mat": "иттаннах",
|
||||
"comp": "иттаннал",
|
||||
"all": "иттанга",
|
||||
"ORD": "уьтталгӀа",
|
||||
},
|
||||
11: {
|
||||
"abs": "цхьайтта",
|
||||
"attr": "цхьайтта",
|
||||
"ORD": "цхьайтталгӀа",
|
||||
},
|
||||
12: {
|
||||
"abs": "шийтта",
|
||||
"attr": "шийтта",
|
||||
"ORD": "шийтталга",
|
||||
},
|
||||
13: {
|
||||
"abs": "кхойтта",
|
||||
"attr": "кхойтта",
|
||||
"ORD": "кхойтталгӀа",
|
||||
},
|
||||
14: {
|
||||
"abs": "д*ейтта",
|
||||
"attr": "д*ейтта",
|
||||
"ORD": "д*ейтталгӀа",
|
||||
},
|
||||
15: {
|
||||
"abs": "пхийтта",
|
||||
"attr": "пхийтта",
|
||||
"ORD": "пхийтталгӀа",
|
||||
},
|
||||
16: {
|
||||
"abs": "ялхитта",
|
||||
"attr": "ялхитта",
|
||||
"ORD": "ялхитталгӀа",
|
||||
},
|
||||
17: {
|
||||
"abs": "вуьрхӀитта",
|
||||
"attr": "вуьрхӀитта",
|
||||
"ORD": "вуьрхӀитталгӀа",
|
||||
},
|
||||
18: {
|
||||
"abs": "берхӀитта",
|
||||
"attr": "берхӀитта",
|
||||
"ORD": "берхитталӀа",
|
||||
},
|
||||
19: {
|
||||
"abs": "ткъайесна",
|
||||
"attr": "ткъайесна",
|
||||
"ORD": "ткъаесналгӀа",
|
||||
},
|
||||
20: {
|
||||
"abs": "ткъа",
|
||||
"gen": "ткъаннан",
|
||||
"dat": "ткъанна",
|
||||
"erg": "ткъамма",
|
||||
"instr": "ткъанца",
|
||||
"mat": "ткъаннах",
|
||||
"comp": "ткъаннал",
|
||||
"all": "ткъанга",
|
||||
"attr": "ткъе",
|
||||
"ORD": "ткъолгӀа",
|
||||
},
|
||||
40: {
|
||||
"abs": "шовзткъа",
|
||||
"attr": "шовзткъе",
|
||||
"ORD": "шовзткъалгІа",
|
||||
},
|
||||
60: {
|
||||
"abs": "кхузткъа",
|
||||
"attr": "кхузткъе",
|
||||
"ORD": "кхузткъалгІа",
|
||||
},
|
||||
80: {
|
||||
"abs": "дезткъа",
|
||||
"attr": "дезткъе",
|
||||
"ORD": "дезткъалгІа",
|
||||
},
|
||||
100: {
|
||||
"attr": "бӀе",
|
||||
"abs": "бӀе",
|
||||
"obl": "бӀен",
|
||||
"gen": "бӀеннан",
|
||||
"dat": "бӀенна",
|
||||
"erg": "бӀемма",
|
||||
"instr": "бӀенца",
|
||||
"mat": "бӀеннах",
|
||||
"comp": "бӀеннал",
|
||||
"all": "бӀенга",
|
||||
"ORD": "бІолгІа",
|
||||
},
|
||||
1000: {
|
||||
"attr": "эзар",
|
||||
"abs": "эзар",
|
||||
"obl": "эзаран",
|
||||
"gen": "эзарнан",
|
||||
"dat": "эзарна",
|
||||
"erg": "эзарно",
|
||||
"instr": "эзарнаца",
|
||||
"mat": "эзарнах",
|
||||
"comp": "эзарнал",
|
||||
"all": "эзаранга",
|
||||
"ORD": "эзарлагІа",
|
||||
},
|
||||
1000000: {
|
||||
"attr": "миллион",
|
||||
"abs": "миллион",
|
||||
"ORD": "миллионалгІа",
|
||||
},
|
||||
}
|
||||
|
||||
ILLIONS = {
|
||||
6: {
|
||||
"attr": "миллион",
|
||||
"abs": "миллион",
|
||||
"ORD": "миллионалгІа",
|
||||
},
|
||||
9: {
|
||||
"attr": "миллиард",
|
||||
"abs": "миллиард",
|
||||
"ORD": "миллиардалгІа",
|
||||
},
|
||||
12: {
|
||||
"attr": "биллион",
|
||||
"abs": "биллион",
|
||||
"ORD": "биллионалгІа",
|
||||
},
|
||||
15: {
|
||||
"attr": "биллиард",
|
||||
"abs": "биллиард",
|
||||
"ORD": "биллиардалгІа",
|
||||
},
|
||||
18: {
|
||||
"attr": "триллион",
|
||||
"abs": "триллион",
|
||||
"ORD": "триллионалгІа",
|
||||
},
|
||||
21: {
|
||||
"attr": "триллиард",
|
||||
"abs": "триллиард",
|
||||
"ORD": "триллиардалгІа",
|
||||
},
|
||||
24: {
|
||||
"attr": "квадриллион",
|
||||
"abs": "квадриллион",
|
||||
"ORD": "квадриллионалгІа",
|
||||
},
|
||||
27: {
|
||||
"attr": "квадриллиард",
|
||||
"abs": "квадриллиард",
|
||||
"ORD": "квадриллиардалгІа",
|
||||
},
|
||||
30: {
|
||||
"attr": "квинтиллион",
|
||||
"abs": "квинтиллион",
|
||||
"ORD": "квинтиллионалгІа",
|
||||
},
|
||||
33: {
|
||||
"attr": "квинтиллиард",
|
||||
"abs": "квинтиллиард",
|
||||
"ORD": "квинтиллиардалгІа",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
MINUS = "минус"
|
||||
# DECIMALPOINT = "запятая" # check !
|
||||
DECIMALPOINT = "а"
|
||||
|
||||
|
||||
class Num2Word_CE(Num2Word_EU):
|
||||
CURRENCY_FORMS = {
|
||||
# currency code: (sg, pl), (sg, pl)
|
||||
"EUR": (("Евро", "Евро"), ("Сент", "Сенташ")),
|
||||
"RUB": (("Сом", "Сомаш"), ("Кепек", "Кепекаш")),
|
||||
"USD": (("Доллар", "Доллараш"), ("Сент", "Сенташ")),
|
||||
"GBP": (("Фунт", "Фунташ"), ("Пенни", "Пенни")),
|
||||
}
|
||||
|
||||
def setup(self):
|
||||
Num2Word_EU.setup(self)
|
||||
self.negword = "минус"
|
||||
self.pointword = "запятая" # check !
|
||||
# self.errmsg_nonnum = (
|
||||
# u"Seulement des nombres peuvent être convertis en mots."
|
||||
# )
|
||||
# self.errmsg_toobig = (
|
||||
# u"Nombre trop grand pour être converti en mots (abs(%s) > %s)."
|
||||
# )
|
||||
# self.exclude_title = ["et", "virgule", "moins"]
|
||||
self.mid_numwords = []
|
||||
self.low_numwords = []
|
||||
self.ords = {}
|
||||
|
||||
def to_ordinal(self, number, clazz="д"):
|
||||
# implement here your code. number is the integer to
|
||||
# be transformed into an ordinal as a word (str)
|
||||
# which is returned
|
||||
return self.to_cardinal(number, clazz=clazz, case="ORD")
|
||||
|
||||
def to_cardinal(self, number, clazz="д", case="abs"):
|
||||
if isinstance(number, float):
|
||||
entires = self.to_cardinal(int(number))
|
||||
float_part = str(number).split(".")[1]
|
||||
postfix = " ".join(
|
||||
# Drops the trailing zero and comma
|
||||
[self.to_cardinal(int(c)) for c in float_part]
|
||||
)
|
||||
return entires + " " + DECIMALPOINT + " " + postfix
|
||||
|
||||
elif number < 20:
|
||||
return self.makecase(number, case, clazz)
|
||||
elif number < 100:
|
||||
twens = number // 20
|
||||
units = number % 20
|
||||
base = twens * 20
|
||||
if units == 0:
|
||||
return self.makecase(number, case, clazz)
|
||||
else:
|
||||
twenties = self.makecase(base, "attr", clazz)
|
||||
rest = self.to_cardinal(units, clazz=clazz, case=case)
|
||||
return twenties + " " + rest.replace("д*", clazz)
|
||||
elif number < 1000:
|
||||
hundreds = number // 100
|
||||
tens = number % 100
|
||||
if hundreds > 1:
|
||||
hundert = (
|
||||
CARDINALS[hundreds]["attr"].replace("д*", clazz) + " "
|
||||
)
|
||||
else:
|
||||
hundert = ""
|
||||
if tens != 0:
|
||||
rest = self.to_cardinal(tens, clazz=clazz, case=case)
|
||||
return hundert + CARDINALS[100]["abs"] + " " + rest
|
||||
else:
|
||||
return hundert + self.makecase(100, case, clazz)
|
||||
elif number < 1000000:
|
||||
thousands = number // 1000
|
||||
hundert = number % 1000
|
||||
if hundert > 0:
|
||||
tcase = "attr"
|
||||
else:
|
||||
tcase = case
|
||||
if thousands > 1:
|
||||
tausend = (
|
||||
self.to_cardinal(thousands, clazz=clazz, case="attr")
|
||||
+ " "
|
||||
+ CARDINALS[1000][tcase]
|
||||
)
|
||||
else:
|
||||
tausend = self.makecase(1000, tcase, clazz)
|
||||
|
||||
if hundert != 0:
|
||||
rest = " " + self.to_cardinal(hundert, clazz=clazz, case=case)
|
||||
else:
|
||||
rest = ""
|
||||
return tausend + rest
|
||||
|
||||
elif number < 10**34:
|
||||
out = []
|
||||
for pot in reversed([6, 9, 12, 15, 18, 21, 24, 27, 30, 33]):
|
||||
# 3 digits of billion, trillion etc
|
||||
step = number // 10**pot % 1000
|
||||
if step > 0:
|
||||
words = self.to_cardinal(step, clazz=clazz, case="attr")
|
||||
out.append(words + " " + ILLIONS[pot]["attr"])
|
||||
rest = number % 10**6
|
||||
if rest:
|
||||
out.append(self.to_cardinal(rest, clazz=clazz, case=case))
|
||||
return " ".join(out)
|
||||
|
||||
return "NOT IMPLEMENTED"
|
||||
|
||||
def _money_verbose(self, number, currency, case):
|
||||
mcase = "attr"
|
||||
if case != "abs":
|
||||
mcase = "obl"
|
||||
return self.to_cardinal(number, case=mcase)
|
||||
|
||||
def _cents_verbose(self, number, currency, case):
|
||||
mcase = "attr"
|
||||
if case != "abs":
|
||||
mcase = "obl"
|
||||
return self.to_cardinal(number, case=mcase)
|
||||
|
||||
def to_currency(
|
||||
self,
|
||||
val,
|
||||
currency="RUB",
|
||||
cents=True,
|
||||
separator=",",
|
||||
adjective=False,
|
||||
case="abs",
|
||||
):
|
||||
"""
|
||||
Args:
|
||||
val: Numeric value
|
||||
currency (str): Currency code
|
||||
cents (bool): Verbose cents
|
||||
separator (str): Cent separator
|
||||
adjective (bool): Prefix currency name with adjective
|
||||
Returns:
|
||||
str: Formatted string
|
||||
|
||||
"""
|
||||
left, right, is_negative = parse_currency_parts(val)
|
||||
|
||||
try:
|
||||
cr1, cr2 = self.CURRENCY_FORMS[currency]
|
||||
devise = cr1[0]
|
||||
centime = cr2[0]
|
||||
except KeyError:
|
||||
raise NotImplementedError(
|
||||
'Currency code "%s" not implemented for "%s"'
|
||||
% (currency, self.__class__.__name__)
|
||||
)
|
||||
|
||||
minus_str = "%s " % self.negword.strip() if is_negative else ""
|
||||
money_str = self._money_verbose(left, currency, case)
|
||||
cents_str = (
|
||||
self._cents_verbose(right, currency, case)
|
||||
if cents
|
||||
else self._cents_terse(right, currency)
|
||||
)
|
||||
|
||||
return "%s%s %s%s %s %s" % (
|
||||
minus_str,
|
||||
money_str,
|
||||
devise, # always singular
|
||||
separator,
|
||||
cents_str,
|
||||
centime,
|
||||
)
|
||||
|
||||
def to_ordinal_num(self, number):
|
||||
self.verify_ordinal(number)
|
||||
return str(number) + "-й"
|
||||
|
||||
def to_year(self, year, case="abs"):
|
||||
return self.to_cardinal(year, case=case)
|
||||
|
||||
def makecase(self, number, case, clazz):
|
||||
# print("ZZZZ", number, CARDINALS[number])
|
||||
if case in CARDINALS[number]:
|
||||
return CARDINALS[number][case].replace("д*", clazz)
|
||||
else:
|
||||
if CARDINALS[number]["abs"][-1] in "а":
|
||||
return (
|
||||
CARDINALS[number]["abs"].replace("д*", clazz)
|
||||
+ CARDINALS["casesuffix_voc"][case]
|
||||
)
|
||||
else:
|
||||
return (
|
||||
CARDINALS[number]["abs"].replace("д*", clazz)
|
||||
+ CARDINALS["casesuffix_cons"][case]
|
||||
)
|
||||
157
path/to/venv/lib/python3.12/site-packages/num2words/lang_CS.py
Normal file
157
path/to/venv/lib/python3.12/site-packages/num2words/lang_CS.py
Normal file
@@ -0,0 +1,157 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
||||
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from .base import Num2Word_Base
|
||||
from .utils import get_digits, splitbyx
|
||||
|
||||
ZERO = ('nula',)
|
||||
|
||||
ONES = {
|
||||
1: ('jedna',),
|
||||
2: ('dva',),
|
||||
3: ('tři',),
|
||||
4: ('čtyři',),
|
||||
5: ('pět',),
|
||||
6: ('šest',),
|
||||
7: ('sedm',),
|
||||
8: ('osm',),
|
||||
9: ('devět',),
|
||||
}
|
||||
|
||||
TENS = {
|
||||
0: ('deset',),
|
||||
1: ('jedenáct',),
|
||||
2: ('dvanáct',),
|
||||
3: ('třináct',),
|
||||
4: ('čtrnáct',),
|
||||
5: ('patnáct',),
|
||||
6: ('šestnáct',),
|
||||
7: ('sedmnáct',),
|
||||
8: ('osmnáct',),
|
||||
9: ('devatenáct',),
|
||||
}
|
||||
|
||||
TWENTIES = {
|
||||
2: ('dvacet',),
|
||||
3: ('třicet',),
|
||||
4: ('čtyřicet',),
|
||||
5: ('padesát',),
|
||||
6: ('šedesát',),
|
||||
7: ('sedmdesát',),
|
||||
8: ('osmdesát',),
|
||||
9: ('devadesát',),
|
||||
}
|
||||
|
||||
HUNDREDS = {
|
||||
1: ('sto',),
|
||||
2: ('dvěstě',),
|
||||
3: ('třista',),
|
||||
4: ('čtyřista',),
|
||||
5: ('pětset',),
|
||||
6: ('šestset',),
|
||||
7: ('sedmset',),
|
||||
8: ('osmset',),
|
||||
9: ('devětset',),
|
||||
}
|
||||
|
||||
THOUSANDS = {
|
||||
1: ('tisíc', 'tisíce', 'tisíc'), # 10^3
|
||||
2: ('milion', 'miliony', 'milionů'), # 10^6
|
||||
3: ('miliarda', 'miliardy', 'miliard'), # 10^9
|
||||
4: ('bilion', 'biliony', 'bilionů'), # 10^12
|
||||
5: ('biliarda', 'biliardy', 'biliard'), # 10^15
|
||||
6: ('trilion', 'triliony', 'trilionů'), # 10^18
|
||||
7: ('triliarda', 'triliardy', 'triliard'), # 10^21
|
||||
8: ('kvadrilion', 'kvadriliony', 'kvadrilionů'), # 10^24
|
||||
9: ('kvadriliarda', 'kvadriliardy', 'kvadriliard'), # 10^27
|
||||
10: ('quintillion', 'quintilliony', 'quintillionů'), # 10^30
|
||||
}
|
||||
|
||||
|
||||
class Num2Word_CS(Num2Word_Base):
|
||||
CURRENCY_FORMS = {
|
||||
'CZK': (
|
||||
('koruna', 'koruny', 'korun'), ('halíř', 'halíře', 'haléřů')
|
||||
),
|
||||
'EUR': (
|
||||
('euro', 'euro', 'euro'), ('cent', 'centy', 'centů')
|
||||
),
|
||||
}
|
||||
|
||||
def setup(self):
|
||||
self.negword = "mínus"
|
||||
self.pointword = "celá"
|
||||
|
||||
def to_cardinal(self, number):
|
||||
n = str(number).replace(',', '.')
|
||||
if '.' in n:
|
||||
left, right = n.split('.')
|
||||
leading_zero_count = len(right) - len(right.lstrip('0'))
|
||||
decimal_part = ((ZERO[0] + ' ') * leading_zero_count +
|
||||
self._int2word(int(right)))
|
||||
return u'%s %s %s' % (
|
||||
self._int2word(int(left)),
|
||||
self.pointword,
|
||||
decimal_part
|
||||
)
|
||||
else:
|
||||
return self._int2word(int(n))
|
||||
|
||||
def pluralize(self, n, forms):
|
||||
if n == 1:
|
||||
form = 0
|
||||
elif 5 > n % 10 > 1 and (n % 100 < 10 or n % 100 > 20):
|
||||
form = 1
|
||||
else:
|
||||
form = 2
|
||||
return forms[form]
|
||||
|
||||
def to_ordinal(self, number):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _int2word(self, n):
|
||||
if n == 0:
|
||||
return ZERO[0]
|
||||
|
||||
words = []
|
||||
chunks = list(splitbyx(str(n), 3))
|
||||
i = len(chunks)
|
||||
for x in chunks:
|
||||
i -= 1
|
||||
|
||||
if x == 0:
|
||||
continue
|
||||
|
||||
n1, n2, n3 = get_digits(x)
|
||||
|
||||
if n3 > 0:
|
||||
words.append(HUNDREDS[n3][0])
|
||||
|
||||
if n2 > 1:
|
||||
words.append(TWENTIES[n2][0])
|
||||
|
||||
if n2 == 1:
|
||||
words.append(TENS[n1][0])
|
||||
elif n1 > 0 and not (i > 0 and x == 1):
|
||||
words.append(ONES[n1][0])
|
||||
|
||||
if i > 0:
|
||||
words.append(self.pluralize(x, THOUSANDS[i]))
|
||||
|
||||
return ' '.join(words)
|
||||
607
path/to/venv/lib/python3.12/site-packages/num2words/lang_CY.py
Normal file
607
path/to/venv/lib/python3.12/site-packages/num2words/lang_CY.py
Normal file
@@ -0,0 +1,607 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2023, Johannes Heinecke. 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 .currency import parse_currency_parts
|
||||
from .lang_EU import Num2Word_EU
|
||||
|
||||
# Welsh numerals differs to many other languages since the counted
|
||||
# object does not follow the numeral but is inserted between
|
||||
# e.g. "23 hours" is
|
||||
# tri awr ar hugain
|
||||
# 3 hour on twenty
|
||||
# in addition to that some numeral trigger a mutation on the following word
|
||||
# either another numeral or the counted object
|
||||
# (https://en.wikipedia.org/wiki/Consonant_mutation#Welsh)
|
||||
# e.g. "23 dogs" (aspirated mutation, c -> ch)
|
||||
# tri chi ar hugain
|
||||
# 3 dog on twenty
|
||||
# but "22 dogs" (soft mutation, c -> g)
|
||||
# dau gi ar hugain
|
||||
# 2 dog on twenty
|
||||
# and "24 dogs" (no mutation)
|
||||
# pedwar ci ar hugain
|
||||
# 4 dog on twenty
|
||||
# (BTW, the counted word is always in singular when following a numeral)
|
||||
# numerals are mutated as well
|
||||
# e.g. "300"
|
||||
# tri chant
|
||||
# 3 hundred
|
||||
# "200"
|
||||
# dau gant
|
||||
# 2 hundred
|
||||
# "500"
|
||||
# pump cant
|
||||
# 5 hundreds
|
||||
# the numerals for 2, 3 and 4 are different in function of gender (MASC, FEM)
|
||||
# 2 cats
|
||||
# dwy gath
|
||||
|
||||
# 2 dogs
|
||||
# dau gi
|
||||
|
||||
# 2000
|
||||
# dwy fil
|
||||
|
||||
# 3000
|
||||
# tair mil
|
||||
|
||||
# to add the counted object in the correct position use
|
||||
# num2words(17, lang="cy", counted="ci", gender="masc")
|
||||
# num2words(17, lang="cy", counted="cath", gender="fem")
|
||||
# if the number is > 99, use plural form of counted object
|
||||
# num2words(117, lang="cy", counted="cathod", gender="fem")
|
||||
|
||||
|
||||
# Globals
|
||||
# -------
|
||||
|
||||
OBJ = "__OBJECT__"
|
||||
|
||||
CARDINAL_WORDS = {
|
||||
# masc, fem, triggers mutation
|
||||
0: [("dim", None), (OBJ, None)],
|
||||
1: [("un", None), (OBJ, None)],
|
||||
2: [("dau", "SM"), (OBJ, None)],
|
||||
3: [("tri", "AM"), (OBJ, None)],
|
||||
4: [("pedwar", None), (OBJ, None)],
|
||||
5: [("pump", None), (OBJ, None)],
|
||||
6: [("chwech", "AM"), (OBJ, None)],
|
||||
7: [("saith", None), (OBJ, None)],
|
||||
8: [("wyth", None), (OBJ, None)],
|
||||
9: [("naw", None), (OBJ, None)],
|
||||
10: [("deg", None), (OBJ, None)],
|
||||
11: [("un", None), (OBJ, None), ("ar ddeg", None)],
|
||||
12: [("deuddeg", None), (OBJ, None)],
|
||||
13: [("tri", "AM"), (OBJ, None), ("ar ddeg", None)],
|
||||
14: [("pedwar", None), (OBJ, None), ("ar ddeg", None)],
|
||||
15: [("pymtheg", None), (OBJ, None)],
|
||||
16: [("un", None), (OBJ, None), ("ar bymtheg", None)],
|
||||
17: [("dau", "SM"), (OBJ, None), ("ar bymtheg", None)],
|
||||
18: [("deunaw", None), (OBJ, None)],
|
||||
19: [("pedwar", None), ("ar bymtheg", None)],
|
||||
}
|
||||
|
||||
CARDINAL_WORDS_FEM = {
|
||||
# masc, fem, triggers mutation
|
||||
0: [("dim", None), (OBJ, None)],
|
||||
1: [("un", None), (OBJ, None)],
|
||||
2: [("dwy", "SM"), (OBJ, None)],
|
||||
3: [("tair", None), (OBJ, None)],
|
||||
4: [("pedair", None), (OBJ, None)],
|
||||
5: [("pump", None), (OBJ, None)],
|
||||
6: [("chwech", "AM"), (OBJ, None)],
|
||||
7: [("saith", None), (OBJ, None)],
|
||||
8: [("wyth", None), (OBJ, None)],
|
||||
9: [("naw", None), (OBJ, None)],
|
||||
10: [("deg", None), (OBJ, None)],
|
||||
11: [("un", None), (OBJ, None), ("ar ddeg", None)],
|
||||
12: [("deuddeg", None), (OBJ, None)],
|
||||
13: [("tair", None), (OBJ, None), ("ar ddeg", None)],
|
||||
14: [("pedair", None), (OBJ, None), ("ar ddeg", None)],
|
||||
15: [("pymtheg", None), (OBJ, None)],
|
||||
16: [("un", None), (OBJ, None), ("ar bymtheg", None)],
|
||||
17: [("dwy", "SM"), (OBJ, None), ("ar bymtheg", None)],
|
||||
18: [("deunaw", None), (OBJ, None)],
|
||||
19: [("pedair", None), ("ar bymtheg", None)],
|
||||
}
|
||||
|
||||
MILLION_WORDS = {
|
||||
3: ("mil", None),
|
||||
6: ("miliwn", None),
|
||||
9: ("biliwn", None),
|
||||
12: ("triliwn", None),
|
||||
15: ("cwadriliwn", None),
|
||||
18: ("cwintiliwn", None),
|
||||
21: ("secsttiliwn", None),
|
||||
24: ("septiliwn", None),
|
||||
27: ("octiliwn", None),
|
||||
30: ("noniliwn", None),
|
||||
33: ("dengiliwn", None),
|
||||
}
|
||||
|
||||
ORDINAL_WORDS = {
|
||||
0: [("dimfed", None), (OBJ, None)],
|
||||
1: [(OBJ, None), ("cyntaf", None)],
|
||||
2: [("ail", "SM"), (OBJ, None)],
|
||||
3: [("trydydd", None), (OBJ, None)],
|
||||
4: [("pedwerydd", None), (OBJ, None)],
|
||||
5: [("pumed", None), (OBJ, None)],
|
||||
6: [("chweched", None), (OBJ, None)],
|
||||
7: [("saithfed", None), (OBJ, None)],
|
||||
8: [("wythfed", None), (OBJ, None)],
|
||||
9: [("nawfed", None), (OBJ, None)],
|
||||
10: [("degfed", None), (OBJ, None)],
|
||||
11: [("unfed", "SM"), (OBJ, None), ("ar ddeg", None)],
|
||||
12: [("deuddegfed", None), (OBJ, None)],
|
||||
13: [("trydydd", None), (OBJ, None), ("ar ddeg", None)],
|
||||
14: [("pedwerydd", None), (OBJ, None), ("ar ddeg", None)],
|
||||
15: [("pymthegfed", None), (OBJ, None)],
|
||||
16: [("unfed", None), (OBJ, None), ("ar bymtheg", None)],
|
||||
17: [("ail", "SM"), (OBJ, None), ("ar bymtheg", None)],
|
||||
18: [("deunawfed", None), (OBJ, None)],
|
||||
19: [("pedwerydd", None), (OBJ, None), ("ar bymtheg", None)],
|
||||
}
|
||||
ORDINAL_WORDS_FEM = {
|
||||
0: [("dimfed", None), (OBJ, None)],
|
||||
1: [(OBJ, None), ("gyntaf", None)],
|
||||
2: [("ail", "SM"), (OBJ, None)],
|
||||
3: [("trydedd", "SM"), (OBJ, None)],
|
||||
4: [("pedwaredd", "SM"), (OBJ, None)],
|
||||
5: [("pumed", None), (OBJ, None)],
|
||||
6: [("chweched", None), (OBJ, None)],
|
||||
7: [("saithfed", None), (OBJ, None)],
|
||||
8: [("wythfed", None), (OBJ, None)],
|
||||
9: [("nawfed", None), (OBJ, None)],
|
||||
10: [("degfed", None), (OBJ, None)],
|
||||
11: [("unfed", "SM"), (OBJ, None), ("ar ddeg", None)],
|
||||
12: [("deuddegfed", None), (OBJ, None)],
|
||||
13: [("trydedd", "SM"), (OBJ, None), ("ar ddeg", None)],
|
||||
14: [("pedwaredd", "SM"), (OBJ, None), ("ar ddeg", None)],
|
||||
15: [("pymthegfed", None), (OBJ, None)],
|
||||
16: [("unfed", None), (OBJ, None), ("ar bymtheg", None)],
|
||||
17: [("ail", "SM"), (OBJ, None), ("ar bymtheg", None)],
|
||||
18: [("deunawfed", None), (OBJ, None)],
|
||||
19: [("pedwaredd", None), (OBJ, None), ("ar bymtheg", None)],
|
||||
}
|
||||
|
||||
# The script can extrapolate the missing numbers from the base forms.
|
||||
STR_TENS = {
|
||||
1: [("ugain", None), (OBJ, None)],
|
||||
2: [("deugain", None), (OBJ, None)],
|
||||
3: [("trigain", None), (OBJ, None)],
|
||||
4: [("pedwar ugain", None), (OBJ, None)],
|
||||
}
|
||||
|
||||
ORD_STR_TENS = {
|
||||
1: [("ugainfed", None), (OBJ, None)],
|
||||
2: [("deugainfed", None), (OBJ, None)],
|
||||
3: [("trigainfed", None), (OBJ, None)],
|
||||
4: [("pedwar ugainfed", None), (OBJ, None)],
|
||||
}
|
||||
|
||||
STR_TENS_INFORMAL = {
|
||||
1: ("undeg", None),
|
||||
2: ("dauddeg", None),
|
||||
3: ("trideg", None),
|
||||
4: ("pedwardeg", None),
|
||||
5: ("pumdeg", None),
|
||||
6: ("chwedeg", None),
|
||||
7: ("saithdeg", None),
|
||||
8: ("wythdeg", None),
|
||||
9: ("nawdeg", None),
|
||||
}
|
||||
|
||||
|
||||
GENERIC_DOLLARS = ("dolar", "dolarau")
|
||||
GENERIC_CENTS = ("ceiniog", "ceiniogau")
|
||||
|
||||
CURRENCIES_FEM = ["GBP"]
|
||||
|
||||
|
||||
class Num2Word_CY(Num2Word_EU):
|
||||
CURRENCY_FORMS = {
|
||||
# currency code: (sg, pl), (sg, pl)
|
||||
# in Welsh a noun after a numeral is ALWAYS in the singular
|
||||
"EUR": (("euro", "euros"), GENERIC_CENTS),
|
||||
"USD": (GENERIC_DOLLARS, GENERIC_CENTS),
|
||||
"GBP": (("punt", "punnoedd"), ("ceiniog", "ceiniogau")),
|
||||
"CNY": (("yuan", "yuans"), ("ffen", "ffens")),
|
||||
}
|
||||
|
||||
MINUS_PREFIX_WORD = "meinws "
|
||||
FLOAT_INFIX_WORD = " pwynt "
|
||||
|
||||
# def setup(self):
|
||||
# Num2Word_EU.setup(self)
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def float_to_words(self, float_number):
|
||||
# if ordinal:
|
||||
# prefix = self.to_ordinal(int(float_number))
|
||||
# else:
|
||||
prefix = self.to_cardinal(int(float_number))
|
||||
float_part = str(float_number).split(".")[1]
|
||||
postfix = " ".join(
|
||||
# Drops the trailing zero and comma
|
||||
[self.to_cardinal(int(c)) for c in float_part]
|
||||
)
|
||||
return prefix + Num2Word_CY.FLOAT_INFIX_WORD + postfix
|
||||
|
||||
def hundred_group(
|
||||
self, number, informal=False, gender="masc", ordinal=False
|
||||
):
|
||||
hundreds = number // 100
|
||||
until100 = number % 100 # 0 - 99
|
||||
# list group of number words and mutation info (for the following word)
|
||||
result = (
|
||||
[]
|
||||
)
|
||||
if gender == "fem":
|
||||
CW = CARDINAL_WORDS_FEM
|
||||
else:
|
||||
if ordinal:
|
||||
CW = ORDINAL_WORDS
|
||||
else:
|
||||
CW = CARDINAL_WORDS
|
||||
|
||||
if hundreds > 0:
|
||||
if hundreds > 1:
|
||||
result.extend((CARDINAL_WORDS[hundreds]))
|
||||
result.extend([("cant", None), (OBJ, None)])
|
||||
if until100:
|
||||
if until100 in [
|
||||
1,
|
||||
8,
|
||||
11,
|
||||
16,
|
||||
20,
|
||||
21,
|
||||
31,
|
||||
36,
|
||||
41,
|
||||
48,
|
||||
61,
|
||||
68,
|
||||
71,
|
||||
81,
|
||||
88,
|
||||
91,
|
||||
]:
|
||||
result.append(("ac", None))
|
||||
else:
|
||||
result.append(("a", "AM"))
|
||||
if until100:
|
||||
# if informal:
|
||||
# pass
|
||||
if not ordinal and until100 >= 50 and until100 <= 59:
|
||||
units = number % 10
|
||||
if hundreds > 0:
|
||||
if units == 0:
|
||||
result.append(("hanner", None))
|
||||
elif units == 1:
|
||||
result.extend([("hanner ac un", None), (OBJ, None)])
|
||||
else:
|
||||
result.append(("hanner a", "AM"))
|
||||
result.extend(CW[units])
|
||||
else:
|
||||
if units == 0:
|
||||
result.extend([("hanner cant", None), (OBJ, None)])
|
||||
elif units == 1:
|
||||
result.extend(
|
||||
[("hanner cant ac un", None), (OBJ, None)]
|
||||
)
|
||||
else:
|
||||
result.append(("hanner cant a", "AM"))
|
||||
result.extend(CW[units])
|
||||
else:
|
||||
if (number < 20 and number > 0) or (
|
||||
number == 0 and hundreds == 0
|
||||
):
|
||||
if gender == "fem":
|
||||
result.extend(CARDINAL_WORDS_FEM[int(number)])
|
||||
else:
|
||||
result.extend(CARDINAL_WORDS[int(number)])
|
||||
|
||||
else:
|
||||
tens = until100 // 20
|
||||
units = number % 20
|
||||
if ordinal and units == 0:
|
||||
degau = ORD_STR_TENS.get(tens)
|
||||
else:
|
||||
degau = STR_TENS.get(tens)
|
||||
|
||||
if units != 0:
|
||||
if tens > 1:
|
||||
result.extend(CW[units])
|
||||
if degau:
|
||||
result.append(("a", "AM"))
|
||||
result.extend(degau)
|
||||
else:
|
||||
result.extend(CW[units])
|
||||
if degau:
|
||||
result.append(("ar", "SM"))
|
||||
result.extend(degau)
|
||||
elif degau:
|
||||
result.extend(degau)
|
||||
return result
|
||||
|
||||
def to_ordinal(self, number, informal=False, gender="masc"):
|
||||
if number < 20:
|
||||
return makestring(ORDINAL_WORDS[number])
|
||||
if number == 100:
|
||||
return "canfed"
|
||||
elif number > 100:
|
||||
raise NotImplementedError("The given number is too large.")
|
||||
|
||||
return self.to_cardinal(
|
||||
number, informal=False, gender=gender, ordinal=True
|
||||
)
|
||||
|
||||
def to_cardinal(
|
||||
self,
|
||||
number,
|
||||
informal=False,
|
||||
gender="masc",
|
||||
ordinal=False,
|
||||
counted=None,
|
||||
raw=False,
|
||||
):
|
||||
negative = False
|
||||
if number < 0:
|
||||
negative = True
|
||||
number = -1 * number
|
||||
if number == 0:
|
||||
if raw:
|
||||
return CARDINAL_WORDS[0]
|
||||
else:
|
||||
return makestring(CARDINAL_WORDS[0])
|
||||
elif not number < 999 * 10**33:
|
||||
raise NotImplementedError("The given number is too large.")
|
||||
|
||||
elif isinstance(number, float):
|
||||
return self.float_to_words(number)
|
||||
|
||||
# split in groups of 10**3
|
||||
# groups of three digits starting from right (units (1 - 999),
|
||||
# thousands, millions, ...)
|
||||
groups = (
|
||||
[]
|
||||
)
|
||||
lowestgroup = (
|
||||
None # find the lowest group of 3 digits > 0 for the ordinals
|
||||
)
|
||||
for pot in [3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36]:
|
||||
gr = (number % 10**pot) // 10 ** (pot - 3)
|
||||
groups.append((gr, pot))
|
||||
if gr and not lowestgroup:
|
||||
lowestgroup = gr
|
||||
# print("groups", groups)
|
||||
|
||||
result = []
|
||||
if negative:
|
||||
result.append(("meinws", None))
|
||||
|
||||
for gr, pot in reversed(groups):
|
||||
if gr:
|
||||
# print("AAAA", gr, pot, gender)
|
||||
if pot == 6:
|
||||
g = "fem" # mil (1000) is feminine
|
||||
elif pot == 3:
|
||||
g = gender # units depend on the following noun
|
||||
else:
|
||||
g = "masc" # millions etc are masculine
|
||||
# "mil" is feminine
|
||||
if gr > 1 or pot == 3:
|
||||
words = self.hundred_group(
|
||||
gr,
|
||||
informal=informal,
|
||||
gender=g,
|
||||
ordinal=ordinal and (lowestgroup == gr),
|
||||
)
|
||||
result += words
|
||||
# print(">>>> ", words)
|
||||
if pot > 3:
|
||||
result.append(MILLION_WORDS[pot - 3])
|
||||
if raw:
|
||||
# need to be able trigger correct mutation on currencies
|
||||
return result
|
||||
else:
|
||||
if number < 100:
|
||||
return makestring(result, counted=counted)
|
||||
else:
|
||||
if counted:
|
||||
result.extend([("o", "SM"), (counted, None)])
|
||||
return makestring(result)
|
||||
|
||||
def to_currency(
|
||||
self, val, currency="EUR", cents=True, separator=",", adjective=False
|
||||
):
|
||||
"""
|
||||
Args:
|
||||
val: Numeric value
|
||||
currency (str): Currency code
|
||||
cents (bool): Verbose cents
|
||||
separator (str): Cent separator
|
||||
adjective (bool): Prefix currency name with adjective
|
||||
Returns:
|
||||
str: Formatted string
|
||||
|
||||
"""
|
||||
left, right, is_negative = parse_currency_parts(val)
|
||||
try:
|
||||
cr1, cr2 = self.CURRENCY_FORMS[currency]
|
||||
|
||||
except KeyError:
|
||||
raise NotImplementedError(
|
||||
'Currency code "%s" not implemented for "%s"'
|
||||
% (currency, self.__class__.__name__)
|
||||
)
|
||||
|
||||
# if adjective and currency in self.CURRENCY_ADJECTIVES:
|
||||
# cr1 = prefix_currency(self.CURRENCY_ADJECTIVES[currency], cr1)
|
||||
|
||||
minus_str = "%s " % self.negword.strip() if is_negative else ""
|
||||
money_str = self._money_verbose(left, currency)
|
||||
cents_str = (
|
||||
self._cents_verbose(right, currency)
|
||||
if cents
|
||||
else self._cents_terse(right, currency)
|
||||
)
|
||||
|
||||
if right == 0:
|
||||
# no pence
|
||||
return "%s%s" % (
|
||||
minus_str,
|
||||
money_str,
|
||||
# self.pluralize(right, cr2)
|
||||
)
|
||||
elif left == 0:
|
||||
# no pounds
|
||||
return "%s%s" % (
|
||||
minus_str,
|
||||
cents_str,
|
||||
# self.pluralize(right, cr2)
|
||||
)
|
||||
|
||||
return "%s%s%s %s" % (
|
||||
minus_str,
|
||||
money_str,
|
||||
# self.pluralize(left, cr1),
|
||||
separator,
|
||||
cents_str,
|
||||
# self.pluralize(right, cr2)
|
||||
)
|
||||
|
||||
def _money_verbose(self, number, currency):
|
||||
# used in super().to_currency(), we need to add gender
|
||||
# here for feminine currencies
|
||||
# if currency in CURRENCIES_FEM: # always true in this context
|
||||
if number > 100:
|
||||
m = self.to_cardinal(number, gender="fem", raw=True)
|
||||
# if currency in self.CURRENCY_FORMS:
|
||||
c = self.CURRENCY_FORMS[currency][0][1]
|
||||
m.append(("o", "SM"))
|
||||
m.append((c, None))
|
||||
# else:
|
||||
# c = currency
|
||||
# m.append((c, None))
|
||||
return makestring(m)
|
||||
else:
|
||||
# if number > 1:
|
||||
m = self.to_cardinal(number, gender="fem", raw=True)
|
||||
# elif number == 0:
|
||||
# m = self.to_cardinal(number, gender="fem", raw=True)
|
||||
# else:
|
||||
# m = [(OBJ, None)]
|
||||
# if currency in self.CURRENCY_FORMS:
|
||||
c = self.CURRENCY_FORMS[currency][0][0]
|
||||
# else:
|
||||
# c = currency
|
||||
# print("eeeeeeeee", m)
|
||||
# m.append((c, None))
|
||||
# print("fffffffff", m)
|
||||
return makestring(m, counted=c)
|
||||
# else:
|
||||
# return self.to_cardinal(number, raw=True)
|
||||
|
||||
def _cents_verbose(self, number, currency):
|
||||
if number == 0:
|
||||
return ""
|
||||
# elif number > 100:
|
||||
# m = self.to_cardinal(number, raw=True)
|
||||
# # if currency in self.CURRENCY_FORMS:
|
||||
# c = self.CURRENCY_FORMS[currency][0][1]
|
||||
# m.append(("o", "SM"))
|
||||
# m.append((c, None))
|
||||
# # else:
|
||||
# # c = currency
|
||||
# # m.append((c, None))
|
||||
# return makestring(m)
|
||||
else:
|
||||
if number > 1:
|
||||
m = self.to_cardinal(number, raw=True)
|
||||
else:
|
||||
m = [(OBJ, None)]
|
||||
# if currency in self.CURRENCY_FORMS:
|
||||
c = self.CURRENCY_FORMS[currency][1][0]
|
||||
# else:
|
||||
# c = currency
|
||||
return makestring(m, counted=c)
|
||||
|
||||
|
||||
def makestring(result, counted=None):
|
||||
# concatenate numberwords with correct mutation
|
||||
out = []
|
||||
lastmut = None
|
||||
for w, mut in result:
|
||||
if w == OBJ:
|
||||
if not counted:
|
||||
continue
|
||||
else:
|
||||
w = counted
|
||||
counted = None # only first position
|
||||
if lastmut:
|
||||
out.append(mutate(w, lastmut))
|
||||
else:
|
||||
out.append(w)
|
||||
lastmut = mut
|
||||
return " ".join(out)
|
||||
|
||||
|
||||
def mutate(word, mutation):
|
||||
# print("uuu", word, mutation)
|
||||
if mutation == "SM":
|
||||
return softmutation(word)
|
||||
elif mutation == "AM":
|
||||
return aspiratedmutation(word)
|
||||
# return word # does not occur
|
||||
|
||||
|
||||
def softmutation(word):
|
||||
# print("SM<<<<%s>" % word)
|
||||
if word[0] == "p" and word[1] != "h":
|
||||
return "b" + word[1:]
|
||||
elif word[0] == "t" and word[1] != "h":
|
||||
return "d" + word[1:]
|
||||
elif word[0] == "c" and word[1] != "h":
|
||||
return "g" + word[1:]
|
||||
elif word[0] == "b" or word[0] == "m":
|
||||
return "f" + word[1:]
|
||||
elif word[0] == "d" and word[1] != "d":
|
||||
return "d" + word
|
||||
elif word.startswith("ll"):
|
||||
return word[1:]
|
||||
elif word.startswith("rh"):
|
||||
return "r" + word[2:]
|
||||
elif word == "ugain":
|
||||
return "hugain"
|
||||
else:
|
||||
return word
|
||||
|
||||
|
||||
def aspiratedmutation(word):
|
||||
if word[0] == "p" and word[1] != "h":
|
||||
return "ph" + word[1:]
|
||||
elif word[0] == "t" and word[1] != "h":
|
||||
return "th" + word[1:]
|
||||
elif word[0] == "c" and word[1] != "h":
|
||||
return "ch" + word[1:]
|
||||
else:
|
||||
return word
|
||||
133
path/to/venv/lib/python3.12/site-packages/num2words/lang_DA.py
Normal file
133
path/to/venv/lib/python3.12/site-packages/num2words/lang_DA.py
Normal file
@@ -0,0 +1,133 @@
|
||||
# -*- 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, print_function, unicode_literals
|
||||
|
||||
from . import lang_EU
|
||||
|
||||
|
||||
class Num2Word_DA(lang_EU.Num2Word_EU):
|
||||
GIGA_SUFFIX = "illiarder"
|
||||
MEGA_SUFFIX = "illioner"
|
||||
|
||||
def setup(self):
|
||||
super(Num2Word_DA, self).setup()
|
||||
|
||||
self.negword = "minus "
|
||||
self.pointword = "komma"
|
||||
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"}
|
||||
self.ordflag = False
|
||||
|
||||
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)
|
||||
157
path/to/venv/lib/python3.12/site-packages/num2words/lang_DE.py
Normal file
157
path/to/venv/lib/python3.12/site-packages/num2words/lang_DE.py
Normal file
@@ -0,0 +1,157 @@
|
||||
# -*- 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 print_function, unicode_literals
|
||||
|
||||
import re
|
||||
|
||||
from .lang_EU import Num2Word_EU
|
||||
|
||||
|
||||
class Num2Word_DE(Num2Word_EU):
|
||||
CURRENCY_FORMS = {
|
||||
'EUR': (('Euro', 'Euro'), ('Cent', 'Cent')),
|
||||
'GBP': (('Pfund', 'Pfund'), ('Penny', 'Pence')),
|
||||
'USD': (('Dollar', 'Dollar'), ('Cent', 'Cent')),
|
||||
'CNY': (('Yuan', 'Yuan'), ('Jiao', 'Fen')),
|
||||
'DEM': (('Mark', 'Mark'), ('Pfennig', 'Pfennig')),
|
||||
}
|
||||
|
||||
GIGA_SUFFIX = "illiarde"
|
||||
MEGA_SUFFIX = "illion"
|
||||
|
||||
def setup(self):
|
||||
self.negword = "minus "
|
||||
self.pointword = "Komma"
|
||||
# "Cannot treat float %s as ordinal."
|
||||
self.errmsg_floatord = (
|
||||
"Die Gleitkommazahl %s kann nicht in eine Ordnungszahl " +
|
||||
"konvertiert werden."
|
||||
)
|
||||
# "type(((type(%s)) ) not in [long, int, float]"
|
||||
self.errmsg_nonnum = (
|
||||
"Nur Zahlen (type(%s)) können in Wörter konvertiert werden."
|
||||
)
|
||||
# "Cannot treat negative num %s as ordinal."
|
||||
self.errmsg_negord = (
|
||||
"Die negative Zahl %s kann nicht in eine Ordnungszahl " +
|
||||
"konvertiert werden."
|
||||
)
|
||||
# "abs(%s) must be less than %s."
|
||||
self.errmsg_toobig = "Die Zahl %s muss kleiner als %s sein."
|
||||
self.exclude_title = []
|
||||
|
||||
lows = ["Non", "Okt", "Sept", "Sext", "Quint", "Quadr", "Tr", "B", "M"]
|
||||
units = ["", "un", "duo", "tre", "quattuor", "quin", "sex", "sept",
|
||||
"okto", "novem"]
|
||||
tens = ["dez", "vigint", "trigint", "quadragint", "quinquagint",
|
||||
"sexagint", "septuagint", "oktogint", "nonagint"]
|
||||
self.high_numwords = (
|
||||
["zent"] + self.gen_high_numwords(units, tens, lows)
|
||||
)
|
||||
self.mid_numwords = [(1000, "tausend"), (100, "hundert"),
|
||||
(90, "neunzig"), (80, "achtzig"), (70, "siebzig"),
|
||||
(60, "sechzig"), (50, "f\xFCnfzig"),
|
||||
(40, "vierzig"), (30, "drei\xDFig")]
|
||||
self.low_numwords = ["zwanzig", "neunzehn", "achtzehn", "siebzehn",
|
||||
"sechzehn", "f\xFCnfzehn", "vierzehn", "dreizehn",
|
||||
"zw\xF6lf", "elf", "zehn", "neun", "acht",
|
||||
"sieben", "sechs", "f\xFCnf", "vier", "drei",
|
||||
"zwei", "eins", "null"]
|
||||
self.ords = {"eins": "ers",
|
||||
"drei": "drit",
|
||||
"acht": "ach",
|
||||
"sieben": "sieb",
|
||||
"ig": "igs",
|
||||
"ert": "erts",
|
||||
"end": "ends",
|
||||
"ion": "ions",
|
||||
"nen": "ns",
|
||||
"rde": "rds",
|
||||
"rden": "rds"}
|
||||
|
||||
def merge(self, curr, next):
|
||||
ctext, cnum, ntext, nnum = curr + next
|
||||
|
||||
if cnum == 1:
|
||||
if nnum == 100 or nnum == 1000:
|
||||
return ("ein" + ntext, nnum)
|
||||
elif nnum < 10 ** 6:
|
||||
return next
|
||||
ctext = "eine"
|
||||
|
||||
if nnum > cnum:
|
||||
if nnum >= 10 ** 6:
|
||||
if cnum > 1:
|
||||
if ntext.endswith("e"):
|
||||
ntext += "n"
|
||||
else:
|
||||
ntext += "en"
|
||||
ctext += " "
|
||||
val = cnum * nnum
|
||||
else:
|
||||
if nnum < 10 < cnum < 100:
|
||||
if nnum == 1:
|
||||
ntext = "ein"
|
||||
ntext, ctext = ctext, ntext + "und"
|
||||
elif cnum >= 10 ** 6:
|
||||
ctext += " "
|
||||
val = cnum + nnum
|
||||
|
||||
word = ctext + ntext
|
||||
return (word, val)
|
||||
|
||||
def to_ordinal(self, value):
|
||||
self.verify_ordinal(value)
|
||||
outword = self.to_cardinal(value).lower()
|
||||
for key in self.ords:
|
||||
if outword.endswith(key):
|
||||
outword = outword[:len(outword) - len(key)] + self.ords[key]
|
||||
break
|
||||
|
||||
res = outword + "te"
|
||||
|
||||
# Exception: "hundertste" is usually preferred over "einhundertste"
|
||||
if res == "eintausendste" or res == "einhundertste":
|
||||
res = res.replace("ein", "", 1)
|
||||
# ... similarly for "millionste" etc.
|
||||
res = re.sub(r'eine ([a-z]+(illion|illiard)ste)$',
|
||||
lambda m: m.group(1), res)
|
||||
# Ordinals involving "Million" etc. are written without a space.
|
||||
# see https://de.wikipedia.org/wiki/Million#Sprachliches
|
||||
res = re.sub(r' ([a-z]+(illion|illiard)ste)$',
|
||||
lambda m: m.group(1), res)
|
||||
|
||||
return res
|
||||
|
||||
def to_ordinal_num(self, value):
|
||||
self.verify_ordinal(value)
|
||||
return str(value) + "."
|
||||
|
||||
def to_currency(self, val, currency='EUR', cents=True, separator=' und',
|
||||
adjective=False):
|
||||
result = super(Num2Word_DE, self).to_currency(
|
||||
val, currency=currency, cents=cents, separator=separator,
|
||||
adjective=adjective)
|
||||
# Handle exception, in german is "ein Euro" and not "eins Euro"
|
||||
return result.replace("eins ", "ein ")
|
||||
|
||||
def to_year(self, val, longval=True):
|
||||
if not (val // 100) % 10:
|
||||
return self.to_cardinal(val)
|
||||
return self.to_splitnum(val, hightxt="hundert", longval=longval)\
|
||||
.replace(' ', '')
|
||||
110
path/to/venv/lib/python3.12/site-packages/num2words/lang_EN.py
Normal file
110
path/to/venv/lib/python3.12/site-packages/num2words/lang_EN.py
Normal file
@@ -0,0 +1,110 @@
|
||||
# -*- 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, print_function, unicode_literals
|
||||
|
||||
from . import lang_EU
|
||||
|
||||
|
||||
class Num2Word_EN(lang_EU.Num2Word_EU):
|
||||
def set_high_numwords(self, high):
|
||||
max = 3 + 3 * len(high)
|
||||
for word, n in zip(high, range(max, 3, -3)):
|
||||
self.cards[10 ** n] = word + "illion"
|
||||
|
||||
def setup(self):
|
||||
super(Num2Word_EN, self).setup()
|
||||
|
||||
self.negword = "minus "
|
||||
self.pointword = "point"
|
||||
self.exclude_title = ["and", "point", "minus"]
|
||||
|
||||
self.mid_numwords = [(1000, "thousand"), (100, "hundred"),
|
||||
(90, "ninety"), (80, "eighty"), (70, "seventy"),
|
||||
(60, "sixty"), (50, "fifty"), (40, "forty"),
|
||||
(30, "thirty")]
|
||||
self.low_numwords = ["twenty", "nineteen", "eighteen", "seventeen",
|
||||
"sixteen", "fifteen", "fourteen", "thirteen",
|
||||
"twelve", "eleven", "ten", "nine", "eight",
|
||||
"seven", "six", "five", "four", "three", "two",
|
||||
"one", "zero"]
|
||||
self.ords = {"one": "first",
|
||||
"two": "second",
|
||||
"three": "third",
|
||||
"four": "fourth",
|
||||
"five": "fifth",
|
||||
"six": "sixth",
|
||||
"seven": "seventh",
|
||||
"eight": "eighth",
|
||||
"nine": "ninth",
|
||||
"ten": "tenth",
|
||||
"eleven": "eleventh",
|
||||
"twelve": "twelfth"}
|
||||
|
||||
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 and %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[-1] == "y":
|
||||
lastword = lastword[:-1] + "ie"
|
||||
lastword += "th"
|
||||
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, suffix=None, longval=True):
|
||||
if val < 0:
|
||||
val = abs(val)
|
||||
suffix = 'BC' if not suffix else suffix
|
||||
high, low = (val // 100, val % 100)
|
||||
# If year is 00XX, X00X, or beyond 9999, go cardinal.
|
||||
if (high == 0
|
||||
or (high % 10 == 0 and low < 10)
|
||||
or high >= 100):
|
||||
valtext = self.to_cardinal(val)
|
||||
else:
|
||||
hightext = self.to_cardinal(high)
|
||||
if low == 0:
|
||||
lowtext = "hundred"
|
||||
elif low < 10:
|
||||
lowtext = "oh-%s" % self.to_cardinal(low)
|
||||
else:
|
||||
lowtext = self.to_cardinal(low)
|
||||
valtext = "%s %s" % (hightext, lowtext)
|
||||
return (valtext if not suffix
|
||||
else "%s %s" % (valtext, suffix))
|
||||
@@ -0,0 +1,26 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
||||
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from .lang_EN import Num2Word_EN
|
||||
|
||||
|
||||
class Num2Word_EN_IN(Num2Word_EN):
|
||||
def set_high_numwords(self, high):
|
||||
self.cards[10 ** 7] = "crore"
|
||||
self.cards[10 ** 5] = "lakh"
|
||||
@@ -0,0 +1,37 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
||||
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from . import lang_EN
|
||||
|
||||
|
||||
class Num2Word_EN_NG(lang_EN.Num2Word_EN):
|
||||
|
||||
CURRENCY_FORMS = {'NGN': (('naira', 'naira'), ('kobo', 'kobo'))}
|
||||
|
||||
CURRENCY_ADJECTIVES = {'NGN': 'Nigerian'}
|
||||
|
||||
def to_currency(
|
||||
self, val, currency='NGN',
|
||||
kobo=True, separator=',',
|
||||
adjective=False
|
||||
):
|
||||
result = super(Num2Word_EN_NG, self).to_currency(
|
||||
val, currency=currency, cents=kobo, separator=separator,
|
||||
adjective=adjective)
|
||||
return result
|
||||
130
path/to/venv/lib/python3.12/site-packages/num2words/lang_EO.py
Normal file
130
path/to/venv/lib/python3.12/site-packages/num2words/lang_EO.py
Normal file
@@ -0,0 +1,130 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2021, 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 print_function, unicode_literals
|
||||
|
||||
from .base import Num2Word_Base
|
||||
|
||||
|
||||
class Num2Word_EO(Num2Word_Base):
|
||||
CURRENCY_FORMS = {
|
||||
"EUR": (("eŭro", "eŭroj"), ("centimo", "centimoj")),
|
||||
"USD": (("dolaro", "dolaroj"), ("cendo", "cendoj")),
|
||||
"FRF": (("franko", "frankoj"), ("centimo", "centimoj")),
|
||||
"GBP": (("pundo", "pundoj"), ("penco", "pencoj")),
|
||||
"CNY": (("juano", "juanoj"), ("feno", "fenoj")),
|
||||
}
|
||||
|
||||
GIGA_SUFFIX = "iliardo"
|
||||
MEGA_SUFFIX = "iliono"
|
||||
|
||||
def set_high_numwords(self, high):
|
||||
cap = 3 + 6 * len(high)
|
||||
|
||||
for word, n in zip(high, range(cap, 3, -6)):
|
||||
if self.GIGA_SUFFIX:
|
||||
self.cards[10 ** n] = word + self.GIGA_SUFFIX
|
||||
|
||||
if self.MEGA_SUFFIX:
|
||||
self.cards[10 ** (n - 3)] = word + self.MEGA_SUFFIX
|
||||
|
||||
def gen_high_numwords(self, units, tens, lows):
|
||||
out = [u + t for t in tens for u in units]
|
||||
out.reverse()
|
||||
return out + lows
|
||||
|
||||
def setup(self):
|
||||
lows = ["naŭ", "ok", "sep", "ses", "kvin", "kvar", "tr", "b", "m"]
|
||||
units = ["", "un", "duo", "tre", "kvatuor",
|
||||
"kvin", "seks", "septen", "okto", "novem"]
|
||||
tens = ["dek", "vigint", "trigint", "kvadragint", "kvinkvagint",
|
||||
"seksagint", "septuagint", "oktogint", "nonagint"]
|
||||
|
||||
self.high_numwords = ["cent"] + self.gen_high_numwords(units, tens,
|
||||
lows)
|
||||
|
||||
self.negword = "minus "
|
||||
self.pointword = "komo"
|
||||
self.errmsg_nonnum = u"Sole nombroj povas esti konvertita en vortojn."
|
||||
self.errmsg_toobig = (
|
||||
u"Tro granda nombro por esti konvertita en vortojn (abs(%s) > %s)."
|
||||
)
|
||||
self.exclude_title = ["kaj", "komo", "minus"]
|
||||
self.mid_numwords = [(1000, "mil"), (100, "cent"), (90, "naŭdek"),
|
||||
(80, "okdek"), (70, "sepdek"), (60, "sesdek"),
|
||||
(50, "kvindek"), (40, "kvardek"), (30, "tridek")]
|
||||
self.low_numwords = ["dudek", "dek naŭ", "dek ok", "dek sep",
|
||||
"dek ses", "dek kvin", "dek kvar", "dek tri",
|
||||
"dek du", "dek unu", "dek", "naŭ", "ok", "sep",
|
||||
"ses", "kvin", "kvar", "tri", "du", "unu", "nul"]
|
||||
self.ords = {
|
||||
"unu": "unua",
|
||||
"du": "dua",
|
||||
"tri": "tria",
|
||||
"kvar": "kvara",
|
||||
"kvin": "kvina",
|
||||
"ses": "sesa",
|
||||
"sep": "sepa",
|
||||
"ok": "oka",
|
||||
"naŭ": "naŭa",
|
||||
"dek": "deka"
|
||||
}
|
||||
|
||||
def merge(self, curr, next):
|
||||
ctext, cnum, ntext, nnum = curr + next
|
||||
if cnum == 1 and nnum < 1000000:
|
||||
return next
|
||||
|
||||
if nnum >= 10**6 and cnum > 1:
|
||||
return ("%s %sj" % (ctext, ntext), cnum + nnum)
|
||||
|
||||
if nnum == 100:
|
||||
return ("%s%s" % (ctext, ntext), cnum + nnum)
|
||||
|
||||
return ("%s %s" % (ctext, ntext), cnum + nnum)
|
||||
|
||||
def to_ordinal(self, value):
|
||||
self.verify_ordinal(value)
|
||||
word = self.to_cardinal(value)
|
||||
for src, repl in self.ords.items():
|
||||
if word.endswith(src):
|
||||
word = word[:-len(src)] + repl
|
||||
return word
|
||||
|
||||
if word.endswith("o"):
|
||||
word = word[:-1] + "a"
|
||||
elif word.endswith("oj"):
|
||||
word = word[:-2] + "a"
|
||||
else:
|
||||
word = word + "a"
|
||||
return word
|
||||
|
||||
def to_ordinal_num(self, value):
|
||||
self.verify_ordinal(value)
|
||||
out = str(value)
|
||||
out += "a"
|
||||
return out
|
||||
|
||||
def to_currency(self, val, currency="EUR", cents=True, separator=" kaj",
|
||||
adjective=False):
|
||||
result = super(Num2Word_EO, self).to_currency(
|
||||
val, currency=currency, cents=cents, separator=separator,
|
||||
adjective=adjective)
|
||||
return result
|
||||
|
||||
def pluralize(self, n, forms):
|
||||
form = 0 if n <= 1 else 1
|
||||
return forms[form]
|
||||
408
path/to/venv/lib/python3.12/site-packages/num2words/lang_ES.py
Normal file
408
path/to/venv/lib/python3.12/site-packages/num2words/lang_ES.py
Normal file
@@ -0,0 +1,408 @@
|
||||
# -*- 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, print_function, unicode_literals
|
||||
|
||||
import math
|
||||
|
||||
from .lang_EU import Num2Word_EU
|
||||
|
||||
GENERIC_DOLLARS = ('dólar', 'dólares')
|
||||
GENERIC_CENTS = ('centavo', 'centavos')
|
||||
CURRENCIES_UNA = ('SLL', 'SEK', 'NOK', 'CZK', 'DKK', 'ISK',
|
||||
'SKK', 'GBP', 'CYP', 'EGP', 'FKP', 'GIP',
|
||||
'LBP', 'SDG', 'SHP', 'SSP', 'SYP', 'INR',
|
||||
'IDR', 'LKR', 'MUR', 'NPR', 'PKR', 'SCR',
|
||||
'ESP', 'TRY', 'ITL')
|
||||
CENTS_UNA = ('EGP', 'JOD', 'LBP', 'SDG', 'SSP', 'SYP')
|
||||
|
||||
|
||||
class Num2Word_ES(Num2Word_EU):
|
||||
CURRENCY_FORMS = {
|
||||
'EUR': (('euro', 'euros'), ('céntimo', 'céntimos')),
|
||||
'ESP': (('peseta', 'pesetas'), ('céntimo', 'céntimos')),
|
||||
'USD': (GENERIC_DOLLARS, GENERIC_CENTS),
|
||||
'PEN': (('sol', 'soles'), ('céntimo', 'céntimos')),
|
||||
'CRC': (('colón', 'colones'), GENERIC_CENTS),
|
||||
'AUD': (GENERIC_DOLLARS, GENERIC_CENTS),
|
||||
'CAD': (GENERIC_DOLLARS, GENERIC_CENTS),
|
||||
'GBP': (('libra', 'libras'), ('penique', 'peniques')),
|
||||
'RUB': (('rublo', 'rublos'), ('kopeyka', 'kopeykas')),
|
||||
'SEK': (('corona', 'coronas'), ('öre', 'öre')),
|
||||
'NOK': (('corona', 'coronas'), ('øre', 'øre')),
|
||||
'PLN': (('zloty', 'zlotys'), ('grosz', 'groszy')),
|
||||
'MXN': (('peso', 'pesos'), GENERIC_CENTS),
|
||||
'RON': (('leu', 'leus'), ('ban', 'bani')),
|
||||
'INR': (('rupia', 'rupias'), ('paisa', 'paisas')),
|
||||
'HUF': (('florín', 'florines'), ('fillér', 'fillér')),
|
||||
'FRF': (('franco', 'francos'), ('céntimo', 'céntimos')),
|
||||
'CNY': (('yuan', 'yuanes'), ('fen', 'jiaos')),
|
||||
'CZK': (('corona', 'coronas'), ('haléř', 'haléř')),
|
||||
'NIO': (('córdoba', 'córdobas'), GENERIC_CENTS),
|
||||
'VES': (('bolívar', 'bolívares'), ('céntimo', 'céntimos')),
|
||||
'BRL': (('real', 'reales'), GENERIC_CENTS),
|
||||
'CHF': (('franco', 'francos'), ('céntimo', 'céntimos')),
|
||||
'JPY': (('yen', 'yenes'), ('sen', 'sen')),
|
||||
'KRW': (('won', 'wones'), ('jeon', 'jeon')),
|
||||
'KPW': (('won', 'wones'), ('chon', 'chon')),
|
||||
'TRY': (('lira', 'liras'), ('kuruş', 'kuruş')),
|
||||
'ZAR': (('rand', 'rands'), ('céntimo', 'céntimos')),
|
||||
'KZT': (('tenge', 'tenges'), ('tïın', 'tïın')),
|
||||
'UAH': (('hryvnia', 'hryvnias'), ('kopiyka', 'kopiykas')),
|
||||
'THB': (('baht', 'bahts'), ('satang', 'satang')),
|
||||
'AED': (('dirham', 'dirhams'), ('fils', 'fils')),
|
||||
'AFN': (('afghani', 'afghanis'), ('pul', 'puls')),
|
||||
'ALL': (('lek ', 'leke'), ('qindarkë', 'qindarka')),
|
||||
'AMD': (('dram', 'drams'), ('luma', 'lumas')),
|
||||
'ANG': (('florín', 'florines'), GENERIC_CENTS),
|
||||
'AOA': (('kwanza', 'kwanzas'), ('céntimo', 'céntimos')),
|
||||
'ARS': (('peso', 'pesos'), GENERIC_CENTS),
|
||||
'AWG': (('florín', 'florines'), GENERIC_CENTS),
|
||||
'AZN': (('manat', 'manat'), ('qəpik', 'qəpik')),
|
||||
'BBD': (GENERIC_DOLLARS, GENERIC_CENTS),
|
||||
'BDT': (('taka', 'takas'), ('paisa', 'paisas')),
|
||||
'BGN': (('lev', 'leva'), ('stotinka', 'stotinki')),
|
||||
'BHD': (('dinar', 'dinares'), ('fils', 'fils')),
|
||||
'BIF': (('franco', 'francos'), ('céntimo', 'céntimos')),
|
||||
'BMD': (GENERIC_DOLLARS, GENERIC_CENTS),
|
||||
'BND': (GENERIC_DOLLARS, GENERIC_CENTS),
|
||||
'BOB': (('boliviano', 'bolivianos'), GENERIC_CENTS),
|
||||
'BSD': (GENERIC_DOLLARS, GENERIC_CENTS),
|
||||
'BTN': (('ngultrum', 'ngultrum'), ('chetrum', 'chetrum')),
|
||||
'BWP': (('pula', 'pulas'), ('thebe', 'thebes')),
|
||||
'BYN': (('rublo', 'rublos'), ('kópek', 'kópeks')),
|
||||
'BYR': (('rublo', 'rublos'), ('kópek', 'kópeks')),
|
||||
'BZD': (GENERIC_DOLLARS, ('céntimo', 'céntimos')),
|
||||
'CDF': (('franco', 'francos'), ('céntimo', 'céntimos')),
|
||||
'CLP': (('peso', 'pesos'), GENERIC_CENTS),
|
||||
'COP': (('peso', 'pesos'), GENERIC_CENTS),
|
||||
'CUP': (('peso', 'pesos'), GENERIC_CENTS),
|
||||
'CVE': (('escudo', 'escudos'), GENERIC_CENTS),
|
||||
'CYP': (('libra', 'libras'), ('céntimo', 'céntimos')),
|
||||
'DJF': (('franco', 'francos'), ('céntimo', 'céntimos')),
|
||||
'DKK': (('corona', 'coronas'), ('øre', 'øre')),
|
||||
'DOP': (('peso', 'pesos'), GENERIC_CENTS),
|
||||
'DZD': (('dinar', 'dinares'), ('céntimo', 'céntimos')),
|
||||
'ECS': (('sucre', 'sucres'), GENERIC_CENTS),
|
||||
'EGP': (('libra', 'libras'), ('piastra', 'piastras')),
|
||||
'ERN': (('nakfa', 'nakfas'), ('céntimo', 'céntimos')),
|
||||
'ETB': (('birr', 'birrs'), ('céntimo', 'céntimos')),
|
||||
'FJD': (GENERIC_DOLLARS, GENERIC_CENTS),
|
||||
'FKP': (('libra', 'libras'), ('penique', 'peniques')),
|
||||
'GEL': (('lari', 'laris'), ('tetri', 'tetris')),
|
||||
'GHS': (('cedi', 'cedis'), ('pesewa', 'pesewas')),
|
||||
'GIP': (('libra', 'libras'), ('penique', 'peniques')),
|
||||
'GMD': (('dalasi', 'dalasis'), ('butut', 'bututs')),
|
||||
'GNF': (('franco', 'francos'), ('céntimo', 'céntimos')),
|
||||
'GTQ': (('quetzal', 'quetzales'), GENERIC_CENTS),
|
||||
'GYD': (GENERIC_DOLLARS, GENERIC_CENTS),
|
||||
'HKD': (GENERIC_DOLLARS, GENERIC_CENTS),
|
||||
'HNL': (('lempira', 'lempiras'), GENERIC_CENTS),
|
||||
'HRK': (('kuna', 'kunas'), ('lipa', 'lipas')),
|
||||
'HTG': (('gourde', 'gourdes'), ('céntimo', 'céntimos')),
|
||||
'IDR': (('rupia', 'rupias'), ('céntimo', 'céntimos')),
|
||||
'ILS': (('séquel', 'séqueles'), ('agora', 'agoras')),
|
||||
'IQD': (('dinar', 'dinares'), ('fils', 'fils')),
|
||||
'IRR': (('rial', 'riales'), ('dinar', 'dinares')),
|
||||
'ISK': (('corona', 'coronas'), ('eyrir', 'aurar')),
|
||||
'ITL': (('lira', 'liras'), ('céntimo', 'céntimos')),
|
||||
'JMD': (GENERIC_DOLLARS, ('céntimo', 'céntimos')),
|
||||
'JOD': (('dinar', 'dinares'), ('piastra', 'piastras')),
|
||||
'KES': (('chelín', 'chelines'), ('céntimo', 'céntimos')),
|
||||
'KGS': (('som', 'som'), ('tyiyn', 'tyiyn')),
|
||||
'KHR': (('riel', 'rieles'), ('céntimo', 'céntimos')),
|
||||
'KMF': (('franco', 'francos'), ('céntimo', 'céntimos')),
|
||||
'KWD': (('dinar', 'dinares'), ('fils', 'fils')),
|
||||
'KYD': (GENERIC_DOLLARS, ('céntimo', 'céntimos')),
|
||||
'LAK': (('kip', 'kips'), ('att', 'att')),
|
||||
'LBP': (('libra', 'libras'), ('piastra', 'piastras')),
|
||||
'LKR': (('rupia', 'rupias'), ('céntimo', 'céntimos')),
|
||||
'LRD': (GENERIC_DOLLARS, ('céntimo', 'céntimos')),
|
||||
'LSL': (('loti', 'lotis'), ('céntimo', 'céntimos')),
|
||||
'LTL': (('lita', 'litas'), ('céntimo', 'céntimos')),
|
||||
'LVL': (('lat', 'lats'), ('céntimo', 'céntimos')),
|
||||
'LYD': (('dinar', 'dinares'), ('dírham', 'dírhams')),
|
||||
'MAD': (('dírham', 'dirhams'), ('céntimo', 'céntimos')),
|
||||
'MDL': (('leu', 'lei'), ('ban', 'bani')),
|
||||
'MGA': (('ariary', 'ariaris'), ('iraimbilanja', 'iraimbilanja')),
|
||||
'MKD': (('denar', 'denares'), ('deni', 'denis')),
|
||||
'MMK': (('kiat', 'kiats'), ('pya', 'pyas')),
|
||||
'MNT': (('tugrik', 'tugriks'), ('möngö', 'möngö')),
|
||||
'MOP': (('pataca', 'patacas'), ('avo', 'avos')),
|
||||
'MRO': (('ouguiya', 'ouguiyas'), ('khoums', 'khoums')),
|
||||
'MRU': (('ouguiya', 'ouguiyas'), ('khoums', 'khoums')),
|
||||
'MUR': (('rupia', 'rupias'), ('céntimo', 'céntimos')),
|
||||
'MVR': (('rufiyaa', 'rufiyaas'), ('laari', 'laari')),
|
||||
'MWK': (('kuacha', 'kuachas'), ('tambala', 'tambalas')),
|
||||
'MYR': (('ringgit', 'ringgit'), ('céntimo', 'céntimos')),
|
||||
'MZN': (('metical', 'metical'), GENERIC_CENTS),
|
||||
'NAD': (GENERIC_DOLLARS, ('céntimo', 'céntimos')),
|
||||
'NGN': (('naira', 'nairas'), ('kobo', 'kobo')),
|
||||
'NPR': (('rupia', 'rupias'), ('paisa', 'paisas')),
|
||||
'NZD': (GENERIC_DOLLARS, GENERIC_CENTS),
|
||||
'OMR': (('rial', 'riales'), ('baisa', 'baisa')),
|
||||
'PAB': (('balboa', 'balboas'), ('centésimo', 'centésimos')),
|
||||
'PGK': (('kina', 'kinas'), ('toea', 'toea')),
|
||||
'PHP': (('peso', 'pesos'), GENERIC_CENTS),
|
||||
'PKR': (('rupia', 'rupias'), ('paisa', 'paisas')),
|
||||
'PLZ': (('zloty', 'zlotys'), ('grosz', 'groszy')),
|
||||
'PYG': (('guaraní', 'guaranís'), ('céntimo', 'céntimos')),
|
||||
'QAR': (('rial', 'riales'), ('dírham', 'dírhams')),
|
||||
'QTQ': (('quetzal', 'quetzales'), GENERIC_CENTS),
|
||||
'RSD': (('dinar', 'dinares'), ('para', 'para')),
|
||||
'RUR': (('rublo', 'rublos'), ('kopek', 'kopeks')),
|
||||
'RWF': (('franco', 'francos'), ('céntimo', 'céntimos')),
|
||||
'SAR': (('riyal', 'riales'), ('halala', 'halalas')),
|
||||
'SBD': (GENERIC_DOLLARS, ('céntimo', 'céntimos')),
|
||||
'SCR': (('rupia', 'rupias'), ('céntimo', 'céntimos')),
|
||||
'SDG': (('libra', 'libras'), ('piastra', 'piastras')),
|
||||
'SGD': (GENERIC_DOLLARS, ('céntimo', 'céntimos')),
|
||||
'SHP': (('libra', 'libras'), ('penique', 'peniques')),
|
||||
'SKK': (('corona', 'coronas'), ('halier', 'haliers')),
|
||||
'SLL': (('leona', 'leonas'), ('céntimo', 'céntimos')),
|
||||
'SRD': (GENERIC_DOLLARS, ('céntimo', 'céntimos')),
|
||||
'SSP': (('libra', 'libras'), ('piastra', 'piastras')),
|
||||
'STD': (('dobra', 'dobras'), ('céntimo', 'céntimos')),
|
||||
'SVC': (('colón', 'colones'), GENERIC_CENTS),
|
||||
'SYP': (('libra', 'libras'), ('piastra', 'piastras')),
|
||||
'SZL': (('lilangeni', 'emalangeni'), ('céntimo', 'céntimos')),
|
||||
'TJS': (('somoni', 'somonis'), ('dirame', 'dirames')),
|
||||
'TMT': (('manat', 'manat'), ('tenge', 'tenge')),
|
||||
'TND': (('dinar', 'dinares'), ('milésimo', 'milésimos')),
|
||||
'TOP': (('paanga', 'paangas'), ('céntimo', 'céntimos')),
|
||||
'TTD': (GENERIC_DOLLARS, ('céntimo', 'céntimos')),
|
||||
'TWD': (('nuevo dólar', 'nuevos dólares'), ('céntimo', 'céntimos')),
|
||||
'TZS': (('chelín', 'chelines'), ('céntimo', 'céntimos')),
|
||||
'UAG': (('hryvnia', 'hryvnias'), ('kopiyka', 'kopiykas')),
|
||||
'UGX': (('chelín', 'chelines'), ('céntimo', 'céntimos')),
|
||||
'UYU': (('peso', 'pesos'), ('centésimo', 'centésimos')),
|
||||
'UZS': (('sum', 'sum'), ('tiyin', 'tiyin')),
|
||||
'VEF': (('bolívar fuerte', 'bolívares fuertes'),
|
||||
('céntimo', 'céntimos')),
|
||||
'VND': (('dong', 'dongs'), ('xu', 'xu')),
|
||||
'VUV': (('vatu', 'vatu'), ('nenhum', 'nenhum')),
|
||||
'WST': (('tala', 'tala'), GENERIC_CENTS),
|
||||
'XAF': (('franco CFA', 'francos CFA'), ('céntimo', 'céntimos')),
|
||||
'XCD': (GENERIC_DOLLARS, ('céntimo', 'céntimos')),
|
||||
'XOF': (('franco CFA', 'francos CFA'), ('céntimo', 'céntimos')),
|
||||
'XPF': (('franco CFP', 'francos CFP'), ('céntimo', 'céntimos')),
|
||||
'YER': (('rial', 'riales'), ('fils', 'fils')),
|
||||
'YUM': (('dinar', 'dinares'), ('para', 'para')),
|
||||
'ZMW': (('kwacha', 'kwachas'), ('ngwee', 'ngwee')),
|
||||
'ZRZ': (('zaire', 'zaires'), ('likuta', 'makuta')),
|
||||
'ZWL': (GENERIC_DOLLARS, ('céntimo', 'céntimos')),
|
||||
'ZWL': (GENERIC_DOLLARS, ('céntimo', 'céntimos')),
|
||||
}
|
||||
|
||||
# //CHECK: Is this sufficient??
|
||||
GIGA_SUFFIX = None
|
||||
MEGA_SUFFIX = "illón"
|
||||
|
||||
def setup(self):
|
||||
lows = ["cuatr", "tr", "b", "m"]
|
||||
self.high_numwords = self.gen_high_numwords([], [], lows)
|
||||
self.negword = "menos "
|
||||
self.pointword = "punto"
|
||||
self.errmsg_nonnum = "type(%s) no es [long, int, float]"
|
||||
self.errmsg_floatord = "El float %s no puede ser tratado como un" \
|
||||
" ordinal."
|
||||
self.errmsg_negord = "El número negativo %s no puede ser tratado" \
|
||||
" como un ordinal."
|
||||
self.errmsg_toobig = (
|
||||
"abs(%s) deber ser inferior a %s."
|
||||
)
|
||||
self.gender_stem = "o"
|
||||
self.exclude_title = ["y", "menos", "punto"]
|
||||
self.mid_numwords = [(1000, "mil"), (100, "cien"), (90, "noventa"),
|
||||
(80, "ochenta"), (70, "setenta"), (60, "sesenta"),
|
||||
(50, "cincuenta"), (40, "cuarenta"),
|
||||
(30, "treinta")]
|
||||
self.low_numwords = ["veintinueve", "veintiocho", "veintisiete",
|
||||
"veintiséis", "veinticinco", "veinticuatro",
|
||||
"veintitrés", "veintidós", "veintiuno",
|
||||
"veinte", "diecinueve", "dieciocho", "diecisiete",
|
||||
"dieciséis", "quince", "catorce", "trece", "doce",
|
||||
"once", "diez", "nueve", "ocho", "siete", "seis",
|
||||
"cinco", "cuatro", "tres", "dos", "uno", "cero"]
|
||||
self.ords = {1: "primer",
|
||||
2: "segund",
|
||||
3: "tercer",
|
||||
4: "cuart",
|
||||
5: "quint",
|
||||
6: "sext",
|
||||
7: "séptim",
|
||||
8: "octav",
|
||||
9: "noven",
|
||||
10: "décim",
|
||||
20: "vigésim",
|
||||
30: "trigésim",
|
||||
40: "quadragésim",
|
||||
50: "quincuagésim",
|
||||
60: "sexagésim",
|
||||
70: "septuagésim",
|
||||
80: "octogésim",
|
||||
90: "nonagésim",
|
||||
100: "centésim",
|
||||
200: "ducentésim",
|
||||
300: "tricentésim",
|
||||
400: "cuadrigentésim",
|
||||
500: "quingentésim",
|
||||
600: "sexcentésim",
|
||||
700: "septigentésim",
|
||||
800: "octigentésim",
|
||||
900: "noningentésim",
|
||||
1e3: "milésim",
|
||||
1e6: "millonésim",
|
||||
1e9: "billonésim",
|
||||
1e12: "trillonésim",
|
||||
1e15: "cuadrillonésim"}
|
||||
|
||||
def merge(self, curr, next):
|
||||
ctext, cnum, ntext, nnum = curr + next
|
||||
|
||||
if cnum == 1:
|
||||
if nnum < 1000000:
|
||||
return next
|
||||
ctext = "un"
|
||||
elif cnum == 100 and not nnum % 1000 == 0:
|
||||
ctext += "t" + self.gender_stem
|
||||
|
||||
if nnum < cnum:
|
||||
if cnum < 100:
|
||||
return "%s y %s" % (ctext, ntext), cnum + nnum
|
||||
return "%s %s" % (ctext, ntext), cnum + nnum
|
||||
elif (not nnum % 1000000) and cnum > 1:
|
||||
ntext = ntext[:-3] + "lones"
|
||||
|
||||
if nnum == 100:
|
||||
if cnum == 5:
|
||||
ctext = "quinien"
|
||||
ntext = ""
|
||||
elif cnum == 7:
|
||||
ctext = "sete"
|
||||
elif cnum == 9:
|
||||
ctext = "nove"
|
||||
ntext += "t" + self.gender_stem + "s"
|
||||
else:
|
||||
ntext = " " + ntext
|
||||
|
||||
return (ctext + ntext, cnum * nnum)
|
||||
|
||||
def to_ordinal(self, value):
|
||||
self.verify_ordinal(value)
|
||||
if value == 0:
|
||||
text = ""
|
||||
elif value <= 10:
|
||||
text = "%s%s" % (self.ords[value], self.gender_stem)
|
||||
elif value <= 12:
|
||||
text = (
|
||||
"%s%s%s" % (self.ords[10], self.gender_stem,
|
||||
self.to_ordinal(value - 10))
|
||||
)
|
||||
elif value <= 100:
|
||||
dec = (value // 10) * 10
|
||||
text = (
|
||||
"%s%s %s" % (self.ords[dec], self.gender_stem,
|
||||
self.to_ordinal(value - dec))
|
||||
)
|
||||
elif value <= 1e3:
|
||||
cen = (value // 100) * 100
|
||||
text = (
|
||||
"%s%s %s" % (self.ords[cen], self.gender_stem,
|
||||
self.to_ordinal(value - cen))
|
||||
)
|
||||
elif value < 1e18:
|
||||
# Round down to the nearest 1e(3n)
|
||||
# dec contains the following:
|
||||
# [ 1e3, 1e6): 1e3
|
||||
# [ 1e6, 1e9): 1e6
|
||||
# [ 1e9, 1e12): 1e9
|
||||
# [1e12, 1e15): 1e12
|
||||
# [1e15, 1e18): 1e15
|
||||
dec = 1000 ** int(math.log(int(value), 1000))
|
||||
|
||||
# Split the parts before and after the word for 'dec'
|
||||
# eg (12, 345) = divmod(12_345, 1_000)
|
||||
high_part, low_part = divmod(value, dec)
|
||||
|
||||
cardinal = self.to_cardinal(high_part) if high_part != 1 else ""
|
||||
text = (
|
||||
"%s%s%s %s" % (cardinal, self.ords[dec], self.gender_stem,
|
||||
self.to_ordinal(low_part))
|
||||
)
|
||||
else:
|
||||
text = self.to_cardinal(value)
|
||||
return text.strip()
|
||||
|
||||
def to_ordinal_num(self, value):
|
||||
self.verify_ordinal(value)
|
||||
return "%s%s" % (value, "º" if self.gender_stem == 'o' else "ª")
|
||||
|
||||
def to_currency(self, val, currency='EUR', cents=True, separator=' con',
|
||||
adjective=False):
|
||||
result = super(Num2Word_ES, self).to_currency(
|
||||
val, currency=currency, cents=cents, separator=separator,
|
||||
adjective=adjective)
|
||||
# Handle exception: In Spanish it's "un euro" and not "uno euro",
|
||||
# except in these currencies, where it's "una": leona, corona,
|
||||
# libra, lira, rupia, lempira, peseta.
|
||||
# The same goes for "veintiuna", "treinta y una"...
|
||||
# Also, this needs to be handled separately for "dollars" and
|
||||
# "cents".
|
||||
# All "cents" are masculine except for: piastra.
|
||||
# Source: https://www.rae.es/dpd/una (section 2.2)
|
||||
|
||||
# split "dollars" part from "cents" part
|
||||
list_result = result.split(separator + " ")
|
||||
|
||||
# "DOLLARS" PART (list_result[0])
|
||||
|
||||
# Feminine currencies ("una libra", "trescientas libras"...)
|
||||
if currency in CURRENCIES_UNA:
|
||||
|
||||
# "una libra", "veintiuna libras", "treinta y una libras"...
|
||||
list_result[0] = list_result[0].replace("uno", "una")
|
||||
|
||||
# "doscientas libras", "trescientas libras"...
|
||||
list_result[0] = list_result[0].replace("cientos", "cientas")
|
||||
|
||||
# Masc.: Correct orthography for the specific case of "veintiún":
|
||||
list_result[0] = list_result[0].replace("veintiuno", "veintiún")
|
||||
|
||||
# Masculine currencies: general case ("un euro", "treinta y un
|
||||
# euros"...):
|
||||
list_result[0] = list_result[0].replace("uno", "un")
|
||||
|
||||
# "CENTS" PART (list_result[1])
|
||||
|
||||
# Feminine "cents" ("una piastra", "veintiuna piastras"...)
|
||||
if currency in CENTS_UNA:
|
||||
|
||||
# "una piastra", "veintiuna piastras", "treinta y una piastras"...
|
||||
list_result[1] = list_result[1].replace("uno", "una")
|
||||
|
||||
# Masc.: Correct orthography for the specific case of "veintiún":
|
||||
list_result[1] = list_result[1].replace("veintiuno", "veintiún")
|
||||
|
||||
# Masculine "cents": general case ("un centavo", "treinta y un
|
||||
# centavos"...):
|
||||
list_result[1] = list_result[1].replace("uno", "un")
|
||||
|
||||
# join back "dollars" part with "cents" part
|
||||
result = (separator + " ").join(list_result)
|
||||
|
||||
return result
|
||||
@@ -0,0 +1,29 @@
|
||||
# -*- 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 print_function, unicode_literals
|
||||
|
||||
from .lang_ES import Num2Word_ES
|
||||
|
||||
|
||||
class Num2Word_ES_CO(Num2Word_ES):
|
||||
|
||||
def to_currency(self, val, longval=True, old=False):
|
||||
result = self.to_splitnum(val, hightxt="peso/s", lowtxt="centavo/s",
|
||||
divisor=1, jointxt="y", longval=longval)
|
||||
# Handle exception, in spanish is "un euro" and not "uno euro"
|
||||
return result.replace("uno", "un")
|
||||
@@ -0,0 +1,30 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
||||
# Copyright (c) 2024, Randall Castro. 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 print_function, unicode_literals
|
||||
|
||||
from .lang_ES import Num2Word_ES
|
||||
|
||||
|
||||
class Num2Word_ES_CR(Num2Word_ES):
|
||||
|
||||
def to_currency(self, val, longval=True, old=False):
|
||||
result = self.to_splitnum(val, hightxt="colón/es", lowtxt="céntimo/s",
|
||||
divisor=1, jointxt="y", longval=longval)
|
||||
# Handle exception, in spanish is "un euro" and not "uno euro"
|
||||
return result.replace("uno", "un")
|
||||
@@ -0,0 +1,32 @@
|
||||
# -*- 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 print_function, unicode_literals
|
||||
|
||||
from .lang_ES import Num2Word_ES
|
||||
|
||||
|
||||
class Num2Word_ES_GT(Num2Word_ES):
|
||||
|
||||
def to_currency(self, val, longval=True, old=False):
|
||||
result = self.to_splitnum(val, hightxt="quetzal/es",
|
||||
lowtxt="centavo/s",
|
||||
divisor=1, jointxt="y",
|
||||
longval=longval)
|
||||
# Handle exception, in spanish is "un euro"
|
||||
# and not "uno euro"
|
||||
return result.replace("uno", "un")
|
||||
@@ -0,0 +1,33 @@
|
||||
# -*- 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 print_function, unicode_literals
|
||||
|
||||
from .lang_ES import Num2Word_ES
|
||||
|
||||
|
||||
class Num2Word_ES_NI(Num2Word_ES):
|
||||
CURRENCY_FORMS = {
|
||||
'NIO': (('córdoba', 'córdobas'), ('centavo', 'centavos')),
|
||||
}
|
||||
|
||||
def to_currency(self, val, currency='NIO', cents=True, separator=' con',
|
||||
adjective=False):
|
||||
result = super(Num2Word_ES, self).to_currency(
|
||||
val, currency=currency, cents=cents, separator=separator,
|
||||
adjective=adjective)
|
||||
return result.replace("uno", "un")
|
||||
@@ -0,0 +1,32 @@
|
||||
# -*- 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 print_function, unicode_literals
|
||||
|
||||
from .lang_ES import Num2Word_ES
|
||||
|
||||
|
||||
class Num2Word_ES_VE(Num2Word_ES):
|
||||
|
||||
def to_currency(self, val, longval=True, old=False):
|
||||
hightxt = "bolívar/es" if old else "bolívar/es fuerte/s"
|
||||
result = self.to_splitnum(
|
||||
val, hightxt=hightxt, lowtxt="centavo/s",
|
||||
divisor=1, jointxt="y", longval=longval
|
||||
)
|
||||
# Handle exception, in spanish is "un euro" and not "uno euro"
|
||||
return result.replace("uno", "un")
|
||||
100
path/to/venv/lib/python3.12/site-packages/num2words/lang_EU.py
Normal file
100
path/to/venv/lib/python3.12/site-packages/num2words/lang_EU.py
Normal file
@@ -0,0 +1,100 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
||||
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from .base import Num2Word_Base
|
||||
|
||||
GENERIC_DOLLARS = ('dollar', 'dollars')
|
||||
GENERIC_CENTS = ('cent', 'cents')
|
||||
|
||||
|
||||
class Num2Word_EU(Num2Word_Base):
|
||||
CURRENCY_FORMS = {
|
||||
'AUD': (GENERIC_DOLLARS, GENERIC_CENTS),
|
||||
'BYN': (('rouble', 'roubles'), ('kopek', 'kopeks')),
|
||||
'CAD': (GENERIC_DOLLARS, GENERIC_CENTS),
|
||||
# repalced by EUR
|
||||
'EEK': (('kroon', 'kroons'), ('sent', 'senti')),
|
||||
'EUR': (('euro', 'euro'), GENERIC_CENTS),
|
||||
'GBP': (('pound sterling', 'pounds sterling'), ('penny', 'pence')),
|
||||
# replaced by EUR
|
||||
'LTL': (('litas', 'litas'), GENERIC_CENTS),
|
||||
# replaced by EUR
|
||||
'LVL': (('lat', 'lats'), ('santim', 'santims')),
|
||||
'USD': (GENERIC_DOLLARS, GENERIC_CENTS),
|
||||
'RUB': (('rouble', 'roubles'), ('kopek', 'kopeks')),
|
||||
'SEK': (('krona', 'kronor'), ('öre', 'öre')),
|
||||
'NOK': (('krone', 'kroner'), ('øre', 'øre')),
|
||||
'PLN': (('zloty', 'zlotys', 'zlotu'), ('grosz', 'groszy')),
|
||||
'MXN': (('peso', 'pesos'), GENERIC_CENTS),
|
||||
'RON': (('leu', 'lei', 'de lei'), ('ban', 'bani', 'de bani')),
|
||||
'INR': (('rupee', 'rupees'), ('paisa', 'paise')),
|
||||
'HUF': (('forint', 'forint'), ('fillér', 'fillér')),
|
||||
'ISK': (('króna', 'krónur'), ('aur', 'aurar')),
|
||||
'UZS': (('sum', 'sums'), ('tiyin', 'tiyins')),
|
||||
'SAR': (('saudi riyal', 'saudi riyals'), ('halalah', 'halalas'))
|
||||
|
||||
}
|
||||
|
||||
CURRENCY_ADJECTIVES = {
|
||||
'AUD': 'Australian',
|
||||
'BYN': 'Belarusian',
|
||||
'CAD': 'Canadian',
|
||||
'EEK': 'Estonian',
|
||||
'USD': 'US',
|
||||
'RUB': 'Russian',
|
||||
'NOK': 'Norwegian',
|
||||
'MXN': 'Mexican',
|
||||
'RON': 'Romanian',
|
||||
'INR': 'Indian',
|
||||
'HUF': 'Hungarian',
|
||||
'ISK': 'íslenskar',
|
||||
'UZS': 'Uzbekistan',
|
||||
'SAR': 'Saudi'
|
||||
}
|
||||
|
||||
GIGA_SUFFIX = "illiard"
|
||||
MEGA_SUFFIX = "illion"
|
||||
|
||||
def set_high_numwords(self, high):
|
||||
cap = 3 + 6 * len(high)
|
||||
|
||||
for word, n in zip(high, range(cap, 3, -6)):
|
||||
if self.GIGA_SUFFIX:
|
||||
self.cards[10 ** n] = word + self.GIGA_SUFFIX
|
||||
|
||||
if self.MEGA_SUFFIX:
|
||||
self.cards[10 ** (n - 3)] = word + self.MEGA_SUFFIX
|
||||
|
||||
def gen_high_numwords(self, units, tens, lows):
|
||||
out = [u + t for t in tens for u in units]
|
||||
out.reverse()
|
||||
return out + lows
|
||||
|
||||
def pluralize(self, n, forms):
|
||||
form = 0 if n == 1 else 1
|
||||
return forms[form]
|
||||
|
||||
def setup(self):
|
||||
lows = ["non", "oct", "sept", "sext", "quint", "quadr", "tr", "b", "m"]
|
||||
units = ["", "un", "duo", "tre", "quattuor", "quin", "sex", "sept",
|
||||
"octo", "novem"]
|
||||
tens = ["dec", "vigint", "trigint", "quadragint", "quinquagint",
|
||||
"sexagint", "septuagint", "octogint", "nonagint"]
|
||||
self.high_numwords = ["cent"] + self.gen_high_numwords(units, tens,
|
||||
lows)
|
||||
168
path/to/venv/lib/python3.12/site-packages/num2words/lang_FA.py
Normal file
168
path/to/venv/lib/python3.12/site-packages/num2words/lang_FA.py
Normal file
@@ -0,0 +1,168 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
||||
# Copyright (c) 2018, Abdullah Alhazmy, Alhazmy13. All Rights Reserved.
|
||||
# Copyright (c) 2020, Hamidreza Kalbasi. All Rights Reserved.
|
||||
# Copyright (c) 2023, Nika Soltani Tehrani. 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 decimal import Decimal
|
||||
from math import floor
|
||||
|
||||
farsiOnes = [
|
||||
"", "یک", "دو", "سه", "چهار", "پنج", "شش", "هفت", "هشت",
|
||||
"نه",
|
||||
"ده",
|
||||
"یازده",
|
||||
"دوازده",
|
||||
"سیزده",
|
||||
"چهارده",
|
||||
"پانزده",
|
||||
"شانزده",
|
||||
"هفده",
|
||||
"هجده",
|
||||
"نوزده",
|
||||
]
|
||||
|
||||
farsiTens = [
|
||||
"",
|
||||
"ده",
|
||||
"بیست",
|
||||
"سی",
|
||||
"چهل",
|
||||
"پنجاه",
|
||||
"شصت",
|
||||
"هفتاد",
|
||||
"هشتاد",
|
||||
"نود",
|
||||
]
|
||||
|
||||
farsiHundreds = [
|
||||
"",
|
||||
"صد",
|
||||
"دویست",
|
||||
"سیصد",
|
||||
"چهارصد",
|
||||
"پانصد",
|
||||
"ششصد",
|
||||
"هفتصد",
|
||||
"هشتصد",
|
||||
"نهصد",
|
||||
]
|
||||
|
||||
farsiBig = [
|
||||
'',
|
||||
' هزار',
|
||||
' میلیون',
|
||||
" میلیارد",
|
||||
' تریلیون',
|
||||
" تریلیارد",
|
||||
]
|
||||
|
||||
farsiFrac = ["", "دهم", "صدم"]
|
||||
farsiFracBig = ["", "هزارم", "میلیونیم", "میلیاردیم"]
|
||||
|
||||
farsiSeperator = ' و '
|
||||
|
||||
|
||||
class Num2Word_FA(object):
|
||||
# Those are unused
|
||||
errmsg_toobig = "Too large"
|
||||
MAXNUM = 10 ** 36
|
||||
|
||||
def __init__(self):
|
||||
self.number = 0
|
||||
|
||||
def float2tuple(self, value):
|
||||
pre = int(value)
|
||||
|
||||
# Simple way of finding decimal places to update the precision
|
||||
self.precision = abs(Decimal(str(value)).as_tuple().exponent)
|
||||
|
||||
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(floor(post))
|
||||
return pre, post, self.precision
|
||||
|
||||
def cardinal3(self, number):
|
||||
if number <= 19:
|
||||
return farsiOnes[number]
|
||||
if number < 100:
|
||||
x, y = divmod(number, 10)
|
||||
if y == 0:
|
||||
return farsiTens[x]
|
||||
return farsiTens[x] + farsiSeperator + farsiOnes[y]
|
||||
x, y = divmod(number, 100)
|
||||
if y == 0:
|
||||
return farsiHundreds[x]
|
||||
return farsiHundreds[x] + farsiSeperator + self.cardinal3(y)
|
||||
|
||||
def cardinalPos(self, number):
|
||||
x = number
|
||||
res = ''
|
||||
for b in farsiBig:
|
||||
x, y = divmod(x, 1000)
|
||||
if y == 0:
|
||||
continue
|
||||
yx = self.cardinal3(y) + b
|
||||
if b == ' هزار' and y == 1:
|
||||
yx = 'هزار'
|
||||
if res == '':
|
||||
res = yx
|
||||
else:
|
||||
res = yx + farsiSeperator + res
|
||||
return res
|
||||
|
||||
def fractional(self, number, level):
|
||||
if number == 5:
|
||||
return "نیم"
|
||||
x = self.cardinalPos(number)
|
||||
ld3, lm3 = divmod(level, 3)
|
||||
ltext = (farsiFrac[lm3] + " " + farsiFracBig[ld3]).strip()
|
||||
return x + " " + ltext
|
||||
|
||||
def to_currency(self, value):
|
||||
return self.to_cardinal(value) + " تومان"
|
||||
|
||||
def to_ordinal(self, number):
|
||||
r = self.to_cardinal(number)
|
||||
if r[-1] == 'ه' and r[-2] == 'س':
|
||||
return r[:-1] + 'وم'
|
||||
return r + 'م'
|
||||
|
||||
def to_year(self, value):
|
||||
return self.to_cardinal(value)
|
||||
|
||||
@staticmethod
|
||||
def to_ordinal_num(value):
|
||||
return str(value)+"م"
|
||||
|
||||
def to_cardinal(self, number):
|
||||
if number < 0:
|
||||
return "منفی " + self.to_cardinal(-number)
|
||||
if number == 0:
|
||||
return "صفر"
|
||||
x, y, level = self.float2tuple(number)
|
||||
if y == 0:
|
||||
return self.cardinalPos(x)
|
||||
if x == 0:
|
||||
return self.fractional(y, level)
|
||||
return self.cardinalPos(x) + farsiSeperator + self.fractional(y, level)
|
||||
736
path/to/venv/lib/python3.12/site-packages/num2words/lang_FI.py
Normal file
736
path/to/venv/lib/python3.12/site-packages/num2words/lang_FI.py
Normal file
@@ -0,0 +1,736 @@
|
||||
# -*- 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, print_function, unicode_literals
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
from . import lang_EU
|
||||
|
||||
GENERIC_CENTS = ('sentti', 'senttiä')
|
||||
GENERIC_CENTAVOS = ('centavo', 'centavoa')
|
||||
|
||||
# grammatical cases
|
||||
NOM = 10 # nominative: the dictionary form
|
||||
GEN = 11 # genitive: ~of/'s
|
||||
ACC = 12 # accusative: not used; either nominative or genitive
|
||||
PTV = 13 # partitive: as an object
|
||||
# locative cases (internal)
|
||||
INE = 14 # inessive: in
|
||||
ELA = 15 # elative: from/out of
|
||||
ILL = 16 # illative: into
|
||||
# locative cases (external)
|
||||
ADE = 17 # adessive: at/on
|
||||
ABL = 18 # ablative: from (after being at/on, not in)
|
||||
ALL = 19 # allative: to
|
||||
# essive
|
||||
ESS = 20 # essive: as (in the role of)
|
||||
TRANSL = 21 # translative: to (the role of; being sth)
|
||||
# rare
|
||||
INSTRUC = 22 # instructive: with (plural is the same as singular)
|
||||
ABE = 23 # abessive: without
|
||||
COM = 24 # comitative: together with (plural = singular)
|
||||
|
||||
NAME_TO_CASE = {
|
||||
'nominative': NOM,
|
||||
'genitive': GEN,
|
||||
'accusative': ACC,
|
||||
'partitive': PTV,
|
||||
'inessive': INE,
|
||||
'elative': ELA,
|
||||
'illative': ILL,
|
||||
'adessive': ADE,
|
||||
'ablative': ABL,
|
||||
'allative': ALL,
|
||||
'essive': ESS,
|
||||
'translative': TRANSL,
|
||||
'instructive': INSTRUC,
|
||||
'abessive': ABE,
|
||||
'comitative': COM,
|
||||
}
|
||||
|
||||
# https://en.wikibooks.org/wiki/Finnish/Grammar-Vowel_harmony
|
||||
BACK_TO_FRONT = {
|
||||
'a': 'ä',
|
||||
'o': 'ö',
|
||||
'u': 'y',
|
||||
}
|
||||
|
||||
# https://en.wiktionary.org/wiki/Appendix:Finnish_nominal_inflection
|
||||
# CASE: (SINGULAR_SUFFIX+, PLURAL_SUFFIX+)
|
||||
KOTUS_TYPE = {
|
||||
|
||||
# Kotus type 5/risti, no gradation
|
||||
5: {
|
||||
# grammatical
|
||||
NOM: ('i', 'it'),
|
||||
GEN: ('in', 'ien'),
|
||||
PTV: ('ia', 'eja'),
|
||||
# locative, internal
|
||||
INE: ('issa', 'eissa'),
|
||||
ELA: ('ista', 'eista'),
|
||||
ILL: ('iin', 'eihin'),
|
||||
# locative, external
|
||||
ADE: ('illa', 'eilla'),
|
||||
ABL: ('ilta', 'eilta'),
|
||||
ALL: ('ille', 'eille'),
|
||||
# essive
|
||||
ESS: ('ina', 'eina'),
|
||||
TRANSL: ('iksi', 'eiksi'),
|
||||
# rare
|
||||
INSTRUC: ('ein', 'ein'),
|
||||
ABE: ('itta', 'eitta'),
|
||||
COM: ('eine', 'eine'), # works better
|
||||
},
|
||||
|
||||
# Kotus type 7/ovi, no gradation
|
||||
7: {
|
||||
# grammatical
|
||||
NOM: ('i', 'et'),
|
||||
GEN: ('en', 'ien'),
|
||||
PTV: ('ea', 'ia'),
|
||||
# locative, internal
|
||||
INE: ('essa', 'issa'),
|
||||
ELA: ('esta', 'ista'),
|
||||
ILL: ('een', 'iin'),
|
||||
# locative, external
|
||||
ADE: ('ella', 'illa'),
|
||||
ABL: ('elta', 'ilta'),
|
||||
ALL: ('elle', 'ille'),
|
||||
# essive
|
||||
ESS: ('ena', 'ina'),
|
||||
TRANSL: ('eksi', 'iksi'),
|
||||
# rare
|
||||
INSTRUC: ('in', 'in'),
|
||||
ABE: ('etta', 'itta'),
|
||||
COM: ('ine', 'ine'), # works better
|
||||
},
|
||||
|
||||
# Kotus type 8/nalle, no gradation
|
||||
8: {
|
||||
# grammatical
|
||||
NOM: ('e', 'et'),
|
||||
GEN: ('en', ('ejen', 'ein')),
|
||||
PTV: ('ea', 'eja'),
|
||||
# locative, internal
|
||||
INE: ('essa', 'eissa'),
|
||||
ELA: ('esta', 'eista'),
|
||||
ILL: ('een', 'eihin'),
|
||||
# locative, external
|
||||
ADE: ('ella', 'eilla'),
|
||||
ABL: ('elta', 'eilta'),
|
||||
ALL: ('elle', 'eille'),
|
||||
# essive
|
||||
ESS: ('ena', 'eina'),
|
||||
TRANSL: ('eksi', 'eiksi'),
|
||||
# rare
|
||||
INSTRUC: ('ein', 'ein'),
|
||||
ABE: ('etta', 'eitta'),
|
||||
COM: ('eine', 'eine'), # works better
|
||||
},
|
||||
|
||||
# Kotus type 9/kala, t-d gradation (sata)
|
||||
109: {
|
||||
# grammatical
|
||||
NOM: ('ta', 'dat'),
|
||||
GEN: ('dan', ('tojen', 'tain')),
|
||||
PTV: ('taa', 'toja'),
|
||||
# locative, internal
|
||||
INE: ('dassa', 'doissa'),
|
||||
ELA: ('dasta', 'doista'),
|
||||
ILL: ('taan', 'toihin'),
|
||||
# locative, external
|
||||
ADE: ('dalla', 'doilla'),
|
||||
ABL: ('dalta', 'doilta'),
|
||||
ALL: ('dalle', 'doille'),
|
||||
# essive
|
||||
ESS: ('tana', 'toina'),
|
||||
TRANSL: ('daksi', 'doiksi'),
|
||||
# rare
|
||||
INSTRUC: ('doin', 'doin'),
|
||||
ABE: ('datta', 'doitta'),
|
||||
COM: ('toine', 'toine'), # works better
|
||||
},
|
||||
|
||||
# Kotus type 10/koira, no gradation
|
||||
10: {
|
||||
# grammatical
|
||||
NOM: ('a', 'at'),
|
||||
GEN: ('an', ('ien', 'ain')),
|
||||
PTV: ('aa', 'ia'),
|
||||
# locative, internal
|
||||
INE: ('assa', 'issa'),
|
||||
ELA: ('asta', 'ista'),
|
||||
ILL: ('aan', 'iin'),
|
||||
# locative, external
|
||||
ADE: ('alla', 'illa'),
|
||||
ABL: ('alta', 'ilta'),
|
||||
ALL: ('alle', 'ille'),
|
||||
# essive
|
||||
ESS: ('ana', 'ina'),
|
||||
TRANSL: ('aksi', 'iksi'),
|
||||
# rare
|
||||
INSTRUC: ('in', 'in'),
|
||||
ABE: ('atta', 'itta'),
|
||||
COM: ('ine', 'ine'), # works better
|
||||
},
|
||||
|
||||
# Kotus type 27/käsi, t-d gradation
|
||||
27: {
|
||||
# grammatical
|
||||
NOM: ('si', 'det'),
|
||||
GEN: ('den', ('sien', 'tten')),
|
||||
PTV: ('tta', 'sia'),
|
||||
# locative, internal
|
||||
INE: ('dessa', 'sissa'),
|
||||
ELA: ('desta', 'sista'),
|
||||
ILL: ('teen', 'siin'),
|
||||
# locative, external
|
||||
ADE: ('della', 'silla'),
|
||||
ABL: ('delta', 'silta'),
|
||||
ALL: ('delle', 'sille'),
|
||||
# essive
|
||||
ESS: ('tena', 'sina'),
|
||||
TRANSL: ('deksi', 'siksi'),
|
||||
# rare
|
||||
INSTRUC: ('sin', 'sin'),
|
||||
ABE: ('detta', 'sitta'),
|
||||
COM: ('sine', 'sine'), # works better
|
||||
},
|
||||
|
||||
# Kotus type 31/kaksi, t-d gradation
|
||||
31: {
|
||||
# grammatical
|
||||
NOM: ('ksi', 'hdet'),
|
||||
GEN: ('hden', 'ksien'),
|
||||
PTV: ('hta', 'ksia'),
|
||||
# locative, internal
|
||||
INE: ('hdessa', 'ksissa'),
|
||||
ELA: ('hdesta', 'ksista'),
|
||||
ILL: ('hteen', 'ksiin'),
|
||||
# locative, external
|
||||
ADE: ('hdella', 'ksilla'),
|
||||
ABL: ('hdelta', 'ksilta'),
|
||||
ALL: ('hdelle', 'ksille'),
|
||||
# essive
|
||||
ESS: ('htena', 'ksina'),
|
||||
TRANSL: ('hdeksi', 'ksiksi'),
|
||||
# rare
|
||||
INSTRUC: ('ksin', 'ksin'),
|
||||
ABE: ('hdetta', 'ksitta'),
|
||||
COM: ('ksine', 'ksine'), # works better
|
||||
},
|
||||
|
||||
# Kotus type 32/sisar, no gradation
|
||||
32: {
|
||||
# grammatical
|
||||
NOM: ('', 'et'),
|
||||
GEN: ('en', ('ien', 'ten')),
|
||||
PTV: ('ta', 'ia'),
|
||||
# locative, internal
|
||||
INE: ('essa', 'issa'),
|
||||
ELA: ('esta', 'ista'),
|
||||
ILL: ('een', 'iin'),
|
||||
# locative, external
|
||||
ADE: ('ella', 'illa'),
|
||||
ABL: ('elta', 'ilta'),
|
||||
ALL: ('elle', 'ille'),
|
||||
# essive
|
||||
ESS: ('ena', 'ina'),
|
||||
TRANSL: ('eksi', 'iksi'),
|
||||
# rare
|
||||
INSTRUC: ('in', 'in'),
|
||||
ABE: ('etta', 'itta'),
|
||||
COM: ('ine', 'ine'), # works better
|
||||
},
|
||||
|
||||
# Kotus type 38/nainen, no gradation
|
||||
38: {
|
||||
# grammatical
|
||||
NOM: ('nen', 'set'),
|
||||
GEN: ('sen', ('sten', 'sien')),
|
||||
PTV: ('sta', 'sia'),
|
||||
# locative, internal
|
||||
INE: ('sessa', 'sissa'),
|
||||
ELA: ('sesta', 'sista'),
|
||||
ILL: ('seen', 'siin'),
|
||||
# locative, external
|
||||
ADE: ('sella', 'silla'),
|
||||
ABL: ('selta', 'silta'),
|
||||
ALL: ('selle', 'sille'),
|
||||
# essive
|
||||
ESS: ('sena', 'sina'),
|
||||
TRANSL: ('seksi', 'siksi'),
|
||||
# rare
|
||||
INSTRUC: ('sin', 'sin'),
|
||||
ABE: ('setta', 'sitta'),
|
||||
COM: ('sine', 'sine'), # works better
|
||||
},
|
||||
|
||||
# Kotus type 45/kahdeksas, nt-nn gradation
|
||||
45: {
|
||||
# grammatical
|
||||
NOM: ('s', 'nnet'),
|
||||
GEN: ('nnen', 'nsien'),
|
||||
PTV: ('tta', 'nsia'),
|
||||
# locative, internal
|
||||
INE: ('nnessa', 'nsissa'),
|
||||
ELA: ('nnesta', 'nsista'),
|
||||
ILL: ('nteen', 'nsiin'),
|
||||
# locative, external
|
||||
ADE: ('nnella', 'nsilla'),
|
||||
ABL: ('nnelta', 'nsilta'),
|
||||
ALL: ('nnelle', 'nsille'),
|
||||
# essive
|
||||
ESS: ('ntena', 'nsina'),
|
||||
TRANSL: ('nneksi', 'nsiksi'),
|
||||
# rare
|
||||
INSTRUC: ('nsin', 'nsin'),
|
||||
ABE: ('nnetta', 'nsitta'),
|
||||
COM: ('nsine', 'nsine'), # works better
|
||||
},
|
||||
|
||||
# Kotus type 46/tuhat, nt-nn gradation
|
||||
46: {
|
||||
# grammatical
|
||||
NOM: ('t', 'nnet'),
|
||||
GEN: ('nnen', ('nsien', 'nten')),
|
||||
PTV: ('tta', 'nsia'),
|
||||
# locative, internal
|
||||
INE: ('nnessa', 'nsissa'),
|
||||
ELA: ('nnesta', 'nsista'),
|
||||
ILL: ('nteen', 'nsiin'),
|
||||
# locative, external
|
||||
ADE: ('nnella', 'nsilla'),
|
||||
ABL: ('nnelta', 'nsilta'),
|
||||
ALL: ('nnelle', 'nsille'),
|
||||
# essive
|
||||
ESS: ('ntena', 'nsina'),
|
||||
TRANSL: ('nneksi', 'nsiksi'),
|
||||
# rare
|
||||
INSTRUC: ('nsin', 'nsin'),
|
||||
ABE: ('nnetta', 'nsitta'),
|
||||
COM: ('nsine', 'nsine'), # works better
|
||||
},
|
||||
}
|
||||
|
||||
# kolme
|
||||
KOTUS_TYPE[108] = {
|
||||
c: (KOTUS_TYPE[8][c][0], KOTUS_TYPE[7][c][1])
|
||||
for c in KOTUS_TYPE[8]
|
||||
}
|
||||
KOTUS_TYPE[108][INSTRUC] = ('en', 'in')
|
||||
KOTUS_TYPE[108][ABE] = ('etta', 'itta')
|
||||
KOTUS_TYPE[108][COM] = ('ine', 'ine')
|
||||
|
||||
# seitsemän, kahdeksan, yhdeksän
|
||||
KOTUS_TYPE[110] = KOTUS_TYPE[10].copy()
|
||||
KOTUS_TYPE[110][NOM] = ('an', 'at')
|
||||
|
||||
# kymmenen
|
||||
KOTUS_TYPE[132] = KOTUS_TYPE[32].copy()
|
||||
KOTUS_TYPE[132][NOM] = ('en', 'et')
|
||||
|
||||
|
||||
def inflect(parts, options):
|
||||
if not isinstance(parts, list):
|
||||
parts = [parts]
|
||||
|
||||
out = ''
|
||||
for part in parts:
|
||||
# part is plain text, concat and continue
|
||||
if not isinstance(part, tuple):
|
||||
out += part
|
||||
continue
|
||||
# predefined case (kaksikymmentä, ...)
|
||||
tmp_case = options.case
|
||||
if len(part) == 3:
|
||||
# override singular nominative only
|
||||
if options.case == NOM and not options.plural:
|
||||
tmp_case = part[2]
|
||||
part = part[:2]
|
||||
# stem and suffix
|
||||
stem, kotus_type = part
|
||||
suffix = KOTUS_TYPE[kotus_type][tmp_case][options.plural]
|
||||
# many choices, choose preferred or first
|
||||
if isinstance(suffix, tuple):
|
||||
common = set(suffix) & set(options.prefer or set())
|
||||
if len(common) == 1:
|
||||
suffix = common.pop()
|
||||
else:
|
||||
suffix = suffix[0]
|
||||
# apply vowel harmony
|
||||
if not set(BACK_TO_FRONT) & set(stem):
|
||||
for back, front in BACK_TO_FRONT.items():
|
||||
suffix = suffix.replace(back, front)
|
||||
# concat
|
||||
out += stem + suffix
|
||||
|
||||
return out
|
||||
|
||||
|
||||
class Options(object):
|
||||
def __init__(self, ordinal, case, plural, prefer):
|
||||
self.ordinal = ordinal
|
||||
self.case = case
|
||||
self.plural = plural
|
||||
self.prefer = prefer
|
||||
|
||||
def variation(self, ordinal=None, case=None, plural=None, prefer=None):
|
||||
return Options(
|
||||
ordinal if ordinal is not None else self.ordinal,
|
||||
case if case is not None else self.case,
|
||||
plural if plural is not None else self.plural,
|
||||
prefer if prefer is not None else self.prefer,
|
||||
)
|
||||
|
||||
|
||||
class Num2Word_FI(lang_EU.Num2Word_EU):
|
||||
CURRENCY_FORMS = {
|
||||
'BRL': (('real', 'realia'), GENERIC_CENTAVOS),
|
||||
'CHF': (('frangi', 'frangia'), ('rappen', 'rappenia')),
|
||||
'CNY': (('juan', 'juania'), ('fen', 'feniä')),
|
||||
'EUR': (('euro', 'euroa'), GENERIC_CENTS),
|
||||
'FIM': (('markka', 'markkaa'), ('penni', 'penniä')), # historical
|
||||
'INR': (('rupia', 'rupiaa'), ('paisa', 'paisaa')),
|
||||
'JPY': (('jeni', 'jeniä'), ('sen', 'seniä')), # rare subunit
|
||||
'KRW': (('won', 'wonia'), ('jeon', 'jeonia')), # rare subunit
|
||||
'KPW': (('won', 'wonia'), ('chon', 'chonia')), # rare subunit
|
||||
'MXN': (('peso', 'pesoa'), GENERIC_CENTAVOS),
|
||||
'RUB': (('rupla', 'ruplaa'), ('kopeekka', 'kopeekkaa')),
|
||||
'TRY': (('liira', 'liiraa'), ('kuruş', 'kuruşia')),
|
||||
'ZAR': (('randi', 'randia'), GENERIC_CENTS),
|
||||
}
|
||||
|
||||
# crowns
|
||||
for curr_code in 'DKK', 'ISK', 'NOK', 'SEK':
|
||||
CURRENCY_FORMS[curr_code] = (('kruunu', 'kruunua'), ('äyri', 'äyriä'))
|
||||
|
||||
# dollars
|
||||
for curr_code in 'AUD', 'CAD', 'HKD', 'NZD', 'SGD', 'USD':
|
||||
CURRENCY_FORMS[curr_code] = (
|
||||
('dollari', 'dollaria'), GENERIC_CENTS)
|
||||
|
||||
# pounds
|
||||
for curr_code in ('GBP',):
|
||||
CURRENCY_FORMS[curr_code] = (('punta', 'puntaa'), ('penny', 'pennyä'))
|
||||
|
||||
CURRENCY_ADJECTIVES = {
|
||||
'AUD': 'Australian',
|
||||
'BRL': 'Brasilian',
|
||||
'CAD': 'Kanadan',
|
||||
'CHF': 'Sveitsin',
|
||||
'DKK': 'Tanskan',
|
||||
'FIM': 'Suomen', # historical
|
||||
'GBP': 'Englannin',
|
||||
'HKD': 'Hongkongin',
|
||||
'INR': 'Intian',
|
||||
'ISK': 'Islannin',
|
||||
'KRW': 'Etelä-Korean',
|
||||
'KPW': 'Pohjois-Korean',
|
||||
'MXN': 'Meksikon',
|
||||
'NOK': 'Norjan',
|
||||
'NZD': 'Uuden-Seelannin',
|
||||
'RUB': 'Venäjän',
|
||||
'SEK': 'Ruotsin',
|
||||
'SGD': 'Singaporen',
|
||||
'TRY': 'Turkin',
|
||||
'USD': 'Yhdysvaltain',
|
||||
'ZAR': 'Etelä-Afrikan',
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.ords = OrderedDict()
|
||||
super(Num2Word_FI, self).__init__()
|
||||
|
||||
def set_numwords(self):
|
||||
self.set_high_numwords(self.high_numwords)
|
||||
self.set_mid_numwords(self.mid_numwords, self.mid_ords)
|
||||
self.set_low_numwords(self.low_numwords, self.low_ords)
|
||||
|
||||
def set_high_numwords(self, high):
|
||||
# references:
|
||||
# https://fi.wikipedia.org/wiki/Suurten_lukujen_nimet
|
||||
# https://en.wikipedia.org/wiki/Names_of_large_numbers#Standard_dictionary_numbers
|
||||
|
||||
# translate to Finnish
|
||||
replacements = [
|
||||
("qu", "kv"),
|
||||
("x", "ks"),
|
||||
("c", "k"),
|
||||
("kent", "sent"), # applied after c -> k to cent
|
||||
]
|
||||
translated = []
|
||||
for i, numword in enumerate(high):
|
||||
# notes:
|
||||
# - 1e6**9 can be either noviljoona or noniljoona
|
||||
# - 1e6**38 and above are untested
|
||||
|
||||
# 1e6**6 is sekstiljoona but 1e6**16 is sedekiljoona
|
||||
if numword.startswith("sex") and numword != "sext":
|
||||
numword = numword.replace("sex", "se")
|
||||
# 1e6**7 is septiljoona but 1e6**17 is septendekiljoona
|
||||
elif numword.startswith("sept") and numword != "sept":
|
||||
numword = "septen" + numword[len("sept"):]
|
||||
# 1e6**8 is oktiljoona but 1e6**18 is duodevigintiljoona
|
||||
# (2 from 20)
|
||||
elif numword.startswith("octo"):
|
||||
numword = high[i + -10]
|
||||
numword = "duode" + numword[len("octo"):]
|
||||
# 1e6**9 is noniljoona but 1e6**19 is undevigintiljoona (1 from 20)
|
||||
elif numword.startswith("nove"):
|
||||
numword = high[i + -10]
|
||||
numword = "unde" + numword[len("nove") + 1:]
|
||||
|
||||
# apply general replacements to all numwords
|
||||
for repl in replacements:
|
||||
numword = numword.replace(repl[0], repl[1])
|
||||
translated.append(numword)
|
||||
|
||||
max = 6 * len(translated)
|
||||
for word, n in zip(translated, range(max, 0, -6)):
|
||||
if n == 6:
|
||||
# irregularity considering short scale and long scale
|
||||
self.cards[10 ** 9] = ("miljard", 5)
|
||||
self.ords[10 ** 9] = ("miljardi", 45)
|
||||
self.cards[10 ** n] = (word + "iljoon", 10)
|
||||
self.ords[10 ** n] = (word + "iljoona", 45)
|
||||
|
||||
def set_mid_numwords(self, cards, ords):
|
||||
for key, val in cards:
|
||||
self.cards[key] = val
|
||||
for key, val in ords:
|
||||
self.ords[key] = val
|
||||
|
||||
def set_low_numwords(self, cards, ords):
|
||||
for key, val in cards:
|
||||
self.cards[key] = val
|
||||
for key, val in ords:
|
||||
self.ords[key] = val
|
||||
|
||||
def setup(self):
|
||||
super(Num2Word_FI, self).setup()
|
||||
|
||||
self.negword = "miinus "
|
||||
self.pointword = "pilkku"
|
||||
self.exclude_title = ["pilkku", "miinus"]
|
||||
|
||||
self.mid_numwords = [
|
||||
(1000, ("tuha", 46)),
|
||||
(100, ("sa", 109)),
|
||||
(90, [("yhdeks", 110), ("kymmen", 132, PTV)]),
|
||||
(80, [("kahdeks", 110), ("kymmen", 132, PTV)]),
|
||||
(70, [("seitsem", 110), ("kymmen", 132, PTV)]),
|
||||
(60, [("kuu", 27), ("kymmen", 132, PTV)]),
|
||||
(50, [("vii", 27), ("kymmen", 132, PTV)]),
|
||||
(40, [("nelj", 10), ("kymmen", 132, PTV)]),
|
||||
(30, [("kolm", 108), ("kymmen", 132, PTV)]),
|
||||
]
|
||||
|
||||
self.mid_ords = [
|
||||
(1000, ("tuhanne", 45)),
|
||||
(100, ("sada", 45)),
|
||||
(90, [("yhdeksä", 45), ("kymmene", 45)]),
|
||||
(80, [("kahdeksa", 45), ("kymmene", 45)]),
|
||||
(70, [("seitsemä", 45), ("kymmene", 45)]),
|
||||
(60, [("kuude", 45), ("kymmene", 45)]),
|
||||
(50, [("viide", 45), ("kymmene", 45)]),
|
||||
(40, [("neljä", 45), ("kymmene", 45)]),
|
||||
(30, [("kolma", 45), ("kymmene", 45)]),
|
||||
]
|
||||
|
||||
self.low_numwords = [
|
||||
(20, [("ka", 31), ("kymmen", 132, PTV)]),
|
||||
(19, [("yhdeks", 110), "toista"]),
|
||||
(18, [("kahdeks", 110), "toista"]),
|
||||
(17, [("seitsem", 110), "toista"]),
|
||||
(16, [("kuu", 27), "toista"]),
|
||||
(15, [("vii", 27), "toista"]),
|
||||
(14, [("nelj", 10), "toista"]),
|
||||
(13, [("kolm", 108), "toista"]),
|
||||
(12, [("ka", 31), "toista"]),
|
||||
(11, [("y", 31), "toista"]),
|
||||
(10, ("kymmen", 132)),
|
||||
(9, ("yhdeks", 110)),
|
||||
(8, ("kahdeks", 110)),
|
||||
(7, ("seitsem", 110)),
|
||||
(6, ("kuu", 27)),
|
||||
(5, ("vii", 27)),
|
||||
(4, ("nelj", 10)),
|
||||
(3, ("kolm", 108)),
|
||||
(2, ("ka", 31)),
|
||||
(1, ("y", 31)),
|
||||
(0, ("noll", 10)),
|
||||
]
|
||||
|
||||
self.low_ords = [
|
||||
(20, [("kahde", 45), ("kymmene", 45)]),
|
||||
(19, [("yhdeksä", 45), "toista"]),
|
||||
(18, [("kahdeksa", 45), "toista"]),
|
||||
(17, [("seitsemä", 45), "toista"]),
|
||||
(16, [("kuude", 45), "toista"]),
|
||||
(15, [("viide", 45), "toista"]),
|
||||
(14, [("neljä", 45), "toista"]),
|
||||
(13, [("kolma", 45), "toista"]),
|
||||
(12, [("kahde", 45), "toista"]),
|
||||
(11, [("yhde", 45), "toista"]),
|
||||
(10, ("kymmene", 45)),
|
||||
(9, ("yhdeksä", 45)),
|
||||
(8, ("kahdeksa", 45)),
|
||||
(7, ("seitsemä", 45)),
|
||||
(6, ("kuude", 45)),
|
||||
(5, ("viide", 45)),
|
||||
(4, ("neljä", 45)),
|
||||
(3, ("kolma", 45)),
|
||||
(2, ("toi", 38)),
|
||||
(1, ("ensimmäi", 38)),
|
||||
(0, ("nolla", 45)),
|
||||
]
|
||||
|
||||
def merge(self, lpair, rpair, options):
|
||||
ltext, lnum = lpair
|
||||
rtext, rnum = rpair
|
||||
|
||||
# http://www.kielitoimistonohjepankki.fi/ohje/49
|
||||
fmt = "%s%s"
|
||||
# ignore lpair if lnum is 1
|
||||
if lnum == 1:
|
||||
rtext = inflect(rtext, options)
|
||||
return (rtext, rnum)
|
||||
# rnum is added to lnum
|
||||
elif lnum > rnum:
|
||||
ltext = inflect(ltext, options)
|
||||
rtext = inflect(rtext, options)
|
||||
# separate groups with space
|
||||
if lnum >= 1000:
|
||||
fmt = "%s %s"
|
||||
return (fmt % (ltext, rtext), lnum + rnum)
|
||||
# rnum is multiplied by lnum
|
||||
elif lnum < rnum:
|
||||
if options.ordinal:
|
||||
# kahdessadas, not toinensadas
|
||||
if lnum == 2:
|
||||
ltext = ("kahde", 45)
|
||||
rtext = inflect(rtext, options)
|
||||
else:
|
||||
# kaksituhatta but kahdettuhannet
|
||||
rcase = options.case
|
||||
if options.case == NOM and not options.plural:
|
||||
rcase = PTV
|
||||
rtext = inflect(rtext, options.variation(case=rcase))
|
||||
ltext = inflect(ltext, options)
|
||||
return (fmt % (ltext, rtext), lnum * rnum)
|
||||
|
||||
def to_cardinal(self, value, case='nominative', plural=False, prefer=None):
|
||||
case = NAME_TO_CASE[case]
|
||||
options = Options(False, case, plural, prefer)
|
||||
try:
|
||||
assert int(value) == value
|
||||
except (ValueError, TypeError, AssertionError):
|
||||
if case != NOM:
|
||||
raise NotImplementedError(
|
||||
"Cases other than nominative are not implemented for "
|
||||
"cardinal floating point numbers.")
|
||||
return self.to_cardinal_float(value)
|
||||
|
||||
out = ""
|
||||
if value < 0:
|
||||
value = abs(value)
|
||||
out = self.negword
|
||||
|
||||
if value >= self.MAXVAL:
|
||||
raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL))
|
||||
|
||||
val = self.splitnum(value, options)
|
||||
words, num = self.clean(val, options)
|
||||
return self.title(out + words)
|
||||
|
||||
def to_ordinal(self, value, case='nominative', plural=False, prefer=None):
|
||||
case = NAME_TO_CASE[case]
|
||||
options = Options(True, case, plural, prefer)
|
||||
|
||||
self.verify_ordinal(value)
|
||||
if value >= self.MAXVAL:
|
||||
raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL))
|
||||
|
||||
val = self.splitnum(value, options)
|
||||
words, num = self.clean(val, options)
|
||||
return self.title(words)
|
||||
|
||||
def to_ordinal_num(self, value, case='nominative', plural=False):
|
||||
case = NAME_TO_CASE[case]
|
||||
raise NotImplementedError
|
||||
|
||||
def to_year(self, val, suffix=None, longval=True):
|
||||
suffix = suffix or ""
|
||||
if val < 0:
|
||||
val = abs(val)
|
||||
suffix = suffix or " ennen ajanlaskun alkua"
|
||||
return self.to_cardinal(val).replace(" ", "") + suffix
|
||||
|
||||
def to_currency(self, val, currency="EUR", cents=True, separator=" ja",
|
||||
adjective=False):
|
||||
return super(Num2Word_FI, self).to_currency(
|
||||
val, currency=currency, cents=cents, separator=separator,
|
||||
adjective=adjective)
|
||||
|
||||
def splitnum(self, value, options):
|
||||
elems = self.ords if options.ordinal else self.cards
|
||||
for elem in elems:
|
||||
if elem > value:
|
||||
continue
|
||||
|
||||
out = []
|
||||
if value == 0:
|
||||
div, mod = 1, 0
|
||||
else:
|
||||
div, mod = divmod(value, elem)
|
||||
|
||||
if div == 1:
|
||||
out.append((elems[1], 1))
|
||||
else:
|
||||
if div == value: # The system tallies, eg Roman Numerals
|
||||
return [(div * elems[elem], div*elem)]
|
||||
out.append(self.splitnum(div, options))
|
||||
|
||||
out.append((elems[elem], elem))
|
||||
|
||||
if mod:
|
||||
out.append(self.splitnum(mod, options))
|
||||
|
||||
return out
|
||||
|
||||
def clean(self, val, options):
|
||||
out = val
|
||||
while len(val) != 1:
|
||||
out = []
|
||||
left, right = val[:2]
|
||||
if isinstance(left, tuple) and isinstance(right, tuple):
|
||||
out.append(self.merge(left, right, options))
|
||||
if val[2:]:
|
||||
out.append(val[2:])
|
||||
else:
|
||||
for elem in val:
|
||||
if isinstance(elem, list):
|
||||
if len(elem) == 1:
|
||||
out.append(elem[0])
|
||||
else:
|
||||
out.append(self.clean(elem, options))
|
||||
else:
|
||||
out.append(elem)
|
||||
val = out
|
||||
return out[0]
|
||||
110
path/to/venv/lib/python3.12/site-packages/num2words/lang_FR.py
Normal file
110
path/to/venv/lib/python3.12/site-packages/num2words/lang_FR.py
Normal file
@@ -0,0 +1,110 @@
|
||||
# -*- 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 print_function, unicode_literals
|
||||
|
||||
from .lang_EU import Num2Word_EU
|
||||
|
||||
|
||||
class Num2Word_FR(Num2Word_EU):
|
||||
CURRENCY_FORMS = {
|
||||
'EUR': (('euro', 'euros'), ('centime', 'centimes')),
|
||||
'USD': (('dollar', 'dollars'), ('cent', 'cents')),
|
||||
'FRF': (('franc', 'francs'), ('centime', 'centimes')),
|
||||
'GBP': (('livre', 'livres'), ('penny', 'pence')),
|
||||
'CNY': (('yuan', 'yuans'), ('fen', 'jiaos')),
|
||||
}
|
||||
|
||||
def setup(self):
|
||||
Num2Word_EU.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 (abs(%s) > %s)."
|
||||
)
|
||||
self.exclude_title = ["et", "virgule", "moins"]
|
||||
self.mid_numwords = [(1000, "mille"), (100, "cent"),
|
||||
(80, "quatre-vingts"), (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
|
||||
else:
|
||||
if (not (cnum - 80) % 100
|
||||
or (not cnum % 100 and cnum < 1000))\
|
||||
and nnum < 1000000 \
|
||||
and ctext[-1] == "s":
|
||||
ctext = ctext[:-1]
|
||||
if cnum < 1000 and nnum != 1000 and \
|
||||
ntext[-1] != "s" and not nnum % 100:
|
||||
ntext += "s"
|
||||
|
||||
if nnum < cnum < 100:
|
||||
if nnum % 10 == 1 and cnum != 80:
|
||||
return ("%s et %s" % (ctext, ntext), cnum + nnum)
|
||||
return ("%s-%s" % (ctext, ntext), cnum + nnum)
|
||||
if 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 += "er" if value == 1 else "me"
|
||||
return out
|
||||
|
||||
def to_currency(self, val, currency='EUR', cents=True, separator=' et',
|
||||
adjective=False):
|
||||
result = super(Num2Word_FR, self).to_currency(
|
||||
val, currency=currency, cents=cents, separator=separator,
|
||||
adjective=adjective)
|
||||
return result
|
||||
@@ -0,0 +1,49 @@
|
||||
# -*- 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 print_function, unicode_literals
|
||||
|
||||
from .lang_FR import Num2Word_FR
|
||||
|
||||
|
||||
class Num2Word_FR_BE(Num2Word_FR):
|
||||
def setup(self):
|
||||
Num2Word_FR.setup(self)
|
||||
|
||||
self.mid_numwords = [(1000, "mille"), (100, "cent"), (90, "nonante"),
|
||||
(80, "quatre-vingt"), (70, "septante"),
|
||||
(60, "soixante"), (50, "cinquante"),
|
||||
(40, "quarante"), (30, "trente")]
|
||||
|
||||
def merge(self, curr, next):
|
||||
ctext, cnum, ntext, nnum = curr + next
|
||||
|
||||
if cnum == 1:
|
||||
if nnum < 1000000:
|
||||
return next
|
||||
|
||||
if cnum < 1000 and nnum != 1000 and\
|
||||
ntext[-1] != "s" and not nnum % 100:
|
||||
ntext += "s"
|
||||
|
||||
if nnum < cnum < 100:
|
||||
if nnum % 10 == 1:
|
||||
return ("%s et %s" % (ctext, ntext), cnum + nnum)
|
||||
return ("%s-%s" % (ctext, ntext), cnum + nnum)
|
||||
if nnum > cnum:
|
||||
return ("%s %s" % (ctext, ntext), cnum * nnum)
|
||||
return ("%s %s" % (ctext, ntext), cnum + nnum)
|
||||
@@ -0,0 +1,48 @@
|
||||
# -*- 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 print_function, unicode_literals
|
||||
|
||||
from .lang_FR import Num2Word_FR
|
||||
|
||||
|
||||
class Num2Word_FR_CH(Num2Word_FR):
|
||||
def setup(self):
|
||||
Num2Word_FR.setup(self)
|
||||
|
||||
self.mid_numwords = [(1000, "mille"), (100, "cent"), (90, "nonante"),
|
||||
(80, "huitante"), (70, "septante"),
|
||||
(60, "soixante"), (50, "cinquante"),
|
||||
(40, "quarante"), (30, "trente")]
|
||||
|
||||
def merge(self, curr, next):
|
||||
ctext, cnum, ntext, nnum = curr + next
|
||||
|
||||
if cnum == 1:
|
||||
if nnum < 1000000:
|
||||
return next
|
||||
|
||||
if cnum < 1000 and nnum != 1000 and\
|
||||
ntext[-1] != "s" and not nnum % 100:
|
||||
ntext += "s"
|
||||
|
||||
if nnum < cnum < 100:
|
||||
if nnum % 10 == 1:
|
||||
return ("%s et %s" % (ctext, ntext), cnum + nnum)
|
||||
return ("%s-%s" % (ctext, ntext), cnum + nnum)
|
||||
if nnum > cnum:
|
||||
return ("%s %s" % (ctext, ntext), cnum * nnum)
|
||||
return ("%s %s" % (ctext, ntext), cnum + nnum)
|
||||
@@ -0,0 +1,33 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
|
||||
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
|
||||
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from .lang_FR import Num2Word_FR
|
||||
|
||||
|
||||
class Num2Word_FR_DZ(Num2Word_FR):
|
||||
CURRENCY_FORMS = {
|
||||
'DIN': (('dinard', 'dinards'), ('centime', 'centimes')),
|
||||
}
|
||||
|
||||
def to_currency(self, val, currency='DIN', cents=True, separator=' et',
|
||||
adjective=False):
|
||||
result = super(Num2Word_FR, self).to_currency(
|
||||
val, currency=currency, cents=cents, separator=separator,
|
||||
adjective=adjective)
|
||||
return result
|
||||
327
path/to/venv/lib/python3.12/site-packages/num2words/lang_HE.py
Normal file
327
path/to/venv/lib/python3.12/site-packages/num2words/lang_HE.py
Normal file
@@ -0,0 +1,327 @@
|
||||
# -*- 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 print_function, unicode_literals
|
||||
|
||||
from .base import Num2Word_Base
|
||||
from .compat import to_s
|
||||
from .currency import parse_currency_parts
|
||||
from .utils import get_digits, splitbyx
|
||||
|
||||
ZERO = (u'אפס',)
|
||||
|
||||
ONES = {
|
||||
1: (u'אחת', u'אחד', u'אחת', u'אחד',
|
||||
u'ראשונה', u'ראשון', u'ראשונות', u'ראשונים'),
|
||||
2: (u'שתיים', u'שניים', u'שתי', u'שני',
|
||||
u'שנייה', u'שני', u'שניות', u'שניים'),
|
||||
3: (u'שלוש', u'שלושה', u'שלוש', u'שלושת',
|
||||
u'שלישית', u'שלישי', u'שלישיות', u'שלישיים'),
|
||||
4: (u'ארבע', u'ארבעה', u'ארבע', u'ארבעת',
|
||||
u'רביעית', u'רביעי', u'רביעיות', u'רביעיים'),
|
||||
5: (u'חמש', u'חמישה', u'חמש', u'חמשת',
|
||||
u'חמישית', u'חמישי', u'חמישיות', u'חמישיים'),
|
||||
6: (u'שש', u'שישה', u'שש', u'ששת',
|
||||
u'שישית', u'שישי', u'שישיות', u'שישיים'),
|
||||
7: (u'שבע', u'שבעה', u'שבע', u'שבעת',
|
||||
u'שביעית', u'שביעי', u'שביעיות', u'שביעיים'),
|
||||
8: (u'שמונה', u'שמונה', u'שמונה', u'שמונת',
|
||||
u'שמינית', u'שמיני', u'שמיניות', u'שמיניים'),
|
||||
9: (u'תשע', u'תשעה', u'תשע', u'תשעת',
|
||||
u'תשיעית', u'תשיעי', u'תשיעיות', u'תשיעיים'),
|
||||
}
|
||||
|
||||
TENS = {
|
||||
0: (u'עשר', u'עשרה', u'עשר', u'עשרת',
|
||||
u'עשירית', u'עשירי', u'עשיריות', u'עשיריים'),
|
||||
1: (u'עשרה', u'עשר'),
|
||||
2: (u'שתים עשרה', u'שנים עשר'),
|
||||
}
|
||||
|
||||
TWENTIES = {
|
||||
2: (u'עשרים',),
|
||||
3: (u'שלושים',),
|
||||
4: (u'ארבעים',),
|
||||
5: (u'חמישים',),
|
||||
6: (u'שישים',),
|
||||
7: (u'שבעים',),
|
||||
8: (u'שמונים',),
|
||||
9: (u'תשעים',),
|
||||
}
|
||||
|
||||
HUNDREDS = {
|
||||
1: (u'מאה', u'מאת'),
|
||||
2: (u'מאתיים',),
|
||||
3: (u'מאות',)
|
||||
}
|
||||
|
||||
THOUSANDS = {
|
||||
1: (u'אלף',),
|
||||
2: (u'אלפיים',),
|
||||
3: (u'אלפים', 'אלפי'),
|
||||
}
|
||||
|
||||
LARGE = {
|
||||
1: (u'מיליון', u'מיליוני'),
|
||||
2: (u'מיליארד', u'מיליארדי'),
|
||||
3: (u'טריליון', u'טריליוני'),
|
||||
4: (u'קוודריליון', u'קוודריליוני'),
|
||||
5: (u'קווינטיליון', u'קווינטיליוני'),
|
||||
6: (u'סקסטיליון', u'סקסטיליוני'),
|
||||
7: (u'ספטיליון', u'ספטיליוני'),
|
||||
8: (u'אוקטיליון', u'אוקטיליוני'),
|
||||
9: (u'נוניליון', u'נוניליוני'),
|
||||
10: (u'דסיליון', u'דסיליוני'),
|
||||
11: (u'אונדסיליון', u'אונדסיליוני'),
|
||||
12: (u'דואודסיליון', u'דואודסיליוני'),
|
||||
13: (u'טרדסיליון', u'טרדסיליוני'),
|
||||
14: (u'קווטואורדסיליון', u'קווטואורדסיליוני'),
|
||||
15: (u'קווינדסיליון', u'קווינדסיליוני'),
|
||||
16: (u'סקסדסיליון', u'סקסדסיליוני'),
|
||||
17: (u'ספטנדסיליון', u'ספטנדסיליוני'),
|
||||
18: (u'אוקטודסיליון', u'אוקטודסיליוני'),
|
||||
19: (u'נובמדסיליון', u'נובמדסיליוני'),
|
||||
20: (u'ויגינטיליון', u'ויגינטיליוני')
|
||||
}
|
||||
|
||||
AND = u'ו'
|
||||
|
||||
DEF = u'ה'
|
||||
|
||||
MAXVAL = int('1' + '0'*66)
|
||||
|
||||
|
||||
def chunk2word(n, i, x, gender='f', construct=False,
|
||||
ordinal=False, plural=False):
|
||||
words = []
|
||||
n1, n2, n3 = get_digits(x)
|
||||
|
||||
if n3 > 0:
|
||||
if construct and n == 100:
|
||||
words.append(HUNDREDS[n3][1])
|
||||
elif n3 <= 2:
|
||||
words.append(HUNDREDS[n3][0])
|
||||
else:
|
||||
words.append(ONES[n3][0] + ' ' + HUNDREDS[3][0])
|
||||
|
||||
if n2 > 1:
|
||||
words.append(TWENTIES[n2][0])
|
||||
|
||||
if i == 0 or x >= 11:
|
||||
male = gender == 'm' or i > 0
|
||||
cop = (2*(construct and i == 0)+4*ordinal+2*plural) * (n < 11)
|
||||
if n2 == 1:
|
||||
if n1 == 0:
|
||||
words.append(TENS[n1][male + cop])
|
||||
elif n1 == 2:
|
||||
words.append(TENS[n1][male])
|
||||
else:
|
||||
words.append(ONES[n1][male] + ' ' + TENS[1][male])
|
||||
elif n1 > 0:
|
||||
words.append(ONES[n1][male + cop])
|
||||
|
||||
construct_last = construct and (n % 1000 ** i == 0)
|
||||
|
||||
if i == 1:
|
||||
if x >= 11:
|
||||
words[-1] = words[-1] + ' ' + THOUSANDS[1][0]
|
||||
elif n1 == 0:
|
||||
words.append(TENS[0][3] + ' ' + THOUSANDS[3][construct_last])
|
||||
elif n1 <= 2:
|
||||
words.append(THOUSANDS[n1][0])
|
||||
else:
|
||||
words.append(ONES[n1][3] + ' ' + THOUSANDS[3][construct_last])
|
||||
|
||||
elif i > 1:
|
||||
if x >= 11:
|
||||
words[-1] = words[-1] + ' ' + LARGE[i - 1][construct_last]
|
||||
elif n1 == 0:
|
||||
words.append(TENS[0][1 + 2*construct_last] + ' ' +
|
||||
LARGE[i - 1][construct_last])
|
||||
elif n1 == 1:
|
||||
words.append(LARGE[i - 1][0])
|
||||
else:
|
||||
words.append(ONES[n1][1 + 2*(construct_last or x == 2)] + ' ' +
|
||||
LARGE[i - 1][construct_last])
|
||||
|
||||
return words
|
||||
|
||||
|
||||
def int2word(n, gender='f', construct=False,
|
||||
ordinal=False, definite=False, plural=False):
|
||||
assert n == int(n)
|
||||
assert not construct or not ordinal
|
||||
assert ordinal or (not definite and not plural)
|
||||
if n >= MAXVAL:
|
||||
raise OverflowError('abs(%s) must be less than %s.' % (n, MAXVAL))
|
||||
|
||||
if n == 0:
|
||||
if ordinal:
|
||||
return DEF + ZERO[0]
|
||||
return ZERO[0]
|
||||
|
||||
words = []
|
||||
|
||||
chunks = list(splitbyx(str(n), 3))
|
||||
i = len(chunks)
|
||||
for x in chunks:
|
||||
i -= 1
|
||||
|
||||
if x == 0:
|
||||
continue
|
||||
|
||||
words += chunk2word(n, i, x, gender=gender, construct=construct,
|
||||
ordinal=ordinal, plural=plural)
|
||||
|
||||
# https://hebrew-academy.org.il/2017/01/30/%D7%95-%D7%94%D7%97%D7%99%D7%91%D7%95%D7%A8-%D7%91%D7%9E%D7%A1%D7%A4%D7%A8%D7%99%D7%9D # noqa
|
||||
if len(words) > 1:
|
||||
words[-1] = AND + words[-1]
|
||||
|
||||
if ordinal and (n >= 11 or definite):
|
||||
words[0] = DEF + words[0]
|
||||
|
||||
return ' '.join(words)
|
||||
|
||||
|
||||
class Num2Word_HE(Num2Word_Base):
|
||||
CURRENCY_FORMS = {
|
||||
'ILS': ((u'שקל', u'שקלים'), (u'אגורה', u'אגורות')),
|
||||
'EUR': ((u'אירו', u'אירו'), (u'סנט', u'סנטים')),
|
||||
'USD': ((u'דולר', u'דולרים'), (u'סנט', u'סנטים')),
|
||||
}
|
||||
|
||||
CURRENCY_GENDERS = {
|
||||
'ILS': ('m', 'f'),
|
||||
'EUR': ('m', 'm'),
|
||||
'USD': ('m', 'm'),
|
||||
}
|
||||
|
||||
def __init__(self, makaf='-'):
|
||||
super(Num2Word_HE, self).__init__()
|
||||
self.makaf = makaf
|
||||
|
||||
def setup(self):
|
||||
super(Num2Word_HE, self).setup()
|
||||
self.negword = u'מינוס'
|
||||
self.pointword = u'נקודה'
|
||||
self.MAXVAL = MAXVAL
|
||||
|
||||
def to_cardinal_float(self, value, gender='f'):
|
||||
try:
|
||||
float(value) == value
|
||||
except (ValueError, TypeError, AssertionError, AttributeError):
|
||||
raise TypeError(self.errmsg_nonnum % value)
|
||||
|
||||
pre, post = self.float2tuple(float(value))
|
||||
|
||||
post = str(post)
|
||||
post = '0'*(self.precision - len(post)) + post
|
||||
|
||||
out = [self.to_cardinal(pre, gender=gender)]
|
||||
if self.precision:
|
||||
out.append(self.title(self.pointword))
|
||||
|
||||
for i in range(self.precision):
|
||||
curr = int(post[i])
|
||||
out.append(to_s(self.to_cardinal(curr)))
|
||||
|
||||
return ' '.join(out)
|
||||
|
||||
def to_cardinal(self, value, gender='f', construct=False):
|
||||
try:
|
||||
assert int(value) == value
|
||||
except (ValueError, TypeError, AssertionError):
|
||||
# https://hebrew-academy.org.il/2019/12/03/%D7%A2%D7%9C-%D7%94%D7%91%D7%A2%D7%AA-%D7%94%D7%9E%D7%A1%D7%A4%D7%A8-%D7%94%D7%9E%D7%A2%D7%95%D7%A8%D7%91 # noqa
|
||||
return self.to_cardinal_float(value, gender=gender)
|
||||
|
||||
out = ""
|
||||
if value < 0:
|
||||
value = abs(value)
|
||||
out = "%s " % self.negword.strip()
|
||||
|
||||
if value >= self.MAXVAL:
|
||||
raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL))
|
||||
|
||||
return out + int2word(int(value), gender=gender, construct=construct)
|
||||
|
||||
def to_ordinal(self, value, gender='m', definite=False, plural=False):
|
||||
self.verify_ordinal(value)
|
||||
|
||||
if value >= self.MAXVAL:
|
||||
raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL))
|
||||
|
||||
return int2word(int(value), gender=gender, ordinal=True,
|
||||
definite=definite, plural=plural)
|
||||
|
||||
def pluralize(self, n, forms, currency=None, prefer_singular=False):
|
||||
assert n == int(n)
|
||||
form = 1
|
||||
if n == 1 or prefer_singular and (
|
||||
abs(n) >= 11 or n == 0 or currency != 'ILS'):
|
||||
form = 0
|
||||
return forms[form]
|
||||
|
||||
def to_currency(self, val, currency='ILS', cents=True,
|
||||
separator=AND, adjective=False,
|
||||
prefer_singular=False, prefer_singular_cents=False):
|
||||
left, right, is_negative = parse_currency_parts(val)
|
||||
|
||||
if not separator.startswith(' '):
|
||||
separator = ' ' + separator
|
||||
|
||||
try:
|
||||
cr1, cr2 = self.CURRENCY_FORMS[currency]
|
||||
|
||||
except KeyError:
|
||||
raise NotImplementedError(
|
||||
'Currency code "%s" not implemented for "%s"' %
|
||||
(currency, self.__class__.__name__))
|
||||
|
||||
minus_str = "%s " % self.negword.strip() if is_negative else ""
|
||||
try:
|
||||
gender1, gender2 = self.CURRENCY_GENDERS[currency]
|
||||
except KeyError:
|
||||
gender1 = gender2 = ''
|
||||
|
||||
money_str = self.to_cardinal(left, gender=gender1,
|
||||
construct=left == 2)
|
||||
if cents:
|
||||
cents_str = self.to_cardinal(right, gender=gender2,
|
||||
construct=right == 2)
|
||||
else:
|
||||
cents_str = self._cents_terse(right, currency)
|
||||
sep_parts = separator.split()
|
||||
if sep_parts and sep_parts[-1] == AND:
|
||||
separator += self.makaf
|
||||
|
||||
strings = [
|
||||
minus_str,
|
||||
money_str,
|
||||
self.pluralize(left, cr1, currency=currency,
|
||||
prefer_singular=prefer_singular),
|
||||
separator,
|
||||
cents_str,
|
||||
self.pluralize(right, cr2, currency=currency,
|
||||
prefer_singular=prefer_singular_cents)
|
||||
]
|
||||
if left == 1:
|
||||
strings[1], strings[2] = strings[2], strings[1]
|
||||
if right == 1:
|
||||
strings[4], strings[5] = strings[5], strings[4]
|
||||
# In Hebrew the separator is along with the following word
|
||||
return u'%s%s %s%s%s %s' % tuple(strings)
|
||||
165
path/to/venv/lib/python3.12/site-packages/num2words/lang_HU.py
Normal file
165
path/to/venv/lib/python3.12/site-packages/num2words/lang_HU.py
Normal file
@@ -0,0 +1,165 @@
|
||||
# -*- 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, print_function, unicode_literals
|
||||
|
||||
from . import lang_EU
|
||||
|
||||
ZERO = 'nulla'
|
||||
|
||||
|
||||
class Num2Word_HU(lang_EU.Num2Word_EU):
|
||||
GIGA_SUFFIX = "illiárd"
|
||||
MEGA_SUFFIX = "illió"
|
||||
|
||||
def setup(self):
|
||||
super(Num2Word_HU, self).setup()
|
||||
|
||||
self.negword = "mínusz "
|
||||
self.pointword = "egész"
|
||||
|
||||
self.mid_numwords = [(1000, "ezer"), (100, "száz"), (90, "kilencven"),
|
||||
(80, "nyolcvan"), (70, "hetven"), (60, "hatvan"),
|
||||
(50, "ötven"), (40, "negyven"), (30, "harminc")]
|
||||
|
||||
low_numwords = ["kilenc", "nyolc", "hét", "hat", "öt", "négy", "három",
|
||||
"kettő", "egy"]
|
||||
self.low_numwords = (['tizen' + w for w in low_numwords]
|
||||
+ ['tíz']
|
||||
+ low_numwords)
|
||||
self.low_numwords = (['huszon' + w for w in low_numwords]
|
||||
+ ['húsz']
|
||||
+ self.low_numwords
|
||||
+ [ZERO])
|
||||
|
||||
self.partial_ords = {
|
||||
'nulla': 'nullad',
|
||||
'egy': 'egyed',
|
||||
'kettő': 'ketted',
|
||||
'három': 'harmad',
|
||||
'négy': 'negyed',
|
||||
'öt': 'ötöd',
|
||||
'hat': 'hatod',
|
||||
'hét': 'heted',
|
||||
'nyolc': 'nyolcad',
|
||||
'kilenc': 'kilenced',
|
||||
'tíz': 'tized',
|
||||
'húsz': 'huszad',
|
||||
'harminc': 'harmincad',
|
||||
'negyven': 'negyvened',
|
||||
'ötven': 'ötvened',
|
||||
'hatvan': 'hatvanad',
|
||||
'hetven': 'hetvened',
|
||||
'nyolcvan': 'nyolcvanad',
|
||||
'kilencven': 'kilencvened',
|
||||
'száz': 'század',
|
||||
'ezer': 'ezred',
|
||||
'illió': 'milliomod',
|
||||
'illiárd': 'milliárdod'
|
||||
}
|
||||
|
||||
def to_cardinal(self, value, zero=ZERO):
|
||||
if int(value) != value:
|
||||
return self.to_cardinal_float(value)
|
||||
elif value < 0:
|
||||
out = self.negword + self.to_cardinal(-value)
|
||||
elif value == 0:
|
||||
out = zero
|
||||
elif zero == '' and value == 2:
|
||||
out = 'két'
|
||||
elif value < 30:
|
||||
out = self.cards[value]
|
||||
elif value < 100:
|
||||
out = self.tens_to_cardinal(value)
|
||||
elif value < 1000:
|
||||
out = self.hundreds_to_cardinal(value)
|
||||
elif value < 10**6:
|
||||
out = self.thousands_to_cardinal(value)
|
||||
else:
|
||||
out = self.big_number_to_cardinal(value)
|
||||
return out
|
||||
|
||||
def tens_to_cardinal(self, value):
|
||||
try:
|
||||
return self.cards[value]
|
||||
except KeyError:
|
||||
return self.cards[value // 10 * 10] + self.to_cardinal(value % 10)
|
||||
|
||||
def hundreds_to_cardinal(self, value):
|
||||
hundreds = value // 100
|
||||
prefix = "száz"
|
||||
if hundreds != 1:
|
||||
prefix = self.to_cardinal(hundreds, zero="") + prefix
|
||||
postfix = self.to_cardinal(value % 100, zero="")
|
||||
return prefix + postfix
|
||||
|
||||
def thousands_to_cardinal(self, value):
|
||||
thousands = value // 1000
|
||||
prefix = "ezer"
|
||||
if thousands != 1:
|
||||
prefix = self.to_cardinal(thousands, zero="") + prefix
|
||||
postfix = self.to_cardinal(value % 1000, zero="")
|
||||
return prefix + ('' if value <= 2000 or not postfix else '-') + postfix
|
||||
|
||||
def big_number_to_cardinal(self, value):
|
||||
digits = len(str(value))
|
||||
digits = digits if digits % 3 != 0 else digits - 2
|
||||
exp = 10 ** (digits // 3 * 3)
|
||||
rest = self.to_cardinal(value % exp, '')
|
||||
return (self.to_cardinal(value // exp, '') + self.cards[exp]
|
||||
+ ('-' + rest if rest else ''))
|
||||
|
||||
def to_ordinal(self, value):
|
||||
if value < 0:
|
||||
return self.negword + self.to_ordinal(-value)
|
||||
if value == 1:
|
||||
return 'első'
|
||||
elif value == 2:
|
||||
return 'második'
|
||||
else:
|
||||
out = self.to_cardinal(value)
|
||||
for card_word, ord_word in self.partial_ords.items():
|
||||
if out[-len(card_word):] == card_word:
|
||||
out = out[:-len(card_word)] + ord_word
|
||||
break
|
||||
return out + 'ik'
|
||||
|
||||
def to_ordinal_num(self, value):
|
||||
self.verify_ordinal(value)
|
||||
return str(value) + '.'
|
||||
|
||||
def to_year(self, val, suffix=None, longval=True):
|
||||
# suffix is prefix here
|
||||
prefix = ''
|
||||
if val < 0 or suffix is not None:
|
||||
val = abs(val)
|
||||
prefix = (suffix + ' ' if suffix is not None else 'i. e. ')
|
||||
return prefix + self.to_cardinal(val)
|
||||
|
||||
def to_currency(self, val, currency='HUF', cents=True, separator=',',
|
||||
adjective=False):
|
||||
return super(Num2Word_HU, self).to_currency(
|
||||
val, currency, cents, separator, adjective)
|
||||
|
||||
def to_cardinal_float(self, value):
|
||||
if abs(value) != value:
|
||||
return self.negword + self.to_cardinal_float(-value)
|
||||
left, right = str(value).split('.')
|
||||
return (self.to_cardinal(int(left))
|
||||
+ ' egész '
|
||||
+ self.to_cardinal(int(right))
|
||||
+ ' ' + self.partial_ords[self.cards[10 ** len(right)]])
|
||||
204
path/to/venv/lib/python3.12/site-packages/num2words/lang_ID.py
Normal file
204
path/to/venv/lib/python3.12/site-packages/num2words/lang_ID.py
Normal file
@@ -0,0 +1,204 @@
|
||||
# -*- 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 print_function, unicode_literals
|
||||
|
||||
|
||||
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 = "Number is too large to convert to words (abs(%s) > %s)."
|
||||
MAXVAL = 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.MAXVAL:
|
||||
raise OverflowError(self.errmsg_toobig % (number, self.MAXVAL))
|
||||
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)
|
||||
127
path/to/venv/lib/python3.12/site-packages/num2words/lang_IS.py
Normal file
127
path/to/venv/lib/python3.12/site-packages/num2words/lang_IS.py
Normal file
@@ -0,0 +1,127 @@
|
||||
# -*- 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, print_function, unicode_literals
|
||||
|
||||
from . import lang_EU
|
||||
|
||||
# Genders
|
||||
KK = 0 # Karlkyn (male)
|
||||
KVK = 1 # Kvenkyn (female)
|
||||
HK = 2 # Hvorugkyn (neuter)
|
||||
|
||||
GENDERS = {
|
||||
"einn": ("einn", "ein", "eitt"),
|
||||
"tveir": ("tveir", "tvær", "tvö"),
|
||||
"þrír": ("þrír", "þrjár", "þrjú"),
|
||||
"fjórir": ("fjórir", "fjórar", "fjögur"),
|
||||
}
|
||||
|
||||
PLURALS = {
|
||||
"hundrað": ("hundrað", "hundruð"),
|
||||
}
|
||||
|
||||
|
||||
class Num2Word_IS(lang_EU.Num2Word_EU):
|
||||
|
||||
GIGA_SUFFIX = "illjarður"
|
||||
MEGA_SUFFIX = "illjón"
|
||||
|
||||
def setup(self):
|
||||
lows = ["okt", "sept", "sext", "kvint", "kvaðr", "tr", "b", "m"]
|
||||
self.high_numwords = self.gen_high_numwords([], [], lows)
|
||||
|
||||
self.negword = "mínus "
|
||||
self.pointword = "komma"
|
||||
|
||||
# All words should be excluded, title case is not used in Icelandic
|
||||
self.exclude_title = ["og", "komma", "mínus"]
|
||||
|
||||
self.mid_numwords = [(1000, "þúsund"), (100, "hundrað"),
|
||||
(90, "níutíu"), (80, "áttatíu"), (70, "sjötíu"),
|
||||
(60, "sextíu"), (50, "fimmtíu"), (40, "fjörutíu"),
|
||||
(30, "þrjátíu")]
|
||||
self.low_numwords = ["tuttugu", "nítján", "átján", "sautján",
|
||||
"sextán", "fimmtán", "fjórtán", "þrettán",
|
||||
"tólf", "ellefu", "tíu", "níu", "átta",
|
||||
"sjö", "sex", "fimm", "fjórir", "þrír",
|
||||
"tveir", "einn", "núll"]
|
||||
self.ords = {"einn": "fyrsti",
|
||||
"tveir": "annar",
|
||||
"þrír": "þriðji",
|
||||
"fjórir": "fjórði",
|
||||
"fimm": "fimmti",
|
||||
"sex": "sjötti",
|
||||
"sjö": "sjöundi",
|
||||
"átta": "áttundi",
|
||||
"níu": "níundi",
|
||||
"tíu": "tíundi",
|
||||
"ellefu": "ellefti",
|
||||
"tólf": "tólfti"}
|
||||
|
||||
def pluralize(self, n, noun):
|
||||
form = 0 if (n % 10 == 1 and n % 100 != 11) else 1
|
||||
if form == 0:
|
||||
return noun
|
||||
elif self.GIGA_SUFFIX in noun:
|
||||
return noun.replace(self.GIGA_SUFFIX, "illjarðar")
|
||||
elif self.MEGA_SUFFIX in noun:
|
||||
return noun.replace(self.MEGA_SUFFIX, "illjónir")
|
||||
elif noun not in PLURALS:
|
||||
return noun
|
||||
return PLURALS[noun][form]
|
||||
|
||||
def genderize(self, adj, noun):
|
||||
last = adj.split()[-1]
|
||||
if last not in GENDERS:
|
||||
return adj
|
||||
gender = KK
|
||||
if "hund" in noun or "þús" in noun:
|
||||
gender = HK
|
||||
elif "illjarð" in noun:
|
||||
gender = KK
|
||||
elif "illjón" in noun:
|
||||
gender = KVK
|
||||
return adj.replace(last, GENDERS[last][gender])
|
||||
|
||||
def merge(self, lpair, rpair):
|
||||
ltext, lnum = lpair
|
||||
rtext, rnum = rpair
|
||||
|
||||
if lnum == 1 and rnum < 100:
|
||||
return (rtext, rnum)
|
||||
elif lnum < rnum:
|
||||
rtext = self.pluralize(lnum, rtext)
|
||||
ltext = self.genderize(ltext, rtext)
|
||||
return ("%s %s" % (ltext, rtext), lnum * rnum)
|
||||
elif lnum > rnum and rnum in self.cards:
|
||||
rtext = self.pluralize(lnum, rtext)
|
||||
ltext = self.genderize(ltext, rtext)
|
||||
return ("%s og %s" % (ltext, rtext), lnum + rnum)
|
||||
return ("%s %s" % (ltext, rtext), lnum + rnum)
|
||||
|
||||
def to_ordinal(self, value):
|
||||
raise NotImplementedError
|
||||
|
||||
def to_ordinal_num(self, value):
|
||||
raise NotImplementedError
|
||||
|
||||
def to_year(self, val, suffix=None, longval=True):
|
||||
raise NotImplementedError
|
||||
|
||||
def to_currency(self, val, longval=True):
|
||||
raise NotImplementedError
|
||||
241
path/to/venv/lib/python3.12/site-packages/num2words/lang_IT.py
Normal file
241
path/to/venv/lib/python3.12/site-packages/num2words/lang_IT.py
Normal file
@@ -0,0 +1,241 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2018-2019, Filippo Costa. All Rights Reserved.
|
||||
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2.1 of the License, or (at your option) any later version.
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
# MA 02110-1301 USA
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from .lang_EU import Num2Word_EU
|
||||
|
||||
# Globals
|
||||
# -------
|
||||
|
||||
ZERO = "zero"
|
||||
|
||||
CARDINAL_WORDS = [
|
||||
ZERO, "uno", "due", "tre", "quattro", "cinque", "sei", "sette", "otto",
|
||||
"nove", "dieci", "undici", "dodici", "tredici", "quattordici", "quindici",
|
||||
"sedici", "diciassette", "diciotto", "diciannove"
|
||||
]
|
||||
|
||||
ORDINAL_WORDS = [
|
||||
ZERO, "primo", "secondo", "terzo", "quarto", "quinto", "sesto", "settimo",
|
||||
"ottavo", "nono", "decimo", "undicesimo", "dodicesimo", "tredicesimo",
|
||||
"quattordicesimo", "quindicesimo", "sedicesimo", "diciassettesimo",
|
||||
"diciottesimo", "diciannovesimo"
|
||||
]
|
||||
|
||||
# The script can extrapolate the missing numbers from the base forms.
|
||||
STR_TENS = {2: "venti", 3: "trenta", 4: "quaranta", 6: "sessanta"}
|
||||
|
||||
# These prefixes are used for extremely big numbers.
|
||||
EXPONENT_PREFIXES = [
|
||||
ZERO, "m", "b", "tr", "quadr", "quint", "sest", "sett", "ott", "nov", "dec"
|
||||
]
|
||||
|
||||
|
||||
GENERIC_DOLLARS = ('dollaro', 'dollari')
|
||||
GENERIC_CENTS = ('centesimo', 'centesimi')
|
||||
CURRENCIES_UNA = ('GBP')
|
||||
|
||||
|
||||
# Main class
|
||||
# ==========
|
||||
|
||||
class Num2Word_IT(Num2Word_EU):
|
||||
CURRENCY_FORMS = {
|
||||
'EUR': (('euro', 'euro'), GENERIC_CENTS),
|
||||
'USD': (GENERIC_DOLLARS, GENERIC_CENTS),
|
||||
'GBP': (('sterlina', 'sterline'), ('penny', 'penny')),
|
||||
'CNY': (('yuan', 'yuan'), ('fen', 'fen')),
|
||||
}
|
||||
MINUS_PREFIX_WORD = "meno "
|
||||
FLOAT_INFIX_WORD = " virgola "
|
||||
|
||||
def setup(self):
|
||||
Num2Word_EU.setup(self)
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def float_to_words(self, float_number, ordinal=False):
|
||||
if ordinal:
|
||||
prefix = self.to_ordinal(int(float_number))
|
||||
else:
|
||||
prefix = self.to_cardinal(int(float_number))
|
||||
float_part = str(float_number).split('.')[1]
|
||||
postfix = " ".join(
|
||||
# Drops the trailing zero and comma
|
||||
[self.to_cardinal(int(c)) for c in float_part]
|
||||
)
|
||||
return prefix + Num2Word_IT.FLOAT_INFIX_WORD + postfix
|
||||
|
||||
def tens_to_cardinal(self, number):
|
||||
tens = number // 10
|
||||
units = number % 10
|
||||
if tens in STR_TENS:
|
||||
prefix = STR_TENS[tens]
|
||||
else:
|
||||
prefix = CARDINAL_WORDS[tens][:-1] + "anta"
|
||||
postfix = omitt_if_zero(CARDINAL_WORDS[units])
|
||||
return phonetic_contraction(prefix + postfix)
|
||||
|
||||
def hundreds_to_cardinal(self, number):
|
||||
hundreds = number // 100
|
||||
prefix = "cento"
|
||||
if hundreds != 1:
|
||||
prefix = CARDINAL_WORDS[hundreds] + prefix
|
||||
postfix = omitt_if_zero(self.to_cardinal(number % 100))
|
||||
return phonetic_contraction(prefix + postfix)
|
||||
|
||||
def thousands_to_cardinal(self, number):
|
||||
thousands = number // 1000
|
||||
if thousands == 1:
|
||||
prefix = "mille"
|
||||
else:
|
||||
prefix = self.to_cardinal(thousands) + "mila"
|
||||
postfix = omitt_if_zero(self.to_cardinal(number % 1000))
|
||||
# "mille" and "mila" don't need any phonetic contractions
|
||||
return prefix + postfix
|
||||
|
||||
def big_number_to_cardinal(self, number):
|
||||
digits = [c for c in str(number)]
|
||||
length = len(digits)
|
||||
if length >= 66:
|
||||
raise NotImplementedError("The given number is too large.")
|
||||
# This is how many digits come before the "illion" term.
|
||||
# cento miliardi => 3
|
||||
# dieci milioni => 2
|
||||
# un miliardo => 1
|
||||
predigits = length % 3 or 3
|
||||
multiplier = digits[:predigits]
|
||||
exponent = digits[predigits:]
|
||||
# Default infix string: "milione", "biliardo", "sestilione", ecc.
|
||||
infix = exponent_length_to_string(len(exponent))
|
||||
if multiplier == ["1"]:
|
||||
prefix = "un "
|
||||
else:
|
||||
prefix = self.to_cardinal(int("".join(multiplier)))
|
||||
# Plural form ~~~~~~~~~~~
|
||||
infix = " " + infix[:-1] + "i"
|
||||
# Read as: Does the value of exponent equal 0?
|
||||
if set(exponent) != set("0"):
|
||||
postfix = self.to_cardinal(int("".join(exponent)))
|
||||
if " e " in postfix:
|
||||
infix += ", "
|
||||
else:
|
||||
infix += " e "
|
||||
else:
|
||||
postfix = ""
|
||||
return prefix + infix + postfix
|
||||
|
||||
def to_cardinal(self, number):
|
||||
if number < 0:
|
||||
string = Num2Word_IT.MINUS_PREFIX_WORD + self.to_cardinal(-number)
|
||||
elif isinstance(number, float):
|
||||
string = self.float_to_words(number)
|
||||
elif number < 20:
|
||||
string = CARDINAL_WORDS[int(number)]
|
||||
elif number < 100:
|
||||
string = self.tens_to_cardinal(int(number))
|
||||
elif number < 1000:
|
||||
string = self.hundreds_to_cardinal(int(number))
|
||||
elif number < 1000000:
|
||||
string = self.thousands_to_cardinal(int(number))
|
||||
else:
|
||||
string = self.big_number_to_cardinal(number)
|
||||
return accentuate(string)
|
||||
|
||||
def to_ordinal(self, number):
|
||||
tens = number % 100
|
||||
# Italian grammar is poorly defined here ¯\_(ツ)_/¯:
|
||||
# centodecimo VS centodieciesimo VS centesimo decimo?
|
||||
is_outside_teens = not 10 < tens < 20
|
||||
if number < 0:
|
||||
return Num2Word_IT.MINUS_PREFIX_WORD + self.to_ordinal(-number)
|
||||
elif number % 1 != 0:
|
||||
return self.float_to_words(number, ordinal=True)
|
||||
elif number < 20:
|
||||
return ORDINAL_WORDS[int(number)]
|
||||
elif is_outside_teens and tens % 10 == 3:
|
||||
# Gets rid of the accent
|
||||
return self.to_cardinal(number)[:-1] + "eesimo"
|
||||
elif is_outside_teens and tens % 10 == 6:
|
||||
return self.to_cardinal(number) + "esimo"
|
||||
else:
|
||||
string = self.to_cardinal(number)[:-1]
|
||||
if string[-3:] == "mil":
|
||||
string += "l"
|
||||
return string + "esimo"
|
||||
|
||||
def to_currency(self, val, currency='EUR', cents=True, separator=' e',
|
||||
adjective=False):
|
||||
result = super(Num2Word_IT, self).to_currency(
|
||||
val, currency=currency, cents=cents, separator=separator,
|
||||
adjective=adjective)
|
||||
# Handle exception. In italian language is "un euro",
|
||||
# "un dollaro" etc. (not "uno euro", "uno dollaro").
|
||||
# There is an exception, some currencies need "una":
|
||||
# e.g. "una sterlina"
|
||||
if currency in CURRENCIES_UNA:
|
||||
list_result = result.split(" ")
|
||||
if list_result[0] == "uno":
|
||||
list_result[0] = list_result[0].replace("uno", "una")
|
||||
result = " ".join(list_result)
|
||||
result = result.replace("uno", "un")
|
||||
return result
|
||||
|
||||
# Utils
|
||||
# =====
|
||||
|
||||
|
||||
def phonetic_contraction(string):
|
||||
return (string
|
||||
.replace("oo", "o") # ex. "centootto"
|
||||
.replace("ao", "o") # ex. "settantaotto"
|
||||
.replace("io", "o") # ex. "ventiotto"
|
||||
.replace("au", "u") # ex. "trentauno"
|
||||
.replace("iu", "u") # ex. "ventiunesimo"
|
||||
)
|
||||
|
||||
|
||||
def exponent_length_to_string(exponent_length):
|
||||
# We always assume `exponent` to be a multiple of 3. If it's not true, then
|
||||
# Num2Word_IT.big_number_to_cardinal did something wrong.
|
||||
prefix = EXPONENT_PREFIXES[exponent_length // 6]
|
||||
if exponent_length % 6 == 0:
|
||||
return prefix + "ilione"
|
||||
else:
|
||||
return prefix + "iliardo"
|
||||
|
||||
|
||||
def accentuate(string):
|
||||
# This is inefficient: it may do several rewritings when deleting
|
||||
# half-sentence accents. However, it is the easiest method and speed is
|
||||
# not crucial (duh), so...
|
||||
return " ".join(
|
||||
# Deletes half-sentence accents and accentuates the last "tre"
|
||||
[w.replace("tré", "tre")[:-3] + "tré"
|
||||
# We shouldn't accentuate a single "tre": is has to be a composite
|
||||
# word. ~~~~~~~~~~
|
||||
if w[-3:] == "tre" and len(w) > 3
|
||||
# Deletes half-sentence accents anyway
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~
|
||||
else w.replace("tré", "tre")
|
||||
for w in string.split()
|
||||
])
|
||||
|
||||
|
||||
def omitt_if_zero(number_to_string):
|
||||
return "" if number_to_string == ZERO else number_to_string
|
||||
590
path/to/venv/lib/python3.12/site-packages/num2words/lang_JA.py
Normal file
590
path/to/venv/lib/python3.12/site-packages/num2words/lang_JA.py
Normal file
@@ -0,0 +1,590 @@
|
||||
# -*- 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, print_function, unicode_literals
|
||||
|
||||
from .base import Num2Word_Base
|
||||
from .compat import strtype, to_s
|
||||
from .currency import parse_currency_parts, prefix_currency
|
||||
|
||||
|
||||
def select_text(text, reading=False, prefer=None):
|
||||
"""Select the correct text from the Japanese number, reading and
|
||||
alternatives"""
|
||||
# select kanji number or kana reading
|
||||
if reading:
|
||||
text = text[1]
|
||||
else:
|
||||
text = text[0]
|
||||
|
||||
# select the preferred one or the first one from multiple alternatives
|
||||
if not isinstance(text, strtype):
|
||||
common = set(text) & set(prefer or set())
|
||||
if len(common) == 1:
|
||||
text = common.pop()
|
||||
else:
|
||||
text = text[0]
|
||||
|
||||
return text
|
||||
|
||||
|
||||
def rendaku_merge_pairs(lpair, rpair):
|
||||
"""Merge lpair < rpair while applying semi-irregular rendaku rules"""
|
||||
ltext, lnum = lpair
|
||||
rtext, rnum = rpair
|
||||
if lnum > rnum:
|
||||
raise ValueError
|
||||
|
||||
if rpair == ("ひゃく", 100):
|
||||
if lpair == ("さん", 3):
|
||||
rtext = "びゃく"
|
||||
elif lpair == ("ろく", 6):
|
||||
ltext = "ろっ"
|
||||
rtext = "ぴゃく"
|
||||
elif lpair == ("はち", 8):
|
||||
ltext = "はっ"
|
||||
rtext = "ぴゃく"
|
||||
elif rpair == ("せん", 1000):
|
||||
if lpair == ("さん", 3):
|
||||
rtext = "ぜん"
|
||||
elif lpair == ("はち", 8):
|
||||
ltext = "はっ"
|
||||
elif rpair == ("ちょう", 10**12):
|
||||
if lpair == ("いち", 1):
|
||||
ltext = "いっ"
|
||||
elif lpair == ("はち", 8):
|
||||
ltext = "はっ"
|
||||
elif lpair == ("じゅう", 10):
|
||||
ltext = "じゅっ"
|
||||
elif rpair == ("けい", 10**16):
|
||||
if lpair == ("いち", 1):
|
||||
ltext = "いっ"
|
||||
elif lpair == ("ろく", 6):
|
||||
ltext = "ろっ"
|
||||
elif lpair == ("はち", 8):
|
||||
ltext = "はっ"
|
||||
elif lpair == ("じゅう", 10):
|
||||
ltext = "じゅっ"
|
||||
elif lpair == ("ひゃく", 100):
|
||||
ltext = "ひゃっ"
|
||||
|
||||
return ("%s%s" % (ltext, rtext), lnum * rnum)
|
||||
|
||||
|
||||
# Source: https://www.sljfaq.org/afaq/era-list.html
|
||||
# if there are multiple eras for the same year, use the last one
|
||||
ERA_START = [
|
||||
(645, ("大化", "たいか")),
|
||||
(650, ("白雉", "はくち")),
|
||||
(686, ("朱鳥", "しゅちょう")),
|
||||
(701, ("大宝", "たいほう")),
|
||||
(704, ("慶雲", "けいうん")),
|
||||
(708, ("和銅", "わどう")),
|
||||
(715, ("霊亀", "れいき")),
|
||||
(717, ("養老", "ようろう")),
|
||||
(724, ("神亀", "じんき")),
|
||||
(729, ("天平", "てんぴょう")),
|
||||
(749, ("天平感宝", "てんぴょうかんぽう")),
|
||||
(749, ("天平勝宝", "てんぴょうしょうほう")),
|
||||
(757, ("天平宝字", "てんぴょうじょうじ")),
|
||||
(765, ("天平神護", "てんぴょうじんご")),
|
||||
(767, ("神護景雲", "じんごけいうん")),
|
||||
(770, ("宝亀", "ほうき")),
|
||||
(781, ("天応", "てんおう")),
|
||||
(782, ("延暦", "えんりゃく")),
|
||||
(806, ("大同", "だいどう")),
|
||||
(810, ("弘仁", "こうにん")),
|
||||
(823, ("天長", "てんちょう")),
|
||||
(834, ("承和", "じょうわ")),
|
||||
(848, ("嘉祥", "かしょう")),
|
||||
(851, ("仁寿", "にんじゅ")),
|
||||
(855, ("斉衡", "さいこう")),
|
||||
(857, ("天安", "てんあん")),
|
||||
(859, ("貞観", "じょうがん")),
|
||||
(877, ("元慶", "がんぎょう")),
|
||||
(885, ("仁和", "にんな")),
|
||||
(889, ("寛平", "かんぴょう")),
|
||||
(898, ("昌泰", "しょうたい")),
|
||||
(901, ("延喜", "えんぎ")),
|
||||
(923, ("延長", "えんちょう")),
|
||||
(931, ("承平", "じょうへい")),
|
||||
(938, ("天慶", "てんぎょう")),
|
||||
(947, ("天暦", "てんりゃく")),
|
||||
(957, ("天徳", "てんとく")),
|
||||
(961, ("応和", "おうわ")),
|
||||
(964, ("康保", "こうほう")),
|
||||
(968, ("安和", "あんな")),
|
||||
(970, ("天禄", "てんろく")),
|
||||
(974, ("天延", "てんえん")),
|
||||
(976, ("貞元", "じょうげん")),
|
||||
(979, ("天元", "てんげん")),
|
||||
(983, ("永観", "えいかん")),
|
||||
(985, ("寛和", "かんな")),
|
||||
(987, ("永延", "えいえん")),
|
||||
(989, ("永祚", "えいそ")),
|
||||
(990, ("正暦", "しょうりゃく")),
|
||||
(995, ("長徳", "ちょうとく")),
|
||||
(999, ("長保", "ちょうほう")),
|
||||
(1004, ("寛弘", "かんこう")),
|
||||
(1013, ("長和", "ちょうわ")),
|
||||
(1017, ("寛仁", "かんにん")),
|
||||
(1021, ("治安", "じあん")),
|
||||
(1024, ("万寿", "まんじゅ")),
|
||||
(1028, ("長元", "ちょうげん")),
|
||||
(1037, ("長暦", "ちょうりゃく")),
|
||||
(1040, ("長久", "ちょうきゅう")),
|
||||
(1045, ("寛徳", "かんとく")),
|
||||
(1046, ("永承", "えいしょう")),
|
||||
(1053, ("天喜", "てんぎ")),
|
||||
(1058, ("康平", "こうへい")),
|
||||
(1065, ("治暦", "じりゃく")),
|
||||
(1069, ("延久", "えんきゅう")),
|
||||
(1074, ("承保", "じょうほう")),
|
||||
(1078, ("承暦", "じょうりゃく")),
|
||||
(1081, ("永保", "えいほう")),
|
||||
(1084, ("応徳", "おうとく")),
|
||||
(1087, ("寛治", "かんじ")),
|
||||
(1095, ("嘉保", "かほう")),
|
||||
(1097, ("永長", "えいちょう")),
|
||||
(1098, ("承徳", "じょうとく")),
|
||||
(1099, ("康和", "こうわ")),
|
||||
(1104, ("長治", "ちょうじ")),
|
||||
(1106, ("嘉承", "かじょう")),
|
||||
(1108, ("天仁", "てんにん")),
|
||||
(1110, ("天永", "てんねい")),
|
||||
(1113, ("永久", "えいきゅう")),
|
||||
(1118, ("元永", "げんえい")),
|
||||
(1120, ("保安", "ほうあん")),
|
||||
(1124, ("天治", "てんじ")),
|
||||
(1126, ("大治", "だいじ")),
|
||||
(1131, ("天承", "てんしょう")),
|
||||
(1132, ("長承", "ちょうしょう")),
|
||||
(1135, ("保延", "ほうえん")),
|
||||
(1141, ("永治", "えいじ")),
|
||||
(1142, ("康治", "こうじ")),
|
||||
(1144, ("天養", "てんよう")),
|
||||
(1145, ("久安", "きゅうあん")),
|
||||
(1151, ("仁平", "にんぺい")),
|
||||
(1154, ("久寿", "きゅうじゅ")),
|
||||
(1156, ("保元", "ほうげん")),
|
||||
(1159, ("平治", "へいじ")),
|
||||
(1160, ("永暦", "えいりゃく")),
|
||||
(1161, ("応保", "おうほう")),
|
||||
(1163, ("長寛", "ちょうかん")),
|
||||
(1165, ("永万", "えいまん")),
|
||||
(1166, ("仁安", "にんあん")),
|
||||
(1169, ("嘉応", "かおう")),
|
||||
(1171, ("承安", "しょうあん")),
|
||||
(1175, ("安元", "あんげん")),
|
||||
(1177, ("治承", "じしょう")),
|
||||
(1181, ("養和", "ようわ")),
|
||||
(1182, ("寿永", "じゅえい")),
|
||||
(1184, ("元暦", "げんりゃく")),
|
||||
(1185, ("文治", "ぶんじ")),
|
||||
(1190, ("建久", "けんきゅう")),
|
||||
(1199, ("正治", "しょうじ")),
|
||||
(1201, ("建仁", "けんにん")),
|
||||
(1204, ("元久", "げんきゅう")),
|
||||
(1206, ("建永", "けんえい")),
|
||||
(1207, ("承元", "じょうげん")),
|
||||
(1211, ("建暦", "けんりゃく")),
|
||||
(1214, ("建保", "けんぽう")),
|
||||
(1219, ("承久", "じょうきゅう")),
|
||||
(1222, ("貞応", "じょうおう")),
|
||||
(1225, ("元仁", "げんにん")),
|
||||
(1225, ("嘉禄", "かろく")),
|
||||
(1228, ("安貞", "あんてい")),
|
||||
(1229, ("寛喜", "かんき")),
|
||||
(1232, ("貞永", "じょうえい")),
|
||||
(1233, ("天福", "てんぷく")),
|
||||
(1235, ("文暦", "ぶんりゃく")),
|
||||
(1235, ("嘉禎", "かてい")),
|
||||
(1239, ("暦仁", "りゃくにん")),
|
||||
(1239, ("延応", "えんおう")),
|
||||
(1240, ("仁治", "にんじ")),
|
||||
(1243, ("寛元", "かんげん")),
|
||||
(1247, ("宝治", "ほうじ")),
|
||||
(1249, ("建長", "けんちょう")),
|
||||
(1256, ("康元", "こうげん")),
|
||||
(1257, ("正嘉", "しょうか")),
|
||||
(1259, ("正元", "しょうげん")),
|
||||
(1260, ("文応", "ぶんおう")),
|
||||
(1261, ("弘長", "こうちょう")),
|
||||
(1264, ("文永", "ぶんえい")),
|
||||
(1275, ("健治", "けんじ")),
|
||||
(1278, ("弘安", "こうあん")),
|
||||
(1288, ("正応", "しょうおう")),
|
||||
(1293, ("永仁", "えいにん")),
|
||||
(1299, ("正安", "しょうあん")),
|
||||
(1303, ("乾元", "けんげん")),
|
||||
(1303, ("嘉元", "かげん")),
|
||||
(1307, ("徳治", "とくじ")),
|
||||
(1308, ("延慶", "えんきょう")),
|
||||
(1311, ("応長", "おうちょう")),
|
||||
(1312, ("正和", "しょうわ")),
|
||||
(1317, ("文保", "ぶんぽう")),
|
||||
(1319, ("元応", "げんおう")),
|
||||
(1321, ("元亨", "げんこう")),
|
||||
(1325, ("正中", "しょうちゅ")),
|
||||
(1326, ("嘉暦", "かりゃく")),
|
||||
(1329, ("元徳", "げんとく")),
|
||||
(1331, ("元弘", "げんこう")),
|
||||
(1332, ("正慶", "しょうけい")),
|
||||
(1334, ("建武", "けんむ")),
|
||||
(1336, ("延元", "えいげん")),
|
||||
(1338, ("暦応", "りゃくおう")),
|
||||
(1340, ("興国", "こうこく")),
|
||||
(1342, ("康永", "こうえい")),
|
||||
(1345, ("貞和", "じょうわ")),
|
||||
(1347, ("正平", "しょうへい")),
|
||||
(1350, ("観応", "かんおう")),
|
||||
(1352, ("文和", "ぶんな")),
|
||||
(1356, ("延文", "えんぶん")),
|
||||
(1361, ("康安", "こうあん")),
|
||||
(1362, ("貞治", "じょうじ")),
|
||||
(1368, ("応安", "おうあん")),
|
||||
(1370, ("建徳", "けんとく")),
|
||||
(1372, ("文中", "ぶんちゅう")),
|
||||
(1375, ("永和", "えいわ")),
|
||||
(1375, ("天授", "てんじゅ")),
|
||||
(1379, ("康暦", "こうりゃく")),
|
||||
(1381, ("永徳", "えいとく")),
|
||||
(1381, ("弘和", "こうわ")),
|
||||
(1384, ("至徳", "しとく")),
|
||||
(1384, ("元中", "げんちゅう")),
|
||||
(1387, ("嘉慶", "かけい")),
|
||||
(1389, ("康応", "こうおう")),
|
||||
(1390, ("明徳", "めいとく")),
|
||||
(1394, ("応永", "おうえい")),
|
||||
(1428, ("正長", "しょうちょう")),
|
||||
(1429, ("永享", "えいきょう")),
|
||||
(1441, ("嘉吉", "かきつ")),
|
||||
(1444, ("文安", "ぶんあん")),
|
||||
(1449, ("宝徳", "ほうとく")),
|
||||
(1452, ("享徳", "きょうとく")),
|
||||
(1455, ("康正", "こうしょう")),
|
||||
(1457, ("長禄", "ちょうろく")),
|
||||
(1461, ("寛正", "かんしょう")),
|
||||
(1466, ("文正", "ぶんしょう")),
|
||||
(1467, ("応仁", "おうにん")),
|
||||
(1469, ("文明", "ぶんめい")),
|
||||
(1487, ("長享", "ちょうきょう")),
|
||||
(1489, ("延徳", "えんとく")),
|
||||
(1492, ("明応", "めいおう")),
|
||||
(1501, ("文亀", "ぶんき")),
|
||||
(1504, ("永正", "えいしょう")),
|
||||
(1521, ("大永", "だいえい")),
|
||||
(1528, ("享禄", "きょうろく")),
|
||||
(1532, ("天文", "てんぶん")),
|
||||
(1555, ("弘治", "こうじ")),
|
||||
(1558, ("永禄", "えいろく")),
|
||||
(1570, ("元亀", "げんき")),
|
||||
(1573, ("天正", "てんしょう")),
|
||||
(1593, ("文禄", "ぶんろく")),
|
||||
(1596, ("慶長", "けいちょう")),
|
||||
(1615, ("元和", "げんな")),
|
||||
(1624, ("寛永", "かんえい")),
|
||||
(1645, ("正保", "しょうほう")),
|
||||
(1648, ("慶安", "けいあん")),
|
||||
(1652, ("承応", "じょうおう")),
|
||||
(1655, ("明暦", "めいれき")),
|
||||
(1658, ("万治", "まんじ")),
|
||||
(1661, ("寛文", "かんぶん")),
|
||||
(1673, ("延宝", "えんぽう")),
|
||||
(1681, ("天和", "てんな")),
|
||||
(1684, ("貞享", "じょうきょう")),
|
||||
(1688, ("元禄", "げんろく")),
|
||||
(1704, ("宝永", "ほうえい")),
|
||||
(1711, ("正徳", "しょうとく")),
|
||||
(1716, ("享保", "きょうほう")),
|
||||
(1736, ("元文", "げんぶん")),
|
||||
(1741, ("寛保", "かんぽう")),
|
||||
(1744, ("延享", "えんきょう")),
|
||||
(1748, ("寛延", "かんえん")),
|
||||
(1751, ("宝暦", "ほうれき")),
|
||||
(1764, ("明和", "めいわ")),
|
||||
(1773, ("安永", "あんえい")),
|
||||
(1781, ("天明", "てんめい")),
|
||||
(1801, ("寛政", "かんせい")),
|
||||
(1802, ("享和", "きょうわ")),
|
||||
(1804, ("文化", "ぶんか")),
|
||||
(1818, ("文政", "ぶんせい")),
|
||||
(1831, ("天保", "てんぽう")),
|
||||
(1845, ("弘化", "こうか")),
|
||||
(1848, ("嘉永", "かえい")),
|
||||
(1855, ("安政", "あんせい")),
|
||||
(1860, ("万延", "まんえい")),
|
||||
(1861, ("文久", "ぶんきゅう")),
|
||||
(1864, ("元治", "げんじ")),
|
||||
(1865, ("慶応", "けいおう")),
|
||||
(1868, ("明治", "めいじ")),
|
||||
(1912, ("大正", "たいしょう")),
|
||||
(1926, ("昭和", "しょうわ")),
|
||||
(1989, ("平成", "へいせい")),
|
||||
(2019, ("令和", "れいわ")),
|
||||
]
|
||||
|
||||
|
||||
class Num2Word_JA(Num2Word_Base):
|
||||
CURRENCY_FORMS = {
|
||||
'JPY': (('円', 'えん'), ()),
|
||||
}
|
||||
|
||||
def set_high_numwords(self, high):
|
||||
max = 4 * len(high)
|
||||
for word, n in zip(high, range(max, 0, -4)):
|
||||
self.cards[10 ** n] = word
|
||||
|
||||
def setup(self):
|
||||
self.negword = "マイナス"
|
||||
self.pointword = ("点", "てん")
|
||||
self.exclude_title = ["点", "マイナス"]
|
||||
|
||||
self.high_numwords = [
|
||||
("万", "まん"), # 10**4 man
|
||||
("億", "おく"), # 10**8 oku
|
||||
("兆", "ちょう"), # 10**12 chō
|
||||
("京", "けい"), # 10**16 kei
|
||||
("垓", "がい"), # 10**20 gai
|
||||
("秭", "し"), # 10**24 shi
|
||||
("穣", "じょう"), # 10**28 jō
|
||||
("溝", "こう"), # 10**32 kō
|
||||
("澗", "かん"), # 10**36 kan
|
||||
("正", "せい"), # 10**40 sei
|
||||
("載", "さい"), # 10**44 sai
|
||||
("極", "ごく"), # 10**48 goku
|
||||
]
|
||||
|
||||
self.high_numwords.reverse()
|
||||
|
||||
self.mid_numwords = [
|
||||
(1000, ("千", "せん")),
|
||||
(100, ("百", "ひゃく")),
|
||||
]
|
||||
|
||||
self.low_numwords = [
|
||||
("十", "じゅう"), # 10 jū
|
||||
("九", "きゅう"), # 9 kyū
|
||||
("八", "はち"), # 8 hachi
|
||||
("七", ("なな", "しち")), # 7 nana, shichi
|
||||
("六", "ろく"), # 6 roku
|
||||
("五", "ご"), # 5 go
|
||||
("四", ("よん", "し")), # 4 yon, shi
|
||||
("三", "さん"), # 3 san
|
||||
("二", "に"), # 2 ni
|
||||
("一", "いち"), # 1 ichi
|
||||
# both are alternatives, 零 doesn't map to ゼロ or 〇 to れい
|
||||
(("零", "〇"), ("ゼロ", "れい")), # 0 ZERO, rei
|
||||
]
|
||||
|
||||
def merge(self, lpair, rpair):
|
||||
ltext, lnum = lpair
|
||||
rtext, rnum = rpair
|
||||
|
||||
fmt = "%s%s"
|
||||
# ignore lpair if lnum is 1 and rnum is less than 10000
|
||||
if lnum == 1 and rnum < 10000:
|
||||
return rpair
|
||||
# rnum is added to lnum
|
||||
elif lnum > rnum:
|
||||
return (fmt % (ltext, rtext), lnum + rnum)
|
||||
# rnum is multiplied by lnum
|
||||
elif lnum < rnum:
|
||||
return rendaku_merge_pairs(lpair, rpair)
|
||||
|
||||
def _ordinal_suffix(self, reading, counter):
|
||||
if reading:
|
||||
if counter == "番":
|
||||
return "ばんめ"
|
||||
else:
|
||||
raise NotImplementedError(
|
||||
"Reading not implemented for %s" % counter)
|
||||
else:
|
||||
return counter + "目"
|
||||
|
||||
def to_ordinal(self, value, reading=False, prefer=None, counter="番"):
|
||||
self.verify_ordinal(value)
|
||||
base = self.to_cardinal(value, reading=reading, prefer=prefer)
|
||||
return "%s%s" % (base, self._ordinal_suffix(reading, counter))
|
||||
|
||||
def to_ordinal_num(self, value, reading=False, counter="番"):
|
||||
return "%s%s" % (value, self._ordinal_suffix(reading, counter))
|
||||
|
||||
def to_year(self, val, suffix=None, longval=True, reading=False,
|
||||
prefer=None, era=True):
|
||||
year = val
|
||||
# Gregorian calendar
|
||||
if not era:
|
||||
prefix = ""
|
||||
if year < 0:
|
||||
year = abs(year)
|
||||
prefix = "きげんぜん" if reading else "紀元前"
|
||||
|
||||
year_words = self.to_cardinal(year, reading=reading, prefer=prefer)
|
||||
if reading and year % 10 == 9:
|
||||
year_words = year_words[:-3] + "く"
|
||||
|
||||
return "%s%s%s" % (prefix, year_words, "ねん" if reading else "年")
|
||||
|
||||
# Era calendar (default)
|
||||
min_year = ERA_START[0][0]
|
||||
last_era_idx = len(ERA_START) - 1
|
||||
if year < min_year:
|
||||
raise ValueError(
|
||||
"Can't convert years less than %s to era" % min_year)
|
||||
|
||||
first = 0
|
||||
last = last_era_idx
|
||||
era_idx = None
|
||||
while era_idx is None:
|
||||
mid = (first + last) // 2
|
||||
if mid == last_era_idx or (ERA_START[mid][0] <= year and
|
||||
ERA_START[mid + 1][0] > year):
|
||||
era_idx = mid
|
||||
# if an era lasting less than a year is preferred, choose it
|
||||
if prefer:
|
||||
i = mid - 1
|
||||
while i >= 0 and ERA_START[i][0] == year:
|
||||
# match kanji or hiragana
|
||||
if set(ERA_START[i][1]) & set(prefer):
|
||||
era_idx = i
|
||||
break
|
||||
i -= 1
|
||||
|
||||
# ends up at the last index where year >= ERA_START[mid][0]
|
||||
if year < ERA_START[mid][0]:
|
||||
last = mid - 1
|
||||
else:
|
||||
first = mid + 1
|
||||
|
||||
era = ERA_START[era_idx]
|
||||
era_name = era[1][0]
|
||||
era_year = year - era[0] + 1
|
||||
fmt = "%s%s年"
|
||||
if reading == "arabic":
|
||||
era_year_words = str(era_year)
|
||||
elif reading:
|
||||
era_name = era[1][1]
|
||||
era_year_words = (self.to_cardinal(era_year, reading=True,
|
||||
prefer=prefer)
|
||||
if era_year != 1 else "がん")
|
||||
if era_year % 10 == 9:
|
||||
era_year_words = era_year_words[:-3] + "く"
|
||||
fmt = "%s%sねん"
|
||||
else:
|
||||
era_year_words = (self.to_cardinal(era_year, reading=False,
|
||||
prefer=prefer)
|
||||
if era_year != 1 else "元")
|
||||
|
||||
return fmt % (era_name, era_year_words)
|
||||
|
||||
def to_currency(self, val, currency="JPY", cents=False, separator="",
|
||||
adjective=False, reading=False, prefer=None):
|
||||
left, right, is_negative = parse_currency_parts(
|
||||
val, is_int_with_cents=cents)
|
||||
|
||||
try:
|
||||
cr1, cr2 = self.CURRENCY_FORMS[currency]
|
||||
if (cents or abs(val) != left) and not cr2:
|
||||
raise ValueError('Decimals not supported for "%s"' % currency)
|
||||
except KeyError:
|
||||
raise NotImplementedError(
|
||||
'Currency code "%s" not implemented for "%s"' %
|
||||
(currency, self.__class__.__name__))
|
||||
|
||||
if adjective and currency in self.CURRENCY_ADJECTIVES:
|
||||
cr1 = prefix_currency(self.CURRENCY_ADJECTIVES[currency], cr1)
|
||||
|
||||
minus_str = self.negword if is_negative else ""
|
||||
|
||||
return '%s%s%s%s%s' % (
|
||||
minus_str,
|
||||
self.to_cardinal(left, reading=reading, prefer=prefer),
|
||||
cr1[1] if reading else cr1[0],
|
||||
self.to_cardinal(right, reading=reading, prefer=prefer)
|
||||
if cr2 else '',
|
||||
(cr2[1] if reading else cr2[0]) if cr2 else '',
|
||||
)
|
||||
|
||||
def splitnum(self, value, reading, prefer):
|
||||
for elem in self.cards:
|
||||
if elem > value:
|
||||
continue
|
||||
|
||||
out = []
|
||||
if value == 0:
|
||||
div, mod = 1, 0
|
||||
else:
|
||||
div, mod = divmod(value, elem)
|
||||
|
||||
if div == 1:
|
||||
out.append((select_text(self.cards[1], reading, prefer), 1))
|
||||
else:
|
||||
if div == value: # The system tallies, eg Roman Numerals
|
||||
return [(
|
||||
div * select_text(self.cards[elem], reading, prefer),
|
||||
div * elem)]
|
||||
out.append(self.splitnum(div, reading, prefer))
|
||||
|
||||
out.append((select_text(self.cards[elem], reading, prefer), elem))
|
||||
|
||||
if mod:
|
||||
out.append(self.splitnum(mod, reading, prefer))
|
||||
|
||||
return out
|
||||
|
||||
def to_cardinal(self, value, reading=False, prefer=None):
|
||||
try:
|
||||
assert int(value) == value
|
||||
except (ValueError, TypeError, AssertionError):
|
||||
return self.to_cardinal_float(value, reading=reading,
|
||||
prefer=prefer)
|
||||
|
||||
out = ""
|
||||
if value < 0:
|
||||
value = abs(value)
|
||||
out = self.negword
|
||||
|
||||
if value >= self.MAXVAL:
|
||||
raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL))
|
||||
|
||||
val = self.splitnum(value, reading, prefer)
|
||||
words, _ = self.clean(val)
|
||||
return self.title(out + words)
|
||||
|
||||
def to_cardinal_float(self, value, reading=False, prefer=None):
|
||||
prefer = prefer or ["れい"]
|
||||
try:
|
||||
float(value) == value
|
||||
except (ValueError, TypeError, AssertionError):
|
||||
raise TypeError(self.errmsg_nonnum % value)
|
||||
|
||||
pre, post = self.float2tuple(float(value))
|
||||
|
||||
post = str(post)
|
||||
post = '0' * (self.precision - len(post)) + post
|
||||
|
||||
out = [self.to_cardinal(pre, reading=reading, prefer=prefer)]
|
||||
if self.precision:
|
||||
out.append(self.title(self.pointword[1 if reading else 0]))
|
||||
|
||||
for i in range(self.precision):
|
||||
curr = int(post[i])
|
||||
out.append(to_s(
|
||||
self.to_cardinal(curr, reading=reading, prefer=prefer)))
|
||||
|
||||
return "".join(out)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user