From 47a3cac323bf9290a28ec1f28b5c5fb9dcf1318c Mon Sep 17 00:00:00 2001 From: Willem Van Onsem Date: Mon, 21 Sep 2020 18:53:47 +0200 Subject: [PATCH 001/200] Fix zeroth in Dutch to nulde fixing #325 --- num2words/lang_NL.py | 5 ++++- tests/test_nl.py | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/num2words/lang_NL.py b/num2words/lang_NL.py index ac4d4051..8725714c 100644 --- a/num2words/lang_NL.py +++ b/num2words/lang_NL.py @@ -76,7 +76,10 @@ def setup(self): "zes", "vijf", "vier", "drie", "twee", "één", "nul"] - self.ords = {"één": "eerst", + # Wiktionary says it is "nulde", not "nulte" or "nule" + # https://en.wiktionary.org/wiki/nulde + self.ords = {"nul": "nuld", + "één": "eerst", "twee": "tweed", "drie": "derd", "vier": "vierd", diff --git a/tests/test_nl.py b/tests/test_nl.py index e72b43bf..95c690f4 100644 --- a/tests/test_nl.py +++ b/tests/test_nl.py @@ -36,6 +36,7 @@ def test_ordinal_more_than_twenty(self): ) def test_ordinal_at_crucial_number(self): + self.assertEqual(num2words(0, ordinal=True, lang='nl'), "nulde") self.assertEqual(num2words(100, ordinal=True, lang='nl'), "honderdste") self.assertEqual( num2words(1000, ordinal=True, lang='nl'), "duizendste" From a6cae07703045c251fc8f608aef55ba706896499 Mon Sep 17 00:00:00 2001 From: gshekler Date: Sat, 3 Oct 2020 15:02:49 +0300 Subject: [PATCH 002/200] fix pluralize --- num2words/lang_HE.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/num2words/lang_HE.py b/num2words/lang_HE.py index 34b2ec8a..2b96dc1b 100644 --- a/num2words/lang_HE.py +++ b/num2words/lang_HE.py @@ -81,11 +81,7 @@ def pluralize(n, forms): - # gettext implementation: - # (n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2) - - form = 0 if (n % 10 == 1 and n % 100 != 11) else 1 if n != 0 else 2 - + form = 1 if n == 0 else 0 if n == 1 else 1 return forms[form] @@ -151,6 +147,9 @@ def to_cardinal(self, number): def to_ordinal(self, number): raise NotImplementedError() + def pluralize(self, n, forms): + return pluralize(n, forms) + if __name__ == '__main__': yo = Num2Word_HE() From 92a0915508514983a8f1388d6acf062f593ac8e4 Mon Sep 17 00:00:00 2001 From: gshekler Date: Sat, 3 Oct 2020 15:03:43 +0300 Subject: [PATCH 003/200] implement currency for HE --- num2words/lang_HE.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/num2words/lang_HE.py b/num2words/lang_HE.py index 2b96dc1b..f9871925 100644 --- a/num2words/lang_HE.py +++ b/num2words/lang_HE.py @@ -136,11 +136,13 @@ def n2w(n): return int2word(int(n)) -def to_currency(n, currency='EUR', cents=True, separator=','): - raise NotImplementedError() - - class Num2Word_HE(Num2Word_Base): + CURRENCY_FORMS = { + 'NIS': (('שקל', 'שקלים'), ('אגורה', 'אגורות')), + 'EUR': (('אירו', 'אירו'), ('סנט', 'סנט')), + 'USD': (('דולר', 'דולרים'), ('סנט', 'סנט')), + } + def to_cardinal(self, number): return n2w(number) @@ -150,6 +152,14 @@ def to_ordinal(self, number): def pluralize(self, n, forms): return pluralize(n, forms) + def to_currency(self, val, currency='NIS', cents=True, separator=' ו', + adjective=False): + result = super(Num2Word_HE, self).to_currency( + val, currency=currency, cents=cents, separator=separator, + adjective=adjective) + # In Hebrew the separator is along with the following word + return result.replace(" ו ", " ו") + if __name__ == '__main__': yo = Num2Word_HE() From 6ea1a3da713906117e0660bd5dd68a5cad392053 Mon Sep 17 00:00:00 2001 From: gshekler Date: Sat, 3 Oct 2020 15:03:57 +0300 Subject: [PATCH 004/200] add unit tests --- tests/test_he.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/tests/test_he.py b/tests/test_he.py index 206d7cc5..5a17694e 100644 --- a/tests/test_he.py +++ b/tests/test_he.py @@ -20,6 +20,7 @@ from unittest import TestCase from num2words import num2words +from num2words.lang_HE import Num2Word_HE class Num2WordsHETest(TestCase): @@ -71,3 +72,39 @@ def test_1000_to_9999(self): self.assertEqual( num2words(6870, lang="he"), u'ששת אלפים שמונה מאות ושבעים' ) + + def test_pluralize(self): + n = Num2Word_HE() + cr1, cr2 = n.CURRENCY_FORMS['NIS'] + self.assertEqual(n.pluralize(1, cr1), 'שקל') + self.assertEqual(n.pluralize(2, cr1), 'שקלים') + self.assertEqual(n.pluralize(1, cr2), 'אגורה') + self.assertEqual(n.pluralize(2, cr2), 'אגורות') + + cr1, cr2 = n.CURRENCY_FORMS['USD'] + self.assertEqual(n.pluralize(1, cr1), 'דולר') + self.assertEqual(n.pluralize(2, cr1), 'דולרים') + self.assertEqual(n.pluralize(1, cr2), 'סנט') + self.assertEqual(n.pluralize(2, cr2), 'סנט') + + def test_currency_(self): + n = Num2Word_HE() + self.assertEqual(n.to_currency(20.0 ,currency='NIS'), 'עשרים שקלים ואפס אגורות') + self.assertEqual(n.to_currency(100.0 ,currency='NIS'), 'מאה שקלים ואפס אגורות') + self.assertEqual(n.to_currency(100.50 ,currency='NIS'), 'מאה שקלים וחמישים אגורות') + + def test_to_cardinal(self): + n = Num2Word_HE() + self.assertEqual(n.to_cardinal(1500), u'אלף וחמש מאות') + + +class Num2WordsHETestNotImplementedMethofs(TestCase): + n = Num2Word_HE() + + def test_to_ordinal(self): + with self.assertRaises(NotImplementedError): + self.n.to_ordinal('1') + + def test_large_number(self): + with self.assertRaises(NotImplementedError): + num2words(2000000, lang="he") From c95fe6260b1a5fd3f40cb4ac5f10557315d1507f Mon Sep 17 00:00:00 2001 From: gshekler Date: Sat, 3 Oct 2020 15:14:21 +0300 Subject: [PATCH 005/200] typo --- tests/test_he.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_he.py b/tests/test_he.py index 5a17694e..688bbf04 100644 --- a/tests/test_he.py +++ b/tests/test_he.py @@ -87,7 +87,7 @@ def test_pluralize(self): self.assertEqual(n.pluralize(1, cr2), 'סנט') self.assertEqual(n.pluralize(2, cr2), 'סנט') - def test_currency_(self): + def test_to_currency(self): n = Num2Word_HE() self.assertEqual(n.to_currency(20.0 ,currency='NIS'), 'עשרים שקלים ואפס אגורות') self.assertEqual(n.to_currency(100.0 ,currency='NIS'), 'מאה שקלים ואפס אגורות') From f65df3fc613b45a6987fa966fb99ffcc89efe58e Mon Sep 17 00:00:00 2001 From: hamidreza kalbasi Date: Wed, 16 Dec 2020 21:11:52 +0330 Subject: [PATCH 006/200] add basic farsi support --- README.rst | 1 + num2words/__init__.py | 3 +- num2words/lang_FA.py | 165 ++++++++++++++++++++++++++++++++++++++++++ tests/test_fa.py | 85 ++++++++++++++++++++++ 4 files changed, 253 insertions(+), 1 deletion(-) create mode 100644 num2words/lang_FA.py create mode 100644 tests/test_fa.py diff --git a/README.rst b/README.rst index db64202b..c8524c58 100644 --- a/README.rst +++ b/README.rst @@ -86,6 +86,7 @@ Besides the numerical argument, there are two main optional arguments. * ``es_CO`` (Spanish - Colombia) * ``es_VE`` (Spanish - Venezuela) * ``eu`` (EURO) +* ``fa`` (Farsi) * ``fi`` (Finnish) * ``fr`` (French) * ``fr_CH`` (French - Switzerland) diff --git a/num2words/__init__.py b/num2words/__init__.py index 931d28af..0b85ec7f 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -18,7 +18,7 @@ from __future__ import unicode_literals from . import (lang_AR, lang_CZ, lang_DE, lang_DK, lang_EN, lang_EN_IN, - lang_ES, lang_ES_CO, lang_ES_NI, lang_ES_VE, lang_FI, lang_FR, + lang_ES, lang_ES_CO, 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_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, @@ -30,6 +30,7 @@ 'cz': lang_CZ.Num2Word_CZ(), 'en': lang_EN.Num2Word_EN(), 'en_IN': lang_EN_IN.Num2Word_EN_IN(), + '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(), diff --git a/num2words/lang_FA.py b/num2words/lang_FA.py new file mode 100644 index 00000000..9e232a79 --- /dev/null +++ b/num2words/lang_FA.py @@ -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. +# Copyright (c) 2018, Abdullah Alhazmy, Alhazmy13. All Rights Reserved. +# Copyright (c) 2020, Hamidreza Kalbasi. 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 re +from decimal import Decimal +from math import floor + +farsiOnes = [ + "", "یک", "دو", "سه", "چهار", "پنج", "شش", "هفت", "هشت", + "نه", + "ده", + "یازده", + "دوازده", + "سیزده", + "چهارده", + "پونزده", + "شونزده", + "هیفده", + "هیجده", + "نوزده", +] + +farsiTens = [ + "", + "ده", + "بیست", + "سی", + "چهل", + "پنجاه", + "شصت", + "هفتاد", + "هشتاد", + "نود", +] + +farsiHundreds = [ + "", + "صد", + "دویست", + "سیصد", + "چهارصد", + "پانصد", + "ششصد", + "هفتصد", + "هشتصد", + "نهصد", +] + +farsiBig = [ + '', + ' هزار', + ' میلیون', + " میلیارد", + ' تریلیون', + " تریلیارد", +] + +farsiFrac = ["", "دهم", "صدم"] +farsiFracBig = ["", "هزارم", "میلیونیم", "میلیاردیم"] + +farsiSeperator = ' و ' + +class Num2Word_FA(object): + errmsg_too_big = "Too large" + max_num = 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(math.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 (res == ''): + res = yx + else: + res = yx + farsiSeperator + return res + + def fractional(self, number, l): + if (number == 5): + return "نیم" + x = self.cardinalPos(number) + ld3, lm3 = divmod(l, 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) + + def to_ordinal_num(self, value): + return str(value)+"م" + + def to_cardinal(self, number): + if number < 0: + return "منفی " + self.to_cardinal(-number) + if (number == 0): + return "صفر" + x, y, l = self.float2tuple(number) + if y == 0: + return self.cardinalPos(x) + if x == 0: + return self.fractional(y, l) + return self.cardinalPos(x) + farsiSeperator + self.fractional(y, l) \ No newline at end of file diff --git a/tests/test_fa.py b/tests/test_fa.py new file mode 100644 index 00000000..dbe9574c --- /dev/null +++ b/tests/test_fa.py @@ -0,0 +1,85 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. +# Copyright (c) 2020, Hamidreza Kalbasi. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + +from unittest import TestCase + +from num2words import num2words + + +class Num2WordsFATest(TestCase): + def test_and_join_199(self): + self.assertEqual(num2words(199, lang='fa'), "صد و نود و نه") + + def test_ordinal(self): + self.assertEqual( + num2words(0, lang='fa', to='ordinal'), + 'صفرم' + ) + self.assertEqual( + num2words(1, lang='fa', to='ordinal'), + 'یکم' + ) + self.assertEqual( + num2words(13, lang='fa', to='ordinal'), + 'سیزدهم' + ) + self.assertEqual( + num2words(23, lang='fa', to='ordinal'), + 'بیست و سوم' + ) + self.assertEqual( + num2words(12, lang='fa', to='ordinal'), + 'دوازدهم' + ) + self.assertEqual( + num2words(113, lang='fa', to='ordinal'), + 'صد و سیزدهم' + ) + self.assertEqual( + num2words(103, lang='fa', to='ordinal'), + 'صد و سوم' + ) + + def test_cardinal(self): + self.assertEqual(num2words(130000, lang='fa'), "صد و سی هزار") + self.assertEqual(num2words(242, lang='fa'), "دویست و چهل و دو") + + + + def test_ordinal_num(self): + self.assertEqual(num2words(10, lang='fa', to='ordinal_num'), '10م') + self.assertEqual(num2words(21, lang='fa', to='ordinal_num'), '21م') + self.assertEqual(num2words(102, lang='fa', to='ordinal_num'), '102م') + self.assertEqual(num2words(73, lang='fa', to='ordinal_num'), '73م') + + def test_cardinal_for_float_number(self): + self.assertEqual(num2words(12.5, lang='fa'), "دوازده و نیم") + self.assertEqual(num2words(0.75, lang='fa'), "هفتاد و پنج صدم") + self.assertEqual(num2words(12.51, lang='fa'), "دوازده و پنجاه و یک صدم") + self.assertEqual(num2words(12.53, lang='fa'), "دوازده و پنجاه و سه صدم") + self.assertEqual(num2words(12.59, lang='fa'), "دوازده و پنجاه و نه صدم") + self.assertEqual(num2words(0.000001, lang='fa'), "یک میلیونیم") + + def test_overflow(self): + with self.assertRaises(OverflowError): + num2words("1000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000") From b191c1fe1eca031a1fa144b66ea859b9ca5793d2 Mon Sep 17 00:00:00 2001 From: hamidreza kalbasi Date: Sun, 24 Jan 2021 10:10:24 +0330 Subject: [PATCH 007/200] fix test coverage --- num2words/lang_FA.py | 4 +++- tests/test_fa.py | 18 +++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/num2words/lang_FA.py b/num2words/lang_FA.py index 9e232a79..ca7004ca 100644 --- a/num2words/lang_FA.py +++ b/num2words/lang_FA.py @@ -123,10 +123,12 @@ def cardinalPos(self, number): if (y == 0): continue yx = self.cardinal3(y) + b + if b == ' هزار' and y == 1: + yx = 'هزار' if (res == ''): res = yx else: - res = yx + farsiSeperator + res = yx + farsiSeperator + res return res def fractional(self, number, l): diff --git a/tests/test_fa.py b/tests/test_fa.py index dbe9574c..4082e7f1 100644 --- a/tests/test_fa.py +++ b/tests/test_fa.py @@ -58,8 +58,24 @@ def test_ordinal(self): def test_cardinal(self): self.assertEqual(num2words(130000, lang='fa'), "صد و سی هزار") self.assertEqual(num2words(242, lang='fa'), "دویست و چهل و دو") + self.assertEqual(num2words(800, lang='fa'), "هشتصد") + self.assertEqual(num2words(-203, lang='fa'), "منفی دویست و سه") + self.assertEqual( + num2words(1234567890, lang='fa'), + "یک میلیارد و دویست و سی و چهار میلیون و پانصد و شصت و هفت هزار و هشتصد و نود" + ) + + def test_year(self): + self.assertEqual(num2words(1398, lang='fa', to='year'), "هزار و سیصد و نود و هشت") + self.assertEqual(num2words(1399, lang='fa', to='year'), "هزار و سیصد و نود و نه") + self.assertEqual(num2words(1400, lang='fa', to='year'), "هزار و چهارصد") - + def test_currency(self): + self.assertEqual(num2words(1000, lang='fa', to='currency'), 'هزار تومان') + self.assertEqual( + num2words(1500000, lang='fa', to='currency'), + 'یک میلیون و پانصد هزار تومان' + ) def test_ordinal_num(self): self.assertEqual(num2words(10, lang='fa', to='ordinal_num'), '10م') From ca2651ad0f71632a0681805f83fedb63cb35769e Mon Sep 17 00:00:00 2001 From: hamidreza kalbasi Date: Sun, 24 Jan 2021 10:30:06 +0330 Subject: [PATCH 008/200] remove unneccery if --- num2words/lang_FA.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/num2words/lang_FA.py b/num2words/lang_FA.py index ca7004ca..9c5ff749 100644 --- a/num2words/lang_FA.py +++ b/num2words/lang_FA.py @@ -90,14 +90,7 @@ def float2tuple(self, value): 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)) + post = int(math.floor(post)) return pre, post, self.precision From a51b3e4d2be219818467cd2a06eb0d312d30da58 Mon Sep 17 00:00:00 2001 From: hamidreza kalbasi Date: Mon, 25 Jan 2021 00:14:05 +0330 Subject: [PATCH 009/200] try fix test failure --- num2words/lang_FA.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/num2words/lang_FA.py b/num2words/lang_FA.py index 9c5ff749..f49b5f35 100644 --- a/num2words/lang_FA.py +++ b/num2words/lang_FA.py @@ -90,8 +90,14 @@ def float2tuple(self, value): self.precision = abs(Decimal(str(value)).as_tuple().exponent) post = abs(value - pre) * 10**self.precision - post = int(math.floor(post)) - + 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 From 5bb2be74a2d24c3adfc3cbba653b7a95ed6332ee Mon Sep 17 00:00:00 2001 From: hamidreza kalbasi Date: Mon, 25 Jan 2021 01:16:45 +0330 Subject: [PATCH 010/200] fix format problem --- num2words/__init__.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/num2words/__init__.py b/num2words/__init__.py index 0b85ec7f..67b86316 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -18,12 +18,12 @@ from __future__ import unicode_literals from . import (lang_AR, lang_CZ, lang_DE, lang_DK, lang_EN, lang_EN_IN, - lang_ES, lang_ES_CO, 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_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_SL, lang_SR, lang_TE, lang_TH, lang_TR, lang_UK, - lang_VI) + lang_ES, lang_ES_CO, 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_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_SL, lang_SR, lang_TE, lang_TH, lang_TR, + lang_UK, lang_VI) CONVERTER_CLASSES = { 'ar': lang_AR.Num2Word_AR(), From 6cbd81cfbb291eccbed6bd79206caead8938ce06 Mon Sep 17 00:00:00 2001 From: hamidreza kalbasi Date: Mon, 25 Jan 2021 10:34:01 +0330 Subject: [PATCH 011/200] fix flake8 problems --- num2words/lang_FA.py | 17 ++++++++--------- tests/test_fa.py | 26 +++++++++++++++++--------- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/num2words/lang_FA.py b/num2words/lang_FA.py index f49b5f35..96e9e526 100644 --- a/num2words/lang_FA.py +++ b/num2words/lang_FA.py @@ -17,7 +17,6 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA -import re from decimal import Decimal from math import floor @@ -76,6 +75,7 @@ farsiSeperator = ' و ' + class Num2Word_FA(object): errmsg_too_big = "Too large" max_num = 10 ** 36 @@ -100,7 +100,6 @@ def float2tuple(self, value): post = int(floor(post)) return pre, post, self.precision - def cardinal3(self, number): if (number < 19): return farsiOnes[number] @@ -108,12 +107,12 @@ def cardinal3(self, number): x, y = divmod(number, 10) if y == 0: return farsiTens[x] - return farsiTens[x] + farsiSeperator + farsiOnes[y] + 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 = '' @@ -130,11 +129,11 @@ def cardinalPos(self, number): res = yx + farsiSeperator + res return res - def fractional(self, number, l): + def fractional(self, number, level): if (number == 5): return "نیم" x = self.cardinalPos(number) - ld3, lm3 = divmod(l, 3) + ld3, lm3 = divmod(level, 3) ltext = (farsiFrac[lm3] + " " + farsiFracBig[ld3]).strip() return x + " " + ltext @@ -158,9 +157,9 @@ def to_cardinal(self, number): return "منفی " + self.to_cardinal(-number) if (number == 0): return "صفر" - x, y, l = self.float2tuple(number) + x, y, level = self.float2tuple(number) if y == 0: return self.cardinalPos(x) if x == 0: - return self.fractional(y, l) - return self.cardinalPos(x) + farsiSeperator + self.fractional(y, l) \ No newline at end of file + return self.fractional(y, level) + return self.cardinalPos(x) + farsiSeperator + self.fractional(y, level) diff --git a/tests/test_fa.py b/tests/test_fa.py index 4082e7f1..9a9c4ead 100644 --- a/tests/test_fa.py +++ b/tests/test_fa.py @@ -62,16 +62,21 @@ def test_cardinal(self): self.assertEqual(num2words(-203, lang='fa'), "منفی دویست و سه") self.assertEqual( num2words(1234567890, lang='fa'), - "یک میلیارد و دویست و سی و چهار میلیون و پانصد و شصت و هفت هزار و هشتصد و نود" + "یک میلیارد و دویست و سی و چهار میلیون و" + " پانصد و شصت و هفت هزار و هشتصد و نود" ) def test_year(self): - self.assertEqual(num2words(1398, lang='fa', to='year'), "هزار و سیصد و نود و هشت") - self.assertEqual(num2words(1399, lang='fa', to='year'), "هزار و سیصد و نود و نه") - self.assertEqual(num2words(1400, lang='fa', to='year'), "هزار و چهارصد") - + self.assertEqual(num2words(1398, lang='fa', to='year'), + "هزار و سیصد و نود و هشت") + self.assertEqual(num2words(1399, lang='fa', to='year'), + "هزار و سیصد و نود و نه") + self.assertEqual( + num2words(1400, lang='fa', to='year'), "هزار و چهارصد") + def test_currency(self): - self.assertEqual(num2words(1000, lang='fa', to='currency'), 'هزار تومان') + self.assertEqual( + num2words(1000, lang='fa', to='currency'), 'هزار تومان') self.assertEqual( num2words(1500000, lang='fa', to='currency'), 'یک میلیون و پانصد هزار تومان' @@ -86,9 +91,12 @@ def test_ordinal_num(self): def test_cardinal_for_float_number(self): self.assertEqual(num2words(12.5, lang='fa'), "دوازده و نیم") self.assertEqual(num2words(0.75, lang='fa'), "هفتاد و پنج صدم") - self.assertEqual(num2words(12.51, lang='fa'), "دوازده و پنجاه و یک صدم") - self.assertEqual(num2words(12.53, lang='fa'), "دوازده و پنجاه و سه صدم") - self.assertEqual(num2words(12.59, lang='fa'), "دوازده و پنجاه و نه صدم") + self.assertEqual(num2words(12.51, lang='fa'), + "دوازده و پنجاه و یک صدم") + self.assertEqual(num2words(12.53, lang='fa'), + "دوازده و پنجاه و سه صدم") + self.assertEqual(num2words(12.59, lang='fa'), + "دوازده و پنجاه و نه صدم") self.assertEqual(num2words(0.000001, lang='fa'), "یک میلیونیم") def test_overflow(self): From 21d02eaec9ae3a8e903ac36ef2ee77462df786c3 Mon Sep 17 00:00:00 2001 From: Jonas Triki Date: Sat, 6 Feb 2021 14:42:28 +0100 Subject: [PATCH 012/200] Fixes #339 --- num2words/lang_DK.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/num2words/lang_DK.py b/num2words/lang_DK.py index 1a09094b..50ab110c 100644 --- a/num2words/lang_DK.py +++ b/num2words/lang_DK.py @@ -21,7 +21,7 @@ class Num2Word_DK(lang_EU.Num2Word_EU): - GIGA_SUFFIX = "illarder" + GIGA_SUFFIX = "illiarder" MEGA_SUFFIX = "illioner" def setup(self): @@ -61,6 +61,7 @@ def setup(self): "atten": "att", "nitten": "nitt", "tyve": "tyv"} + self.ordflag = False def merge(self, curr, next): ctext, cnum, ntext, nnum = curr + next From e4bfffaf55202c2797a88e423508051bc332fafe Mon Sep 17 00:00:00 2001 From: Birgir Steinarsson Date: Wed, 31 Mar 2021 22:03:00 +0000 Subject: [PATCH 013/200] Added Icelandic cardinals and tests. Missing genders and plurals. --- .gitignore | 1 + num2words/__init__.py | 5 +- num2words/lang_IS.py | 110 ++++++++++++++++++++++++++++++++++++++++++ tests/test_is.py | 37 ++++++++++++++ 4 files changed, 151 insertions(+), 2 deletions(-) create mode 100644 num2words/lang_IS.py create mode 100644 tests/test_is.py diff --git a/.gitignore b/.gitignore index e5a9b78d..2a9b1bf8 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ dist *.egg-info /.tox .eggs/ +/venv/ diff --git a/num2words/__init__.py b/num2words/__init__.py index a8c47370..10f05bb7 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -23,7 +23,7 @@ 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_SL, lang_SR, lang_SV, lang_TE, lang_TH, lang_TR, - lang_UK, lang_VI) + lang_UK, lang_VI, lang_IS) CONVERTER_CLASSES = { 'ar': lang_AR.Num2Word_AR(), @@ -65,7 +65,8 @@ 'nl': lang_NL.Num2Word_NL(), 'uk': lang_UK.Num2Word_UK(), 'te': lang_TE.Num2Word_TE(), - 'hu': lang_HU.Num2Word_HU() + 'hu': lang_HU.Num2Word_HU(), + 'is': lang_IS.Num2Word_IS() } CONVERTES_TYPES = ['cardinal', 'ordinal', 'ordinal_num', 'year', 'currency'] diff --git a/num2words/lang_IS.py b/num2words/lang_IS.py new file mode 100644 index 00000000..3b572b6d --- /dev/null +++ b/num2words/lang_IS.py @@ -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_IS(lang_EU.Num2Word_EU): + GIGA_SUFFIX = "illjarðar" + MEGA_SUFFIX = "illjónir" + + def setup(self): + super(Num2Word_IS, self).setup() + + self.negword = "mínus " + self.pointword = "komma" + 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ögur", "þrjú", "tvö", + "eitt", "núll"] + self.ords = {"eitt": "fyrsti", + "tvö": "annar", + "þrjú": "þriðji", + "fjögur": "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, forms): + form = 0 if (n%10 == 1 and n%100 != 11) else 1 + return forms[form] + + def merge(self, lpair, rpair): + ltext, lnum = lpair + rtext, rnum = rpair + if lnum == 1 and rnum < 100: + return (rtext, rnum) + elif rnum > lnum: + return ("%s %s" % (ltext, rtext), lnum * rnum) + elif lnum > rnum and rnum in self.cards: + return ("%s og %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)) diff --git a/tests/test_is.py b/tests/test_is.py new file mode 100644 index 00000000..68c307c9 --- /dev/null +++ b/tests/test_is.py @@ -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 unittest import TestCase + +from num2words import num2words + + +class Num2WordsISTest(TestCase): + + def test_cardinal(self): + self.assertEqual(num2words(0, to="cardinal", lang="is"), "núll") + self.assertEqual(num2words(1, to="cardinal", lang="is"), "eitt") + self.assertEqual(num2words(2, to="cardinal", lang="is"), "tvö") + self.assertEqual(num2words(5, to="cardinal", lang="is"), "fimm") + self.assertEqual(num2words(8, to="cardinal", lang="is"), "átta") + self.assertEqual(num2words(18, to="cardinal", lang="is"), "átján") + self.assertEqual(num2words(45, to="cardinal", lang="is"), "fjörutíu og fimm") + self.assertEqual(num2words(145, to="cardinal", lang="is"), "eitt hundrað fjörutíu og fimm") + self.assertEqual(num2words(1245, to="cardinal", lang="is"), "eitt þúsund tvö hundruð fjörutíu og fimm") + self.assertEqual(num2words(1010234045, to="cardinal", lang="is"), "einn milljarður tíu milljónir tvö hundruð þrjátíu og fjögur þúsund fjörutíu og fimm") \ No newline at end of file From 9ba0074fd041fd13325fa65610fb178dc4b60972 Mon Sep 17 00:00:00 2001 From: Birgir Steinarsson Date: Wed, 7 Apr 2021 23:43:14 +0000 Subject: [PATCH 014/200] Added genders and plurals for Icelandic cardinals. --- num2words/lang_IS.py | 108 +++++++++++++++++++++++-------------------- tests/test_is.py | 25 +++++++--- 2 files changed, 77 insertions(+), 56 deletions(-) diff --git a/num2words/lang_IS.py b/num2words/lang_IS.py index 3b572b6d..9a90657b 100644 --- a/num2words/lang_IS.py +++ b/num2words/lang_IS.py @@ -19,17 +19,33 @@ 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ðar" - MEGA_SUFFIX = "illjónir" + GIGA_SUFFIX = "illjarður" + MEGA_SUFFIX = "illjón" def setup(self): - super(Num2Word_IS, self).setup() + 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" - self.exclude_title = ["og", "komma", "mínus"] + # 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"), @@ -38,12 +54,12 @@ def setup(self): 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ögur", "þrjú", "tvö", - "eitt", "núll"] - self.ords = {"eitt": "fyrsti", - "tvö": "annar", - "þrjú": "þriðji", - "fjögur": "fjórði", + "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", @@ -53,58 +69,52 @@ def setup(self): "ellefu": "ellefti", "tólf": "tólfti"} - def pluralize(self, n, forms): - form = 0 if (n%10 == 1 and n%100 != 11) else 1 - return forms[form] + 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 rnum > lnum: + 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): - 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) + raise NotImplementedError def to_ordinal_num(self, value): - self.verify_ordinal(value) - return "%s%s" % (value, self.to_ordinal(value)[-2:]) + raise NotImplementedError 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)) + raise NotImplementedError diff --git a/tests/test_is.py b/tests/test_is.py index 68c307c9..13326988 100644 --- a/tests/test_is.py +++ b/tests/test_is.py @@ -26,12 +26,23 @@ class Num2WordsISTest(TestCase): def test_cardinal(self): self.assertEqual(num2words(0, to="cardinal", lang="is"), "núll") - self.assertEqual(num2words(1, to="cardinal", lang="is"), "eitt") - self.assertEqual(num2words(2, to="cardinal", lang="is"), "tvö") - self.assertEqual(num2words(5, to="cardinal", lang="is"), "fimm") - self.assertEqual(num2words(8, to="cardinal", lang="is"), "átta") - self.assertEqual(num2words(18, to="cardinal", lang="is"), "átján") + self.assertEqual(num2words(1, to="cardinal", lang="is"), "einn") self.assertEqual(num2words(45, to="cardinal", lang="is"), "fjörutíu og fimm") self.assertEqual(num2words(145, to="cardinal", lang="is"), "eitt hundrað fjörutíu og fimm") - self.assertEqual(num2words(1245, to="cardinal", lang="is"), "eitt þúsund tvö hundruð fjörutíu og fimm") - self.assertEqual(num2words(1010234045, to="cardinal", lang="is"), "einn milljarður tíu milljónir tvö hundruð þrjátíu og fjögur þúsund fjörutíu og fimm") \ No newline at end of file + self.assertEqual(num2words(-1245, to="cardinal", lang="is"), "mínus eitt þúsund tvö hundruð fjörutíu og fimm") + self.assertEqual(num2words(1002234045, to="cardinal", lang="is"), "einn milljarður tvær milljónir tvö hundruð þrjátíu og fjögur þúsund fjörutíu og fimm") + + def test_cardinal_for_float_number(self): + self.assertEqual(num2words(12.5, to="cardinal", lang="is"), "tólf komma fimm") + self.assertEqual(num2words(12.51, to="cardinal", lang="is"), "tólf komma fimm einn") + self.assertEqual(num2words(-12.53, to="cardinal", lang="is"), "mínus tólf komma fimm þrír") + self.assertEqual(num2words(12.59, to="cardinal", lang="is"), "tólf komma fimm níu") + + def test_overflow(self): + with self.assertRaises(OverflowError): + num2words("1000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000", lang="is") \ No newline at end of file From 880dd7465da76be592cda2001011070e2c1f8864 Mon Sep 17 00:00:00 2001 From: Birgir Steinarsson Date: Thu, 8 Apr 2021 00:00:42 +0000 Subject: [PATCH 015/200] Fixing 'flake8' issues --- num2words/lang_IS.py | 1 + tests/test_is.py | 31 +++++++++++++++++++++---------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/num2words/lang_IS.py b/num2words/lang_IS.py index 9a90657b..3cd33cec 100644 --- a/num2words/lang_IS.py +++ b/num2words/lang_IS.py @@ -36,6 +36,7 @@ } class Num2Word_IS(lang_EU.Num2Word_EU): + GIGA_SUFFIX = "illjarður" MEGA_SUFFIX = "illjón" diff --git a/tests/test_is.py b/tests/test_is.py index 13326988..459f9826 100644 --- a/tests/test_is.py +++ b/tests/test_is.py @@ -25,18 +25,29 @@ class Num2WordsISTest(TestCase): def test_cardinal(self): - self.assertEqual(num2words(0, to="cardinal", lang="is"), "núll") - self.assertEqual(num2words(1, to="cardinal", lang="is"), "einn") - self.assertEqual(num2words(45, to="cardinal", lang="is"), "fjörutíu og fimm") - self.assertEqual(num2words(145, to="cardinal", lang="is"), "eitt hundrað fjörutíu og fimm") - self.assertEqual(num2words(-1245, to="cardinal", lang="is"), "mínus eitt þúsund tvö hundruð fjörutíu og fimm") - self.assertEqual(num2words(1002234045, to="cardinal", lang="is"), "einn milljarður tvær milljónir tvö hundruð þrjátíu og fjögur þúsund fjörutíu og fimm") + self.assertEqual(num2words(0, to="cardinal", lang="is"), + "núll") + self.assertEqual(num2words(1, to="cardinal", lang="is"), + "einn") + self.assertEqual(num2words(45, to="cardinal", lang="is"), + "fjörutíu og fimm") + self.assertEqual(num2words(145, to="cardinal", lang="is"), + "eitt hundrað fjörutíu og fimm") + self.assertEqual(num2words(-1245, to="cardinal", lang="is"), + "mínus eitt þúsund tvö hundruð fjörutíu og fimm") + self.assertEqual(num2words(1002234045, to="cardinal", lang="is"), + "einn milljarður tvær milljónir tvö hundruð " + "þrjátíu og fjögur þúsund fjörutíu og fimm") def test_cardinal_for_float_number(self): - self.assertEqual(num2words(12.5, to="cardinal", lang="is"), "tólf komma fimm") - self.assertEqual(num2words(12.51, to="cardinal", lang="is"), "tólf komma fimm einn") - self.assertEqual(num2words(-12.53, to="cardinal", lang="is"), "mínus tólf komma fimm þrír") - self.assertEqual(num2words(12.59, to="cardinal", lang="is"), "tólf komma fimm níu") + self.assertEqual(num2words(12.5, to="cardinal", lang="is"), + "tólf komma fimm") + self.assertEqual(num2words(12.51, to="cardinal", lang="is"), + "tólf komma fimm einn") + self.assertEqual(num2words(-12.53, to="cardinal", lang="is"), + "mínus tólf komma fimm þrír") + self.assertEqual(num2words(12.59, to="cardinal", lang="is"), + "tólf komma fimm níu") def test_overflow(self): with self.assertRaises(OverflowError): From e00e543a237d8ab094a4c1ca88569305f2a0b522 Mon Sep 17 00:00:00 2001 From: Birgir Steinarsson Date: Thu, 8 Apr 2021 00:07:28 +0000 Subject: [PATCH 016/200] Fixing more 'flake8' issues --- num2words/lang_IS.py | 1 + tests/test_is.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/num2words/lang_IS.py b/num2words/lang_IS.py index 3cd33cec..b3cff766 100644 --- a/num2words/lang_IS.py +++ b/num2words/lang_IS.py @@ -35,6 +35,7 @@ "hundrað": ("hundrað", "hundruð"), } + class Num2Word_IS(lang_EU.Num2Word_EU): GIGA_SUFFIX = "illjarður" diff --git a/tests/test_is.py b/tests/test_is.py index 459f9826..0ca90a4f 100644 --- a/tests/test_is.py +++ b/tests/test_is.py @@ -56,4 +56,4 @@ def test_overflow(self): "0000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000" - "00000000000000000000000000000000", lang="is") \ No newline at end of file + "00000000000000000000000000000000", lang="is") From e509073a88dc91ab8513a71a5f848b2f33ceca60 Mon Sep 17 00:00:00 2001 From: Birgir Steinarsson Date: Thu, 8 Apr 2021 00:11:55 +0000 Subject: [PATCH 017/200] Fixing 'isort' issues --- num2words/__init__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/num2words/__init__.py b/num2words/__init__.py index 10f05bb7..e1f8bfb4 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -20,10 +20,10 @@ from . import (lang_AR, lang_CZ, lang_DE, lang_DK, lang_EN, lang_EN_IN, lang_ES, lang_ES_CO, lang_ES_NI, lang_ES_VE, lang_FI, lang_FR, lang_FR_BE, lang_FR_CH, lang_FR_DZ, lang_HE, lang_HU, lang_ID, - 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_SL, lang_SR, lang_SV, lang_TE, lang_TH, lang_TR, - lang_UK, lang_VI, lang_IS) + 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_SL, lang_SR, lang_SV, lang_TE, lang_TH, + lang_TR, lang_UK, lang_VI) CONVERTER_CLASSES = { 'ar': lang_AR.Num2Word_AR(), From be7a6ff33cab7cb68372e4eadbe34d2ddc4fd057 Mon Sep 17 00:00:00 2001 From: Birgir Steinarsson Date: Thu, 8 Apr 2021 00:59:19 +0000 Subject: [PATCH 018/200] Final touches. --- README.rst | 1 + num2words/lang_EU.py | 6 ++++-- num2words/lang_IS.py | 7 ++++++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/README.rst b/README.rst index ab4cf652..9064d120 100644 --- a/README.rst +++ b/README.rst @@ -94,6 +94,7 @@ Besides the numerical argument, there are two main optional arguments. * ``he`` (Hebrew) * ``hu`` (Hungarian) * ``id`` (Indonesian) +* ``is`` (Icelandic) * ``it`` (Italian) * ``ja`` (Japanese) * ``kn`` (Kannada) diff --git a/num2words/lang_EU.py b/num2words/lang_EU.py index 09d39c15..204400cf 100644 --- a/num2words/lang_EU.py +++ b/num2words/lang_EU.py @@ -43,7 +43,8 @@ class Num2Word_EU(Num2Word_Base): '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')) + 'HUF': (('forint', 'forint'), ('fillér', 'fillér')), + 'ISK': (('króna', 'krónur'), ('aur', 'aurar')) } CURRENCY_ADJECTIVES = { @@ -56,7 +57,8 @@ class Num2Word_EU(Num2Word_Base): 'MXN': 'Mexican', 'RON': 'Romanian', 'INR': 'Indian', - 'HUF': 'Hungarian' + 'HUF': 'Hungarian', + 'ISK': 'íslenskar' } GIGA_SUFFIX = "illiard" diff --git a/num2words/lang_IS.py b/num2words/lang_IS.py index b3cff766..e29eb7a7 100644 --- a/num2words/lang_IS.py +++ b/num2words/lang_IS.py @@ -47,7 +47,9 @@ def setup(self): self.negword = "mínus " self.pointword = "komma" - # self.exclude_title = ["og", "komma", "mínus"] + + # 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"), @@ -120,3 +122,6 @@ def to_ordinal_num(self, value): def to_year(self, val, suffix=None, longval=True): raise NotImplementedError + + def to_currency(self, val, longval=True): + raise NotImplementedError From 947419d3d4012b1c8d7088cc8cfc5c3107348914 Mon Sep 17 00:00:00 2001 From: Birgir Steinarsson Date: Thu, 8 Apr 2021 09:17:50 +0000 Subject: [PATCH 019/200] Added test coverage. --- tests/test_is.py | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/tests/test_is.py b/tests/test_is.py index 0ca90a4f..a4d58f28 100644 --- a/tests/test_is.py +++ b/tests/test_is.py @@ -35,8 +35,11 @@ def test_cardinal(self): "eitt hundrað fjörutíu og fimm") self.assertEqual(num2words(-1245, to="cardinal", lang="is"), "mínus eitt þúsund tvö hundruð fjörutíu og fimm") - self.assertEqual(num2words(1002234045, to="cardinal", lang="is"), - "einn milljarður tvær milljónir tvö hundruð " + self.assertEqual(num2words(2234045, to="cardinal", lang="is"), + "tvær milljónir tvö hundruð þrjátíu og fjögur þúsund " + "fjörutíu og fimm") + self.assertEqual(num2words(4002234045, to="cardinal", lang="is"), + "fjórir milljarðar tvær milljónir tvö hundruð " "þrjátíu og fjögur þúsund fjörutíu og fimm") def test_cardinal_for_float_number(self): @@ -57,3 +60,20 @@ def test_overflow(self): "0000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000" "00000000000000000000000000000000", lang="is") + + def test_not_implemented(self): + #Ordinals + with self.assertRaises(NotImplementedError): + num2words(1, to="ordinal", lang="is") + + #Ordinal num + with self.assertRaises(NotImplementedError): + num2words(1, to="ordinal_num", lang="is") + + #Year + with self.assertRaises(NotImplementedError): + num2words(1, to="year", lang="is") + + #Currency + with self.assertRaises(NotImplementedError): + num2words(1, to="currency", lang="is") From 5a98abf46bf738451333056fe15ea34909a01622 Mon Sep 17 00:00:00 2001 From: Birgir Steinarsson Date: Thu, 8 Apr 2021 16:55:07 +0000 Subject: [PATCH 020/200] Added test coverage. --- tests/test_is.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_is.py b/tests/test_is.py index a4d58f28..2a836d51 100644 --- a/tests/test_is.py +++ b/tests/test_is.py @@ -62,18 +62,18 @@ def test_overflow(self): "00000000000000000000000000000000", lang="is") def test_not_implemented(self): - #Ordinals + # Ordinals with self.assertRaises(NotImplementedError): num2words(1, to="ordinal", lang="is") - #Ordinal num + # Ordinal num with self.assertRaises(NotImplementedError): num2words(1, to="ordinal_num", lang="is") - #Year + # Year with self.assertRaises(NotImplementedError): num2words(1, to="year", lang="is") - #Currency + # Currency with self.assertRaises(NotImplementedError): num2words(1, to="currency", lang="is") From 1e4470bc2401946d5ddeba71239eea9f0a779555 Mon Sep 17 00:00:00 2001 From: Antoine Planchot Date: Fri, 14 May 2021 22:31:46 +0200 Subject: [PATCH 021/200] Added support for Esperanto numbers. --- num2words/__init__.py | 13 +-- num2words/lang_EO.py | 130 +++++++++++++++++++++++++++++ tests/test_eo.py | 190 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 327 insertions(+), 6 deletions(-) create mode 100644 num2words/lang_EO.py create mode 100644 tests/test_eo.py diff --git a/num2words/__init__.py b/num2words/__init__.py index a8c47370..06004b66 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -18,12 +18,12 @@ from __future__ import unicode_literals from . import (lang_AR, lang_CZ, lang_DE, lang_DK, lang_EN, lang_EN_IN, - lang_ES, lang_ES_CO, lang_ES_NI, lang_ES_VE, lang_FI, lang_FR, - lang_FR_BE, lang_FR_CH, lang_FR_DZ, lang_HE, lang_HU, lang_ID, - 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_SL, lang_SR, lang_SV, lang_TE, lang_TH, lang_TR, - lang_UK, lang_VI) + lang_EO, lang_ES, lang_ES_CO, lang_ES_NI, lang_ES_VE, lang_FI, + lang_FR, lang_FR_BE, lang_FR_CH, lang_FR_DZ, lang_HE, lang_HU, + lang_ID, 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_SL, lang_SR, lang_SV, lang_TE, lang_TH, + lang_TR, lang_UK, lang_VI) CONVERTER_CLASSES = { 'ar': lang_AR.Num2Word_AR(), @@ -36,6 +36,7 @@ '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_NI': lang_ES_NI.Num2Word_ES_NI(), diff --git a/num2words/lang_EO.py b/num2words/lang_EO.py new file mode 100644 index 00000000..473e74d1 --- /dev/null +++ b/num2words/lang_EO.py @@ -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." + ) + 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] diff --git a/tests/test_eo.py b/tests/test_eo.py new file mode 100644 index 00000000..64076cee --- /dev/null +++ b/tests/test_eo.py @@ -0,0 +1,190 @@ +# -*- 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 unicode_literals + +from unittest import TestCase + +from num2words import num2words + +TEST_CASES_CARDINAL = ( + (1, "unu"), + (2, "du"), + (3, "tri"), + (5.5, "kvin komo kvin"), + (11, "dek unu"), + (12, "dek du"), + (16, "dek ses"), + (17.42, "dek sep komo kvar du"), + (19, "dek naŭ"), + (20, "dudek"), + (21, "dudek unu"), + (26, "dudek ses"), + (27.312, "dudek sep komo tri unu du"), + (28, "dudek ok"), + (30, "tridek"), + (31, "tridek unu"), + (40, "kvardek"), + (44, "kvardek kvar"), + (50, "kvindek"), + (53.486, "kvindek tri komo kvar ok ses"), + (55, "kvindek kvin"), + (60, "sesdek"), + (67, "sesdek sep"), + (70, "sepdek"), + (79, "sepdek naŭ"), + (89, "okdek naŭ"), + (95, "naŭdek kvin"), + (100, "cent"), + (101, "cent unu"), + (199, "cent naŭdek naŭ"), + (203, "ducent tri"), + (287, "ducent okdek sep"), + (300.42, "tricent komo kvar du"), + (356, "tricent kvindek ses"), + (400, "kvarcent"), + (434, "kvarcent tridek kvar"), + (578, "kvincent sepdek ok"), + (689, "sescent okdek naŭ"), + (729, "sepcent dudek naŭ"), + (894, "okcent naŭdek kvar"), + (999, "naŭcent naŭdek naŭ"), + (1000, "mil"), + (1001, "mil unu"), + (1097, "mil naŭdek sep"), + (1104, "mil cent kvar"), + (1243, "mil ducent kvardek tri"), + (2385, "du mil tricent okdek kvin"), + (3766, "tri mil sepcent sesdek ses"), + (4196, "kvar mil cent naŭdek ses"), + (4196.42, "kvar mil cent naŭdek ses komo kvar du"), + (5846, "kvin mil okcent kvardek ses"), + (6459, "ses mil kvarcent kvindek naŭ"), + (7232, "sep mil ducent tridek du"), + (8569, "ok mil kvincent sesdek naŭ"), + (9539, "naŭ mil kvincent tridek naŭ"), + (1000000, "unu miliono"), + (1000001, "unu miliono unu"), + (4000000, "kvar milionoj"), + (4000004, "kvar milionoj kvar"), + (4300000, "kvar milionoj tricent mil"), + (80000000, "okdek milionoj"), + (300000000, "tricent milionoj"), + (10000000000000, "dek bilionoj"), + (10000000000010, "dek bilionoj dek"), + (100000000000000, "cent bilionoj"), + (1000000000000000000, "unu triliono"), + (1000000000000000000000, "unu triliardo"), + (10000000000000000000000000, "dek kvarilionoj") +) + +TEST_CASES_ORDINAL = ( + (1, "unua"), + (8, "oka"), + (12, "dek dua"), + (14, "dek kvara"), + (28, "dudek oka"), + (100, "centa"), + (1000, "mila"), + (1000000, "unu miliona"), + (1000000000000000, "unu biliarda"), + (1000000000000000000, "unu triliona") +) + +TEST_CASES_ORDINAL_NUM = ( + (1, "1a"), + (8, "8a"), + (11, "11a"), + (12, "12a"), + (14, "14a"), + (21, "21a"), + (28, "28a"), + (100, "100a"), + (101, "101a"), + (1000, "1000a"), + (1000000, "1000000a") +) + +TEST_CASES_TO_CURRENCY_EUR = ( + (1.00, "unu eŭro kaj nul centimo"), + (2.01, "du eŭroj kaj unu centimo"), + (8.10, "ok eŭroj kaj dek centimoj"), + (12.26, "dek du eŭroj kaj dudek ses centimoj"), + (21.29, "dudek unu eŭroj kaj dudek naŭ centimoj"), + (81.25, "okdek unu eŭroj kaj dudek kvin centimoj"), + (100.00, "cent eŭroj kaj nul centimo"), +) + +TEST_CASES_TO_CURRENCY_FRF = ( + (1.00, "unu franko kaj nul centimo"), + (2.01, "du frankoj kaj unu centimo"), + (8.10, "ok frankoj kaj dek centimoj"), + (12.27, "dek du frankoj kaj dudek sep centimoj"), + (21.29, "dudek unu frankoj kaj dudek naŭ centimoj"), + (81.25, "okdek unu frankoj kaj dudek kvin centimoj"), + (100.00, "cent frankoj kaj nul centimo"), +) + +TEST_CASES_TO_CURRENCY_USD = ( + (1.00, "unu dolaro kaj nul cendo"), + (2.01, "du dolaroj kaj unu cendo"), + (8.10, "ok dolaroj kaj dek cendoj"), + (12.26, "dek du dolaroj kaj dudek ses cendoj"), + (21.29, "dudek unu dolaroj kaj dudek naŭ cendoj"), + (81.25, "okdek unu dolaroj kaj dudek kvin cendoj"), + (100.00, "cent dolaroj kaj nul cendo"), +) + + +class Num2WordsEOTest(TestCase): + def test_number(self): + for test in TEST_CASES_CARDINAL: + self.assertEqual(num2words(test[0], lang="eo"), test[1]) + + def test_ordinal(self): + for test in TEST_CASES_ORDINAL: + self.assertEqual( + num2words(test[0], lang="eo", ordinal=True), + test[1] + ) + + def test_ordinal_num(self): + for test in TEST_CASES_ORDINAL_NUM: + self.assertEqual( + num2words(test[0], lang="eo", to="ordinal_num"), + test[1] + ) + + def test_currency_eur(self): + for test in TEST_CASES_TO_CURRENCY_EUR: + self.assertEqual( + num2words(test[0], lang="eo", to="currency", currency="EUR"), + test[1] + ) + + def test_currency_frf(self): + for test in TEST_CASES_TO_CURRENCY_FRF: + self.assertEqual( + num2words(test[0], lang="eo", to="currency", currency="FRF"), + test[1] + ) + + def test_currency_usd(self): + for test in TEST_CASES_TO_CURRENCY_USD: + self.assertEqual( + num2words(test[0], lang="eo", to="currency", currency="USD"), + test[1] + ) From 5374a0ee44acb9395097164803437ff35d87c4ce Mon Sep 17 00:00:00 2001 From: Drew Echerd Date: Fri, 2 Jul 2021 17:00:13 +0500 Subject: [PATCH 022/200] Added Tajik language support --- README.rst | 1 + num2words/__init__.py | 5 +- num2words/lang_TG.py | 149 ++++++++++++++++++++++++++++++++++++++++++ tests/test_tg.py | 104 +++++++++++++++++++++++++++++ 4 files changed, 257 insertions(+), 2 deletions(-) create mode 100644 num2words/lang_TG.py create mode 100644 tests/test_tg.py diff --git a/README.rst b/README.rst index ab4cf652..e4c9fcfa 100644 --- a/README.rst +++ b/README.rst @@ -111,6 +111,7 @@ Besides the numerical argument, there are two main optional arguments. * ``ro`` (Romanian) * ``ru`` (Russian) * ``te`` (Telugu) +* ``tg`` (Tajik) * ``tr`` (Turkish) * ``th`` (Thai) * ``vi`` (Vietnamese) diff --git a/num2words/__init__.py b/num2words/__init__.py index a8c47370..2ec96e67 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -22,8 +22,8 @@ lang_FR_BE, lang_FR_CH, lang_FR_DZ, lang_HE, lang_HU, lang_ID, 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_SL, lang_SR, lang_SV, lang_TE, lang_TH, lang_TR, - lang_UK, lang_VI) + lang_RU, lang_SL, lang_SR, lang_SV, lang_TE, lang_TG, lang_TH, + lang_TR, lang_UK, lang_VI) CONVERTER_CLASSES = { 'ar': lang_AR.Num2Word_AR(), @@ -60,6 +60,7 @@ '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(), diff --git a/num2words/lang_TG.py b/num2words/lang_TG.py new file mode 100644 index 00000000..cc0bf497 --- /dev/null +++ b/num2words/lang_TG.py @@ -0,0 +1,149 @@ +# -*- 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 + +GENERIC_DOLLARS = ("доллар", "доллар") +GENERIC_CENTS = ("сент", "сент") + + +class Num2Word_TG(lang_EU.Num2Word_EU): + CURRENCY_FORMS = { + # repalced by EUR + "EUR": (("евро", "евро"), GENERIC_CENTS), + # replaced by EUR + "USD": (GENERIC_DOLLARS, GENERIC_CENTS), + "RUB": (("рубл", "рубл"), ("копейк", "копейк")), + "TJS": (("сомонӣ", "сомонӣ"), ("дирам", "дирам")), + } + + 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 + + elif self.MEGA_SUFFIX: + self.cards[10 ** n] = word + self.MEGA_SUFFIX + + def setup(self): + super(Num2Word_TG, self).setup() + + lows = ["квинт", "квадр", "тр", "м", "м"] + self.high_numwords = self.gen_high_numwords([], [], lows) + self.negword = "минус " + self.pointword = "нуқта" + self.exclude_title = ["ва", "минус", "нуқта"] + + self.mid_numwords = [ + (1000, "ҳазор"), + (100, "сад"), + (90, "навад"), + (80, "ҳаштод"), + (70, "ҳафтод"), + (60, "шаст"), + (50, "панҷоҳ"), + (40, "чил"), + (30, "си"), + ] + self.low_numwords = [ + "бист", + "нуздаҳ", + "ҳаждаҳ", + "ҳабдаҳ", + "шонздаҳ", + "понздаҳ", + "чордаҳ", + "сенздаҳ", + "дувоздаҳ", + "ёздаҳ", + "даҳ", + "нӯҳ", + "ҳашт", + "ҳафт", + "шаш", + "панҷ", + "чор", + "се", + "ду", + "як", + "сифр", + ] + + 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 = self.negword + + 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: + if ltext == "си": + return ("%sю %s" % (ltext, rtext), lnum + rnum) + elif ltext == "панҷоҳ": + return ("панҷову %s" % (rtext), lnum + rnum) + else: + return ("%sу %s" % (ltext, rtext), lnum + rnum) + elif lnum >= 100 > rnum: + return ("%sу %s" % (ltext, rtext), lnum + rnum) + elif rnum > lnum: + if ltext == "яксад" and rtext not in self.low_numwords: + return ("сад %s" % (rtext), lnum * rnum) + if rtext == "сад": + return ("%s%s" % (ltext, rtext), lnum * rnum) + else: + return ("%s %s" % (ltext, rtext), lnum * rnum) + return ("%sу %s" % (ltext, rtext), lnum + rnum) + + def to_ordinal(self, value): + self.verify_ordinal(value) + cardinal = self.to_cardinal(value) + outwords = cardinal.split(" ") + lastword = outwords[-1] + if lastword in ["ду", "се", "си"]: + return "%sюм" % (cardinal) + else: + return "%sум" % (cardinal) + + def to_ordinal_num(self, value): + self.verify_ordinal(value) + return "%s%s" % (value, self.to_ordinal(value)[-2:]) diff --git a/tests/test_tg.py b/tests/test_tg.py new file mode 100644 index 00000000..2caa9cf1 --- /dev/null +++ b/tests/test_tg.py @@ -0,0 +1,104 @@ +# -*- 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 unittest import TestCase + +from num2words import num2words + + +class Num2WordsTGTest(TestCase): + def test_cardinal(self): + self.assertEqual(num2words(100, lang="tg"), "сад") + self.assertEqual(num2words(101, lang="tg"), "яксаду як") + self.assertEqual(num2words(110, lang="tg"), "яксаду даҳ") + self.assertEqual(num2words(115, lang="tg"), "яксаду понздаҳ") + self.assertEqual(num2words(123, lang="tg"), "яксаду бисту се") + self.assertEqual(num2words(1000, lang="tg"), "як ҳазор") + self.assertEqual(num2words(1001, lang="tg"), "як ҳазору як") + self.assertEqual(num2words(2012, lang="tg"), "ду ҳазору дувоздаҳ") + self.assertEqual( + num2words(12519.85, lang="tg"), + "дувоздаҳ ҳазору панҷсаду нуздаҳ нуқта ҳашт панҷ", + ) + + self.assertEqual( + num2words(1234567890, lang="tg"), + "як миллиарду дусаду сию чор миллиону панҷсаду шасту ҳафт ҳазору " + "ҳаштсаду навад", + ) + self.assertEqual(num2words(5, lang="tg"), "панҷ") + self.assertEqual(num2words(-1, lang="tg"), "минус як") + self.assertEqual(num2words(-15, lang="tg"), "минус понздаҳ") + self.assertEqual(num2words(-100, lang="tg"), "минус сад") + + def test_to_ordinal(self): + self.assertEqual(num2words(1, lang="tg", to="ordinal"), "якум") + self.assertEqual(num2words(2, lang="tg", to="ordinal"), "дуюм") + self.assertEqual(num2words(3, lang="tg", to="ordinal"), "сеюм") + self.assertEqual(num2words(30, lang="tg", to="ordinal"), "сиюм") + + self.assertEqual(num2words(13, lang="tg", to="ordinal"), "сенздаҳум") + self.assertEqual(num2words(20, lang="tg", to="ordinal"), "бистум") + self.assertEqual(num2words(23, lang="tg", to="ordinal"), "бисту сеюм") + self.assertEqual(num2words(100, lang="tg", to="ordinal"), "садум") + self.assertEqual(num2words(136, lang="tg", to="ordinal"), + "яксаду сию шашум") + self.assertEqual(num2words(500, lang="tg", to="ordinal"), "панҷсадум") + self.assertEqual( + num2words(1000, lang="tg", to="ordinal"), "як ҳазорум" + ) + self.assertEqual( + num2words(1001, lang="tg", to="ordinal"), "як ҳазору якум" + ) + self.assertEqual( + num2words(2000, lang="tg", to="ordinal"), "ду ҳазорум" + ) + self.assertEqual( + num2words(1000000, lang="tg", to="ordinal"), "як миллионум" + ) + self.assertEqual( + num2words(1000000000, lang="tg", to="ordinal"), "як миллиардум" + ) + + def test_to_currency(self): + self.assertEqual( + num2words(1.0, lang="tg", to="currency", currency="EUR"), + "як евро, сифр сент", + ) + self.assertEqual( + num2words(1.0, lang="tg", to="currency", currency="TJS"), + "як сомонӣ, сифр дирам", + ) + self.assertEqual( + num2words(1234.56, lang="tg", to="currency", currency="TJS"), + "як ҳазору дусаду сию чор сомонӣ, панҷову шаш дирам", + ) + self.assertEqual( + num2words(1234.56, lang="tg", to="currency", currency="RUB"), + "як ҳазору дусаду сию чор рубл, панҷову шаш копейк", + ) + self.assertEqual( + num2words(12519.85, lang="tg", to="currency", currency="TJS", + cents=False), + "дувоздаҳ ҳазору панҷсаду нуздаҳ сомонӣ, 85 дирам", + ) + self.assertEqual( + num2words("1230.56", lang="tg", to="currency", currency="USD"), + "як ҳазору дусаду си доллар, панҷову шаш сент", + ) \ No newline at end of file From 1d98e0261e53f27a2537b36d8ae82ebf63d41c32 Mon Sep 17 00:00:00 2001 From: Drew Echerd Date: Fri, 2 Jul 2021 18:51:22 +0500 Subject: [PATCH 023/200] Added test for OverflowError and ordinal_num --- tests/test_tg.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/test_tg.py b/tests/test_tg.py index 2caa9cf1..a846d701 100644 --- a/tests/test_tg.py +++ b/tests/test_tg.py @@ -24,7 +24,10 @@ class Num2WordsTGTest(TestCase): def test_cardinal(self): + with self.assertRaises(OverflowError): + num2words(1000000000000000000000000, lang='tg') self.assertEqual(num2words(100, lang="tg"), "сад") + self.assertEqual(num2words(100000, lang="tg"), "сад ҳазор") self.assertEqual(num2words(101, lang="tg"), "яксаду як") self.assertEqual(num2words(110, lang="tg"), "яксаду даҳ") self.assertEqual(num2words(115, lang="tg"), "яксаду понздаҳ") @@ -101,4 +104,9 @@ def test_to_currency(self): self.assertEqual( num2words("1230.56", lang="tg", to="currency", currency="USD"), "як ҳазору дусаду си доллар, панҷову шаш сент", + ) + + def test_to_ordinal_num(self): + self.assertEqual( + num2words("100", lang="tg", to="ordinal_num"), "100ум", ) \ No newline at end of file From cdb2acb052cae15fb1e37dd3b70dfd8f79adc584 Mon Sep 17 00:00:00 2001 From: Drew Echerd Date: Fri, 2 Jul 2021 22:29:28 +0500 Subject: [PATCH 024/200] Added MEGA_SUFFIX and GIGA_SUFFIX tests --- num2words/lang_TG.py | 3 ++- tests/test_tg.py | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/num2words/lang_TG.py b/num2words/lang_TG.py index cc0bf497..8a028d58 100644 --- a/num2words/lang_TG.py +++ b/num2words/lang_TG.py @@ -43,7 +43,7 @@ def set_high_numwords(self, high): if n == 9: self.cards[10 ** n] = word + self.GIGA_SUFFIX - elif self.MEGA_SUFFIX: + else: self.cards[10 ** n] = word + self.MEGA_SUFFIX def setup(self): @@ -147,3 +147,4 @@ def to_ordinal(self, value): def to_ordinal_num(self, value): self.verify_ordinal(value) return "%s%s" % (value, self.to_ordinal(value)[-2:]) + diff --git a/tests/test_tg.py b/tests/test_tg.py index a846d701..482913be 100644 --- a/tests/test_tg.py +++ b/tests/test_tg.py @@ -45,6 +45,9 @@ def test_cardinal(self): "як миллиарду дусаду сию чор миллиону панҷсаду шасту ҳафт ҳазору " "ҳаштсаду навад", ) + self.assertEqual(num2words(1000000, lang="tg"), "як миллион") + self.assertEqual(num2words(1000000000, lang="tg"), "як миллиард") + self.assertEqual(num2words(1000000000000, lang="tg"), "як триллион") self.assertEqual(num2words(5, lang="tg"), "панҷ") self.assertEqual(num2words(-1, lang="tg"), "минус як") self.assertEqual(num2words(-15, lang="tg"), "минус понздаҳ") From 9b62e333d769acfb634b251187648309f3597269 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0smail=20Eski?= Date: Tue, 12 Oct 2021 10:09:49 +0300 Subject: [PATCH 025/200] [ADD] to ordinal number for Turkish --- num2words/lang_TR.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/num2words/lang_TR.py b/num2words/lang_TR.py index 7fba8711..59393c29 100644 --- a/num2words/lang_TR.py +++ b/num2words/lang_TR.py @@ -806,6 +806,10 @@ def to_ordinal(self, value): return wrd + def to_ordinal_num(self, value): + self.verify_ordinal(value) + return "%s%s" % (value, self.to_ordinal(value)[-4:]) + def to_splitnum(self, val): float_digits = str(int(val * 10 ** self.precision)) if not int(val) == 0: From 84e6322006191ad1acc142f5557a1e7c7caacd67 Mon Sep 17 00:00:00 2001 From: Cris140 <60457418+Cris140@users.noreply.github.com> Date: Thu, 28 Oct 2021 14:53:27 -0400 Subject: [PATCH 026/200] Update lang_PT_BR.py --- num2words/lang_PT_BR.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/num2words/lang_PT_BR.py b/num2words/lang_PT_BR.py index 80eb5e71..2c50f03f 100644 --- a/num2words/lang_PT_BR.py +++ b/num2words/lang_PT_BR.py @@ -53,6 +53,8 @@ def merge(self, curr, next): ctext = "cento" if nnum < cnum: + if cnum < 100: + return ("%s e %s" % (ctext, ntext), cnum + nnum) return ("%s e %s" % (ctext, ntext), cnum + nnum) elif (not nnum % 1000000) and cnum > 1: @@ -75,7 +77,7 @@ def to_cardinal(self, value): for ext in ( 'mil', 'milhão', 'milhões', 'bilhão', 'bilhões', 'trilhão', 'trilhões', 'quatrilhão', 'quatrilhões'): - if re.match('.*{} e \\w*ento'.format(ext), result): + if re.match('.*{} e \\w*entos? (?=.*e)'.format(ext), result): result = result.replace( '{} e'.format(ext), '{},'.format(ext), 1 ) From fe0d1850592f208dd1b3c369bffcccd98f31b53e Mon Sep 17 00:00:00 2001 From: Cris140 <60457418+Cris140@users.noreply.github.com> Date: Fri, 29 Oct 2021 22:42:10 -0400 Subject: [PATCH 027/200] Update lang_PT_BR.py To fix a problem with the thousands when the hundreds are exacts. --- num2words/lang_PT_BR.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/num2words/lang_PT_BR.py b/num2words/lang_PT_BR.py index 80eb5e71..2c50f03f 100644 --- a/num2words/lang_PT_BR.py +++ b/num2words/lang_PT_BR.py @@ -53,6 +53,8 @@ def merge(self, curr, next): ctext = "cento" if nnum < cnum: + if cnum < 100: + return ("%s e %s" % (ctext, ntext), cnum + nnum) return ("%s e %s" % (ctext, ntext), cnum + nnum) elif (not nnum % 1000000) and cnum > 1: @@ -75,7 +77,7 @@ def to_cardinal(self, value): for ext in ( 'mil', 'milhão', 'milhões', 'bilhão', 'bilhões', 'trilhão', 'trilhões', 'quatrilhão', 'quatrilhões'): - if re.match('.*{} e \\w*ento'.format(ext), result): + if re.match('.*{} e \\w*entos? (?=.*e)'.format(ext), result): result = result.replace( '{} e'.format(ext), '{},'.format(ext), 1 ) From 86b9a00a671b0a2dbce8a8ec8d1c8988af393b69 Mon Sep 17 00:00:00 2001 From: "potapov.s" Date: Tue, 2 Nov 2021 12:59:24 +0300 Subject: [PATCH 028/200] - add uzs for ru and en --- num2words/lang_EU.py | 6 ++++-- num2words/lang_RU.py | 3 +++ tests/test_en.py | 6 ++++++ tests/test_ru.py | 5 +++++ 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/num2words/lang_EU.py b/num2words/lang_EU.py index 09d39c15..529547a9 100644 --- a/num2words/lang_EU.py +++ b/num2words/lang_EU.py @@ -43,7 +43,8 @@ class Num2Word_EU(Num2Word_Base): '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')) + 'HUF': (('forint', 'forint'), ('fillér', 'fillér')), + 'UZS': (('sum', 'sums'), ('tiyin', 'tiyins')) } CURRENCY_ADJECTIVES = { @@ -56,7 +57,8 @@ class Num2Word_EU(Num2Word_Base): 'MXN': 'Mexican', 'RON': 'Romanian', 'INR': 'Indian', - 'HUF': 'Hungarian' + 'HUF': 'Hungarian', + 'UZS': 'Uzbekistan' } GIGA_SUFFIX = "illiard" diff --git a/num2words/lang_RU.py b/num2words/lang_RU.py index 8e6c875b..166169c2 100644 --- a/num2words/lang_RU.py +++ b/num2words/lang_RU.py @@ -113,6 +113,9 @@ class Num2Word_RU(Num2Word_Base): 'KZT': ( ('тенге', 'тенге', 'тенге'), ('тиын', 'тиына', 'тиынов') ), + 'UZS': ( + ('сум', 'сума', 'сумов'), ('тийин', 'тийина', 'тийинов') + ), } def setup(self): diff --git a/tests/test_en.py b/tests/test_en.py index 6234ac98..e763841c 100644 --- a/tests/test_en.py +++ b/tests/test_en.py @@ -131,6 +131,12 @@ def test_to_currency(self): "four pesos and one cent" ) + self.assertEqual( + num2words('2000.00', lang='en', to='currency', separator=' and', + cents=True, currency='UZS'), + "two thousand sums and zero tiyins" + ) + def test_to_year(self): # issue 141 # "e2 e2" diff --git a/tests/test_ru.py b/tests/test_ru.py index dc479758..85d6dc3e 100644 --- a/tests/test_ru.py +++ b/tests/test_ru.py @@ -272,3 +272,8 @@ def test_to_currency(self): 'одна тысяча двести тридцать четыре доллара, пятьдесят шесть ' 'центов' ) + self.assertEqual( + num2words(10122, lang='ru', to='currency', currency='UZS', + separator=' и'), + 'сто один сум и двадцать два тийина' + ) From 74ba6ee3b38370853f4e24d5a5da8a8a898531c2 Mon Sep 17 00:00:00 2001 From: Daniel-EST Date: Fri, 28 Jan 2022 15:30:48 -0300 Subject: [PATCH 029/200] Fixes savoirfairelinux/num2words#435 --- num2words/lang_PT_BR.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/num2words/lang_PT_BR.py b/num2words/lang_PT_BR.py index 80eb5e71..82e7eb4b 100644 --- a/num2words/lang_PT_BR.py +++ b/num2words/lang_PT_BR.py @@ -49,7 +49,7 @@ def merge(self, curr, next): if nnum < 1000000: return next ctext = "um" - elif cnum == 100 and not nnum == 1000: + elif cnum == 100 and nnum % 1000 != 0: ctext = "cento" if nnum < cnum: From 31a250eb9035ca301a183f3e19be82516aa68890 Mon Sep 17 00:00:00 2001 From: Daniel-EST Date: Fri, 28 Jan 2022 15:31:41 -0300 Subject: [PATCH 030/200] Tests fix for issue #435 --- tests/test_pt_BR.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/test_pt_BR.py b/tests/test_pt_BR.py index bbf9e8d6..87e231bc 100644 --- a/tests/test_pt_BR.py +++ b/tests/test_pt_BR.py @@ -80,6 +80,12 @@ def test_cardinal_integer(self): self.assertEqual( num2words(6000000, lang='pt_BR'), 'seis milhões' ) + self.assertEqual( + num2words(100000000, lang='pt_BR'), 'cem milhões' + ) + self.assertEqual( + num2words(100000000000, lang='pt_BR'), 'cem bilhões' + ) self.assertEqual( num2words(19000000000, lang='pt_BR'), 'dezenove bilhões' ) From 9a47f62d1c4d661130afe20bdeeaccc3614fc83f Mon Sep 17 00:00:00 2001 From: Sergei Ruzki Date: Sat, 5 Feb 2022 13:16:55 +0100 Subject: [PATCH 031/200] BYN to EU and RU --- num2words/lang_EU.py | 2 ++ num2words/lang_RU.py | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/num2words/lang_EU.py b/num2words/lang_EU.py index 09d39c15..a23cf81f 100644 --- a/num2words/lang_EU.py +++ b/num2words/lang_EU.py @@ -26,6 +26,7 @@ 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')), @@ -48,6 +49,7 @@ class Num2Word_EU(Num2Word_Base): CURRENCY_ADJECTIVES = { 'AUD': 'Australian', + 'BYN': 'Belarussian', 'CAD': 'Canadian', 'EEK': 'Estonian', 'USD': 'US', diff --git a/num2words/lang_RU.py b/num2words/lang_RU.py index 8e6c875b..549710ef 100644 --- a/num2words/lang_RU.py +++ b/num2words/lang_RU.py @@ -113,6 +113,10 @@ class Num2Word_RU(Num2Word_Base): 'KZT': ( ('тенге', 'тенге', 'тенге'), ('тиын', 'тиына', 'тиынов') ), + 'BYN': ( + ('белорусский рубль', 'белорусского рубля', 'белорусских рублей'), ('копейка', 'копейки', 'копеек') + ), + } def setup(self): @@ -208,7 +212,7 @@ def _money_verbose(self, number, currency): return self._int2word(number, currency == 'UAH') def _cents_verbose(self, number, currency): - return self._int2word(number, currency in ('UAH', 'RUB')) + return self._int2word(number, currency in ('UAH', 'RUB', 'BYN')) def _int2word(self, n, feminine=False): if n < 0: From dd8b8bd313ad99c04ef580f867649eee86f2d1d9 Mon Sep 17 00:00:00 2001 From: Sergei Ruzki Date: Sat, 5 Feb 2022 13:43:37 +0100 Subject: [PATCH 032/200] BYN to EU and RU + version --- bin/num2words | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/num2words b/bin/num2words index 068abf25..d89c142a 100755 --- a/bin/num2words +++ b/bin/num2words @@ -55,7 +55,7 @@ import sys from docopt import docopt import num2words -__version__ = "0.5.10" +__version__ = "0.5.11" __license__ = "LGPL" From 994f2eadf1e277e129bc046e33c90278e531e3ff Mon Sep 17 00:00:00 2001 From: Sergei Ruzki Date: Mon, 7 Feb 2022 20:57:47 +0100 Subject: [PATCH 033/200] BYN to EU and RU spelling corrected --- num2words/lang_RU.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/num2words/lang_RU.py b/num2words/lang_RU.py index 549710ef..43781a4d 100644 --- a/num2words/lang_RU.py +++ b/num2words/lang_RU.py @@ -114,7 +114,7 @@ class Num2Word_RU(Num2Word_Base): ('тенге', 'тенге', 'тенге'), ('тиын', 'тиына', 'тиынов') ), 'BYN': ( - ('белорусский рубль', 'белорусского рубля', 'белорусских рублей'), ('копейка', 'копейки', 'копеек') + ('белорусский рубль', 'белорусских рубля', 'белорусских рублей'), ('копейка', 'копейки', 'копеек') ), } From cb1f132c1aab6f61afaf06285f4a762e20ab1cab Mon Sep 17 00:00:00 2001 From: Sergei Ruzki Date: Fri, 15 Jul 2022 10:11:08 +0300 Subject: [PATCH 034/200] USD to PL --- CHANGES.rst | 9 +++++++++ bin/num2words | 2 +- num2words/lang_PL.py | 3 +++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index 298f9db9..861e6abc 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,6 +1,15 @@ Changelog ========= +Version 0.5.12 -- 2022/07/15 +---------------------------- + +* USD added to PL + +Version 0.5.11 -- 2022/02/05 +---------------------------- + +* BYN to EU and RU Version 0.5.10 -- 2019/05/12 ---------------------------- diff --git a/bin/num2words b/bin/num2words index d89c142a..ce5e1393 100755 --- a/bin/num2words +++ b/bin/num2words @@ -55,7 +55,7 @@ import sys from docopt import docopt import num2words -__version__ = "0.5.11" +__version__ = "0.5.12" __license__ = "LGPL" diff --git a/num2words/lang_PL.py b/num2words/lang_PL.py index 1fb1fdcd..88c9c47f 100644 --- a/num2words/lang_PL.py +++ b/num2words/lang_PL.py @@ -155,6 +155,9 @@ class Num2Word_PL(Num2Word_Base): 'EUR': ( ('euro', 'euro', 'euro'), ('cent', 'centy', 'centów') ), + 'USD': ( + ('dolar amerykański', 'dolary amerykańskie', 'dolarów amerykańskich'), ('cent', 'centy', 'centów') + ), } def setup(self): From b8a1d3168ef76a11b8932b4c3cb14e7ed5957d50 Mon Sep 17 00:00:00 2001 From: Katsuya Iida Date: Fri, 20 Aug 2021 17:29:01 +0900 Subject: [PATCH 035/200] =?UTF-8?q?Support=20Japanese=20Reiwa=20(=E4=BB=A4?= =?UTF-8?q?=E5=92=8C/=E3=82=8C=E3=81=84=E3=82=8F)=20era.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- num2words/lang_JA.py | 1 + tests/test_ja.py | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/num2words/lang_JA.py b/num2words/lang_JA.py index 58a29460..1e0e6222 100644 --- a/num2words/lang_JA.py +++ b/num2words/lang_JA.py @@ -335,6 +335,7 @@ def rendaku_merge_pairs(lpair, rpair): (1912, ("大正", "たいしょう")), (1926, ("昭和", "しょうわ")), (1989, ("平成", "へいせい")), + (2019, ("令和", "れいわ")), ] diff --git a/tests/test_ja.py b/tests/test_ja.py index eaac20b7..42da1445 100644 --- a/tests/test_ja.py +++ b/tests/test_ja.py @@ -163,6 +163,21 @@ def test_currency(self): "はちじゅうきゅうえん") def test_year(self): + self.assertEqual(n2j(2021, to="year"), "令和三年") + self.assertEqual(n2j(2021, to="year", reading=True), + "れいわさんねん") + self.assertEqual(n2j(2021, to="year", reading="arabic"), + "令和3年") + self.assertEqual(n2j(2019, to="year"), "令和元年") + self.assertEqual(n2j(2019, to="year", reading=True), + "れいわがんねん") + self.assertEqual(n2j(2019, to="year", reading="arabic"), + "令和1年") + self.assertEqual(n2j(2018, to="year"), "平成三十年") + self.assertEqual(n2j(2018, to="year", reading=True), + "へいせいさんじゅうねん") + self.assertEqual(n2j(2018, to="year", reading="arabic"), + "平成30年") self.assertEqual(n2j(2017, to="year"), "平成二十九年") self.assertEqual(n2j(2017, to="year", reading=True), "へいせいにじゅうくねん") @@ -176,8 +191,6 @@ def test_year(self): "にせんねん") self.assertEqual(n2j(645, to="year"), "大化元年") self.assertEqual(n2j(645, to="year", reading=True), "たいかがんねん") - self.assertEqual(n2j(645, to="year"), "大化元年") - self.assertEqual(n2j(645, to="year", reading=True), "たいかがんねん") self.assertEqual(n2j(-99, to="year", era=False), "紀元前九十九年") self.assertEqual(n2j(-99, to="year", era=False, reading=True), "きげんぜんきゅうじゅうくねん") From d741a9d79015f2b009706951791a09c8b89dd478 Mon Sep 17 00:00:00 2001 From: Marlon Rodriguez Garcia <47992153+mrodriguezg1991@users.noreply.github.com> Date: Thu, 4 Aug 2022 16:17:58 -0400 Subject: [PATCH 036/200] Update __init__.py remove space --- num2words/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/num2words/__init__.py b/num2words/__init__.py index 60400174..1dfb5b06 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -21,7 +21,7 @@ lang_ES, lang_ES_CO, 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_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_LV, lang_NL, lang_NO, lang_PL, lang_PT, lang_PT_BR, lang_RO, lang_RU, lang_SL, lang_SR, lang_SV, lang_TE, lang_TH, lang_TR, lang_UK, lang_VI) From 4b13dfddb7dc60821d840dbdf85c0372ba96c1fd Mon Sep 17 00:00:00 2001 From: Gabriel Shekler <46564521+gs202@users.noreply.github.com> Date: Sat, 6 Aug 2022 13:51:57 +0300 Subject: [PATCH 037/200] fix flake issues --- tests/test_he.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tests/test_he.py b/tests/test_he.py index 688bbf04..2ce6797a 100644 --- a/tests/test_he.py +++ b/tests/test_he.py @@ -89,9 +89,15 @@ def test_pluralize(self): def test_to_currency(self): n = Num2Word_HE() - self.assertEqual(n.to_currency(20.0 ,currency='NIS'), 'עשרים שקלים ואפס אגורות') - self.assertEqual(n.to_currency(100.0 ,currency='NIS'), 'מאה שקלים ואפס אגורות') - self.assertEqual(n.to_currency(100.50 ,currency='NIS'), 'מאה שקלים וחמישים אגורות') + self.assertEqual( + n.to_currency(20.0, currency='NIS'), 'עשרים שקלים ואפס אגורות' + ) + self.assertEqual( + (n.to_currency(100.0, currency='NIS'), 'מאה שקלים ואפס אגורות' + ) + self.assertEqual( + (n.to_currency(100.50, currency='NIS'), 'מאה שקלים וחמישים אגורות' + ) def test_to_cardinal(self): n = Num2Word_HE() From 55deaa9cbee39498baa9614abc33a7c89fcadc57 Mon Sep 17 00:00:00 2001 From: Gabriel Shekler <46564521+gs202@users.noreply.github.com> Date: Sat, 6 Aug 2022 13:53:14 +0300 Subject: [PATCH 038/200] typo --- tests/test_he.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_he.py b/tests/test_he.py index 2ce6797a..e50a6a22 100644 --- a/tests/test_he.py +++ b/tests/test_he.py @@ -93,10 +93,10 @@ def test_to_currency(self): n.to_currency(20.0, currency='NIS'), 'עשרים שקלים ואפס אגורות' ) self.assertEqual( - (n.to_currency(100.0, currency='NIS'), 'מאה שקלים ואפס אגורות' + n.to_currency(100.0, currency='NIS'), 'מאה שקלים ואפס אגורות' ) self.assertEqual( - (n.to_currency(100.50, currency='NIS'), 'מאה שקלים וחמישים אגורות' + n.to_currency(100.50, currency='NIS'), 'מאה שקלים וחמישים אגורות' ) def test_to_cardinal(self): From ed97e11bfbc8521bffc74ead59927f83d813cfc2 Mon Sep 17 00:00:00 2001 From: Eyosiyas Bereketab Date: Sun, 7 Aug 2022 22:19:49 +0300 Subject: [PATCH 039/200] Add Amharic language --- num2words/lang_AM.py | 107 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 num2words/lang_AM.py diff --git a/num2words/lang_AM.py b/num2words/lang_AM.py new file mode 100644 index 00000000..5d1e7bb2 --- /dev/null +++ b/num2words/lang_AM.py @@ -0,0 +1,107 @@ +# -*- 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): + 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 + "ሊዮን" + + 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 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) + 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_currency(self, val, currency='ብር', cents=True, separator='.', + adjective=False): + 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) \ + .replace(' ', '') From c06ff54f6485b67f4d0819be4cf88627eb1ca891 Mon Sep 17 00:00:00 2001 From: Eyosiyas Bereketab Date: Sun, 7 Aug 2022 22:30:30 +0300 Subject: [PATCH 040/200] Update init for Amharic language --- num2words/__init__.py | 3 ++- tests/test_am.py | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 tests/test_am.py diff --git a/num2words/__init__.py b/num2words/__init__.py index 1dfb5b06..baba5bdd 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -23,10 +23,11 @@ lang_ID, 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_SL, lang_SR, lang_SV, lang_TE, lang_TH, - lang_TR, lang_UK, lang_VI) + lang_TR, lang_UK, lang_VI, lang_AM) CONVERTER_CLASSES = { 'ar': lang_AR.Num2Word_AR(), + 'am': lang_AM.Num2Word_AM(), 'cz': lang_CZ.Num2Word_CZ(), 'en': lang_EN.Num2Word_EN(), 'en_IN': lang_EN_IN.Num2Word_EN_IN(), diff --git a/tests/test_am.py b/tests/test_am.py new file mode 100644 index 00000000..1a8436cf --- /dev/null +++ b/tests/test_am.py @@ -0,0 +1,23 @@ +# -*- 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 unittest import TestCase + +from num2words import num2words + + +class Num2WordsAMTest(TestCase): From 47d63acabf78005bc8d71a853425416047dce2b6 Mon Sep 17 00:00:00 2001 From: Eyosiyas Bereketab Date: Sun, 7 Aug 2022 22:34:49 +0300 Subject: [PATCH 041/200] Update Amharic language --- num2words/lang_AM.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/num2words/lang_AM.py b/num2words/lang_AM.py index 5d1e7bb2..6e4f2f92 100644 --- a/num2words/lang_AM.py +++ b/num2words/lang_AM.py @@ -67,9 +67,9 @@ def merge(self, lpair, rpair): if lnum == 1 and rnum < 100: return (rtext, rnum) elif 100 > lnum > rnum: - return ("%s-%s" % (ltext, rtext), lnum + rnum) + return ("%s %s" % (ltext, rtext), lnum + rnum) elif lnum >= 100 > rnum: - return ("%s እና %s" % (ltext, rtext), lnum + rnum) + return ("%s %s" % (ltext, rtext), lnum + rnum) elif rnum > lnum: return ("%s %s" % (ltext, rtext), lnum * rnum) return ("%s, %s" % (ltext, rtext), lnum + rnum) @@ -86,7 +86,7 @@ def to_ordinal(self, value): lastword = lastword[:-1] + "ie" lastword += "th" lastwords[-1] = self.title(lastword) - outwords[-1] = "-".join(lastwords) + outwords[-1] = " ".join(lastwords) return " ".join(outwords) def to_ordinal_num(self, value): From d1a85b315a5401e3313d0023dbe6f19e6b9c5aae Mon Sep 17 00:00:00 2001 From: Eyosiyas Bereketab Date: Sun, 7 Aug 2022 23:02:25 +0300 Subject: [PATCH 042/200] Add Amharic currency form --- num2words/lang_AM.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/num2words/lang_AM.py b/num2words/lang_AM.py index 6e4f2f92..024e3e1e 100644 --- a/num2words/lang_AM.py +++ b/num2words/lang_AM.py @@ -21,6 +21,8 @@ class Num2Word_AM(lang_EU.Num2Word_EU): + CURRENCY_FORMS = {'ETB': (('ብር', 'ብር'), ('ሳንቲም', 'ሳንቲም'))} + def set_high_numwords(self, high): max = 3 + 3 * len(high) for word, n in zip(high, range(max, 3, -3)): @@ -93,8 +95,8 @@ def to_ordinal_num(self, value): self.verify_ordinal(value) return "%s%s" % (value, self.to_ordinal(value)[-2:]) - def to_currency(self, val, currency='ብር', cents=True, separator='.', - adjective=False): + 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) From 308965bb993a46138fdf9585bccfa940f295f631 Mon Sep 17 00:00:00 2001 From: Eyosiyas Bereketab Date: Sun, 7 Aug 2022 23:06:48 +0300 Subject: [PATCH 043/200] Add test cases --- num2words/lang_AM.py | 3 +-- tests/test_am.py | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/num2words/lang_AM.py b/num2words/lang_AM.py index 024e3e1e..40725592 100644 --- a/num2words/lang_AM.py +++ b/num2words/lang_AM.py @@ -105,5 +105,4 @@ def to_currency(self, val, currency='ብር', cents=True, separator=' ከ', 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) \ - .replace(' ', '') + return self.to_splitnum(val, hightxt="መቶ", longval=longval) diff --git a/tests/test_am.py b/tests/test_am.py index 1a8436cf..6c479553 100644 --- a/tests/test_am.py +++ b/tests/test_am.py @@ -21,3 +21,46 @@ class Num2WordsAMTest(TestCase): + def test_and_join_199(self): + self.assertEqual(num2words(199, lang='am'), "አንድ መቶ ዘጠና ዘጠኝ") + + def test_ordinal(self): + self.assertEqual( + num2words(1, lang='am', to='ordinal'), + 'አንደኛ' + ) + self.assertEqual( + num2words(13, lang='am', to='ordinal'), + 'አሥራ ሦስተኛ' + ) + self.assertEqual( + num2words(22, lang='am', to='ordinal'), + 'ሃያ ሁለተኛ' + ) + + def test_to_currency(self): + self.assertEqual( + num2words('38.4', lang='am', to='currency', cents=False, currency='ETB'), + "ሠላሳ ስምንት ብር ከ 40 ሳንቲም" + ) + self.assertEqual( + num2words('0', lang='am', to='currency', separator=' እና', cents=True, currency='ETB'), + "ዜሮ ብር እና ዜሮ ሳንቲም" + ) + + self.assertEqual( + num2words('1.50', lang='am', to='currency', cents=True, currency='ETB'), + "አንድ ብር ከ አምሳ ሳንቲም" + ) + + def test_to_year(self): + self.assertEqual(num2words(1990, lang='am', to='year'), + 'አሥራ ዘጠኝ መቶ ዘጠና') + self.assertEqual(num2words(5555, lang='am', to='year'), + 'አምሳ አምስት መቶ አምሳ አምስት') + self.assertEqual(num2words(2017, lang='am', to='year'), + 'ሁለት ሺህ አሥራ ሰባት') + self.assertEqual(num2words(1066, lang='am', to='year'), + 'አንድ ሺህ ስድሳ ስድስት') + self.assertEqual(num2words(1865, lang='am', to='year'), + 'አሥራ ስምንት መቶ ስድሳ አምስት') From c586bef2d6cdd0e18e8941177674c9ed5ec80c14 Mon Sep 17 00:00:00 2001 From: Eyosiyas Bereketab Date: Tue, 9 Aug 2022 11:14:40 +0300 Subject: [PATCH 044/200] Fix flake 8 requirements in python3.1 and increase test coverage. --- num2words/__init__.py | 16 ++++++++-------- num2words/lang_AM.py | 2 +- tests/test_am.py | 31 +++++++++++++++++++++++++------ 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/num2words/__init__.py b/num2words/__init__.py index baba5bdd..dc422200 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -17,17 +17,17 @@ from __future__ import unicode_literals -from . import (lang_AR, lang_CZ, lang_DE, lang_DK, lang_EN, lang_EN_IN, - lang_ES, lang_ES_CO, 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_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_SL, lang_SR, lang_SV, lang_TE, lang_TH, - lang_TR, lang_UK, lang_VI, lang_AM) +from . import (lang_AM, lang_AR, lang_CZ, lang_DE, lang_DK, lang_EN, + lang_EN_IN, lang_ES, lang_ES_CO, 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_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_SL, lang_SR, lang_SV, lang_TE, + lang_TH, lang_TR, lang_UK, lang_VI) CONVERTER_CLASSES = { - 'ar': lang_AR.Num2Word_AR(), 'am': lang_AM.Num2Word_AM(), + 'ar': lang_AR.Num2Word_AR(), 'cz': lang_CZ.Num2Word_CZ(), 'en': lang_EN.Num2Word_EN(), 'en_IN': lang_EN_IN.Num2Word_EN_IN(), diff --git a/num2words/lang_AM.py b/num2words/lang_AM.py index 40725592..4e40bda7 100644 --- a/num2words/lang_AM.py +++ b/num2words/lang_AM.py @@ -93,7 +93,7 @@ def to_ordinal(self, value): def to_ordinal_num(self, value): self.verify_ordinal(value) - return "%s%s" % (value, self.to_ordinal(value)[-2:]) + return "%s%s" % (value, self.to_ordinal(value)[-1:]) def to_currency(self, val, currency='ብር', cents=True, separator=' ከ', adjective=True): diff --git a/tests/test_am.py b/tests/test_am.py index 6c479553..a3dc95da 100644 --- a/tests/test_am.py +++ b/tests/test_am.py @@ -38,19 +38,38 @@ def test_ordinal(self): 'ሃያ ሁለተኛ' ) + def test_ordinal_num(self): + self.assertEqual(num2words(10, lang='am', to='ordinal_num'), '10ኛ') + self.assertEqual(num2words(21, lang='am', to='ordinal_num'), '21ኛ') + self.assertEqual(num2words(102, lang='am', to='ordinal_num'), '102ኛ') + + def test_cardinal_for_float_number(self): + self.assertEqual(num2words(12.5, lang='am'), "አሥራ ሁለት ነጥብ አምስት") + self.assertEqual(num2words(12.51, lang='am'), "አሥራ ሁለት ነጥብ አምስት አንድ") + self.assertEqual(num2words(12.53, lang='am'), "አሥራ ሁለት ነጥብ አምስት ሦስት") + + def test_overflow(self): + with self.assertRaises(OverflowError): + num2words("1000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000", lang='am') + def test_to_currency(self): self.assertEqual( - num2words('38.4', lang='am', to='currency', cents=False, currency='ETB'), - "ሠላሳ ስምንት ብር ከ 40 ሳንቲም" + num2words('38.4', lang='am', to='currency', cents=False, + currency='ETB'), "ሠላሳ ስምንት ብር ከ 40 ሳንቲም" ) self.assertEqual( - num2words('0', lang='am', to='currency', separator=' እና', cents=True, currency='ETB'), - "ዜሮ ብር እና ዜሮ ሳንቲም" + num2words('0', lang='am', to='currency', separator=' እና', + cents=True, currency='ETB'), "ዜሮ ብር እና ዜሮ ሳንቲም" ) self.assertEqual( - num2words('1.50', lang='am', to='currency', cents=True, currency='ETB'), - "አንድ ብር ከ አምሳ ሳንቲም" + num2words('1.50', lang='am', to='currency', cents=True, + currency='ETB'), "አንድ ብር ከ አምሳ ሳንቲም" ) def test_to_year(self): From c966c983371b665cf294c8804d7cfa58b4b2d451 Mon Sep 17 00:00:00 2001 From: Drew Echerd Date: Tue, 9 Aug 2022 09:57:58 -0400 Subject: [PATCH 045/200] Fixed flake8 errors --- num2words/lang_TG.py | 1 - tests/test_tg.py | 19 +++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/num2words/lang_TG.py b/num2words/lang_TG.py index 8a028d58..48291a26 100644 --- a/num2words/lang_TG.py +++ b/num2words/lang_TG.py @@ -147,4 +147,3 @@ def to_ordinal(self, value): def to_ordinal_num(self, value): self.verify_ordinal(value) return "%s%s" % (value, self.to_ordinal(value)[-2:]) - diff --git a/tests/test_tg.py b/tests/test_tg.py index 482913be..53a49e4f 100644 --- a/tests/test_tg.py +++ b/tests/test_tg.py @@ -25,7 +25,7 @@ class Num2WordsTGTest(TestCase): def test_cardinal(self): with self.assertRaises(OverflowError): - num2words(1000000000000000000000000, lang='tg') + num2words(1000000000000000000000000, lang="tg") self.assertEqual(num2words(100, lang="tg"), "сад") self.assertEqual(num2words(100000, lang="tg"), "сад ҳазор") self.assertEqual(num2words(101, lang="tg"), "яксаду як") @@ -63,8 +63,9 @@ def test_to_ordinal(self): self.assertEqual(num2words(20, lang="tg", to="ordinal"), "бистум") self.assertEqual(num2words(23, lang="tg", to="ordinal"), "бисту сеюм") self.assertEqual(num2words(100, lang="tg", to="ordinal"), "садум") - self.assertEqual(num2words(136, lang="tg", to="ordinal"), - "яксаду сию шашум") + self.assertEqual( + num2words(136, lang="tg", to="ordinal"), "яксаду сию шашум" + ) self.assertEqual(num2words(500, lang="tg", to="ordinal"), "панҷсадум") self.assertEqual( num2words(1000, lang="tg", to="ordinal"), "як ҳазорум" @@ -100,16 +101,18 @@ def test_to_currency(self): "як ҳазору дусаду сию чор рубл, панҷову шаш копейк", ) self.assertEqual( - num2words(12519.85, lang="tg", to="currency", currency="TJS", - cents=False), + num2words( + 12519.85, lang="tg", to="currency", currency="TJS", cents=False + ), "дувоздаҳ ҳазору панҷсаду нуздаҳ сомонӣ, 85 дирам", ) self.assertEqual( num2words("1230.56", lang="tg", to="currency", currency="USD"), "як ҳазору дусаду си доллар, панҷову шаш сент", ) - + def test_to_ordinal_num(self): self.assertEqual( - num2words("100", lang="tg", to="ordinal_num"), "100ум", - ) \ No newline at end of file + num2words("100", lang="tg", to="ordinal_num"), + "100ум", + ) From 6ea21b82005e0faf5d2fb0b0ae58a80237aa37e8 Mon Sep 17 00:00:00 2001 From: Eyosiyas Bereketab Date: Tue, 9 Aug 2022 17:00:56 +0300 Subject: [PATCH 046/200] Fix line too long __init__.py --- num2words/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/num2words/__init__.py b/num2words/__init__.py index dc422200..86f1b63a 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -22,8 +22,8 @@ lang_FA, lang_FI, lang_FR, lang_FR_BE, lang_FR_CH, lang_FR_DZ, lang_HE, lang_HU, lang_ID, 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_SL, lang_SR, lang_SV, lang_TE, - lang_TH, lang_TR, lang_UK, lang_VI) + lang_PT_BR, lang_RO, lang_RU, lang_SL, lang_SR, lang_SV, + lang_TE, lang_TH, lang_TR, lang_UK, lang_VI) CONVERTER_CLASSES = { 'am': lang_AM.Num2Word_AM(), From 75fdd6289f80926d0870206e257436917433b18c Mon Sep 17 00:00:00 2001 From: Eyosiyas Bereketab Date: Tue, 9 Aug 2022 21:13:53 +0300 Subject: [PATCH 047/200] Update Amharic language support --- README.rst | 3 +- num2words/lang_AM.py | 122 ++++++++++++++++++++++++++----------------- tests/test_am.py | 37 +++++++------ 3 files changed, 98 insertions(+), 64 deletions(-) diff --git a/README.rst b/README.rst index 04145315..7b9b487e 100644 --- a/README.rst +++ b/README.rst @@ -76,6 +76,7 @@ Besides the numerical argument, there are two main optional arguments. **lang:** The language in which to convert the number. Supported values are: * ``en`` (English, default) +* ``am`` (Amharic) * ``ar`` (Arabic) * ``cz`` (Czech) * ``de`` (German) @@ -149,4 +150,4 @@ added Lithuanian support, but didn't take over maintenance of the project. I am thus basing myself on Marius Grigaitis' improvements and re-publishing ``pynum2word`` as ``num2words``. -Virgil Dupras, Savoir-faire Linux +Virgil Dupras, Savoir-faire Linux \ No newline at end of file diff --git a/num2words/lang_AM.py b/num2words/lang_AM.py index 4e40bda7..3efd9c25 100644 --- a/num2words/lang_AM.py +++ b/num2words/lang_AM.py @@ -23,45 +23,73 @@ class Num2Word_AM(lang_EU.Num2Word_EU): CURRENCY_FORMS = {'ETB': (('ብር', 'ብር'), ('ሳንቲም', 'ሳንቲም'))} + GIGA_SUFFIX = 'ቢሊዮን' + MEGA_SUFFIX = 'ሚሊዮን' + 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 + "ሊዮን" + 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 = {"አንድ": "አንደኛ", - "ሁለት": "ሁለተኛ", - "ሦስት": "ሦስተኛ", - "አራት": "አራተኛ", - "አምስት": "አምስተኛ", - "ስድስት": "ስድስተኛ", - "ሰባት": "ሰባተኛ", - "ስምንት": "ስምንተኛ", - "ዘጠኝ": "ዘጠነኛ", - "አሥር": "አሥረኛ", - "አሥራ አንድ": "አሥራ አንድ", - "አሥራ ሁለት": "አሥራ ሁለተኛ", - "አሥራ ሦስት": "አሥራ ሦስተኛ", - "አሥራ አራት": "አሥራ አራተኛ", - "አሥራ አምስት": "አሥራ አምስተኛ", - "አሥራ ስድስት": "አሥራ ስድስተኛ", - "አሥራ ሰባት": "አሥራ ሰባተኛ", - "አሥራ ስምንት": "አሥራ ስምንተኛ", - "አሥራ ዘጠኝ": "አሥራ ዘጠነኛ"} + 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 < 0: + value = abs(value) + out = self.negword + + 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 @@ -69,31 +97,31 @@ def merge(self, lpair, rpair): if lnum == 1 and rnum < 100: return (rtext, rnum) elif 100 > lnum > rnum: - return ("%s %s" % (ltext, rtext), lnum + rnum) + return ('%s %s' % (ltext, rtext), lnum + rnum) elif lnum >= 100 > rnum: - return ("%s %s" % (ltext, rtext), lnum + rnum) + return ('%s %s' % (ltext, rtext), lnum + rnum) elif rnum > lnum: - return ("%s %s" % (ltext, rtext), lnum * rnum) - return ("%s, %s" % (ltext, rtext), lnum + rnum) + 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("-") + 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" + if lastword[-1] == 'y': + lastword = lastword[:-1] + 'ie' + lastword += 'th' lastwords[-1] = self.title(lastword) - outwords[-1] = " ".join(lastwords) - return " ".join(outwords) + 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:]) + return '%s%s' % (value, self.to_ordinal(value)[-1:]) def to_currency(self, val, currency='ብር', cents=True, separator=' ከ', adjective=True): @@ -105,4 +133,4 @@ def to_currency(self, val, currency='ብር', cents=True, separator=' ከ', 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) + return self.to_splitnum(val, hightxt='መቶ', longval=longval) diff --git a/tests/test_am.py b/tests/test_am.py index a3dc95da..460ca6e4 100644 --- a/tests/test_am.py +++ b/tests/test_am.py @@ -21,10 +21,15 @@ class Num2WordsAMTest(TestCase): + def test_cardinal(self): + self.assertEqual(num2words(100, lang='am'), 'መቶ') + self.assertEqual(num2words(100000, lang='am'), 'አንድ መቶ ሺህ') + self.assertEqual(num2words(101, lang='am'), 'አንድ መቶ አንድ') + def test_and_join_199(self): - self.assertEqual(num2words(199, lang='am'), "አንድ መቶ ዘጠና ዘጠኝ") + self.assertEqual(num2words(199, lang='am'), 'አንድ መቶ ዘጠና ዘጠኝ') - def test_ordinal(self): + def test_to_ordinal(self): self.assertEqual( num2words(1, lang='am', to='ordinal'), 'አንደኛ' @@ -38,38 +43,38 @@ def test_ordinal(self): 'ሃያ ሁለተኛ' ) - def test_ordinal_num(self): + def test_to_ordinal_num(self): self.assertEqual(num2words(10, lang='am', to='ordinal_num'), '10ኛ') self.assertEqual(num2words(21, lang='am', to='ordinal_num'), '21ኛ') self.assertEqual(num2words(102, lang='am', to='ordinal_num'), '102ኛ') def test_cardinal_for_float_number(self): - self.assertEqual(num2words(12.5, lang='am'), "አሥራ ሁለት ነጥብ አምስት") - self.assertEqual(num2words(12.51, lang='am'), "አሥራ ሁለት ነጥብ አምስት አንድ") - self.assertEqual(num2words(12.53, lang='am'), "አሥራ ሁለት ነጥብ አምስት ሦስት") + self.assertEqual(num2words(12.5, lang='am'), 'አሥራ ሁለት ነጥብ አምስት') + self.assertEqual(num2words(12.51, lang='am'), 'አሥራ ሁለት ነጥብ አምስት አንድ') + self.assertEqual(num2words(12.53, lang='am'), 'አሥራ ሁለት ነጥብ አምስት ሦስት') - def test_overflow(self): + def test_to_overflow(self): with self.assertRaises(OverflowError): - num2words("1000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000" - "00000000000000000000000000000000", lang='am') + num2words('1000000000000000000000000000000000000000000000000000000' + '0000000000000000000000000000000000000000000000000000000' + '0000000000000000000000000000000000000000000000000000000' + '0000000000000000000000000000000000000000000000000000000' + '0000000000000000000000000000000000000000000000000000000' + '00000000000000000000000000000000', lang='am') def test_to_currency(self): self.assertEqual( num2words('38.4', lang='am', to='currency', cents=False, - currency='ETB'), "ሠላሳ ስምንት ብር ከ 40 ሳንቲም" + currency='ETB'), 'ሠላሳ ስምንት ብር ከ 40 ሳንቲም' ) self.assertEqual( num2words('0', lang='am', to='currency', separator=' እና', - cents=True, currency='ETB'), "ዜሮ ብር እና ዜሮ ሳንቲም" + cents=True, currency='ETB'), 'ዜሮ ብር እና ዜሮ ሳንቲም' ) self.assertEqual( num2words('1.50', lang='am', to='currency', cents=True, - currency='ETB'), "አንድ ብር ከ አምሳ ሳንቲም" + currency='ETB'), 'አንድ ብር ከ አምሳ ሳንቲም' ) def test_to_year(self): From b7277ffb93f2421899831dfe3efc53df5467b53e Mon Sep 17 00:00:00 2001 From: Eyosiyas Bereketab Date: Tue, 9 Aug 2022 21:19:56 +0300 Subject: [PATCH 048/200] Update __init__.py --- num2words/__init__.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/num2words/__init__.py b/num2words/__init__.py index 236f2c7c..3c9171a8 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -17,15 +17,16 @@ from __future__ import unicode_literals -from . import (lang_AR, lang_CZ, lang_DE, lang_DK, lang_EN, lang_EN_IN, - lang_ES, lang_ES_CO, 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_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_SL, lang_SR, lang_SV, lang_TE, lang_TG, - lang_TH, lang_TR, lang_UK, lang_VI) +from . import (lang_AM, lang_AR, lang_CZ, lang_DE, lang_DK, lang_EN, + lang_EN_IN, lang_ES, lang_ES_CO, 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_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_SL, lang_SR, lang_SV, + lang_TE, lang_TG, lang_TH, lang_TR, lang_UK, lang_VI) CONVERTER_CLASSES = { + 'am': lang_AM.Num2Word_AM(), 'ar': lang_AR.Num2Word_AR(), 'cz': lang_CZ.Num2Word_CZ(), 'en': lang_EN.Num2Word_EN(), From 4c873a6a88e90333c53a753fcf2f520265258bf6 Mon Sep 17 00:00:00 2001 From: Eyosiyas Bereketab Date: Wed, 10 Aug 2022 09:34:03 +0300 Subject: [PATCH 049/200] Add additional test case --- num2words/lang_AM.py | 19 ++++++------------- tests/test_am.py | 4 ++++ 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/num2words/lang_AM.py b/num2words/lang_AM.py index 3efd9c25..77922db3 100644 --- a/num2words/lang_AM.py +++ b/num2words/lang_AM.py @@ -60,7 +60,7 @@ def setup(self): 'ስምንት': 'ስምንተኛ', 'ዘጠኝ': 'ዘጠነኛ', 'አሥር': 'አሥረኛ', - 'አሥራ አንድ': 'አሥራ አንድ', + 'አሥራ አንድ': 'አሥራ አንደኛ', 'አሥራ ሁለት': 'አሥራ ሁለተኛ', 'አሥራ ሦስት': 'አሥራ ሦስተኛ', 'አሥራ አራት': 'አሥራ አራተኛ', @@ -77,10 +77,6 @@ def to_cardinal(self, value): 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)) @@ -95,14 +91,13 @@ def merge(self, lpair, rpair): ltext, lnum = lpair rtext, rnum = rpair if lnum == 1 and rnum < 100: - return (rtext, rnum) + return rtext, rnum elif 100 > lnum > rnum: - return ('%s %s' % (ltext, rtext), lnum + rnum) + return '%s %s' % (ltext, rtext), lnum + rnum elif lnum >= 100 > rnum: - return ('%s %s' % (ltext, rtext), lnum + rnum) + return '%s %s' % (ltext, rtext), lnum + rnum elif rnum > lnum: - return ('%s %s' % (ltext, rtext), lnum * rnum) - return ('%s, %s' % (ltext, rtext), lnum + rnum) + return '%s %s' % (ltext, rtext), lnum * rnum def to_ordinal(self, value): self.verify_ordinal(value) @@ -112,9 +107,7 @@ def to_ordinal(self, value): try: lastword = self.ords[lastword] except KeyError: - if lastword[-1] == 'y': - lastword = lastword[:-1] + 'ie' - lastword += 'th' + lastword += 'ኛ' lastwords[-1] = self.title(lastword) outwords[-1] = ' '.join(lastwords) return ' '.join(outwords) diff --git a/tests/test_am.py b/tests/test_am.py index 460ca6e4..58709c37 100644 --- a/tests/test_am.py +++ b/tests/test_am.py @@ -42,6 +42,10 @@ def test_to_ordinal(self): num2words(22, lang='am', to='ordinal'), 'ሃያ ሁለተኛ' ) + self.assertEqual( + num2words(10000, lang='am', to='ordinal'), + 'አሥር ሺህኛ' + ) def test_to_ordinal_num(self): self.assertEqual(num2words(10, lang='am', to='ordinal_num'), '10ኛ') From e8425024a6914ab87577b91f09a24d44c8728275 Mon Sep 17 00:00:00 2001 From: Sergio Zanchetta Date: Sun, 16 Jan 2022 00:52:24 +0100 Subject: [PATCH 050/200] Add to_currency and CURRENCY_FORMS for italian --- num2words/lang_IT.py | 119 +++++++++++++++++++++++++++---------------- 1 file changed, 76 insertions(+), 43 deletions(-) diff --git a/num2words/lang_IT.py b/num2words/lang_IT.py index 6966d730..d532f7f4 100644 --- a/num2words/lang_IT.py +++ b/num2words/lang_IT.py @@ -16,6 +16,8 @@ from __future__ import unicode_literals +from .lang_EU import Num2Word_EU + # Globals # ------- @@ -43,57 +45,27 @@ ] -# 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 +GENERIC_DOLLARS = ('dollaro', 'dollari') +GENERIC_CENTS = ('centesimo', 'centesimi') +CURRENCIES_UNA = ('GBP') # Main class # ========== -class Num2Word_IT: +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 @@ -206,3 +178,64 @@ def to_ordinal(self, number): 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 From 389bfd555df56cd715dbdd6e180e41a93595961c Mon Sep 17 00:00:00 2001 From: Sergio Zanchetta Date: Sun, 16 Jan 2022 12:07:43 +0100 Subject: [PATCH 051/200] Add tests for italian language currencies --- tests/test_it.py | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/tests/test_it.py b/tests/test_it.py index 348f4ed8..9023355f 100644 --- a/tests/test_it.py +++ b/tests/test_it.py @@ -21,6 +21,36 @@ from num2words import num2words +TEST_CASES_TO_CURRENCY_EUR = ( + (1.00, 'un euro e zero centesimi'), + (2.01, 'due euro e un centesimo'), + (8.10, 'otto euro e dieci centesimi'), + (12.26, 'dodici euro e ventisei centesimi'), + (21.29, 'ventun euro e ventinove centesimi'), + (81.25, 'ottantun euro e venticinque centesimi'), + (100.00, 'cento euro e zero centesimi'), +) + +TEST_CASES_TO_CURRENCY_USD = ( + (1.00, 'un dollaro e zero centesimi'), + (2.01, 'due dollari e un centesimo'), + (8.10, 'otto dollari e dieci centesimi'), + (12.26, 'dodici dollari e ventisei centesimi'), + (21.29, 'ventun dollari e ventinove centesimi'), + (81.25, 'ottantun dollari e venticinque centesimi'), + (100.00, 'cento dollari e zero centesimi'), +) + +TEST_CASES_TO_CURRENCY_GBP = ( + (1.00, 'una sterlina e zero penny'), + (2.01, 'due sterline e un penny'), + (8.10, 'otto sterline e dieci penny'), + (12.26, 'dodici sterline e ventisei penny'), + (21.29, 'ventun sterline e ventinove penny'), + (81.25, 'ottantun sterline e venticinque penny'), + (100.00, 'cento sterline e zero penny'), +) + class Num2WordsITTest(TestCase): maxDiff = None @@ -240,3 +270,24 @@ def test_with_decimals(self): self.assertAlmostEqual( num2words(1.1, lang="it"), "uno virgola uno" ) + + def test_currency_eur(self): + for test in TEST_CASES_TO_CURRENCY_EUR: + self.assertEqual( + num2words(test[0], lang='it', to='currency', currency='EUR'), + test[1] + ) + + def test_currency_usd(self): + for test in TEST_CASES_TO_CURRENCY_USD: + self.assertEqual( + num2words(test[0], lang='it', to='currency', currency='USD'), + test[1] + ) + + def test_currency_gbp(self): + for test in TEST_CASES_TO_CURRENCY_GBP: + self.assertEqual( + num2words(test[0], lang='it', to='currency', currency='GBP'), + test[1] + ) From e3d53c3ff91dec7543397ec20858cba928e94f01 Mon Sep 17 00:00:00 2001 From: cyriaka90 Date: Mon, 9 Nov 2020 18:16:22 +0100 Subject: [PATCH 052/200] fix Polish twenties --- num2words/lang_PL.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/num2words/lang_PL.py b/num2words/lang_PL.py index 1fb1fdcd..ec7e6a22 100644 --- a/num2words/lang_PL.py +++ b/num2words/lang_PL.py @@ -80,7 +80,7 @@ 6: ('sześćdziesiąt',), 7: ('siedemdziesiąt',), 8: ('osiemdziesiąt',), - 9: ('dziewięćdzisiąt',), + 9: ('dziewięćdziesiąt',), } TWENTIES_ORDINALS = { From e239f1a47403faf52d1df82faa2aeda591438154 Mon Sep 17 00:00:00 2001 From: cyriaka90 Date: Mon, 9 Nov 2020 18:26:47 +0100 Subject: [PATCH 053/200] adapt polish tests --- tests/test_pl.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/test_pl.py b/tests/test_pl.py index 147a747c..cf6e18ad 100644 --- a/tests/test_pl.py +++ b/tests/test_pl.py @@ -52,7 +52,7 @@ def test_cardinal(self): self.assertEqual( num2words(1234567890, lang='pl'), "miliard dwieście trzydzieści cztery miliony pięćset " - "sześćdziesiąt siedem tysięcy osiemset dziewięćdzisiąt" + "sześćdziesiąt siedem tysięcy osiemset dziewięćdziesiąt" ) self.assertEqual( num2words(10000000001000000100000, lang='pl'), @@ -62,20 +62,20 @@ def test_cardinal(self): num2words(215461407892039002157189883901676, lang='pl'), "dwieście piętnaście kwintylionów czterysta sześćdziesiąt jeden " "kwadryliardów czterysta siedem kwadrylionów osiemset " - "dziewięćdzisiąt dwa tryliardy trzydzieści dziewięć trylionów " + "dziewięćdziesiąt dwa tryliardy trzydzieści dziewięć trylionów " "dwa biliardy sto pięćdziesiąt siedem bilionów sto osiemdziesiąt " "dziewięć miliardów osiemset osiemdziesiąt trzy miliony " "dziewięćset jeden tysięcy sześćset siedemdziesiąt sześć" ) self.assertEqual( num2words(719094234693663034822824384220291, lang='pl'), - "siedemset dziewiętnaście kwintylionów dziewięćdzisiąt cztery " + "siedemset dziewiętnaście kwintylionów dziewięćdziesiąt cztery " "kwadryliardy dwieście trzydzieści cztery kwadryliony sześćset " - "dziewięćdzisiąt trzy tryliardy sześćset sześćdziesiąt trzy " + "dziewięćdziesiąt trzy tryliardy sześćset sześćdziesiąt trzy " "tryliony trzydzieści cztery biliardy osiemset dwadzieścia dwa " "biliony osiemset dwadzieścia cztery miliardy trzysta " "osiemdziesiąt cztery miliony dwieście dwadzieścia " - "tysięcy dwieście dziewięćdzisiąt jeden" + "tysięcy dwieście dziewięćdziesiąt jeden" ) self.assertEqual( num2words( From 3715260bc5994eb61e900f56592046c3681b9977 Mon Sep 17 00:00:00 2001 From: cyriaka90 Date: Tue, 16 Aug 2022 14:58:50 +0200 Subject: [PATCH 054/200] increase Polish test coverage --- tests/test_pl.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/test_pl.py b/tests/test_pl.py index cf6e18ad..08ef0394 100644 --- a/tests/test_pl.py +++ b/tests/test_pl.py @@ -24,11 +24,13 @@ class Num2WordsPLTest(TestCase): def test_cardinal(self): + self.assertEqual(num2words(90, lang='pl'), "dziewięćdziesiąt") self.assertEqual(num2words(100, lang='pl'), "sto") self.assertEqual(num2words(101, lang='pl'), "sto jeden") self.assertEqual(num2words(110, lang='pl'), "sto dziesięć") self.assertEqual(num2words(115, lang='pl'), "sto piętnaście") self.assertEqual(num2words(123, lang='pl'), "sto dwadzieścia trzy") + self.assertEqual(num2words(400, lang='pl'), "czterysta") self.assertEqual(num2words(1000, lang='pl'), "tysiąc") self.assertEqual(num2words(1001, lang='pl'), "tysiąc jeden") self.assertEqual(num2words(2012, lang='pl'), "dwa tysiące dwanaście") @@ -94,6 +96,9 @@ def test_to_ordinal(self): self.assertEqual(num2words(100, lang='pl', to='ordinal'), "setny") self.assertEqual( num2words(101, lang='pl', to='ordinal'), "sto pierwszy") + self.assertEqual(num2words(120, lang='pl', to='ordinal'), + "sto dwudziesty") + self.assertEqual(num2words(20, lang='pl', to='ordinal'), "dwudziesty") self.assertEqual(num2words(121, lang='pl', to='ordinal'), "sto dwudziesty pierwszy") self.assertEqual( @@ -118,6 +123,10 @@ def test_to_ordinal(self): self.assertEqual(num2words(1000000, lang='pl', to='ordinal'), "milionowy") + def test_to_ordinal_error(self): + with self.assertRaises(NotImplementedError): + num2words(1.5, lang='pl', to='ordinal') + def test_currency(self): self.assertEqual( num2words(1.0, lang='pl', to='currency', currency='EUR'), From 8633c0baf2cc5c38cc9caa2c06c1660f15edd824 Mon Sep 17 00:00:00 2001 From: ismail eski Date: Wed, 17 Aug 2022 18:09:07 +0300 Subject: [PATCH 055/200] [FIX] /num2words/lang_TR.py:812:1: W293 blank line contains whitespace --- num2words/lang_TR.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/num2words/lang_TR.py b/num2words/lang_TR.py index 59393c29..ee1d6d4c 100644 --- a/num2words/lang_TR.py +++ b/num2words/lang_TR.py @@ -809,7 +809,7 @@ def to_ordinal(self, value): def to_ordinal_num(self, value): self.verify_ordinal(value) return "%s%s" % (value, self.to_ordinal(value)[-4:]) - + def to_splitnum(self, val): float_digits = str(int(val * 10 ** self.precision)) if not int(val) == 0: From 3187fa2e055234c8e23cea3eac7405dc9888164a Mon Sep 17 00:00:00 2001 From: ismail eski Date: Wed, 17 Aug 2022 19:11:37 +0300 Subject: [PATCH 056/200] [TEST] ordinal_num test --- tests/test_tr.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/test_tr.py b/tests/test_tr.py index 84252624..2da70010 100644 --- a/tests/test_tr.py +++ b/tests/test_tr.py @@ -183,6 +183,10 @@ def test_tr(self): "expected": u"yüzbirmilyaryüzbirmilyononbirbinonvirgüliki"}, {"test": 101101011010.2, "to": "cardinal", "expected": u"yüzbirmilyaryüzbirmilyononbirbinonvirgülyirmi"} + {"test": 10, "to": "ordinal_num", "expected": u"10uncu"} + {"test": 1, "to": "ordinal_num","expected": u"1inci"} + {"test": 3, "to": "ordinal_num","expected": u"3üncü"} + {"test": 6, "to": "ordinal_num","expected": u"6ıncı"} ] for casedata in testcases: From c19ea1314598af17f02dcfacc9fe6b262fd282e6 Mon Sep 17 00:00:00 2001 From: ismail eski Date: Wed, 17 Aug 2022 19:56:11 +0300 Subject: [PATCH 057/200] [TEST] ordinal_num test --- tests/test_tr.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_tr.py b/tests/test_tr.py index 2da70010..d01ba060 100644 --- a/tests/test_tr.py +++ b/tests/test_tr.py @@ -182,10 +182,10 @@ def test_tr(self): {"test": 101101011010.02, "to": "cardinal", "expected": u"yüzbirmilyaryüzbirmilyononbirbinonvirgüliki"}, {"test": 101101011010.2, "to": "cardinal", - "expected": u"yüzbirmilyaryüzbirmilyononbirbinonvirgülyirmi"} - {"test": 10, "to": "ordinal_num", "expected": u"10uncu"} - {"test": 1, "to": "ordinal_num","expected": u"1inci"} - {"test": 3, "to": "ordinal_num","expected": u"3üncü"} + "expected": u"yüzbirmilyaryüzbirmilyononbirbinonvirgülyirmi"}, + {"test": 10, "to": "ordinal_num", "expected": u"10uncu"}, + {"test": 1, "to": "ordinal_num","expected": u"1inci"}, + {"test": 3, "to": "ordinal_num","expected": u"3üncü"}, {"test": 6, "to": "ordinal_num","expected": u"6ıncı"} ] From a05f6e5c1d626ddff7f9de0d196ab28915980ffc Mon Sep 17 00:00:00 2001 From: ismail eski Date: Thu, 18 Aug 2022 18:48:10 +0300 Subject: [PATCH 058/200] [FIX] E231 missing whitespace after ',' --- tests/test_tr.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_tr.py b/tests/test_tr.py index d01ba060..e1aefba5 100644 --- a/tests/test_tr.py +++ b/tests/test_tr.py @@ -184,9 +184,9 @@ def test_tr(self): {"test": 101101011010.2, "to": "cardinal", "expected": u"yüzbirmilyaryüzbirmilyononbirbinonvirgülyirmi"}, {"test": 10, "to": "ordinal_num", "expected": u"10uncu"}, - {"test": 1, "to": "ordinal_num","expected": u"1inci"}, - {"test": 3, "to": "ordinal_num","expected": u"3üncü"}, - {"test": 6, "to": "ordinal_num","expected": u"6ıncı"} + {"test": 1, "to": "ordinal_num", "expected": u"1inci"}, + {"test": 3, "to": "ordinal_num", "expected": u"3üncü"}, + {"test": 6, "to": "ordinal_num", "expected": u"6ıncı"} ] for casedata in testcases: From 8db643a918370eec0ef3e2c16b78de42fa9a4999 Mon Sep 17 00:00:00 2001 From: Israel Teixeira Date: Tue, 22 Dec 2020 07:43:10 -0300 Subject: [PATCH 059/200] Remove dupplicated line in lang_PT_BR Remove an unnecessary condition, since the very same action follows it. --- num2words/lang_PT_BR.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/num2words/lang_PT_BR.py b/num2words/lang_PT_BR.py index 4c73cac3..80eb5e71 100644 --- a/num2words/lang_PT_BR.py +++ b/num2words/lang_PT_BR.py @@ -53,8 +53,6 @@ def merge(self, curr, next): ctext = "cento" if nnum < cnum: - if cnum < 100: - return ("%s e %s" % (ctext, ntext), cnum + nnum) return ("%s e %s" % (ctext, ntext), cnum + nnum) elif (not nnum % 1000000) and cnum > 1: From 9c64d486120fbdc57ceb40f7aca4c61eed40f218 Mon Sep 17 00:00:00 2001 From: Maroua Romdhane Date: Thu, 21 Jan 2021 14:24:38 -0500 Subject: [PATCH 060/200] [UPD] Readme file --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index db64202b..c84b491f 100644 --- a/README.rst +++ b/README.rst @@ -1,4 +1,4 @@ -num2words - Convert numbers to words in multiple languages +num2words library - Convert numbers to words in multiple languages ========================================================== .. image:: https://img.shields.io/pypi/v/num2words.svg From cb24e20785b0d069fe95421ea398303e2af5b634 Mon Sep 17 00:00:00 2001 From: Israel Teixeira Date: Mon, 25 Jan 2021 22:28:49 -0300 Subject: [PATCH 061/200] This error is already raised in line 223 --- num2words/lang_PT.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/num2words/lang_PT.py b/num2words/lang_PT.py index 6f459726..ddfa7713 100644 --- a/num2words/lang_PT.py +++ b/num2words/lang_PT.py @@ -227,12 +227,7 @@ def to_currency(self, val, currency='EUR', cents=True, separator=' e', self.negword = backup_negword # transforms "milhões euros" em "milhões de euros" - try: - cr1, _ = self.CURRENCY_FORMS[currency] - except KeyError: - raise NotImplementedError( - 'Currency code "%s" not implemented for "%s"' % - (currency, self.__class__.__name__)) + cr1, _ = self.CURRENCY_FORMS[currency] for ext in ( 'milhão', 'milhões', 'bilião', From 1b35e7fe58e55b0222abc970d1fe7c1cf62975a2 Mon Sep 17 00:00:00 2001 From: Peter Nordstrom Date: Mon, 7 Dec 2020 14:24:51 +0100 Subject: [PATCH 062/200] added swedish language including test cases --- num2words/__init__.py | 3 +- num2words/lang_SV.py | 113 ++++++++++++++++++++++++++++++++++++++++++ tests/test_sv.py | 46 +++++++++++++++++ 3 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 num2words/lang_SV.py create mode 100644 tests/test_sv.py diff --git a/num2words/__init__.py b/num2words/__init__.py index 931d28af..6d40774c 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -22,7 +22,7 @@ lang_FR_BE, lang_FR_CH, lang_FR_DZ, lang_HE, lang_HU, lang_ID, 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_SL, lang_SR, lang_TE, lang_TH, lang_TR, lang_UK, + lang_RU, lang_SL, lang_SR, lang_SV, lang_TE, lang_TH, lang_TR, lang_UK, lang_VI) CONVERTER_CLASSES = { @@ -52,6 +52,7 @@ 'ru': lang_RU.Num2Word_RU(), 'sl': lang_SL.Num2Word_SL(), 'sr': lang_SR.Num2Word_SR(), + 'sv': lang_SV.Num2Word_SV(), 'no': lang_NO.Num2Word_NO(), 'dk': lang_DK.Num2Word_DK(), 'pt': lang_PT.Num2Word_PT(), diff --git a/num2words/lang_SV.py b/num2words/lang_SV.py new file mode 100644 index 00000000..215c196b --- /dev/null +++ b/num2words/lang_SV.py @@ -0,0 +1,113 @@ +# -*- 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_SV(lang_EU.Num2Word_EU): + GIGA_SUFFIX = "iljarder" + MEGA_SUFFIX = "iljoner" + + 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 setup(self): + super(Num2Word_SV, self).setup() + + self.negword = "minus " + self.pointword = "komma" + self.exclude_title = ["och", "komma", "minus"] + + self.mid_numwords = [(1000, "tusen"), (100, "hundra"), + (90, "nittio"), (80, "\åttio"), (70, "sjuttio"), + (60, "sextio"), (50, "femtio"), (40, "förtio"), + (30, "trettio")] + self.low_numwords = ["tjugo", "nitton", "arton", "sjutton", + "sexton", "femton", "fjorton", "tretton", + "tolv", "elva", "tio", "nio", "åtta", + "sju", "sex", "fem", "fyra", "tre", "två", + "ett", "noll"] + self.ords = {"noll": "nollte", + "ett": "första", + "två": "andra", + "tre": "tredje", + "fyra": "fjärde", + "fem": "femte", + "sex": "sjätte", + "sju": "sjunde", + "åtta": "åttonde", + "nio": "nionde", + "tio": "tionde", + "elva": "elfte", + "tolv": "tolfte", + "tjugo": "tjugonde"} + + 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 >= 1000000 and lnum == 1: + return ("%s %s" % ('en', rtext[:-2]), lnum + rnum) + elif rnum >= 1000000 and lnum > 1: + return ("%s %s" % (ltext, rtext), lnum + rnum) + elif rnum > lnum: + return ("%s%s" % (ltext, rtext), lnum * rnum) + return ("%s %s" % (ltext, rtext), lnum + rnum) + + def to_ordinal(self, value): + self.verify_ordinal(value) + outwords = self.to_cardinal(value).split(" ") + lastwords = outwords[-1].split("-") + lastword = lastwords[-1].lower() + try: + lastword = self.ords[lastword] + except KeyError: + if lastword[-2:] == "tio": + lastword = lastword + "onde" + else: + lastword += "de" + lastwords[-1] = self.title(lastword) + outwords[-1] = "".join(lastwords) + return " ".join(outwords) + + def to_ordinal_num(self, value): + self.verify_ordinal(value) + return "%s%s" % (value, self.to_ordinal(value)[-2:]) + + def to_year(self, val, longval=True): + if not (val // 100) % 10: + return self.to_cardinal(val) + return self.to_splitnum(val, hightxt="hundra", jointxt="och", + longval=longval) + + def to_currency(self, val, longval=True): + return self.to_splitnum(val, hightxt="krone/r", lowtxt="öre/n", + jointxt="och", longval=longval, cents=True) diff --git a/tests/test_sv.py b/tests/test_sv.py new file mode 100644 index 00000000..fa3d48da --- /dev/null +++ b/tests/test_sv.py @@ -0,0 +1,46 @@ +# 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 unittest import TestCase + +from num2words import num2words + + +class Num2WordsSVTest(TestCase): + def test_ordinal(self): + pass + self.assertEqual(num2words(1, to="ordinal", lang="sv"), "första") + self.assertEqual(num2words(5, to="ordinal", lang="sv"), "femte") + self.assertEqual(num2words(32, to="ordinal", lang="sv"), "trettioandra") + + + def test_cardinal(self): + self.assertEqual(num2words(0, to="cardinal", lang="sv"), "noll") + self.assertEqual(num2words(1, to="cardinal", lang="sv"), "ett") + self.assertEqual(num2words(2, to="cardinal", lang="sv"), "två") + self.assertEqual(num2words(5, to="cardinal", lang="sv"), "fem") + self.assertEqual(num2words(8, to="cardinal", lang="sv"), "åtta") + self.assertEqual(num2words(18, to="cardinal", lang="sv"), "arton") + self.assertEqual(num2words(45, to="cardinal", lang="sv"), "förtiofem") + self.assertEqual(num2words(1245, to="cardinal", lang="sv"), "etttusen tvåhundraförtiofem") + self.assertEqual(num2words(4235, to="cardinal", lang="sv"), "fyratusen tvåhundratrettiofem") + self.assertEqual(num2words(1004135, to="cardinal", lang="sv"), "en miljon fyratusen etthundratrettiofem") + self.assertEqual(num2words(14004235000, to="cardinal", lang="sv"), "fjorton miljarder fyra miljoner tvåhundratrettiofemtusen") + self.assertEqual(num2words(14004235, to="cardinal", lang="sv"), "fjorton miljoner fyratusen tvåhundratrettiofem") + self.assertEqual(num2words(1.25, to="cardinal", lang="sv"), "ett komma två fem") From a35effbd1b0ccc8016e58c37a682bb06b0076906 Mon Sep 17 00:00:00 2001 From: Peter Nordstrom Date: Mon, 7 Dec 2020 16:24:58 +0100 Subject: [PATCH 063/200] added correct ordinal handling and more test cases --- num2words/lang_SV.py | 22 +++++++++++++--------- tests/test_sv.py | 6 +++--- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/num2words/lang_SV.py b/num2words/lang_SV.py index 215c196b..12ba9ae9 100644 --- a/num2words/lang_SV.py +++ b/num2words/lang_SV.py @@ -85,17 +85,21 @@ def merge(self, lpair, rpair): def to_ordinal(self, value): self.verify_ordinal(value) outwords = self.to_cardinal(value).split(" ") - lastwords = outwords[-1].split("-") - lastword = lastwords[-1].lower() + lastword = outwords[-1] + # lastword = lastwords[-1].lower() + ending_length = 0 try: - lastword = self.ords[lastword] - except KeyError: - if lastword[-2:] == "tio": - lastword = lastword + "onde" - else: + lastword_ending = self.ords[lastword[-4:]] + ending_length = 4 + except: + try: + lastword_ending = self.ords[lastword[-3:]] + ending_length = 3 + except KeyError: lastword += "de" - lastwords[-1] = self.title(lastword) - outwords[-1] = "".join(lastwords) + lastword_first_part = self.title(lastword)[:-ending_length] + lastword_correct = lastword_first_part + lastword_ending + outwords[-1] = lastword_correct return " ".join(outwords) def to_ordinal_num(self, value): diff --git a/tests/test_sv.py b/tests/test_sv.py index fa3d48da..e4ce4662 100644 --- a/tests/test_sv.py +++ b/tests/test_sv.py @@ -24,11 +24,11 @@ class Num2WordsSVTest(TestCase): def test_ordinal(self): - pass + self.assertEqual(num2words(1435, to="ordinal", lang="sv"), "etttusen fyrahundratrettiofemte") + self.assertEqual(num2words(32, to="ordinal", lang="sv"), "trettioandra") self.assertEqual(num2words(1, to="ordinal", lang="sv"), "första") self.assertEqual(num2words(5, to="ordinal", lang="sv"), "femte") - self.assertEqual(num2words(32, to="ordinal", lang="sv"), "trettioandra") - + self.assertEqual(num2words(10, to="ordinal", lang="sv"), "tionde") def test_cardinal(self): self.assertEqual(num2words(0, to="cardinal", lang="sv"), "noll") From 469aaff8e6ac499dee2015f09772f3980d0d49c8 Mon Sep 17 00:00:00 2001 From: Peter Nordstrom Date: Mon, 25 Jan 2021 14:30:43 +0100 Subject: [PATCH 064/200] updated test case to increase coverage. raised NotImplementedError for options not implemented. --- num2words/lang_SV.py | 20 ++++++++++---------- tests/test_sv.py | 15 +++++++++++++++ 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/num2words/lang_SV.py b/num2words/lang_SV.py index 12ba9ae9..34a8827c 100644 --- a/num2words/lang_SV.py +++ b/num2words/lang_SV.py @@ -96,22 +96,22 @@ def to_ordinal(self, value): lastword_ending = self.ords[lastword[-3:]] ending_length = 3 except KeyError: - lastword += "de" - lastword_first_part = self.title(lastword)[:-ending_length] + # lastword += "de" + lastword_ending = "de" + if lastword_ending == 'de': + lastword_first_part = self.title(lastword)[:] + else: + lastword_first_part = self.title(lastword)[:-ending_length] lastword_correct = lastword_first_part + lastword_ending outwords[-1] = lastword_correct return " ".join(outwords) def to_ordinal_num(self, value): - self.verify_ordinal(value) - return "%s%s" % (value, self.to_ordinal(value)[-2:]) + raise NotImplementedError("'ordinal_num' is not implemented for swedish language") def to_year(self, val, longval=True): - if not (val // 100) % 10: - return self.to_cardinal(val) - return self.to_splitnum(val, hightxt="hundra", jointxt="och", - longval=longval) + raise NotImplementedError("'year' is not implemented for swedish language") + def to_currency(self, val, longval=True): - return self.to_splitnum(val, hightxt="krone/r", lowtxt="öre/n", - jointxt="och", longval=longval, cents=True) + raise NotImplementedError("'currency' is not implemented for swedish language") diff --git a/tests/test_sv.py b/tests/test_sv.py index e4ce4662..fffbd0e0 100644 --- a/tests/test_sv.py +++ b/tests/test_sv.py @@ -24,6 +24,7 @@ class Num2WordsSVTest(TestCase): def test_ordinal(self): + self.assertEqual(num2words(14, to="ordinal", lang="sv"), "fjortonde") self.assertEqual(num2words(1435, to="ordinal", lang="sv"), "etttusen fyrahundratrettiofemte") self.assertEqual(num2words(32, to="ordinal", lang="sv"), "trettioandra") self.assertEqual(num2words(1, to="ordinal", lang="sv"), "första") @@ -44,3 +45,17 @@ def test_cardinal(self): self.assertEqual(num2words(14004235000, to="cardinal", lang="sv"), "fjorton miljarder fyra miljoner tvåhundratrettiofemtusen") self.assertEqual(num2words(14004235, to="cardinal", lang="sv"), "fjorton miljoner fyratusen tvåhundratrettiofem") self.assertEqual(num2words(1.25, to="cardinal", lang="sv"), "ett komma två fem") + + def test_not_implemented_options(self): + + with self.assertRaises(NotImplementedError) as context: + num2words(1235, to="year", lang="sv") + self.assertTrue("'year' is not implemented for swedish language" in str(context.exception)) + + with self.assertRaises(NotImplementedError) as context: + num2words(1235, to="currency", lang="sv") + self.assertTrue("'currency' is not implemented for swedish language" in str(context.exception)) + + with self.assertRaises(NotImplementedError) as context: + num2words(1235, to="ordinal_num", lang="sv") + self.assertTrue("'ordinal_num' is not implemented for swedish language" in str(context.exception)) \ No newline at end of file From 3e494d71a0ca618acdbe0aff7ca8efd7a51b80d1 Mon Sep 17 00:00:00 2001 From: Peter Nordstrom Date: Tue, 26 Jan 2021 08:40:17 +0100 Subject: [PATCH 065/200] updated failing flake8 test --- num2words/__init__.py | 5 ++--- num2words/lang_SV.py | 4 +--- tests/test_sv.py | 37 +++++++++++++++++++++++-------------- 3 files changed, 26 insertions(+), 20 deletions(-) diff --git a/num2words/__init__.py b/num2words/__init__.py index 6d40774c..a8c47370 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -22,8 +22,8 @@ lang_FR_BE, lang_FR_CH, lang_FR_DZ, lang_HE, lang_HU, lang_ID, 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_SL, lang_SR, lang_SV, lang_TE, lang_TH, lang_TR, lang_UK, - lang_VI) + lang_RU, lang_SL, lang_SR, lang_SV, lang_TE, lang_TH, lang_TR, + lang_UK, lang_VI) CONVERTER_CLASSES = { 'ar': lang_AR.Num2Word_AR(), @@ -68,7 +68,6 @@ 'hu': lang_HU.Num2Word_HU() } - CONVERTES_TYPES = ['cardinal', 'ordinal', 'ordinal_num', 'year', 'currency'] diff --git a/num2words/lang_SV.py b/num2words/lang_SV.py index 34a8827c..afdd31ee 100644 --- a/num2words/lang_SV.py +++ b/num2words/lang_SV.py @@ -86,17 +86,15 @@ def to_ordinal(self, value): self.verify_ordinal(value) outwords = self.to_cardinal(value).split(" ") lastword = outwords[-1] - # lastword = lastwords[-1].lower() ending_length = 0 try: lastword_ending = self.ords[lastword[-4:]] ending_length = 4 - except: + except KeyError: try: lastword_ending = self.ords[lastword[-3:]] ending_length = 3 except KeyError: - # lastword += "de" lastword_ending = "de" if lastword_ending == 'de': lastword_first_part = self.title(lastword)[:] diff --git a/tests/test_sv.py b/tests/test_sv.py index fffbd0e0..a780dae2 100644 --- a/tests/test_sv.py +++ b/tests/test_sv.py @@ -25,8 +25,10 @@ class Num2WordsSVTest(TestCase): def test_ordinal(self): self.assertEqual(num2words(14, to="ordinal", lang="sv"), "fjortonde") - self.assertEqual(num2words(1435, to="ordinal", lang="sv"), "etttusen fyrahundratrettiofemte") - self.assertEqual(num2words(32, to="ordinal", lang="sv"), "trettioandra") + self.assertEqual(num2words(1435, to="ordinal", lang="sv"), + "etttusen fyrahundratrettiofemte") + self.assertEqual(num2words(32, to="ordinal", lang="sv"), + "trettioandra") self.assertEqual(num2words(1, to="ordinal", lang="sv"), "första") self.assertEqual(num2words(5, to="ordinal", lang="sv"), "femte") self.assertEqual(num2words(10, to="ordinal", lang="sv"), "tionde") @@ -34,28 +36,35 @@ def test_ordinal(self): def test_cardinal(self): self.assertEqual(num2words(0, to="cardinal", lang="sv"), "noll") self.assertEqual(num2words(1, to="cardinal", lang="sv"), "ett") - self.assertEqual(num2words(2, to="cardinal", lang="sv"), "två") + self.assertEqual(num2words(3, to="cardinal", lang="sv"), "tre") self.assertEqual(num2words(5, to="cardinal", lang="sv"), "fem") - self.assertEqual(num2words(8, to="cardinal", lang="sv"), "åtta") self.assertEqual(num2words(18, to="cardinal", lang="sv"), "arton") self.assertEqual(num2words(45, to="cardinal", lang="sv"), "förtiofem") - self.assertEqual(num2words(1245, to="cardinal", lang="sv"), "etttusen tvåhundraförtiofem") - self.assertEqual(num2words(4235, to="cardinal", lang="sv"), "fyratusen tvåhundratrettiofem") - self.assertEqual(num2words(1004135, to="cardinal", lang="sv"), "en miljon fyratusen etthundratrettiofem") - self.assertEqual(num2words(14004235000, to="cardinal", lang="sv"), "fjorton miljarder fyra miljoner tvåhundratrettiofemtusen") - self.assertEqual(num2words(14004235, to="cardinal", lang="sv"), "fjorton miljoner fyratusen tvåhundratrettiofem") - self.assertEqual(num2words(1.25, to="cardinal", lang="sv"), "ett komma två fem") + self.assertEqual(num2words(1345, to="cardinal", lang="sv"), + "etttusen trehundraförtiofem") + self.assertEqual(num2words(4435, to="cardinal", lang="sv"), + "fyratusen fyrahundratrettiofem") + self.assertEqual(num2words(1004135, to="cardinal", lang="sv"), + "en miljon fyratusen etthundratrettiofem") + self.assertEqual(num2words(4335000, to="cardinal", lang="sv"), + "fyra miljoner trehundratrettiofemtusen") + self.assertEqual(num2words(14004535, to="cardinal", lang="sv"), + "fjorton miljoner fyratusen femhundratrettiofem") + self.assertEqual(num2words(1.5, to="cardinal", lang="sv"), + "ett komma fem") def test_not_implemented_options(self): - with self.assertRaises(NotImplementedError) as context: num2words(1235, to="year", lang="sv") - self.assertTrue("'year' is not implemented for swedish language" in str(context.exception)) + self.assertTrue("'year' is not implemented for swedish language" + in str(context.exception)) with self.assertRaises(NotImplementedError) as context: num2words(1235, to="currency", lang="sv") - self.assertTrue("'currency' is not implemented for swedish language" in str(context.exception)) + self.assertTrue("'currency' is not implemented for swedish language" + in str(context.exception)) with self.assertRaises(NotImplementedError) as context: num2words(1235, to="ordinal_num", lang="sv") - self.assertTrue("'ordinal_num' is not implemented for swedish language" in str(context.exception)) \ No newline at end of file + self.assertTrue("'ordinal_num' is not implemented for swedish language" + in str(context.exception)) From 402b1e88e7caabc6d20e94996ef15e15478bc53a Mon Sep 17 00:00:00 2001 From: Fernanda Hernandez Date: Wed, 23 Dec 2020 11:50:06 -0600 Subject: [PATCH 066/200] Add translations to spanish of several currencies --- num2words/lang_ES.py | 191 ++- tests/test_es.py | 2826 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 3014 insertions(+), 3 deletions(-) diff --git a/num2words/lang_ES.py b/num2words/lang_ES.py index a8cc47de..d6fa77aa 100644 --- a/num2words/lang_ES.py +++ b/num2words/lang_ES.py @@ -21,13 +21,190 @@ from .lang_EU import Num2Word_EU +GENERIC_DOLLARS = ('dolar', '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') + class Num2Word_ES(Num2Word_EU): CURRENCY_FORMS = { 'EUR': (('euro', 'euros'), ('céntimo', 'céntimos')), 'ESP': (('peseta', 'pesetas'), ('céntimo', 'céntimos')), - 'USD': (('dolar', 'dólares'), ('centavo', 'centavos')), + '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'), ('penny', 'pence')), + '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'), ('penny', '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'), ('penny', '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 dolares'), ('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?? @@ -176,4 +353,14 @@ def to_currency(self, val, currency='EUR', cents=True, separator=' con', val, currency=currency, cents=cents, separator=separator, adjective=adjective) # Handle exception, in spanish is "un euro" and not "uno euro" - return result.replace("uno", "un") + # except in this currencies: leona, corona, + # libra, rupia, lempira, peseta, is 'una' + # but only when it's first word, otherwise + # it's replaced in others words like 'veintiun' + 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 diff --git a/tests/test_es.py b/tests/test_es.py index d306981b..cf3a8c2b 100644 --- a/tests/test_es.py +++ b/tests/test_es.py @@ -124,7 +124,7 @@ ) TEST_CASES_TO_CURRENCY_ESP = ( - (1.00, 'un peseta con cero céntimos'), + (1.00, 'una peseta con cero céntimos'), (2.00, 'dos pesetas con cero céntimos'), (8.00, 'ocho pesetas con cero céntimos'), (12.00, 'doce pesetas con cero céntimos'), @@ -156,6 +156,1661 @@ (100.00, 'cien soles con cero céntimos'), ) +TEST_CASES_TO_CURRENCY_CRC = ( + (1.00, 'un colón con cero centavos'), + (2.00, 'dos colones con cero centavos'), + (8.00, 'ocho colones con cero centavos'), + (12.00, 'doce colones con cero centavos'), + (21.00, 'veintiun colones con cero centavos'), + (81.25, 'ochenta y un colones con veinticinco centavos'), + (350.90, 'trescientos cincuenta colones con noventa centavos'), + (100.00, 'cien colones con cero centavos'), + (4150.83, + 'cuatro mil ciento cincuenta colones con ochenta y tres centavos'), +) + +TEST_CASES_TO_CURRENCY_GBP = ( + (1.00, 'una libra con cero pence'), + (2.00, 'dos libras con cero pence'), + (8.00, 'ocho libras con cero pence'), + (12.00, 'doce libras con cero pence'), + (21.00, 'veintiun libras con cero pence'), + (81.25, 'ochenta y un libras con veinticinco pence'), + (350.90, 'trescientos cincuenta libras con noventa pence'), + (100.00, 'cien libras con cero pence'), + (4150.83, + 'cuatro mil ciento cincuenta libras con ochenta y tres pence'), +) + +TEST_CASES_TO_CURRENCY_RUB = ( + (1.00, 'un rublo con cero kopeykas'), + (2.00, 'dos rublos con cero kopeykas'), + (8.00, 'ocho rublos con cero kopeykas'), + (12.00, 'doce rublos con cero kopeykas'), + (21.00, 'veintiun rublos con cero kopeykas'), + (81.25, 'ochenta y un rublos con veinticinco kopeykas'), + (350.90, 'trescientos cincuenta rublos con noventa kopeykas'), + (100.00, 'cien rublos con cero kopeykas'), + (4150.83, + 'cuatro mil ciento cincuenta rublos con ochenta y tres kopeykas'), +) + +TEST_CASES_TO_CURRENCY_SEK = ( + (1.00, 'una corona con cero öre'), + (2.00, 'dos coronas con cero öre'), + (8.00, 'ocho coronas con cero öre'), + (12.00, 'doce coronas con cero öre'), + (21.00, 'veintiun coronas con cero öre'), + (81.25, 'ochenta y un coronas con veinticinco öre'), + (350.90, 'trescientos cincuenta coronas con noventa öre'), + (100.00, 'cien coronas con cero öre'), + (4150.83, + 'cuatro mil ciento cincuenta coronas con ochenta y tres öre'), +) + +TEST_CASES_TO_CURRENCY_NOK = ( + (1.00, 'una corona con cero øre'), + (2.00, 'dos coronas con cero øre'), + (8.00, 'ocho coronas con cero øre'), + (12.00, 'doce coronas con cero øre'), + (21.00, 'veintiun coronas con cero øre'), + (81.25, 'ochenta y un coronas con veinticinco øre'), + (350.90, 'trescientos cincuenta coronas con noventa øre'), + (100.00, 'cien coronas con cero øre'), + (4150.83, + 'cuatro mil ciento cincuenta coronas con ochenta y tres øre'), +) + +TEST_CASES_TO_CURRENCY_PLN = ( + (1.00, 'un zloty con cero groszy'), + (2.00, 'dos zlotys con cero groszy'), + (8.00, 'ocho zlotys con cero groszy'), + (12.00, 'doce zlotys con cero groszy'), + (21.00, 'veintiun zlotys con cero groszy'), + (81.25, 'ochenta y un zlotys con veinticinco groszy'), + (350.90, 'trescientos cincuenta zlotys con noventa groszy'), + (100.00, 'cien zlotys con cero groszy'), + (4150.83, + 'cuatro mil ciento cincuenta zlotys con ochenta y tres groszy'), +) + +TEST_CASES_TO_CURRENCY_MXN = ( + (1.00, 'un peso con cero centavos'), + (2.00, 'dos pesos con cero centavos'), + (8.00, 'ocho pesos con cero centavos'), + (12.00, 'doce pesos con cero centavos'), + (21.00, 'veintiun pesos con cero centavos'), + (81.25, 'ochenta y un pesos con veinticinco centavos'), + (350.90, 'trescientos cincuenta pesos con noventa centavos'), + (100.00, 'cien pesos con cero centavos'), + (4150.83, + 'cuatro mil ciento cincuenta pesos con ochenta y tres centavos'), +) + +TEST_CASES_TO_CURRENCY_RON = ( + (1.00, 'un leu con cero bani'), + (2.00, 'dos leus con cero bani'), + (8.00, 'ocho leus con cero bani'), + (12.00, 'doce leus con cero bani'), + (21.00, 'veintiun leus con cero bani'), + (81.25, 'ochenta y un leus con veinticinco bani'), + (350.90, 'trescientos cincuenta leus con noventa bani'), + (100.00, 'cien leus con cero bani'), + (4150.83, + 'cuatro mil ciento cincuenta leus con ochenta y tres bani'), +) + +TEST_CASES_TO_CURRENCY_INR = ( + (1.00, 'una rupia con cero paisas'), + (2.00, 'dos rupias con cero paisas'), + (8.00, 'ocho rupias con cero paisas'), + (12.00, 'doce rupias con cero paisas'), + (21.00, 'veintiun rupias con cero paisas'), + (81.25, 'ochenta y un rupias con veinticinco paisas'), + (350.90, 'trescientos cincuenta rupias con noventa paisas'), + (100.00, 'cien rupias con cero paisas'), + (4150.83, + 'cuatro mil ciento cincuenta rupias con ochenta y tres paisas'), +) + +TEST_CASES_TO_CURRENCY_HUF = ( + (1.00, 'un florín con cero fillér'), + (2.00, 'dos florines con cero fillér'), + (8.00, 'ocho florines con cero fillér'), + (12.00, 'doce florines con cero fillér'), + (21.00, 'veintiun florines con cero fillér'), + (81.25, 'ochenta y un florines con veinticinco fillér'), + (350.90, 'trescientos cincuenta florines con noventa fillér'), + (100.00, 'cien florines con cero fillér'), + (4150.83, + 'cuatro mil ciento cincuenta florines con ochenta y tres fillér'), +) + +TEST_CASES_TO_CURRENCY_FRF = ( + (1.00, 'un franco con cero céntimos'), + (2.00, 'dos francos con cero céntimos'), + (8.00, 'ocho francos con cero céntimos'), + (12.00, 'doce francos con cero céntimos'), + (21.00, 'veintiun francos con cero céntimos'), + (81.25, 'ochenta y un francos con veinticinco céntimos'), + (350.90, 'trescientos cincuenta francos con noventa céntimos'), + (100.00, 'cien francos con cero céntimos'), + (4150.83, + 'cuatro mil ciento cincuenta francos con ochenta y tres céntimos'), +) + +TEST_CASES_TO_CURRENCY_CNY = ( + (1.00, 'un yuan con cero jiaos'), + (2.00, 'dos yuanes con cero jiaos'), + (8.00, 'ocho yuanes con cero jiaos'), + (12.00, 'doce yuanes con cero jiaos'), + (21.00, 'veintiun yuanes con cero jiaos'), + (81.25, 'ochenta y un yuanes con veinticinco jiaos'), + (350.90, 'trescientos cincuenta yuanes con noventa jiaos'), + (100.00, 'cien yuanes con cero jiaos'), + (4150.83, + 'cuatro mil ciento cincuenta yuanes con ochenta y tres jiaos'), +) + +TEST_CASES_TO_CURRENCY_CZK = ( + (1.00, 'una corona con cero haléř'), + (2.00, 'dos coronas con cero haléř'), + (8.00, 'ocho coronas con cero haléř'), + (12.00, 'doce coronas con cero haléř'), + (21.00, 'veintiun coronas con cero haléř'), + (81.25, 'ochenta y un coronas con veinticinco haléř'), + (350.90, 'trescientos cincuenta coronas con noventa haléř'), + (100.00, 'cien coronas con cero haléř'), + (4150.83, + 'cuatro mil ciento cincuenta coronas con ochenta y tres haléř'), +) + +TEST_CASES_TO_CURRENCY_NIO = ( + (1.00, 'un córdoba con cero centavos'), + (2.00, 'dos córdobas con cero centavos'), + (8.00, 'ocho córdobas con cero centavos'), + (12.00, 'doce córdobas con cero centavos'), + (21.00, 'veintiun córdobas con cero centavos'), + (81.25, 'ochenta y un córdobas con veinticinco centavos'), + (350.90, 'trescientos cincuenta córdobas con noventa centavos'), + (100.00, 'cien córdobas con cero centavos'), + (4150.83, + 'cuatro mil ciento cincuenta córdobas con ochenta y tres centavos'), +) + +TEST_CASES_TO_CURRENCY_VES = ( + (1.00, 'un bolívar con cero céntimos'), + (2.00, 'dos bolívares con cero céntimos'), + (8.00, 'ocho bolívares con cero céntimos'), + (12.00, 'doce bolívares con cero céntimos'), + (21.00, 'veintiun bolívares con cero céntimos'), + (81.25, 'ochenta y un bolívares con veinticinco céntimos'), + (350.90, 'trescientos cincuenta bolívares con noventa céntimos'), + (100.00, 'cien bolívares con cero céntimos'), + (4150.83, + 'cuatro mil ciento cincuenta bolívares con ochenta y tres céntimos'), +) + +TEST_CASES_TO_CURRENCY_BRL = ( + (1.00, 'un real con cero centavos'), + (2.00, 'dos reales con cero centavos'), + (8.00, 'ocho reales con cero centavos'), + (12.00, 'doce reales con cero centavos'), + (21.00, 'veintiun reales con cero centavos'), + (81.25, 'ochenta y un reales con veinticinco centavos'), + (350.90, 'trescientos cincuenta reales con noventa centavos'), + (100.00, 'cien reales con cero centavos'), + (4150.83, + 'cuatro mil ciento cincuenta reales con ochenta y tres centavos'), +) + +TEST_CASES_TO_CURRENCY_JPY = ( + (1.00, 'un yen con cero sen'), + (2.00, 'dos yenes con cero sen'), + (8.00, 'ocho yenes con cero sen'), + (12.00, 'doce yenes con cero sen'), + (21.00, 'veintiun yenes con cero sen'), + (81.25, 'ochenta y un yenes con veinticinco sen'), + (350.90, 'trescientos cincuenta yenes con noventa sen'), + (100.00, 'cien yenes con cero sen'), + (4150.83, + 'cuatro mil ciento cincuenta yenes con ochenta y tres sen'), +) + +TEST_CASES_TO_CURRENCY_KRW = ( + (1.00, 'un won con cero jeon'), + (2.00, 'dos wones con cero jeon'), + (8.00, 'ocho wones con cero jeon'), + (12.00, 'doce wones con cero jeon'), + (21.00, 'veintiun wones con cero jeon'), + (81.25, 'ochenta y un wones con veinticinco jeon'), + (350.90, 'trescientos cincuenta wones con noventa jeon'), + (100.00, 'cien wones con cero jeon'), + (4150.83, + 'cuatro mil ciento cincuenta wones con ochenta y tres jeon'), +) + +TEST_CASES_TO_CURRENCY_KPW = ( + (1.00, 'un won con cero chon'), + (2.00, 'dos wones con cero chon'), + (8.00, 'ocho wones con cero chon'), + (12.00, 'doce wones con cero chon'), + (21.00, 'veintiun wones con cero chon'), + (81.25, 'ochenta y un wones con veinticinco chon'), + (350.90, 'trescientos cincuenta wones con noventa chon'), + (100.00, 'cien wones con cero chon'), + (4150.83, + 'cuatro mil ciento cincuenta wones con ochenta y tres chon'), +) + +TEST_CASES_TO_CURRENCY_TRY = ( + (1.00, 'un lira con cero kuruş'), + (2.00, 'dos liras con cero kuruş'), + (8.00, 'ocho liras con cero kuruş'), + (12.00, 'doce liras con cero kuruş'), + (21.00, 'veintiun liras con cero kuruş'), + (81.25, 'ochenta y un liras con veinticinco kuruş'), + (350.90, 'trescientos cincuenta liras con noventa kuruş'), + (100.00, 'cien liras con cero kuruş'), + (4150.83, + 'cuatro mil ciento cincuenta liras con ochenta y tres kuruş'), +) + +TEST_CASES_TO_CURRENCY_ZAR = ( + (1.00, 'un rand con cero céntimos'), + (2.00, 'dos rands con cero céntimos'), + (8.00, 'ocho rands con cero céntimos'), + (12.00, 'doce rands con cero céntimos'), + (21.00, 'veintiun rands con cero céntimos'), + (81.25, 'ochenta y un rands con veinticinco céntimos'), + (350.90, 'trescientos cincuenta rands con noventa céntimos'), + (100.00, 'cien rands con cero céntimos'), + (4150.83, + 'cuatro mil ciento cincuenta rands con ochenta y tres céntimos'), +) + +TEST_CASES_TO_CURRENCY_KZT = ( + (1.00, 'un tenge con cero tïın'), + (2.00, 'dos tenges con cero tïın'), + (8.00, 'ocho tenges con cero tïın'), + (12.00, 'doce tenges con cero tïın'), + (21.00, 'veintiun tenges con cero tïın'), + (81.25, 'ochenta y un tenges con veinticinco tïın'), + (350.90, 'trescientos cincuenta tenges con noventa tïın'), + (100.00, 'cien tenges con cero tïın'), + (4150.83, + 'cuatro mil ciento cincuenta tenges con ochenta y tres tïın'), +) + +TEST_CASES_TO_CURRENCY_UAH = ( + (1.00, 'un hryvnia con cero kopiykas'), + (2.00, 'dos hryvnias con cero kopiykas'), + (8.00, 'ocho hryvnias con cero kopiykas'), + (12.00, 'doce hryvnias con cero kopiykas'), + (21.00, 'veintiun hryvnias con cero kopiykas'), + (81.25, 'ochenta y un hryvnias con veinticinco kopiykas'), + (350.90, 'trescientos cincuenta hryvnias con noventa kopiykas'), + (100.00, 'cien hryvnias con cero kopiykas'), + (4150.83, + 'cuatro mil ciento cincuenta hryvnias con ochenta y tres kopiykas'), +) + +TEST_CASES_TO_CURRENCY_THB = ( + (1.00, 'un baht con cero satang'), + (2.00, 'dos bahts con cero satang'), + (8.00, 'ocho bahts con cero satang'), + (12.00, 'doce bahts con cero satang'), + (21.00, 'veintiun bahts con cero satang'), + (81.25, 'ochenta y un bahts con veinticinco satang'), + (350.90, 'trescientos cincuenta bahts con noventa satang'), + (100.00, 'cien bahts con cero satang'), + (4150.83, + 'cuatro mil ciento cincuenta bahts con ochenta y tres satang'), +) + +TEST_CASES_TO_CURRENCY_AED = ( + (1.00, 'un dirham con cero fils'), + (2.00, 'dos dirhams con cero fils'), + (8.00, 'ocho dirhams con cero fils'), + (12.00, 'doce dirhams con cero fils'), + (21.00, 'veintiun dirhams con cero fils'), + (81.25, 'ochenta y un dirhams con veinticinco fils'), + (350.90, 'trescientos cincuenta dirhams con noventa fils'), + (100.00, 'cien dirhams con cero fils'), + (4150.83, + 'cuatro mil ciento cincuenta dirhams con ochenta y tres fils'), +) + +TEST_CASES_TO_CURRENCY_AFN = ( + (1.00, 'un afghani con cero puls'), + (2.00, 'dos afghanis con cero puls'), + (8.00, 'ocho afghanis con cero puls'), + (12.00, 'doce afghanis con cero puls'), + (21.00, 'veintiun afghanis con cero puls'), + (81.25, 'ochenta y un afghanis con veinticinco puls'), + (350.90, 'trescientos cincuenta afghanis con noventa puls'), + (100.00, 'cien afghanis con cero puls'), + (4150.83, + 'cuatro mil ciento cincuenta afghanis con ochenta y tres puls'), +) + +TEST_CASES_TO_CURRENCY_ALL = ( + (1.00, 'un lek con cero qindarka'), + (2.00, 'dos leke con cero qindarka'), + (8.00, 'ocho leke con cero qindarka'), + (12.00, 'doce leke con cero qindarka'), + (21.00, 'veintiun leke con cero qindarka'), + (81.25, 'ochenta y un leke con veinticinco qindarka'), + (350.90, 'trescientos cincuenta leke con noventa qindarka'), + (100.00, 'cien leke con cero qindarka'), + (4150.83, + 'cuatro mil ciento cincuenta leke con ochenta y tres qindarka'), +) + +TEST_CASES_TO_CURRENCY_AMD = ( + (1.00, 'un dram con cero lumas'), + (2.00, 'dos drams con cero lumas'), + (8.00, 'ocho drams con cero lumas'), + (12.00, 'doce drams con cero lumas'), + (21.00, 'veintiun drams con cero lumas'), + (81.25, 'ochenta y un drams con veinticinco lumas'), + (350.90, 'trescientos cincuenta drams con noventa lumas'), + (100.00, 'cien drams con cero lumas'), + (4150.83, + 'cuatro mil ciento cincuenta drams con ochenta y tres lumas'), +) + +TEST_CASES_TO_CURRENCY_ANG = ( + (1.00, 'un florín con cero centavos'), + (2.00, 'dos florines con cero centavos'), + (8.00, 'ocho florines con cero centavos'), + (12.00, 'doce florines con cero centavos'), + (21.00, 'veintiun florines con cero centavos'), + (81.25, 'ochenta y un florines con veinticinco centavos'), + (350.90, 'trescientos cincuenta florines con noventa centavos'), + (100.00, 'cien florines con cero centavos'), + (4150.83, + 'cuatro mil ciento cincuenta florines con ochenta y tres centavos'), +) + +TEST_CASES_TO_CURRENCY_AOA = ( + (1.00, 'un kwanza con cero céntimos'), + (2.00, 'dos kwanzas con cero céntimos'), + (8.00, 'ocho kwanzas con cero céntimos'), + (12.00, 'doce kwanzas con cero céntimos'), + (21.00, 'veintiun kwanzas con cero céntimos'), + (81.25, 'ochenta y un kwanzas con veinticinco céntimos'), + (350.90, 'trescientos cincuenta kwanzas con noventa céntimos'), + (100.00, 'cien kwanzas con cero céntimos'), + (4150.83, + 'cuatro mil ciento cincuenta kwanzas con ochenta y tres céntimos'), +) + +TEST_CASES_TO_CURRENCY_AWG = ( + (1.00, 'un florín con cero centavos'), + (2.00, 'dos florines con cero centavos'), + (8.00, 'ocho florines con cero centavos'), + (12.00, 'doce florines con cero centavos'), + (21.00, 'veintiun florines con cero centavos'), + (81.25, 'ochenta y un florines con veinticinco centavos'), + (350.90, 'trescientos cincuenta florines con noventa centavos'), + (100.00, 'cien florines con cero centavos'), + (4150.83, + 'cuatro mil ciento cincuenta florines con ochenta y tres centavos'), +) + +TEST_CASES_TO_CURRENCY_AZN = ( + (1.00, 'un manat con cero qəpik'), + (2.00, 'dos manat con cero qəpik'), + (8.00, 'ocho manat con cero qəpik'), + (12.00, 'doce manat con cero qəpik'), + (21.00, 'veintiun manat con cero qəpik'), + (81.25, 'ochenta y un manat con veinticinco qəpik'), + (350.90, 'trescientos cincuenta manat con noventa qəpik'), + (100.00, 'cien manat con cero qəpik'), + (4150.83, + 'cuatro mil ciento cincuenta manat con ochenta y tres qəpik'), +) + +TEST_CASES_TO_CURRENCY_BDT = ( + (1.00, 'un taka con cero paisas'), + (2.00, 'dos takas con cero paisas'), + (8.00, 'ocho takas con cero paisas'), + (12.00, 'doce takas con cero paisas'), + (21.00, 'veintiun takas con cero paisas'), + (81.25, 'ochenta y un takas con veinticinco paisas'), + (350.90, 'trescientos cincuenta takas con noventa paisas'), + (100.00, 'cien takas con cero paisas'), + (4150.83, + 'cuatro mil ciento cincuenta takas con ochenta y tres paisas'), +) + +TEST_CASES_TO_CURRENCY_BGN = ( + (1.00, 'un lev con cero stotinki'), + (2.00, 'dos leva con cero stotinki'), + (8.00, 'ocho leva con cero stotinki'), + (12.00, 'doce leva con cero stotinki'), + (21.00, 'veintiun leva con cero stotinki'), + (81.25, 'ochenta y un leva con veinticinco stotinki'), + (350.90, 'trescientos cincuenta leva con noventa stotinki'), + (100.00, 'cien leva con cero stotinki'), + (4150.83, + 'cuatro mil ciento cincuenta leva con ochenta y tres stotinki'), +) + +TEST_CASES_TO_CURRENCY_BHD = ( + (1.00, 'un dinar con cero fils'), + (2.00, 'dos dinares con cero fils'), + (8.00, 'ocho dinares con cero fils'), + (12.00, 'doce dinares con cero fils'), + (21.00, 'veintiun dinares con cero fils'), + (81.25, 'ochenta y un dinares con veinticinco fils'), + (350.90, 'trescientos cincuenta dinares con noventa fils'), + (100.00, 'cien dinares con cero fils'), + (4150.83, + 'cuatro mil ciento cincuenta dinares con ochenta y tres fils'), +) + +TEST_CASES_TO_CURRENCY_BOB = ( + (1.00, 'un boliviano con cero centavos'), + (2.00, 'dos bolivianos con cero centavos'), + (8.00, 'ocho bolivianos con cero centavos'), + (12.00, 'doce bolivianos con cero centavos'), + (21.00, 'veintiun bolivianos con cero centavos'), + (81.25, 'ochenta y un bolivianos con veinticinco centavos'), + (350.90, 'trescientos cincuenta bolivianos con noventa centavos'), + (100.00, 'cien bolivianos con cero centavos'), + (4150.83, + 'cuatro mil ciento cincuenta bolivianos con ochenta y tres centavos'), +) + +TEST_CASES_TO_CURRENCY_BTN = ( + (1.00, 'un ngultrum con cero chetrum'), + (2.00, 'dos ngultrum con cero chetrum'), + (8.00, 'ocho ngultrum con cero chetrum'), + (12.00, 'doce ngultrum con cero chetrum'), + (21.00, 'veintiun ngultrum con cero chetrum'), + (81.25, 'ochenta y un ngultrum con veinticinco chetrum'), + (350.90, 'trescientos cincuenta ngultrum con noventa chetrum'), + (100.00, 'cien ngultrum con cero chetrum'), + (4150.83, + 'cuatro mil ciento cincuenta ngultrum con ochenta y tres chetrum'), +) + +TEST_CASES_TO_CURRENCY_BWP = ( + (1.00, 'un pula con cero thebes'), + (2.00, 'dos pulas con cero thebes'), + (8.00, 'ocho pulas con cero thebes'), + (12.00, 'doce pulas con cero thebes'), + (21.00, 'veintiun pulas con cero thebes'), + (81.25, 'ochenta y un pulas con veinticinco thebes'), + (350.90, 'trescientos cincuenta pulas con noventa thebes'), + (100.00, 'cien pulas con cero thebes'), + (4150.83, + 'cuatro mil ciento cincuenta pulas con ochenta y tres thebes'), +) + +TEST_CASES_TO_CURRENCY_BYN = ( + (1.00, 'un rublo con cero kópeks'), + (2.00, 'dos rublos con cero kópeks'), + (8.00, 'ocho rublos con cero kópeks'), + (12.00, 'doce rublos con cero kópeks'), + (21.00, 'veintiun rublos con cero kópeks'), + (81.25, 'ochenta y un rublos con veinticinco kópeks'), + (350.90, 'trescientos cincuenta rublos con noventa kópeks'), + (100.00, 'cien rublos con cero kópeks'), + (4150.83, + 'cuatro mil ciento cincuenta rublos con ochenta y tres kópeks'), +) + +TEST_CASES_TO_CURRENCY_BYR = ( + (1.00, 'un rublo con cero kópeks'), + (2.00, 'dos rublos con cero kópeks'), + (8.00, 'ocho rublos con cero kópeks'), + (12.00, 'doce rublos con cero kópeks'), + (21.00, 'veintiun rublos con cero kópeks'), + (81.25, 'ochenta y un rublos con veinticinco kópeks'), + (350.90, 'trescientos cincuenta rublos con noventa kópeks'), + (100.00, 'cien rublos con cero kópeks'), + (4150.83, + 'cuatro mil ciento cincuenta rublos con ochenta y tres kópeks'), +) + +TEST_CASES_TO_CURRENCY_BZD = ( + (1.00, 'un dolar con cero céntimos'), + (2.00, 'dos dólares con cero céntimos'), + (8.00, 'ocho dólares con cero céntimos'), + (12.00, 'doce dólares con cero céntimos'), + (21.00, 'veintiun dólares con cero céntimos'), + (81.25, 'ochenta y un dólares con veinticinco céntimos'), + (350.90, 'trescientos cincuenta dólares con noventa céntimos'), + (100.00, 'cien dólares con cero céntimos'), + (4150.83, + 'cuatro mil ciento cincuenta dólares con ochenta y tres céntimos'), +) + +TEST_CASES_TO_CURRENCY_CVE = ( + (1.00, 'un escudo con cero centavos'), + (2.00, 'dos escudos con cero centavos'), + (8.00, 'ocho escudos con cero centavos'), + (12.00, 'doce escudos con cero centavos'), + (21.00, 'veintiun escudos con cero centavos'), + (81.25, 'ochenta y un escudos con veinticinco centavos'), + (350.90, 'trescientos cincuenta escudos con noventa centavos'), + (100.00, 'cien escudos con cero centavos'), + (4150.83, + 'cuatro mil ciento cincuenta escudos con ochenta y tres centavos'), +) + +TEST_CASES_TO_CURRENCY_CYP = ( + (1.00, 'una libra con cero céntimos'), + (2.00, 'dos libras con cero céntimos'), + (8.00, 'ocho libras con cero céntimos'), + (12.00, 'doce libras con cero céntimos'), + (21.00, 'veintiun libras con cero céntimos'), + (81.25, 'ochenta y un libras con veinticinco céntimos'), + (350.90, 'trescientos cincuenta libras con noventa céntimos'), + (100.00, 'cien libras con cero céntimos'), + (4150.83, + 'cuatro mil ciento cincuenta libras con ochenta y tres céntimos'), +) + +TEST_CASES_TO_CURRENCY_DKK = ( + (1.00, 'una corona con cero øre'), + (2.00, 'dos coronas con cero øre'), + (8.00, 'ocho coronas con cero øre'), + (12.00, 'doce coronas con cero øre'), + (21.00, 'veintiun coronas con cero øre'), + (81.25, 'ochenta y un coronas con veinticinco øre'), + (350.90, 'trescientos cincuenta coronas con noventa øre'), + (100.00, 'cien coronas con cero øre'), + (4150.83, + 'cuatro mil ciento cincuenta coronas con ochenta y tres øre'), +) + +TEST_CASES_TO_CURRENCY_DZD = ( + (1.00, 'un dinar con cero céntimos'), + (2.00, 'dos dinares con cero céntimos'), + (8.00, 'ocho dinares con cero céntimos'), + (12.00, 'doce dinares con cero céntimos'), + (21.00, 'veintiun dinares con cero céntimos'), + (81.25, 'ochenta y un dinares con veinticinco céntimos'), + (350.90, 'trescientos cincuenta dinares con noventa céntimos'), + (100.00, 'cien dinares con cero céntimos'), + (4150.83, + 'cuatro mil ciento cincuenta dinares con ochenta y tres céntimos'), +) + +TEST_CASES_TO_CURRENCY_ECS = ( + (1.00, 'un sucre con cero centavos'), + (2.00, 'dos sucres con cero centavos'), + (8.00, 'ocho sucres con cero centavos'), + (12.00, 'doce sucres con cero centavos'), + (21.00, 'veintiun sucres con cero centavos'), + (81.25, 'ochenta y un sucres con veinticinco centavos'), + (350.90, 'trescientos cincuenta sucres con noventa centavos'), + (100.00, 'cien sucres con cero centavos'), + (4150.83, + 'cuatro mil ciento cincuenta sucres con ochenta y tres centavos'), +) + +TEST_CASES_TO_CURRENCY_EGP = ( + (1.00, 'una libra con cero piastras'), + (2.00, 'dos libras con cero piastras'), + (8.00, 'ocho libras con cero piastras'), + (12.00, 'doce libras con cero piastras'), + (21.00, 'veintiun libras con cero piastras'), + (81.25, 'ochenta y un libras con veinticinco piastras'), + (350.90, 'trescientos cincuenta libras con noventa piastras'), + (100.00, 'cien libras con cero piastras'), + (4150.83, + 'cuatro mil ciento cincuenta libras con ochenta y tres piastras'), +) + +TEST_CASES_TO_CURRENCY_ERN = ( + (1.00, 'un nakfa con cero céntimos'), + (2.00, 'dos nakfas con cero céntimos'), + (8.00, 'ocho nakfas con cero céntimos'), + (12.00, 'doce nakfas con cero céntimos'), + (21.00, 'veintiun nakfas con cero céntimos'), + (81.25, 'ochenta y un nakfas con veinticinco céntimos'), + (350.90, 'trescientos cincuenta nakfas con noventa céntimos'), + (100.00, 'cien nakfas con cero céntimos'), + (4150.83, + 'cuatro mil ciento cincuenta nakfas con ochenta y tres céntimos'), +) + +TEST_CASES_TO_CURRENCY_ETB = ( + (1.00, 'un birr con cero céntimos'), + (2.00, 'dos birrs con cero céntimos'), + (8.00, 'ocho birrs con cero céntimos'), + (12.00, 'doce birrs con cero céntimos'), + (21.00, 'veintiun birrs con cero céntimos'), + (81.25, 'ochenta y un birrs con veinticinco céntimos'), + (350.90, 'trescientos cincuenta birrs con noventa céntimos'), + (100.00, 'cien birrs con cero céntimos'), + (4150.83, + 'cuatro mil ciento cincuenta birrs con ochenta y tres céntimos'), +) + +TEST_CASES_TO_CURRENCY_FKP = ( + (1.00, 'una libra con cero peniques'), + (2.00, 'dos libras con cero peniques'), + (8.00, 'ocho libras con cero peniques'), + (12.00, 'doce libras con cero peniques'), + (21.00, 'veintiun libras con cero peniques'), + (81.25, 'ochenta y un libras con veinticinco peniques'), + (350.90, 'trescientos cincuenta libras con noventa peniques'), + (100.00, 'cien libras con cero peniques'), + (4150.83, + 'cuatro mil ciento cincuenta libras con ochenta y tres peniques'), +) + +TEST_CASES_TO_CURRENCY_GEL = ( + (1.00, 'un lari con cero tetris'), + (2.00, 'dos laris con cero tetris'), + (8.00, 'ocho laris con cero tetris'), + (12.00, 'doce laris con cero tetris'), + (21.00, 'veintiun laris con cero tetris'), + (81.25, 'ochenta y un laris con veinticinco tetris'), + (350.90, 'trescientos cincuenta laris con noventa tetris'), + (100.00, 'cien laris con cero tetris'), + (4150.83, + 'cuatro mil ciento cincuenta laris con ochenta y tres tetris'), +) + +TEST_CASES_TO_CURRENCY_GHS = ( + (1.00, 'un cedi con cero pesewas'), + (2.00, 'dos cedis con cero pesewas'), + (8.00, 'ocho cedis con cero pesewas'), + (12.00, 'doce cedis con cero pesewas'), + (21.00, 'veintiun cedis con cero pesewas'), + (81.25, 'ochenta y un cedis con veinticinco pesewas'), + (350.90, 'trescientos cincuenta cedis con noventa pesewas'), + (100.00, 'cien cedis con cero pesewas'), + (4150.83, + 'cuatro mil ciento cincuenta cedis con ochenta y tres pesewas'), +) + +TEST_CASES_TO_CURRENCY_GMD = ( + (1.00, 'un dalasi con cero bututs'), + (2.00, 'dos dalasis con cero bututs'), + (8.00, 'ocho dalasis con cero bututs'), + (12.00, 'doce dalasis con cero bututs'), + (21.00, 'veintiun dalasis con cero bututs'), + (81.25, 'ochenta y un dalasis con veinticinco bututs'), + (350.90, 'trescientos cincuenta dalasis con noventa bututs'), + (100.00, 'cien dalasis con cero bututs'), + (4150.83, + 'cuatro mil ciento cincuenta dalasis con ochenta y tres bututs'), +) + +TEST_CASES_TO_CURRENCY_GTQ = ( + (1.00, 'un quetzal con cero centavos'), + (2.00, 'dos quetzales con cero centavos'), + (8.00, 'ocho quetzales con cero centavos'), + (12.00, 'doce quetzales con cero centavos'), + (21.00, 'veintiun quetzales con cero centavos'), + (81.25, 'ochenta y un quetzales con veinticinco centavos'), + (350.90, 'trescientos cincuenta quetzales con noventa centavos'), + (100.00, 'cien quetzales con cero centavos'), + (4150.83, + 'cuatro mil ciento cincuenta quetzales con ochenta y tres centavos'), +) + +TEST_CASES_TO_CURRENCY_HNL = ( + (1.00, 'un lempira con cero centavos'), + (2.00, 'dos lempiras con cero centavos'), + (8.00, 'ocho lempiras con cero centavos'), + (12.00, 'doce lempiras con cero centavos'), + (21.00, 'veintiun lempiras con cero centavos'), + (81.25, 'ochenta y un lempiras con veinticinco centavos'), + (350.90, 'trescientos cincuenta lempiras con noventa centavos'), + (100.00, 'cien lempiras con cero centavos'), + (4150.83, + 'cuatro mil ciento cincuenta lempiras con ochenta y tres centavos'), +) + +TEST_CASES_TO_CURRENCY_HRK = ( + (1.00, 'un kuna con cero lipas'), + (2.00, 'dos kunas con cero lipas'), + (8.00, 'ocho kunas con cero lipas'), + (12.00, 'doce kunas con cero lipas'), + (21.00, 'veintiun kunas con cero lipas'), + (81.25, 'ochenta y un kunas con veinticinco lipas'), + (350.90, 'trescientos cincuenta kunas con noventa lipas'), + (100.00, 'cien kunas con cero lipas'), + (4150.83, + 'cuatro mil ciento cincuenta kunas con ochenta y tres lipas'), +) + +TEST_CASES_TO_CURRENCY_HTG = ( + (1.00, 'un gourde con cero céntimos'), + (2.00, 'dos gourdes con cero céntimos'), + (8.00, 'ocho gourdes con cero céntimos'), + (12.00, 'doce gourdes con cero céntimos'), + (21.00, 'veintiun gourdes con cero céntimos'), + (81.25, 'ochenta y un gourdes con veinticinco céntimos'), + (350.90, 'trescientos cincuenta gourdes con noventa céntimos'), + (100.00, 'cien gourdes con cero céntimos'), + (4150.83, + 'cuatro mil ciento cincuenta gourdes con ochenta y tres céntimos'), +) + +TEST_CASES_TO_CURRENCY_IDR = ( + (1.00, 'una rupia con cero céntimos'), + (2.00, 'dos rupias con cero céntimos'), + (8.00, 'ocho rupias con cero céntimos'), + (12.00, 'doce rupias con cero céntimos'), + (21.00, 'veintiun rupias con cero céntimos'), + (81.25, 'ochenta y un rupias con veinticinco céntimos'), + (350.90, 'trescientos cincuenta rupias con noventa céntimos'), + (100.00, 'cien rupias con cero céntimos'), + (4150.83, + 'cuatro mil ciento cincuenta rupias con ochenta y tres céntimos'), +) + +TEST_CASES_TO_CURRENCY_ILS = ( + (1.00, 'un séquel con cero agoras'), + (2.00, 'dos séqueles con cero agoras'), + (8.00, 'ocho séqueles con cero agoras'), + (12.00, 'doce séqueles con cero agoras'), + (21.00, 'veintiun séqueles con cero agoras'), + (81.25, 'ochenta y un séqueles con veinticinco agoras'), + (350.90, 'trescientos cincuenta séqueles con noventa agoras'), + (100.00, 'cien séqueles con cero agoras'), + (4150.83, + 'cuatro mil ciento cincuenta séqueles con ochenta y tres agoras'), +) + +TEST_CASES_TO_CURRENCY_IQD = ( + (1.00, 'un dinar con cero fils'), + (2.00, 'dos dinares con cero fils'), + (8.00, 'ocho dinares con cero fils'), + (12.00, 'doce dinares con cero fils'), + (21.00, 'veintiun dinares con cero fils'), + (81.25, 'ochenta y un dinares con veinticinco fils'), + (350.90, 'trescientos cincuenta dinares con noventa fils'), + (100.00, 'cien dinares con cero fils'), + (4150.83, + 'cuatro mil ciento cincuenta dinares con ochenta y tres fils'), +) + +TEST_CASES_TO_CURRENCY_IRR = ( + (1.00, 'un rial con cero dinares'), + (2.00, 'dos riales con cero dinares'), + (8.00, 'ocho riales con cero dinares'), + (12.00, 'doce riales con cero dinares'), + (21.00, 'veintiun riales con cero dinares'), + (81.25, 'ochenta y un riales con veinticinco dinares'), + (350.90, 'trescientos cincuenta riales con noventa dinares'), + (100.00, 'cien riales con cero dinares'), + (4150.83, + 'cuatro mil ciento cincuenta riales con ochenta y tres dinares'), +) + +TEST_CASES_TO_CURRENCY_ISK = ( + (1.00, 'una corona con cero aurar'), + (2.00, 'dos coronas con cero aurar'), + (8.00, 'ocho coronas con cero aurar'), + (12.00, 'doce coronas con cero aurar'), + (21.00, 'veintiun coronas con cero aurar'), + (81.25, 'ochenta y un coronas con veinticinco aurar'), + (350.90, 'trescientos cincuenta coronas con noventa aurar'), + (100.00, 'cien coronas con cero aurar'), + (4150.83, + 'cuatro mil ciento cincuenta coronas con ochenta y tres aurar'), +) + +TEST_CASES_TO_CURRENCY_ITL = ( + (1.00, 'un lira con cero céntimos'), + (2.00, 'dos liras con cero céntimos'), + (8.00, 'ocho liras con cero céntimos'), + (12.00, 'doce liras con cero céntimos'), + (21.00, 'veintiun liras con cero céntimos'), + (81.25, 'ochenta y un liras con veinticinco céntimos'), + (350.90, 'trescientos cincuenta liras con noventa céntimos'), + (100.00, 'cien liras con cero céntimos'), + (4150.83, + 'cuatro mil ciento cincuenta liras con ochenta y tres céntimos'), +) + +TEST_CASES_TO_CURRENCY_JOD = ( + (1.00, 'un dinar con cero piastras'), + (2.00, 'dos dinares con cero piastras'), + (8.00, 'ocho dinares con cero piastras'), + (12.00, 'doce dinares con cero piastras'), + (21.00, 'veintiun dinares con cero piastras'), + (81.25, 'ochenta y un dinares con veinticinco piastras'), + (350.90, 'trescientos cincuenta dinares con noventa piastras'), + (100.00, 'cien dinares con cero piastras'), + (4150.83, + 'cuatro mil ciento cincuenta dinares con ochenta y tres piastras'), +) + +TEST_CASES_TO_CURRENCY_KES = ( + (1.00, 'un chelín con cero céntimos'), + (2.00, 'dos chelines con cero céntimos'), + (8.00, 'ocho chelines con cero céntimos'), + (12.00, 'doce chelines con cero céntimos'), + (21.00, 'veintiun chelines con cero céntimos'), + (81.25, 'ochenta y un chelines con veinticinco céntimos'), + (350.90, 'trescientos cincuenta chelines con noventa céntimos'), + (100.00, 'cien chelines con cero céntimos'), + (4150.83, + 'cuatro mil ciento cincuenta chelines con ochenta y tres céntimos'), +) + +TEST_CASES_TO_CURRENCY_KGS = ( + (1.00, 'un som con cero tyiyn'), + (2.00, 'dos som con cero tyiyn'), + (8.00, 'ocho som con cero tyiyn'), + (12.00, 'doce som con cero tyiyn'), + (21.00, 'veintiun som con cero tyiyn'), + (81.25, 'ochenta y un som con veinticinco tyiyn'), + (350.90, 'trescientos cincuenta som con noventa tyiyn'), + (100.00, 'cien som con cero tyiyn'), + (4150.83, + 'cuatro mil ciento cincuenta som con ochenta y tres tyiyn'), +) + +TEST_CASES_TO_CURRENCY_KHR = ( + (1.00, 'un riel con cero céntimos'), + (2.00, 'dos rieles con cero céntimos'), + (8.00, 'ocho rieles con cero céntimos'), + (12.00, 'doce rieles con cero céntimos'), + (21.00, 'veintiun rieles con cero céntimos'), + (81.25, 'ochenta y un rieles con veinticinco céntimos'), + (350.90, 'trescientos cincuenta rieles con noventa céntimos'), + (100.00, 'cien rieles con cero céntimos'), + (4150.83, + 'cuatro mil ciento cincuenta rieles con ochenta y tres céntimos'), +) + +TEST_CASES_TO_CURRENCY_KWD = ( + (1.00, 'un dinar con cero fils'), + (2.00, 'dos dinares con cero fils'), + (8.00, 'ocho dinares con cero fils'), + (12.00, 'doce dinares con cero fils'), + (21.00, 'veintiun dinares con cero fils'), + (81.25, 'ochenta y un dinares con veinticinco fils'), + (350.90, 'trescientos cincuenta dinares con noventa fils'), + (100.00, 'cien dinares con cero fils'), + (4150.83, + 'cuatro mil ciento cincuenta dinares con ochenta y tres fils'), +) + +TEST_CASES_TO_CURRENCY_LAK = ( + (1.00, 'un kip con cero att'), + (2.00, 'dos kips con cero att'), + (8.00, 'ocho kips con cero att'), + (12.00, 'doce kips con cero att'), + (21.00, 'veintiun kips con cero att'), + (81.25, 'ochenta y un kips con veinticinco att'), + (350.90, 'trescientos cincuenta kips con noventa att'), + (100.00, 'cien kips con cero att'), + (4150.83, + 'cuatro mil ciento cincuenta kips con ochenta y tres att'), +) + +TEST_CASES_TO_CURRENCY_LKR = ( + (1.00, 'una rupia con cero céntimos'), + (2.00, 'dos rupias con cero céntimos'), + (8.00, 'ocho rupias con cero céntimos'), + (12.00, 'doce rupias con cero céntimos'), + (21.00, 'veintiun rupias con cero céntimos'), + (81.25, 'ochenta y un rupias con veinticinco céntimos'), + (350.90, 'trescientos cincuenta rupias con noventa céntimos'), + (100.00, 'cien rupias con cero céntimos'), + (4150.83, + 'cuatro mil ciento cincuenta rupias con ochenta y tres céntimos'), +) + +TEST_CASES_TO_CURRENCY_LSL = ( + (1.00, 'un loti con cero céntimos'), + (2.00, 'dos lotis con cero céntimos'), + (8.00, 'ocho lotis con cero céntimos'), + (12.00, 'doce lotis con cero céntimos'), + (21.00, 'veintiun lotis con cero céntimos'), + (81.25, 'ochenta y un lotis con veinticinco céntimos'), + (350.90, 'trescientos cincuenta lotis con noventa céntimos'), + (100.00, 'cien lotis con cero céntimos'), + (4150.83, + 'cuatro mil ciento cincuenta lotis con ochenta y tres céntimos'), +) + +TEST_CASES_TO_CURRENCY_LTL = ( + (1.00, 'un lita con cero céntimos'), + (2.00, 'dos litas con cero céntimos'), + (8.00, 'ocho litas con cero céntimos'), + (12.00, 'doce litas con cero céntimos'), + (21.00, 'veintiun litas con cero céntimos'), + (81.25, 'ochenta y un litas con veinticinco céntimos'), + (350.90, 'trescientos cincuenta litas con noventa céntimos'), + (100.00, 'cien litas con cero céntimos'), + (4150.83, + 'cuatro mil ciento cincuenta litas con ochenta y tres céntimos'), +) + +TEST_CASES_TO_CURRENCY_LVL = ( + (1.00, 'un lat con cero céntimos'), + (2.00, 'dos lats con cero céntimos'), + (8.00, 'ocho lats con cero céntimos'), + (12.00, 'doce lats con cero céntimos'), + (21.00, 'veintiun lats con cero céntimos'), + (81.25, 'ochenta y un lats con veinticinco céntimos'), + (350.90, 'trescientos cincuenta lats con noventa céntimos'), + (100.00, 'cien lats con cero céntimos'), + (4150.83, + 'cuatro mil ciento cincuenta lats con ochenta y tres céntimos'), +) + +TEST_CASES_TO_CURRENCY_LYD = ( + (1.00, 'un dinar con cero dírhams'), + (2.00, 'dos dinares con cero dírhams'), + (8.00, 'ocho dinares con cero dírhams'), + (12.00, 'doce dinares con cero dírhams'), + (21.00, 'veintiun dinares con cero dírhams'), + (81.25, 'ochenta y un dinares con veinticinco dírhams'), + (350.90, 'trescientos cincuenta dinares con noventa dírhams'), + (100.00, 'cien dinares con cero dírhams'), + (4150.83, + 'cuatro mil ciento cincuenta dinares con ochenta y tres dírhams'), +) + +TEST_CASES_TO_CURRENCY_MAD = ( + (1.00, 'un dírham con cero céntimos'), + (2.00, 'dos dirhams con cero céntimos'), + (8.00, 'ocho dirhams con cero céntimos'), + (12.00, 'doce dirhams con cero céntimos'), + (21.00, 'veintiun dirhams con cero céntimos'), + (81.25, 'ochenta y un dirhams con veinticinco céntimos'), + (350.90, 'trescientos cincuenta dirhams con noventa céntimos'), + (100.00, 'cien dirhams con cero céntimos'), + (4150.83, + 'cuatro mil ciento cincuenta dirhams con ochenta y tres céntimos'), +) + +TEST_CASES_TO_CURRENCY_MDL = ( + (1.00, 'un leu con cero bani'), + (2.00, 'dos lei con cero bani'), + (8.00, 'ocho lei con cero bani'), + (12.00, 'doce lei con cero bani'), + (21.00, 'veintiun lei con cero bani'), + (81.25, 'ochenta y un lei con veinticinco bani'), + (350.90, 'trescientos cincuenta lei con noventa bani'), + (100.00, 'cien lei con cero bani'), + (4150.83, + 'cuatro mil ciento cincuenta lei con ochenta y tres bani'), +) + +TEST_CASES_TO_CURRENCY_MGA = ( + (1.00, 'un ariary con cero iraimbilanja'), + (2.00, 'dos ariaris con cero iraimbilanja'), + (8.00, 'ocho ariaris con cero iraimbilanja'), + (12.00, 'doce ariaris con cero iraimbilanja'), + (21.00, 'veintiun ariaris con cero iraimbilanja'), + (81.25, 'ochenta y un ariaris con veinticinco iraimbilanja'), + (350.90, 'trescientos cincuenta ariaris con noventa iraimbilanja'), + (100.00, 'cien ariaris con cero iraimbilanja'), + (4150.83, + 'cuatro mil ciento cincuenta ariaris con ochenta y tres iraimbilanja'), +) + +TEST_CASES_TO_CURRENCY_MKD = ( + (1.00, 'un denar con cero denis'), + (2.00, 'dos denares con cero denis'), + (8.00, 'ocho denares con cero denis'), + (12.00, 'doce denares con cero denis'), + (21.00, 'veintiun denares con cero denis'), + (81.25, 'ochenta y un denares con veinticinco denis'), + (350.90, 'trescientos cincuenta denares con noventa denis'), + (100.00, 'cien denares con cero denis'), + (4150.83, + 'cuatro mil ciento cincuenta denares con ochenta y tres denis'), +) + +TEST_CASES_TO_CURRENCY_MMK = ( + (1.00, 'un kiat con cero pyas'), + (2.00, 'dos kiats con cero pyas'), + (8.00, 'ocho kiats con cero pyas'), + (12.00, 'doce kiats con cero pyas'), + (21.00, 'veintiun kiats con cero pyas'), + (81.25, 'ochenta y un kiats con veinticinco pyas'), + (350.90, 'trescientos cincuenta kiats con noventa pyas'), + (100.00, 'cien kiats con cero pyas'), + (4150.83, + 'cuatro mil ciento cincuenta kiats con ochenta y tres pyas'), +) + +TEST_CASES_TO_CURRENCY_MNT = ( + (1.00, 'un tugrik con cero möngö'), + (2.00, 'dos tugriks con cero möngö'), + (8.00, 'ocho tugriks con cero möngö'), + (12.00, 'doce tugriks con cero möngö'), + (21.00, 'veintiun tugriks con cero möngö'), + (81.25, 'ochenta y un tugriks con veinticinco möngö'), + (350.90, 'trescientos cincuenta tugriks con noventa möngö'), + (100.00, 'cien tugriks con cero möngö'), + (4150.83, + 'cuatro mil ciento cincuenta tugriks con ochenta y tres möngö'), +) + +TEST_CASES_TO_CURRENCY_MOP = ( + (1.00, 'un pataca con cero avos'), + (2.00, 'dos patacas con cero avos'), + (8.00, 'ocho patacas con cero avos'), + (12.00, 'doce patacas con cero avos'), + (21.00, 'veintiun patacas con cero avos'), + (81.25, 'ochenta y un patacas con veinticinco avos'), + (350.90, 'trescientos cincuenta patacas con noventa avos'), + (100.00, 'cien patacas con cero avos'), + (4150.83, + 'cuatro mil ciento cincuenta patacas con ochenta y tres avos'), +) + +TEST_CASES_TO_CURRENCY_MRO = ( + (1.00, 'un ouguiya con cero khoums'), + (2.00, 'dos ouguiyas con cero khoums'), + (8.00, 'ocho ouguiyas con cero khoums'), + (12.00, 'doce ouguiyas con cero khoums'), + (21.00, 'veintiun ouguiyas con cero khoums'), + (81.25, 'ochenta y un ouguiyas con veinticinco khoums'), + (350.90, 'trescientos cincuenta ouguiyas con noventa khoums'), + (100.00, 'cien ouguiyas con cero khoums'), + (4150.83, + 'cuatro mil ciento cincuenta ouguiyas con ochenta y tres khoums'), +) + +TEST_CASES_TO_CURRENCY_MRU = ( + (1.00, 'un ouguiya con cero khoums'), + (2.00, 'dos ouguiyas con cero khoums'), + (8.00, 'ocho ouguiyas con cero khoums'), + (12.00, 'doce ouguiyas con cero khoums'), + (21.00, 'veintiun ouguiyas con cero khoums'), + (81.25, 'ochenta y un ouguiyas con veinticinco khoums'), + (350.90, 'trescientos cincuenta ouguiyas con noventa khoums'), + (100.00, 'cien ouguiyas con cero khoums'), + (4150.83, + 'cuatro mil ciento cincuenta ouguiyas con ochenta y tres khoums'), +) + +TEST_CASES_TO_CURRENCY_MUR = ( + (1.00, 'una rupia con cero céntimos'), + (2.00, 'dos rupias con cero céntimos'), + (8.00, 'ocho rupias con cero céntimos'), + (12.00, 'doce rupias con cero céntimos'), + (21.00, 'veintiun rupias con cero céntimos'), + (81.25, 'ochenta y un rupias con veinticinco céntimos'), + (350.90, 'trescientos cincuenta rupias con noventa céntimos'), + (100.00, 'cien rupias con cero céntimos'), + (4150.83, + 'cuatro mil ciento cincuenta rupias con ochenta y tres céntimos'), +) + +TEST_CASES_TO_CURRENCY_MVR = ( + (1.00, 'un rufiyaa con cero laari'), + (2.00, 'dos rufiyaas con cero laari'), + (8.00, 'ocho rufiyaas con cero laari'), + (12.00, 'doce rufiyaas con cero laari'), + (21.00, 'veintiun rufiyaas con cero laari'), + (81.25, 'ochenta y un rufiyaas con veinticinco laari'), + (350.90, 'trescientos cincuenta rufiyaas con noventa laari'), + (100.00, 'cien rufiyaas con cero laari'), + (4150.83, + 'cuatro mil ciento cincuenta rufiyaas con ochenta y tres laari'), +) + +TEST_CASES_TO_CURRENCY_MWK = ( + (1.00, 'un kuacha con cero tambalas'), + (2.00, 'dos kuachas con cero tambalas'), + (8.00, 'ocho kuachas con cero tambalas'), + (12.00, 'doce kuachas con cero tambalas'), + (21.00, 'veintiun kuachas con cero tambalas'), + (81.25, 'ochenta y un kuachas con veinticinco tambalas'), + (350.90, 'trescientos cincuenta kuachas con noventa tambalas'), + (100.00, 'cien kuachas con cero tambalas'), + (4150.83, + 'cuatro mil ciento cincuenta kuachas con ochenta y tres tambalas'), +) + +TEST_CASES_TO_CURRENCY_MYR = ( + (1.00, 'un ringgit con cero céntimos'), + (2.00, 'dos ringgit con cero céntimos'), + (8.00, 'ocho ringgit con cero céntimos'), + (12.00, 'doce ringgit con cero céntimos'), + (21.00, 'veintiun ringgit con cero céntimos'), + (81.25, 'ochenta y un ringgit con veinticinco céntimos'), + (350.90, 'trescientos cincuenta ringgit con noventa céntimos'), + (100.00, 'cien ringgit con cero céntimos'), + (4150.83, + 'cuatro mil ciento cincuenta ringgit con ochenta y tres céntimos'), +) + +TEST_CASES_TO_CURRENCY_MZN = ( + (1.00, 'un metical con cero centavos'), + (2.00, 'dos metical con cero centavos'), + (8.00, 'ocho metical con cero centavos'), + (12.00, 'doce metical con cero centavos'), + (21.00, 'veintiun metical con cero centavos'), + (81.25, 'ochenta y un metical con veinticinco centavos'), + (350.90, 'trescientos cincuenta metical con noventa centavos'), + (100.00, 'cien metical con cero centavos'), + (4150.83, + 'cuatro mil ciento cincuenta metical con ochenta y tres centavos'), +) + +TEST_CASES_TO_CURRENCY_NGN = ( + (1.00, 'un naira con cero kobo'), + (2.00, 'dos nairas con cero kobo'), + (8.00, 'ocho nairas con cero kobo'), + (12.00, 'doce nairas con cero kobo'), + (21.00, 'veintiun nairas con cero kobo'), + (81.25, 'ochenta y un nairas con veinticinco kobo'), + (350.90, 'trescientos cincuenta nairas con noventa kobo'), + (100.00, 'cien nairas con cero kobo'), + (4150.83, + 'cuatro mil ciento cincuenta nairas con ochenta y tres kobo'), +) + +TEST_CASES_TO_CURRENCY_NPR = ( + (1.00, 'una rupia con cero paisas'), + (2.00, 'dos rupias con cero paisas'), + (8.00, 'ocho rupias con cero paisas'), + (12.00, 'doce rupias con cero paisas'), + (21.00, 'veintiun rupias con cero paisas'), + (81.25, 'ochenta y un rupias con veinticinco paisas'), + (350.90, 'trescientos cincuenta rupias con noventa paisas'), + (100.00, 'cien rupias con cero paisas'), + (4150.83, + 'cuatro mil ciento cincuenta rupias con ochenta y tres paisas'), +) + +TEST_CASES_TO_CURRENCY_OMR = ( + (1.00, 'un rial con cero baisa'), + (2.00, 'dos riales con cero baisa'), + (8.00, 'ocho riales con cero baisa'), + (12.00, 'doce riales con cero baisa'), + (21.00, 'veintiun riales con cero baisa'), + (81.25, 'ochenta y un riales con veinticinco baisa'), + (350.90, 'trescientos cincuenta riales con noventa baisa'), + (100.00, 'cien riales con cero baisa'), + (4150.83, + 'cuatro mil ciento cincuenta riales con ochenta y tres baisa'), +) + +TEST_CASES_TO_CURRENCY_PAB = ( + (1.00, 'un balboa con cero centésimos'), + (2.00, 'dos balboas con cero centésimos'), + (8.00, 'ocho balboas con cero centésimos'), + (12.00, 'doce balboas con cero centésimos'), + (21.00, 'veintiun balboas con cero centésimos'), + (81.25, 'ochenta y un balboas con veinticinco centésimos'), + (350.90, 'trescientos cincuenta balboas con noventa centésimos'), + (100.00, 'cien balboas con cero centésimos'), + (4150.83, + 'cuatro mil ciento cincuenta balboas con ochenta y tres centésimos'), +) + +TEST_CASES_TO_CURRENCY_PGK = ( + (1.00, 'un kina con cero toea'), + (2.00, 'dos kinas con cero toea'), + (8.00, 'ocho kinas con cero toea'), + (12.00, 'doce kinas con cero toea'), + (21.00, 'veintiun kinas con cero toea'), + (81.25, 'ochenta y un kinas con veinticinco toea'), + (350.90, 'trescientos cincuenta kinas con noventa toea'), + (100.00, 'cien kinas con cero toea'), + (4150.83, + 'cuatro mil ciento cincuenta kinas con ochenta y tres toea'), +) + +TEST_CASES_TO_CURRENCY_PKR = ( + (1.00, 'una rupia con cero paisas'), + (2.00, 'dos rupias con cero paisas'), + (8.00, 'ocho rupias con cero paisas'), + (12.00, 'doce rupias con cero paisas'), + (21.00, 'veintiun rupias con cero paisas'), + (81.25, 'ochenta y un rupias con veinticinco paisas'), + (350.90, 'trescientos cincuenta rupias con noventa paisas'), + (100.00, 'cien rupias con cero paisas'), + (4150.83, + 'cuatro mil ciento cincuenta rupias con ochenta y tres paisas'), +) + +TEST_CASES_TO_CURRENCY_PLZ = ( + (1.00, 'un zloty con cero groszy'), + (2.00, 'dos zlotys con cero groszy'), + (8.00, 'ocho zlotys con cero groszy'), + (12.00, 'doce zlotys con cero groszy'), + (21.00, 'veintiun zlotys con cero groszy'), + (81.25, 'ochenta y un zlotys con veinticinco groszy'), + (350.90, 'trescientos cincuenta zlotys con noventa groszy'), + (100.00, 'cien zlotys con cero groszy'), + (4150.83, + 'cuatro mil ciento cincuenta zlotys con ochenta y tres groszy'), +) + +TEST_CASES_TO_CURRENCY_PYG = ( + (1.00, 'un guaraní con cero céntimos'), + (2.00, 'dos guaranís con cero céntimos'), + (8.00, 'ocho guaranís con cero céntimos'), + (12.00, 'doce guaranís con cero céntimos'), + (21.00, 'veintiun guaranís con cero céntimos'), + (81.25, 'ochenta y un guaranís con veinticinco céntimos'), + (350.90, 'trescientos cincuenta guaranís con noventa céntimos'), + (100.00, 'cien guaranís con cero céntimos'), + (4150.83, + 'cuatro mil ciento cincuenta guaranís con ochenta y tres céntimos'), +) + +TEST_CASES_TO_CURRENCY_QAR = ( + (1.00, 'un rial con cero dírhams'), + (2.00, 'dos riales con cero dírhams'), + (8.00, 'ocho riales con cero dírhams'), + (12.00, 'doce riales con cero dírhams'), + (21.00, 'veintiun riales con cero dírhams'), + (81.25, 'ochenta y un riales con veinticinco dírhams'), + (350.90, 'trescientos cincuenta riales con noventa dírhams'), + (100.00, 'cien riales con cero dírhams'), + (4150.83, + 'cuatro mil ciento cincuenta riales con ochenta y tres dírhams'), +) + +TEST_CASES_TO_CURRENCY_RSD = ( + (1.00, 'un dinar con cero para'), + (2.00, 'dos dinares con cero para'), + (8.00, 'ocho dinares con cero para'), + (12.00, 'doce dinares con cero para'), + (21.00, 'veintiun dinares con cero para'), + (81.25, 'ochenta y un dinares con veinticinco para'), + (350.90, 'trescientos cincuenta dinares con noventa para'), + (100.00, 'cien dinares con cero para'), + (4150.83, + 'cuatro mil ciento cincuenta dinares con ochenta y tres para'), +) + +TEST_CASES_TO_CURRENCY_RUR = ( + (1.00, 'un rublo con cero kopeks'), + (2.00, 'dos rublos con cero kopeks'), + (8.00, 'ocho rublos con cero kopeks'), + (12.00, 'doce rublos con cero kopeks'), + (21.00, 'veintiun rublos con cero kopeks'), + (81.25, 'ochenta y un rublos con veinticinco kopeks'), + (350.90, 'trescientos cincuenta rublos con noventa kopeks'), + (100.00, 'cien rublos con cero kopeks'), + (4150.83, + 'cuatro mil ciento cincuenta rublos con ochenta y tres kopeks'), +) + +TEST_CASES_TO_CURRENCY_SAR = ( + (1.00, 'un riyal con cero halalas'), + (2.00, 'dos riales con cero halalas'), + (8.00, 'ocho riales con cero halalas'), + (12.00, 'doce riales con cero halalas'), + (21.00, 'veintiun riales con cero halalas'), + (81.25, 'ochenta y un riales con veinticinco halalas'), + (350.90, 'trescientos cincuenta riales con noventa halalas'), + (100.00, 'cien riales con cero halalas'), + (4150.83, + 'cuatro mil ciento cincuenta riales con ochenta y tres halalas'), +) + +TEST_CASES_TO_CURRENCY_SCR = ( + (1.00, 'una rupia con cero céntimos'), + (2.00, 'dos rupias con cero céntimos'), + (8.00, 'ocho rupias con cero céntimos'), + (12.00, 'doce rupias con cero céntimos'), + (21.00, 'veintiun rupias con cero céntimos'), + (81.25, 'ochenta y un rupias con veinticinco céntimos'), + (350.90, 'trescientos cincuenta rupias con noventa céntimos'), + (100.00, 'cien rupias con cero céntimos'), + (4150.83, + 'cuatro mil ciento cincuenta rupias con ochenta y tres céntimos'), +) + +TEST_CASES_TO_CURRENCY_SHP = ( + (1.00, 'una libra con cero peniques'), + (2.00, 'dos libras con cero peniques'), + (8.00, 'ocho libras con cero peniques'), + (12.00, 'doce libras con cero peniques'), + (21.00, 'veintiun libras con cero peniques'), + (81.25, 'ochenta y un libras con veinticinco peniques'), + (350.90, 'trescientos cincuenta libras con noventa peniques'), + (100.00, 'cien libras con cero peniques'), + (4150.83, + 'cuatro mil ciento cincuenta libras con ochenta y tres peniques'), +) + +TEST_CASES_TO_CURRENCY_SKK = ( + (1.00, 'una corona con cero haliers'), + (2.00, 'dos coronas con cero haliers'), + (8.00, 'ocho coronas con cero haliers'), + (12.00, 'doce coronas con cero haliers'), + (21.00, 'veintiun coronas con cero haliers'), + (81.25, 'ochenta y un coronas con veinticinco haliers'), + (350.90, 'trescientos cincuenta coronas con noventa haliers'), + (100.00, 'cien coronas con cero haliers'), + (4150.83, + 'cuatro mil ciento cincuenta coronas con ochenta y tres haliers'), +) + +TEST_CASES_TO_CURRENCY_SLL = ( + (1.00, 'una leona con cero céntimos'), + (2.00, 'dos leonas con cero céntimos'), + (8.00, 'ocho leonas con cero céntimos'), + (12.00, 'doce leonas con cero céntimos'), + (21.00, 'veintiun leonas con cero céntimos'), + (81.25, 'ochenta y un leonas con veinticinco céntimos'), + (350.90, 'trescientos cincuenta leonas con noventa céntimos'), + (100.00, 'cien leonas con cero céntimos'), + (4150.83, + 'cuatro mil ciento cincuenta leonas con ochenta y tres céntimos'), +) + +TEST_CASES_TO_CURRENCY_STD = ( + (1.00, 'un dobra con cero céntimos'), + (2.00, 'dos dobras con cero céntimos'), + (8.00, 'ocho dobras con cero céntimos'), + (12.00, 'doce dobras con cero céntimos'), + (21.00, 'veintiun dobras con cero céntimos'), + (81.25, 'ochenta y un dobras con veinticinco céntimos'), + (350.90, 'trescientos cincuenta dobras con noventa céntimos'), + (100.00, 'cien dobras con cero céntimos'), + (4150.83, + 'cuatro mil ciento cincuenta dobras con ochenta y tres céntimos'), +) + +TEST_CASES_TO_CURRENCY_SVC = ( + (1.00, 'un colón con cero centavos'), + (2.00, 'dos colones con cero centavos'), + (8.00, 'ocho colones con cero centavos'), + (12.00, 'doce colones con cero centavos'), + (21.00, 'veintiun colones con cero centavos'), + (81.25, 'ochenta y un colones con veinticinco centavos'), + (350.90, 'trescientos cincuenta colones con noventa centavos'), + (100.00, 'cien colones con cero centavos'), + (4150.83, + 'cuatro mil ciento cincuenta colones con ochenta y tres centavos'), +) + +TEST_CASES_TO_CURRENCY_SZL = ( + (1.00, 'un lilangeni con cero céntimos'), + (2.00, 'dos emalangeni con cero céntimos'), + (8.00, 'ocho emalangeni con cero céntimos'), + (12.00, 'doce emalangeni con cero céntimos'), + (21.00, 'veintiun emalangeni con cero céntimos'), + (81.25, 'ochenta y un emalangeni con veinticinco céntimos'), + (350.90, 'trescientos cincuenta emalangeni con noventa céntimos'), + (100.00, 'cien emalangeni con cero céntimos'), + (4150.83, + 'cuatro mil ciento cincuenta emalangeni con ochenta y tres céntimos'), +) + +TEST_CASES_TO_CURRENCY_TJS = ( + (1.00, 'un somoni con cero dirames'), + (2.00, 'dos somonis con cero dirames'), + (8.00, 'ocho somonis con cero dirames'), + (12.00, 'doce somonis con cero dirames'), + (21.00, 'veintiun somonis con cero dirames'), + (81.25, 'ochenta y un somonis con veinticinco dirames'), + (350.90, 'trescientos cincuenta somonis con noventa dirames'), + (100.00, 'cien somonis con cero dirames'), + (4150.83, + 'cuatro mil ciento cincuenta somonis con ochenta y tres dirames'), +) + +TEST_CASES_TO_CURRENCY_TMT = ( + (1.00, 'un manat con cero tenge'), + (2.00, 'dos manat con cero tenge'), + (8.00, 'ocho manat con cero tenge'), + (12.00, 'doce manat con cero tenge'), + (21.00, 'veintiun manat con cero tenge'), + (81.25, 'ochenta y un manat con veinticinco tenge'), + (350.90, 'trescientos cincuenta manat con noventa tenge'), + (100.00, 'cien manat con cero tenge'), + (4150.83, + 'cuatro mil ciento cincuenta manat con ochenta y tres tenge'), +) + +TEST_CASES_TO_CURRENCY_TND = ( + (1.00, 'un dinar con cero milésimos'), + (2.00, 'dos dinares con cero milésimos'), + (8.00, 'ocho dinares con cero milésimos'), + (12.00, 'doce dinares con cero milésimos'), + (21.00, 'veintiun dinares con cero milésimos'), + (81.25, 'ochenta y un dinares con veinticinco milésimos'), + (350.90, 'trescientos cincuenta dinares con noventa milésimos'), + (100.00, 'cien dinares con cero milésimos'), + (4150.83, + 'cuatro mil ciento cincuenta dinares con ochenta y tres milésimos'), +) + +TEST_CASES_TO_CURRENCY_TOP = ( + (1.00, 'un paanga con cero céntimos'), + (2.00, 'dos paangas con cero céntimos'), + (8.00, 'ocho paangas con cero céntimos'), + (12.00, 'doce paangas con cero céntimos'), + (21.00, 'veintiun paangas con cero céntimos'), + (81.25, 'ochenta y un paangas con veinticinco céntimos'), + (350.90, 'trescientos cincuenta paangas con noventa céntimos'), + (100.00, 'cien paangas con cero céntimos'), + (4150.83, + 'cuatro mil ciento cincuenta paangas con ochenta y tres céntimos'), +) + +wordamount = "{} {}".format("cuatro mil ciento cincuenta", + "nuevos dolares con ochenta y tres céntimos") + +TEST_CASES_TO_CURRENCY_TWD = ( + (1.00, 'un nuevo dólar con cero céntimos'), + (2.00, 'dos nuevos dolares con cero céntimos'), + (8.00, 'ocho nuevos dolares con cero céntimos'), + (12.00, 'doce nuevos dolares con cero céntimos'), + (21.00, 'veintiun nuevos dolares con cero céntimos'), + (81.25, 'ochenta y un nuevos dolares con veinticinco céntimos'), + (350.90, 'trescientos cincuenta nuevos dolares con noventa céntimos'), + (100.00, 'cien nuevos dolares con cero céntimos'), + (4150.83, wordamount), +) + +TEST_CASES_TO_CURRENCY_TZS = ( + (1.00, 'un chelín con cero céntimos'), + (2.00, 'dos chelines con cero céntimos'), + (8.00, 'ocho chelines con cero céntimos'), + (12.00, 'doce chelines con cero céntimos'), + (21.00, 'veintiun chelines con cero céntimos'), + (81.25, 'ochenta y un chelines con veinticinco céntimos'), + (350.90, 'trescientos cincuenta chelines con noventa céntimos'), + (100.00, 'cien chelines con cero céntimos'), + (4150.83, + 'cuatro mil ciento cincuenta chelines con ochenta y tres céntimos'), +) + +TEST_CASES_TO_CURRENCY_UAG = ( + (1.00, 'un hryvnia con cero kopiykas'), + (2.00, 'dos hryvnias con cero kopiykas'), + (8.00, 'ocho hryvnias con cero kopiykas'), + (12.00, 'doce hryvnias con cero kopiykas'), + (21.00, 'veintiun hryvnias con cero kopiykas'), + (81.25, 'ochenta y un hryvnias con veinticinco kopiykas'), + (350.90, 'trescientos cincuenta hryvnias con noventa kopiykas'), + (100.00, 'cien hryvnias con cero kopiykas'), + (4150.83, + 'cuatro mil ciento cincuenta hryvnias con ochenta y tres kopiykas'), +) + +TEST_CASES_TO_CURRENCY_UGX = ( + (1.00, 'un chelín con cero céntimos'), + (2.00, 'dos chelines con cero céntimos'), + (8.00, 'ocho chelines con cero céntimos'), + (12.00, 'doce chelines con cero céntimos'), + (21.00, 'veintiun chelines con cero céntimos'), + (81.25, 'ochenta y un chelines con veinticinco céntimos'), + (350.90, 'trescientos cincuenta chelines con noventa céntimos'), + (100.00, 'cien chelines con cero céntimos'), + (4150.83, + 'cuatro mil ciento cincuenta chelines con ochenta y tres céntimos'), +) + +TEST_CASES_TO_CURRENCY_UYU = ( + (1.00, 'un peso con cero centésimos'), + (2.00, 'dos pesos con cero centésimos'), + (8.00, 'ocho pesos con cero centésimos'), + (12.00, 'doce pesos con cero centésimos'), + (21.00, 'veintiun pesos con cero centésimos'), + (81.25, 'ochenta y un pesos con veinticinco centésimos'), + (350.90, 'trescientos cincuenta pesos con noventa centésimos'), + (100.00, 'cien pesos con cero centésimos'), + (4150.83, + 'cuatro mil ciento cincuenta pesos con ochenta y tres centésimos'), +) + +TEST_CASES_TO_CURRENCY_UZS = ( + (1.00, 'un sum con cero tiyin'), + (2.00, 'dos sum con cero tiyin'), + (8.00, 'ocho sum con cero tiyin'), + (12.00, 'doce sum con cero tiyin'), + (21.00, 'veintiun sum con cero tiyin'), + (81.25, 'ochenta y un sum con veinticinco tiyin'), + (350.90, 'trescientos cincuenta sum con noventa tiyin'), + (100.00, 'cien sum con cero tiyin'), + (4150.83, + 'cuatro mil ciento cincuenta sum con ochenta y tres tiyin'), +) + +wordamount = "{} {}".format("cuatro mil ciento cincuenta", + "bolívares fuertes con ochenta y tres céntimos") + +TEST_CASES_TO_CURRENCY_VEF = ( + (1.00, 'un bolívar fuerte con cero céntimos'), + (2.00, 'dos bolívares fuertes con cero céntimos'), + (8.00, 'ocho bolívares fuertes con cero céntimos'), + (12.00, 'doce bolívares fuertes con cero céntimos'), + (21.00, 'veintiun bolívares fuertes con cero céntimos'), + (81.25, 'ochenta y un bolívares fuertes con veinticinco céntimos'), + (350.90, 'trescientos cincuenta bolívares fuertes con noventa céntimos'), + (100.00, 'cien bolívares fuertes con cero céntimos'), + (4150.83, wordamount), +) + +TEST_CASES_TO_CURRENCY_VND = ( + (1.00, 'un dong con cero xu'), + (2.00, 'dos dongs con cero xu'), + (8.00, 'ocho dongs con cero xu'), + (12.00, 'doce dongs con cero xu'), + (21.00, 'veintiun dongs con cero xu'), + (81.25, 'ochenta y un dongs con veinticinco xu'), + (350.90, 'trescientos cincuenta dongs con noventa xu'), + (100.00, 'cien dongs con cero xu'), + (4150.83, + 'cuatro mil ciento cincuenta dongs con ochenta y tres xu'), +) + +TEST_CASES_TO_CURRENCY_VUV = ( + (1.00, 'un vatu con cero nenhum'), + (2.00, 'dos vatu con cero nenhum'), + (8.00, 'ocho vatu con cero nenhum'), + (12.00, 'doce vatu con cero nenhum'), + (21.00, 'veintiun vatu con cero nenhum'), + (81.25, 'ochenta y un vatu con veinticinco nenhum'), + (350.90, 'trescientos cincuenta vatu con noventa nenhum'), + (100.00, 'cien vatu con cero nenhum'), + (4150.83, + 'cuatro mil ciento cincuenta vatu con ochenta y tres nenhum'), +) + +TEST_CASES_TO_CURRENCY_WST = ( + (1.00, 'un tala con cero centavos'), + (2.00, 'dos tala con cero centavos'), + (8.00, 'ocho tala con cero centavos'), + (12.00, 'doce tala con cero centavos'), + (21.00, 'veintiun tala con cero centavos'), + (81.25, 'ochenta y un tala con veinticinco centavos'), + (350.90, 'trescientos cincuenta tala con noventa centavos'), + (100.00, 'cien tala con cero centavos'), + (4150.83, + 'cuatro mil ciento cincuenta tala con ochenta y tres centavos'), +) + +TEST_CASES_TO_CURRENCY_XAF = ( + (1.00, 'un franco CFA con cero céntimos'), + (2.00, 'dos francos CFA con cero céntimos'), + (8.00, 'ocho francos CFA con cero céntimos'), + (12.00, 'doce francos CFA con cero céntimos'), + (21.00, 'veintiun francos CFA con cero céntimos'), + (81.25, 'ochenta y un francos CFA con veinticinco céntimos'), + (350.90, 'trescientos cincuenta francos CFA con noventa céntimos'), + (100.00, 'cien francos CFA con cero céntimos'), + (4150.83, + 'cuatro mil ciento cincuenta francos CFA con ochenta y tres céntimos'), +) + +TEST_CASES_TO_CURRENCY_XPF = ( + (1.00, 'un franco CFP con cero céntimos'), + (2.00, 'dos francos CFP con cero céntimos'), + (8.00, 'ocho francos CFP con cero céntimos'), + (12.00, 'doce francos CFP con cero céntimos'), + (21.00, 'veintiun francos CFP con cero céntimos'), + (81.25, 'ochenta y un francos CFP con veinticinco céntimos'), + (350.90, 'trescientos cincuenta francos CFP con noventa céntimos'), + (100.00, 'cien francos CFP con cero céntimos'), + (4150.83, + 'cuatro mil ciento cincuenta francos CFP con ochenta y tres céntimos'), +) + +TEST_CASES_TO_CURRENCY_YER = ( + (1.00, 'un rial con cero fils'), + (2.00, 'dos riales con cero fils'), + (8.00, 'ocho riales con cero fils'), + (12.00, 'doce riales con cero fils'), + (21.00, 'veintiun riales con cero fils'), + (81.25, 'ochenta y un riales con veinticinco fils'), + (350.90, 'trescientos cincuenta riales con noventa fils'), + (100.00, 'cien riales con cero fils'), + (4150.83, + 'cuatro mil ciento cincuenta riales con ochenta y tres fils'), +) + +TEST_CASES_TO_CURRENCY_YUM = ( + (1.00, 'un dinar con cero para'), + (2.00, 'dos dinares con cero para'), + (8.00, 'ocho dinares con cero para'), + (12.00, 'doce dinares con cero para'), + (21.00, 'veintiun dinares con cero para'), + (81.25, 'ochenta y un dinares con veinticinco para'), + (350.90, 'trescientos cincuenta dinares con noventa para'), + (100.00, 'cien dinares con cero para'), + (4150.83, + 'cuatro mil ciento cincuenta dinares con ochenta y tres para'), +) + +TEST_CASES_TO_CURRENCY_ZMW = ( + (1.00, 'un kwacha con cero ngwee'), + (2.00, 'dos kwachas con cero ngwee'), + (8.00, 'ocho kwachas con cero ngwee'), + (12.00, 'doce kwachas con cero ngwee'), + (21.00, 'veintiun kwachas con cero ngwee'), + (81.25, 'ochenta y un kwachas con veinticinco ngwee'), + (350.90, 'trescientos cincuenta kwachas con noventa ngwee'), + (100.00, 'cien kwachas con cero ngwee'), + (4150.83, + 'cuatro mil ciento cincuenta kwachas con ochenta y tres ngwee'), +) + +TEST_CASES_TO_CURRENCY_ZRZ = ( + (1.00, 'un zaire con cero makuta'), + (2.00, 'dos zaires con cero makuta'), + (8.00, 'ocho zaires con cero makuta'), + (12.00, 'doce zaires con cero makuta'), + (21.00, 'veintiun zaires con cero makuta'), + (81.25, 'ochenta y un zaires con veinticinco makuta'), + (350.90, 'trescientos cincuenta zaires con noventa makuta'), + (100.00, 'cien zaires con cero makuta'), + (4150.83, + 'cuatro mil ciento cincuenta zaires con ochenta y tres makuta'), +) + class Num2WordsESTest(TestCase): @@ -204,3 +1859,1172 @@ def test_currency_pen(self): num2words(test[0], lang='es', to='currency', currency='PEN'), test[1] ) + + def test_currency_crc(self): + for test in TEST_CASES_TO_CURRENCY_CRC: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='CRC'), + test[1] + ) + + def test_currency_aud(self): + for test in TEST_CASES_TO_CURRENCY_USD: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='AUD'), + test[1] + ) + + def test_currency_cad(self): + for test in TEST_CASES_TO_CURRENCY_USD: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='CAD'), + test[1] + ) + + def test_currency_gbp(self): + for test in TEST_CASES_TO_CURRENCY_GBP: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='GBP'), + test[1] + ) + + def test_currency_rub(self): + for test in TEST_CASES_TO_CURRENCY_RUB: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='RUB'), + test[1] + ) + + def test_currency_sek(self): + for test in TEST_CASES_TO_CURRENCY_SEK: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='SEK'), + test[1] + ) + + def test_currency_nok(self): + for test in TEST_CASES_TO_CURRENCY_NOK: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='NOK'), + test[1] + ) + + def test_currency_pln(self): + for test in TEST_CASES_TO_CURRENCY_PLN: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='PLN'), + test[1] + ) + + def test_currency_mxn(self): + for test in TEST_CASES_TO_CURRENCY_MXN: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='MXN'), + test[1] + ) + + def test_currency_ron(self): + for test in TEST_CASES_TO_CURRENCY_RON: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='RON'), + test[1] + ) + + def test_currency_inr(self): + for test in TEST_CASES_TO_CURRENCY_INR: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='INR'), + test[1] + ) + + def test_currency_huf(self): + for test in TEST_CASES_TO_CURRENCY_HUF: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='HUF'), + test[1] + ) + + def test_currency_frf(self): + for test in TEST_CASES_TO_CURRENCY_FRF: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='FRF'), + test[1] + ) + + def test_currency_cny(self): + for test in TEST_CASES_TO_CURRENCY_CNY: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='CNY'), + test[1] + ) + + def test_currency_czk(self): + for test in TEST_CASES_TO_CURRENCY_CZK: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='CZK'), + test[1] + ) + + def test_currency_nio(self): + for test in TEST_CASES_TO_CURRENCY_NIO: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='NIO'), + test[1] + ) + + def test_currency_ves(self): + for test in TEST_CASES_TO_CURRENCY_VES: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='VES'), + test[1] + ) + + def test_currency_brl(self): + for test in TEST_CASES_TO_CURRENCY_BRL: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='BRL'), + test[1] + ) + + def test_currency_chf(self): + for test in TEST_CASES_TO_CURRENCY_FRF: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='CHF'), + test[1] + ) + + def test_currency_jpy(self): + for test in TEST_CASES_TO_CURRENCY_JPY: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='JPY'), + test[1] + ) + + def test_currency_krw(self): + for test in TEST_CASES_TO_CURRENCY_KRW: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='KRW'), + test[1] + ) + + def test_currency_kpw(self): + for test in TEST_CASES_TO_CURRENCY_KPW: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='KPW'), + test[1] + ) + + def test_currency_try(self): + for test in TEST_CASES_TO_CURRENCY_TRY: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='TRY'), + test[1] + ) + + def test_currency_zar(self): + for test in TEST_CASES_TO_CURRENCY_ZAR: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='ZAR'), + test[1] + ) + + def test_currency_kzt(self): + for test in TEST_CASES_TO_CURRENCY_KZT: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='KZT'), + test[1] + ) + + def test_currency_uah(self): + for test in TEST_CASES_TO_CURRENCY_UAH: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='UAH'), + test[1] + ) + + def test_currency_thb(self): + for test in TEST_CASES_TO_CURRENCY_THB: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='THB'), + test[1] + ) + + def test_currency_aed(self): + for test in TEST_CASES_TO_CURRENCY_AED: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='AED'), + test[1] + ) + + def test_currency_afn(self): + for test in TEST_CASES_TO_CURRENCY_AFN: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='AFN'), + test[1] + ) + + def test_currency_all(self): + for test in TEST_CASES_TO_CURRENCY_ALL: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='ALL'), + test[1] + ) + + def test_currency_amd(self): + for test in TEST_CASES_TO_CURRENCY_AMD: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='AMD'), + test[1] + ) + + def test_currency_ang(self): + for test in TEST_CASES_TO_CURRENCY_ANG: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='ANG'), + test[1] + ) + + def test_currency_aoa(self): + for test in TEST_CASES_TO_CURRENCY_AOA: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='AOA'), + test[1] + ) + + def test_currency_ars(self): + for test in TEST_CASES_TO_CURRENCY_MXN: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='ARS'), + test[1] + ) + + def test_currency_awg(self): + for test in TEST_CASES_TO_CURRENCY_AWG: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='AWG'), + test[1] + ) + + def test_currency_azn(self): + for test in TEST_CASES_TO_CURRENCY_AZN: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='AZN'), + test[1] + ) + + def test_currency_bbd(self): + for test in TEST_CASES_TO_CURRENCY_USD: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='BBD'), + test[1] + ) + + def test_currency_bdt(self): + for test in TEST_CASES_TO_CURRENCY_BDT: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='BDT'), + test[1] + ) + + def test_currency_bgn(self): + for test in TEST_CASES_TO_CURRENCY_BGN: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='BGN'), + test[1] + ) + + def test_currency_bhd(self): + for test in TEST_CASES_TO_CURRENCY_BHD: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='BHD'), + test[1] + ) + + def test_currency_bif(self): + for test in TEST_CASES_TO_CURRENCY_FRF: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='BIF'), + test[1] + ) + + def test_currency_bmd(self): + for test in TEST_CASES_TO_CURRENCY_USD: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='BMD'), + test[1] + ) + + def test_currency_bnd(self): + for test in TEST_CASES_TO_CURRENCY_USD: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='BND'), + test[1] + ) + + def test_currency_bob(self): + for test in TEST_CASES_TO_CURRENCY_BOB: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='BOB'), + test[1] + ) + + def test_currency_bsd(self): + for test in TEST_CASES_TO_CURRENCY_USD: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='BSD'), + test[1] + ) + + def test_currency_btn(self): + for test in TEST_CASES_TO_CURRENCY_BTN: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='BTN'), + test[1] + ) + + def test_currency_bwp(self): + for test in TEST_CASES_TO_CURRENCY_BWP: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='BWP'), + test[1] + ) + + def test_currency_byn(self): + for test in TEST_CASES_TO_CURRENCY_BYN: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='BYN'), + test[1] + ) + + def test_currency_byr(self): + for test in TEST_CASES_TO_CURRENCY_BYR: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='BYR'), + test[1] + ) + + def test_currency_bzd(self): + for test in TEST_CASES_TO_CURRENCY_BZD: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='BZD'), + test[1] + ) + + def test_currency_cdf(self): + for test in TEST_CASES_TO_CURRENCY_FRF: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='CDF'), + test[1] + ) + + def test_currency_clp(self): + for test in TEST_CASES_TO_CURRENCY_MXN: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='CLP'), + test[1] + ) + + def test_currency_cop(self): + for test in TEST_CASES_TO_CURRENCY_MXN: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='COP'), + test[1] + ) + + def test_currency_cup(self): + for test in TEST_CASES_TO_CURRENCY_MXN: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='CUP'), + test[1] + ) + + def test_currency_cve(self): + for test in TEST_CASES_TO_CURRENCY_CVE: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='CVE'), + test[1] + ) + + def test_currency_cyp(self): + for test in TEST_CASES_TO_CURRENCY_CYP: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='CYP'), + test[1] + ) + + def test_currency_djf(self): + for test in TEST_CASES_TO_CURRENCY_FRF: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='DJF'), + test[1] + ) + + def test_currency_dkk(self): + for test in TEST_CASES_TO_CURRENCY_DKK: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='DKK'), + test[1] + ) + + def test_currency_dop(self): + for test in TEST_CASES_TO_CURRENCY_MXN: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='DOP'), + test[1] + ) + + def test_currency_dzd(self): + for test in TEST_CASES_TO_CURRENCY_DZD: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='DZD'), + test[1] + ) + + def test_currency_ecs(self): + for test in TEST_CASES_TO_CURRENCY_ECS: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='ECS'), + test[1] + ) + + def test_currency_egp(self): + for test in TEST_CASES_TO_CURRENCY_EGP: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='EGP'), + test[1] + ) + + def test_currency_ern(self): + for test in TEST_CASES_TO_CURRENCY_ERN: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='ERN'), + test[1] + ) + + def test_currency_etb(self): + for test in TEST_CASES_TO_CURRENCY_ETB: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='ETB'), + test[1] + ) + + def test_currency_fjd(self): + for test in TEST_CASES_TO_CURRENCY_USD: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='FJD'), + test[1] + ) + + def test_currency_fkp(self): + for test in TEST_CASES_TO_CURRENCY_FKP: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='FKP'), + test[1] + ) + + def test_currency_gel(self): + for test in TEST_CASES_TO_CURRENCY_GEL: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='GEL'), + test[1] + ) + + def test_currency_ghs(self): + for test in TEST_CASES_TO_CURRENCY_GHS: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='GHS'), + test[1] + ) + + def test_currency_gip(self): + for test in TEST_CASES_TO_CURRENCY_FKP: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='GIP'), + test[1] + ) + + def test_currency_gmd(self): + for test in TEST_CASES_TO_CURRENCY_GMD: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='GMD'), + test[1] + ) + + def test_currency_gnf(self): + for test in TEST_CASES_TO_CURRENCY_FRF: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='GNF'), + test[1] + ) + + def test_currency_gtq(self): + for test in TEST_CASES_TO_CURRENCY_GTQ: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='GTQ'), + test[1] + ) + + def test_currency_gyd(self): + for test in TEST_CASES_TO_CURRENCY_USD: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='GYD'), + test[1] + ) + + def test_currency_hkd(self): + for test in TEST_CASES_TO_CURRENCY_USD: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='HKD'), + test[1] + ) + + def test_currency_hnl(self): + for test in TEST_CASES_TO_CURRENCY_HNL: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='HNL'), + test[1] + ) + + def test_currency_hrk(self): + for test in TEST_CASES_TO_CURRENCY_HRK: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='HRK'), + test[1] + ) + + def test_currency_htg(self): + for test in TEST_CASES_TO_CURRENCY_HTG: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='HTG'), + test[1] + ) + + def test_currency_idr(self): + for test in TEST_CASES_TO_CURRENCY_IDR: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='IDR'), + test[1] + ) + + def test_currency_ils(self): + for test in TEST_CASES_TO_CURRENCY_ILS: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='ILS'), + test[1] + ) + + def test_currency_iqd(self): + for test in TEST_CASES_TO_CURRENCY_IQD: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='IQD'), + test[1] + ) + + def test_currency_irr(self): + for test in TEST_CASES_TO_CURRENCY_IRR: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='IRR'), + test[1] + ) + + def test_currency_isk(self): + for test in TEST_CASES_TO_CURRENCY_ISK: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='ISK'), + test[1] + ) + + def test_currency_itl(self): + for test in TEST_CASES_TO_CURRENCY_ITL: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='ITL'), + test[1] + ) + + def test_currency_jmd(self): + for test in TEST_CASES_TO_CURRENCY_BZD: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='JMD'), + test[1] + ) + + def test_currency_jod(self): + for test in TEST_CASES_TO_CURRENCY_JOD: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='JOD'), + test[1] + ) + + def test_currency_kes(self): + for test in TEST_CASES_TO_CURRENCY_KES: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='KES'), + test[1] + ) + + def test_currency_kgs(self): + for test in TEST_CASES_TO_CURRENCY_KGS: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='KGS'), + test[1] + ) + + def test_currency_khr(self): + for test in TEST_CASES_TO_CURRENCY_KHR: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='KHR'), + test[1] + ) + + def test_currency_kmf(self): + for test in TEST_CASES_TO_CURRENCY_FRF: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='KMF'), + test[1] + ) + + def test_currency_kwd(self): + for test in TEST_CASES_TO_CURRENCY_KWD: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='KWD'), + test[1] + ) + + def test_currency_kyd(self): + for test in TEST_CASES_TO_CURRENCY_BZD: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='KYD'), + test[1] + ) + + def test_currency_lak(self): + for test in TEST_CASES_TO_CURRENCY_LAK: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='LAK'), + test[1] + ) + + def test_currency_lbp(self): + for test in TEST_CASES_TO_CURRENCY_EGP: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='LBP'), + test[1] + ) + + def test_currency_lkr(self): + for test in TEST_CASES_TO_CURRENCY_LKR: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='LKR'), + test[1] + ) + + def test_currency_lrd(self): + for test in TEST_CASES_TO_CURRENCY_BZD: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='LRD'), + test[1] + ) + + def test_currency_lsl(self): + for test in TEST_CASES_TO_CURRENCY_LSL: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='LSL'), + test[1] + ) + + def test_currency_ltl(self): + for test in TEST_CASES_TO_CURRENCY_LTL: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='LTL'), + test[1] + ) + + def test_currency_lvl(self): + for test in TEST_CASES_TO_CURRENCY_LVL: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='LVL'), + test[1] + ) + + def test_currency_lyd(self): + for test in TEST_CASES_TO_CURRENCY_LYD: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='LYD'), + test[1] + ) + + def test_currency_mad(self): + for test in TEST_CASES_TO_CURRENCY_MAD: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='MAD'), + test[1] + ) + + def test_currency_mdl(self): + for test in TEST_CASES_TO_CURRENCY_MDL: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='MDL'), + test[1] + ) + + def test_currency_mga(self): + for test in TEST_CASES_TO_CURRENCY_MGA: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='MGA'), + test[1] + ) + + def test_currency_mkd(self): + for test in TEST_CASES_TO_CURRENCY_MKD: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='MKD'), + test[1] + ) + + def test_currency_mmk(self): + for test in TEST_CASES_TO_CURRENCY_MMK: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='MMK'), + test[1] + ) + + def test_currency_mnt(self): + for test in TEST_CASES_TO_CURRENCY_MNT: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='MNT'), + test[1] + ) + + def test_currency_mop(self): + for test in TEST_CASES_TO_CURRENCY_MOP: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='MOP'), + test[1] + ) + + def test_currency_mro(self): + for test in TEST_CASES_TO_CURRENCY_MRO: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='MRO'), + test[1] + ) + + def test_currency_mru(self): + for test in TEST_CASES_TO_CURRENCY_MRU: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='MRU'), + test[1] + ) + + def test_currency_mur(self): + for test in TEST_CASES_TO_CURRENCY_MUR: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='MUR'), + test[1] + ) + + def test_currency_mvr(self): + for test in TEST_CASES_TO_CURRENCY_MVR: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='MVR'), + test[1] + ) + + def test_currency_mwk(self): + for test in TEST_CASES_TO_CURRENCY_MWK: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='MWK'), + test[1] + ) + + def test_currency_myr(self): + for test in TEST_CASES_TO_CURRENCY_MYR: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='MYR'), + test[1] + ) + + def test_currency_mzn(self): + for test in TEST_CASES_TO_CURRENCY_MZN: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='MZN'), + test[1] + ) + + def test_currency_nad(self): + for test in TEST_CASES_TO_CURRENCY_BZD: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='NAD'), + test[1] + ) + + def test_currency_ngn(self): + for test in TEST_CASES_TO_CURRENCY_NGN: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='NGN'), + test[1] + ) + + def test_currency_npr(self): + for test in TEST_CASES_TO_CURRENCY_NPR: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='NPR'), + test[1] + ) + + def test_currency_nzd(self): + for test in TEST_CASES_TO_CURRENCY_USD: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='NZD'), + test[1] + ) + + def test_currency_omr(self): + for test in TEST_CASES_TO_CURRENCY_OMR: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='OMR'), + test[1] + ) + + def test_currency_pab(self): + for test in TEST_CASES_TO_CURRENCY_PAB: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='PAB'), + test[1] + ) + + def test_currency_pgk(self): + for test in TEST_CASES_TO_CURRENCY_PGK: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='PGK'), + test[1] + ) + + def test_currency_php(self): + for test in TEST_CASES_TO_CURRENCY_MXN: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='PHP'), + test[1] + ) + + def test_currency_pkr(self): + for test in TEST_CASES_TO_CURRENCY_PKR: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='PKR'), + test[1] + ) + + def test_currency_plz(self): + for test in TEST_CASES_TO_CURRENCY_PLZ: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='PLZ'), + test[1] + ) + + def test_currency_pyg(self): + for test in TEST_CASES_TO_CURRENCY_PYG: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='PYG'), + test[1] + ) + + def test_currency_qar(self): + for test in TEST_CASES_TO_CURRENCY_QAR: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='QAR'), + test[1] + ) + + def test_currency_qtq(self): + for test in TEST_CASES_TO_CURRENCY_GTQ: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='QTQ'), + test[1] + ) + + def test_currency_rsd(self): + for test in TEST_CASES_TO_CURRENCY_RSD: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='RSD'), + test[1] + ) + + def test_currency_rur(self): + for test in TEST_CASES_TO_CURRENCY_RUR: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='RUR'), + test[1] + ) + + def test_currency_rwf(self): + for test in TEST_CASES_TO_CURRENCY_FRF: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='RWF'), + test[1] + ) + + def test_currency_sar(self): + for test in TEST_CASES_TO_CURRENCY_SAR: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='SAR'), + test[1] + ) + + def test_currency_sbd(self): + for test in TEST_CASES_TO_CURRENCY_BZD: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='SBD'), + test[1] + ) + + def test_currency_scr(self): + for test in TEST_CASES_TO_CURRENCY_SCR: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='SCR'), + test[1] + ) + + def test_currency_sdg(self): + for test in TEST_CASES_TO_CURRENCY_EGP: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='SDG'), + test[1] + ) + + def test_currency_sgd(self): + for test in TEST_CASES_TO_CURRENCY_BZD: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='SGD'), + test[1] + ) + + def test_currency_shp(self): + for test in TEST_CASES_TO_CURRENCY_SHP: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='SHP'), + test[1] + ) + + def test_currency_skk(self): + for test in TEST_CASES_TO_CURRENCY_SKK: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='SKK'), + test[1] + ) + + def test_currency_sll(self): + for test in TEST_CASES_TO_CURRENCY_SLL: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='SLL'), + test[1] + ) + + def test_currency_srd(self): + for test in TEST_CASES_TO_CURRENCY_BZD: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='SRD'), + test[1] + ) + + def test_currency_ssp(self): + for test in TEST_CASES_TO_CURRENCY_EGP: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='SSP'), + test[1] + ) + + def test_currency_std(self): + for test in TEST_CASES_TO_CURRENCY_STD: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='STD'), + test[1] + ) + + def test_currency_svc(self): + for test in TEST_CASES_TO_CURRENCY_SVC: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='SVC'), + test[1] + ) + + def test_currency_syp(self): + for test in TEST_CASES_TO_CURRENCY_EGP: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='SYP'), + test[1] + ) + + def test_currency_szl(self): + for test in TEST_CASES_TO_CURRENCY_SZL: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='SZL'), + test[1] + ) + + def test_currency_tjs(self): + for test in TEST_CASES_TO_CURRENCY_TJS: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='TJS'), + test[1] + ) + + def test_currency_tmt(self): + for test in TEST_CASES_TO_CURRENCY_TMT: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='TMT'), + test[1] + ) + + def test_currency_tnd(self): + for test in TEST_CASES_TO_CURRENCY_TND: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='TND'), + test[1] + ) + + def test_currency_top(self): + for test in TEST_CASES_TO_CURRENCY_TOP: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='TOP'), + test[1] + ) + + def test_currency_ttd(self): + for test in TEST_CASES_TO_CURRENCY_BZD: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='TTD'), + test[1] + ) + + def test_currency_twd(self): + for test in TEST_CASES_TO_CURRENCY_TWD: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='TWD'), + test[1] + ) + + def test_currency_tzs(self): + for test in TEST_CASES_TO_CURRENCY_TZS: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='TZS'), + test[1] + ) + + def test_currency_uag(self): + for test in TEST_CASES_TO_CURRENCY_UAG: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='UAG'), + test[1] + ) + + def test_currency_ugx(self): + for test in TEST_CASES_TO_CURRENCY_UGX: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='UGX'), + test[1] + ) + + def test_currency_uyu(self): + for test in TEST_CASES_TO_CURRENCY_UYU: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='UYU'), + test[1] + ) + + def test_currency_uzs(self): + for test in TEST_CASES_TO_CURRENCY_UZS: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='UZS'), + test[1] + ) + + def test_currency_vef(self): + for test in TEST_CASES_TO_CURRENCY_VEF: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='VEF'), + test[1] + ) + + def test_currency_vnd(self): + for test in TEST_CASES_TO_CURRENCY_VND: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='VND'), + test[1] + ) + + def test_currency_vuv(self): + for test in TEST_CASES_TO_CURRENCY_VUV: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='VUV'), + test[1] + ) + + def test_currency_wst(self): + for test in TEST_CASES_TO_CURRENCY_WST: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='WST'), + test[1] + ) + + def test_currency_xaf(self): + for test in TEST_CASES_TO_CURRENCY_XAF: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='XAF'), + test[1] + ) + + def test_currency_xcd(self): + for test in TEST_CASES_TO_CURRENCY_BZD: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='XCD'), + test[1] + ) + + def test_currency_xof(self): + for test in TEST_CASES_TO_CURRENCY_XAF: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='XOF'), + test[1] + ) + + def test_currency_xpf(self): + for test in TEST_CASES_TO_CURRENCY_XPF: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='XPF'), + test[1] + ) + + def test_currency_yer(self): + for test in TEST_CASES_TO_CURRENCY_YER: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='YER'), + test[1] + ) + + def test_currency_yum(self): + for test in TEST_CASES_TO_CURRENCY_YUM: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='YUM'), + test[1] + ) + + def test_currency_zmw(self): + for test in TEST_CASES_TO_CURRENCY_ZMW: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='ZMW'), + test[1] + ) + + def test_currency_zrz(self): + for test in TEST_CASES_TO_CURRENCY_ZRZ: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='ZRZ'), + test[1] + ) + + def test_currency_zwl(self): + for test in TEST_CASES_TO_CURRENCY_BZD: + self.assertEqual( + num2words(test[0], lang='es', to='currency', currency='ZWL'), + test[1] + ) From 2039df64cff0a36191ac14867ea62dfea6d634c0 Mon Sep 17 00:00:00 2001 From: Peter Nordstrom Date: Wed, 27 Jan 2021 08:09:27 +0100 Subject: [PATCH 067/200] split some lines that were too long for flake8 --- num2words/lang_SV.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/num2words/lang_SV.py b/num2words/lang_SV.py index afdd31ee..4e32841c 100644 --- a/num2words/lang_SV.py +++ b/num2words/lang_SV.py @@ -42,7 +42,7 @@ def setup(self): self.exclude_title = ["och", "komma", "minus"] self.mid_numwords = [(1000, "tusen"), (100, "hundra"), - (90, "nittio"), (80, "\åttio"), (70, "sjuttio"), + (90, "nittio"), (80, "åttio"), (70, "sjuttio"), (60, "sextio"), (50, "femtio"), (40, "förtio"), (30, "trettio")] self.low_numwords = ["tjugo", "nitton", "arton", "sjutton", @@ -105,11 +105,13 @@ def to_ordinal(self, value): return " ".join(outwords) def to_ordinal_num(self, value): - raise NotImplementedError("'ordinal_num' is not implemented for swedish language") + raise NotImplementedError( + "'ordinal_num' is not implemented for swedish language") def to_year(self, val, longval=True): - raise NotImplementedError("'year' is not implemented for swedish language") - + raise NotImplementedError( + "'year' is not implemented for swedish language") def to_currency(self, val, longval=True): - raise NotImplementedError("'currency' is not implemented for swedish language") + raise NotImplementedError( + "'currency' is not implemented for swedish language") From f1cfc8e41ec37ed7dfdc4d803f8a6e7f588154eb Mon Sep 17 00:00:00 2001 From: Peter Nordstrom Date: Thu, 28 Jan 2021 08:09:56 +0100 Subject: [PATCH 068/200] updated readme (added swedish) --- README.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/README.rst b/README.rst index c84b491f..ab4cf652 100644 --- a/README.rst +++ b/README.rst @@ -107,6 +107,7 @@ Besides the numerical argument, there are two main optional arguments. * ``pt_BR`` (Portuguese - Brazilian) * ``sl`` (Slovene) * ``sr`` (Serbian) +* ``sv`` (Swedish) * ``ro`` (Romanian) * ``ru`` (Russian) * ``te`` (Telugu) From 5cb46055d794a4dc3effff22af0b4882900b107e Mon Sep 17 00:00:00 2001 From: Erwin de Haan <1627021+EraYaN@users.noreply.github.com> Date: Sun, 14 Feb 2021 19:56:24 +0100 Subject: [PATCH 069/200] Fix ordinal_num output for Dutch (NL) --- num2words/lang_NL.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/num2words/lang_NL.py b/num2words/lang_NL.py index 8725714c..7251e2ac 100644 --- a/num2words/lang_NL.py +++ b/num2words/lang_NL.py @@ -138,7 +138,7 @@ def to_ordinal(self, value): def to_ordinal_num(self, value): self.verify_ordinal(value) - return str(value) + "." + return str(value) + "e" def pluralize(self, n, forms): """ From ea82fe11ca7c07007b99ba634ffa19429040d621 Mon Sep 17 00:00:00 2001 From: Paulina Komorek <46355739+PaulinaKomorek@users.noreply.github.com> Date: Fri, 23 Apr 2021 21:27:47 +0200 Subject: [PATCH 070/200] [ADD] polish ordinal numbers (#367) --- num2words/lang_PL.py | 94 +++++++++++++++++++++++++++++++++++++++++++- tests/test_pl.py | 29 ++++++++++++-- 2 files changed, 119 insertions(+), 4 deletions(-) diff --git a/num2words/lang_PL.py b/num2words/lang_PL.py index 2fa52f79..0f2bd751 100644 --- a/num2words/lang_PL.py +++ b/num2words/lang_PL.py @@ -36,6 +36,28 @@ 9: ('dziewięć',), } +ONES_ORDINALS = { + 1: ('pierwszy', "pierwszo"), + 2: ('drugi', "dwu"), + 3: ('trzeci', "trzy"), + 4: ('czwarty', "cztero"), + 5: ('piąty', "pięcio"), + 6: ('szósty', "sześcio"), + 7: ('siódmy', "siedmio"), + 8: ('ósmy', "ośmio"), + 9: ('dziewiąty', "dziewięcio"), + 10: ('dziesiąty', "dziesięcio"), + 11: ('jedenasty', "jedenasto"), + 12: ('dwunasty', "dwunasto"), + 13: ('trzynasty', "trzynasto"), + 14: ('czternasty', "czternasto"), + 15: ('piętnasty', "piętnasto"), + 16: ('szesnasty', "szesnasto"), + 17: ('siedemnasty', "siedemnasto"), + 18: ('osiemnasty', "osiemnasto"), + 19: ('dziewiętnasty', "dziewiętnasto"), +} + TENS = { 0: ('dziesięć',), 1: ('jedenaście',), @@ -49,6 +71,7 @@ 9: ('dziewiętnaście',), } + TWENTIES = { 2: ('dwadzieścia',), 3: ('trzydzieści',), @@ -60,6 +83,17 @@ 9: ('dziewięćdzisiąt',), } +TWENTIES_ORDINALS = { + 2: ('dwudziesty', "dwudziesto"), + 3: ('trzydziesty', "trzydiesto"), + 4: ('czterdziesty', "czterdziesto"), + 5: ('pięćdziesiąty', "pięćdziesięcio"), + 6: ('sześćdziesiąty', "sześćdziesięcio"), + 7: ('siedemdziesiąty', "siedemdziesięcio"), + 8: ('osiemdziesiąty', "osiemdziesięcio"), + 9: ('dziewięćdzisiąty', "dziewięćdziesięcio"), +} + HUNDREDS = { 1: ('sto',), 2: ('dwieście',), @@ -72,10 +106,28 @@ 9: ('dziewięćset',), } +HUNDREDS_ORDINALS = { + 1: ('setny', "stu"), + 2: ('dwusetny', "dwustu"), + 3: ('trzysetny', "trzystu"), + 4: ('czterysetny', "czterystu"), + 5: ('pięćsetny', "pięcset"), + 6: ('sześćsetny', "sześćset"), + 7: ('siedemsetny', "siedemset"), + 8: ('osiemsetny', "ośiemset"), + 9: ('dziewięćsetny', "dziewięćset"), +} + THOUSANDS = { 1: ('tysiąc', 'tysiące', 'tysięcy'), # 10^3 } +prefixes_ordinal = { + 1: "tysięczny", + 2: "milionowy", + 3: "milairdowy" +} + prefixes = ( # 10^(6*x) "mi", # 10^6 "bi", # 10^12 @@ -130,8 +182,48 @@ def pluralize(self, n, forms): form = 2 return forms[form] + def last_fragment_to_ordinal(self, last, words, level): + n1, n2, n3 = get_digits(last) + last_two = n2*10+n1 + if last_two == 0: + words.append(HUNDREDS_ORDINALS[n3][level]) + elif level == 1 and last == 1: + return + elif last_two < 20: + if n3 > 0: + words.append(HUNDREDS[n3][level]) + words.append(ONES_ORDINALS[last_two][level]) + elif last_two % 10 == 0: + if n3 > 0: + words.append(HUNDREDS[n3][level]) + words.append(TWENTIES_ORDINALS[n2][level]) + else: + if n3 > 0: + words.append(HUNDREDS[n3][0]) + words.append(TWENTIES_ORDINALS[n2][0]) + words.append(ONES_ORDINALS[n1][0]) + def to_ordinal(self, number): - raise NotImplementedError() + if number % 1 != 0: + raise NotImplementedError() + words = [] + fragments = list(splitbyx(str(number), 3)) + level = 0 + last = fragments[-1] + while last == 0: + level = level+1 + fragments.pop() + last = fragments[-1] + if len(fragments) > 1: + pre_part = self._int2word(number-(last*1000**level)) + words.append(pre_part) + self.last_fragment_to_ordinal(last, words, 0 if level == 0 else 1) + output = " ".join(words) + if last == 1 and level > 0 and output != "": + output = output + " " + if level > 0: + output = output + prefixes_ordinal[level] + return output def _int2word(self, n): if n == 0: diff --git a/tests/test_pl.py b/tests/test_pl.py index ec76ed8c..a268c269 100644 --- a/tests/test_pl.py +++ b/tests/test_pl.py @@ -83,9 +83,32 @@ def test_cardinal(self): ) def test_to_ordinal(self): - # @TODO: implement to_ordinal - with self.assertRaises(NotImplementedError): - num2words(1, lang='pl', to='ordinal') + self.assertEqual(num2words(100, lang='pl', to='ordinal'), "setny") + self.assertEqual( + num2words(101, lang='pl', to='ordinal'), "sto pierwszy") + self.assertEqual(num2words(121, lang='pl', to='ordinal'), + "sto dwudziesty pierwszy") + self.assertEqual( + num2words(115, lang='pl', to='ordinal'), "sto piętnasty") + self.assertEqual( + num2words(25, lang='pl', to='ordinal'), "dwudziesty piąty") + self.assertEqual(num2words(1021, lang='pl', to='ordinal'), + "tysiąc dwudziesty pierwszy") + self.assertEqual( + num2words(120, lang='pl', to='ordinal'), "sto dwudziesty") + self.assertEqual(num2words(1000021, lang='pl', + to='ordinal'), "milion dwudziesty pierwszy") + self.assertEqual(num2words(1000, lang='pl', to='ordinal'), "tysięczny") + self.assertEqual(num2words(10000, lang='pl', + to='ordinal'), "dziesięciotysięczny") + self.assertEqual(num2words(100000000, lang='pl', + to='ordinal'), "stumilionowy") + self.assertEqual(num2words(1002000, lang='pl', + to='ordinal'), "milion dwutysięczny") + self.assertEqual(num2words(1001000, lang='pl', + to='ordinal'), "milion tysięczny") + self.assertEqual(num2words(1000000, lang='pl', + to='ordinal'), "milionowy") def test_currency(self): self.assertEqual( From 79a9abfaba0c1bdb0ba07a70010835672afeba35 Mon Sep 17 00:00:00 2001 From: cyriaka90 Date: Fri, 7 May 2021 17:05:01 +0200 Subject: [PATCH 071/200] [tr] return Turkish 0 ordinal and cardinal (#347) * [tr] return Turkish 0 ordinal and cardinal * add str_to_number to Turkish * try rather use Num2Word_Base --- num2words/lang_TR.py | 8 +++++++- tests/test_tr.py | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/num2words/lang_TR.py b/num2words/lang_TR.py index 51f415b9..7fba8711 100644 --- a/num2words/lang_TR.py +++ b/num2words/lang_TR.py @@ -18,8 +18,10 @@ from __future__ import unicode_literals +from .base import Num2Word_Base -class Num2Word_TR(object): + +class Num2Word_TR(Num2Word_Base): def __init__(self): self.precision = 2 self.negword = u"eksi" @@ -152,6 +154,8 @@ def to_cardinal(self, value): wrd += self.CARDINAL_ONES.get( self.integers_to_read[0][0], "" ) + if self.integers_to_read[0][0] == "0": + return self.ZERO return wrd if self.total_digits_outside_triplets == 0: @@ -507,6 +511,8 @@ def to_ordinal(self, value): wrd += self.ORDINAL_ONES.get( self.integers_to_read[0][0], "" ) + if self.integers_to_read[0][0] == "0": + return u"sıfırıncı" return wrd if self.total_digits_outside_triplets == 0: diff --git a/tests/test_tr.py b/tests/test_tr.py index a6fc968a..84252624 100644 --- a/tests/test_tr.py +++ b/tests/test_tr.py @@ -36,6 +36,7 @@ def test_tr(self): "expected": u"birmilyonikibinbirlira"}, {"test": 1100000, "to": "currency", "expected": u"birmilyonyüzbinlira"}, + {"test": 0, "to": "ordinal", "expected": u"sıfırıncı"}, {"test": 1, "to": "ordinal", "expected": u"birinci"}, {"test": 2, "to": "ordinal", "expected": u"ikinci"}, {"test": 9, "to": "ordinal", "expected": u"dokuzuncu"}, @@ -108,6 +109,7 @@ def test_tr(self): "expected": u"birmilyonüçbininci"}, {"test": 1200000, "to": "ordinal", "expected": u"birmilyonikiyüzbininci"}, + {"test": 0, "to": "cardinal", "expected": u"sıfır"}, {"test": 1, "to": "cardinal", "expected": u"bir"}, {"test": 2, "to": "cardinal", "expected": u"iki"}, {"test": 9, "to": "cardinal", "expected": u"dokuz"}, From 6bf14bee7b8187d99ed8c0f59b6acd3eb0ed648f Mon Sep 17 00:00:00 2001 From: Rostyslav Ivanyk Date: Wed, 30 Jun 2021 20:23:46 +0300 Subject: [PATCH 072/200] Improve Ukrainian support and minor fixes in CZ, KZ, LT, LV, PL, RU, SR languages (#400) * Fix English char 'i' in Ukrainian words * Fix the feminine currency processing for UAH in lang_UK.py * Fix test_ua.py * Fix the feminine currency processing for UAH in lang_RU.py * Add tests for UAH in test_ru.py * Add world currencies to lang_UK.py; Add test cases to test_uk.py for world currencies * Fix incorrect handling of zeros after decimal point for CZ, KZ, LT, LV, PL, RU, SR and UK languages * Add ukrainian ordinal numbers * Fix too long lines of code * Add test for negative cardinal number --- num2words/base.py | 6 +- num2words/lang_CZ.py | 5 +- num2words/lang_KZ.py | 3 +- num2words/lang_LT.py | 5 +- num2words/lang_LV.py | 5 +- num2words/lang_PL.py | 5 +- num2words/lang_RU.py | 10 +- num2words/lang_SR.py | 5 +- num2words/lang_UK.py | 747 ++++++++- tests/test_cz.py | 8 + tests/test_kz.py | 8 + tests/test_lt.py | 8 + tests/test_lv.py | 8 + tests/test_pl.py | 8 + tests/test_ru.py | 65 +- tests/test_sr.py | 8 + tests/test_uk.py | 3438 ++++++++++++++++++++++++++++++++++++++++-- 17 files changed, 4189 insertions(+), 153 deletions(-) diff --git a/num2words/base.py b/num2words/base.py index ccf52482..0929cb93 100644 --- a/num2words/base.py +++ b/num2words/base.py @@ -257,6 +257,9 @@ def pluralize(self, n, forms): """ raise NotImplementedError + def _money_verbose(self, number, currency): + return self.to_cardinal(number) + def _cents_verbose(self, number, currency): return self.to_cardinal(number) @@ -290,12 +293,13 @@ def to_currency(self, val, currency='EUR', cents=True, separator=',', cr1 = prefix_currency(self.CURRENCY_ADJECTIVES[currency], cr1) minus_str = "%s " % self.negword 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, - self.to_cardinal(left), + money_str, self.pluralize(left, cr1), separator, cents_str, diff --git a/num2words/lang_CZ.py b/num2words/lang_CZ.py index 548c48bb..04c44a07 100644 --- a/num2words/lang_CZ.py +++ b/num2words/lang_CZ.py @@ -102,10 +102,13 @@ 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, - self._int2word(int(right)) + decimal_part ) else: return self._int2word(int(n)) diff --git a/num2words/lang_KZ.py b/num2words/lang_KZ.py index 2486325d..67df20ed 100644 --- a/num2words/lang_KZ.py +++ b/num2words/lang_KZ.py @@ -77,10 +77,11 @@ 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')) return u'%s %s %s' % ( self._int2word(int(left)), self.pointword, - self._int2word(int(right)) + (ZERO + ' ') * leading_zero_count + self._int2word(int(right)) ) else: return self._int2word(int(n)) diff --git a/num2words/lang_LT.py b/num2words/lang_LT.py index 8c6623e2..8f723e88 100644 --- a/num2words/lang_LT.py +++ b/num2words/lang_LT.py @@ -124,11 +124,14 @@ def to_cardinal(self, number): base_str, n = self.parse_minus(n) 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 '%s%s %s %s' % ( base_str, self._int2word(int(left)), self.pointword, - self._int2word(int(right)) + decimal_part ) else: return "%s%s" % (base_str, self._int2word(int(n))) diff --git a/num2words/lang_LV.py b/num2words/lang_LV.py index 289c37f7..6e71c609 100644 --- a/num2words/lang_LV.py +++ b/num2words/lang_LV.py @@ -132,11 +132,14 @@ def to_cardinal(self, number): base_str, n = self.parse_minus(n) 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 '%s%s %s %s' % ( base_str, self._int2word(int(left)), self.pointword, - self._int2word(int(right)) + decimal_part ) else: return "%s%s" % (base_str, self._int2word(int(n))) diff --git a/num2words/lang_PL.py b/num2words/lang_PL.py index 0f2bd751..1fb1fdcd 100644 --- a/num2words/lang_PL.py +++ b/num2words/lang_PL.py @@ -165,10 +165,13 @@ 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, - self._int2word(int(right)) + decimal_part ) else: return self._int2word(int(n)) diff --git a/num2words/lang_RU.py b/num2words/lang_RU.py index e822d381..8e6c875b 100644 --- a/num2words/lang_RU.py +++ b/num2words/lang_RU.py @@ -144,10 +144,13 @@ 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, - self._int2word(int(right)) + decimal_part ) else: return self._int2word(int(n)) @@ -201,8 +204,11 @@ def to_ordinal(self, number): outwords[-1] = self.title(lastword) return " ".join(outwords).strip() + def _money_verbose(self, number, currency): + return self._int2word(number, currency == 'UAH') + def _cents_verbose(self, number, currency): - return self._int2word(number, currency == 'RUB') + return self._int2word(number, currency in ('UAH', 'RUB')) def _int2word(self, n, feminine=False): if n < 0: diff --git a/num2words/lang_SR.py b/num2words/lang_SR.py index 74ff0f04..254209fe 100644 --- a/num2words/lang_SR.py +++ b/num2words/lang_SR.py @@ -110,10 +110,13 @@ def to_cardinal(self, number, feminine=False): 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), feminine)) return u'%s %s %s' % ( self._int2word(int(left), feminine), self.pointword, - self._int2word(int(right), feminine) + decimal_part ) else: return self._int2word(int(n), feminine) diff --git a/num2words/lang_UK.py b/num2words/lang_UK.py index 45f87124..a6c0a3bb 100644 --- a/num2words/lang_UK.py +++ b/num2words/lang_UK.py @@ -24,13 +24,13 @@ ONES_FEMININE = { 1: ('одна',), - 2: ('двi',), + 2: ('дві',), 3: ('три',), 4: ('чотири',), 5: ('п\'ять',), - 6: ('шiсть',), - 7: ('сiм',), - 8: ('вiсiм',), + 6: ('шість',), + 7: ('сім',), + 8: ('вісім',), 9: ('дев\'ять',), } @@ -40,12 +40,34 @@ 3: ('три',), 4: ('чотири',), 5: ('п\'ять',), - 6: ('шiсть',), - 7: ('сiм',), - 8: ('вiсiм',), + 6: ('шість',), + 7: ('сім',), + 8: ('вісім',), 9: ('дев\'ять',), } +ONES_ORDINALS = { + 1: ("перший", "одно"), + 2: ("другий", "двох"), + 3: ("третій", "трьох"), + 4: ("четвертий", "чотирьох"), + 5: ("п'ятий", "п'яти"), + 6: ("шостий", "шести"), + 7: ("сьомий", "семи"), + 8: ("восьмий", "восьми"), + 9: ("дев'ятий", "дев'яти"), + 10: ("десятий", "десяти"), + 11: ("одинадцятий", "одинадцяти"), + 12: ("дванадцятий", "дванадцяти"), + 13: ("тринадцятий", "тринадцяти"), + 14: ("чотирнадцятий", "чотирнадцяти"), + 15: ("п'ятнадцятий", "п'ятнадцяти"), + 16: ("шістнадцятий", "шістнадцяти"), + 17: ("сімнадцятий", "сімнадцяти"), + 18: ("вісімнадцятий", "вісімнадцяти"), + 19: ("дев'ятнадцятий", "дев'ятнадцяти"), +} + TENS = { 0: ('десять',), 1: ('одинадцять',), @@ -53,9 +75,9 @@ 3: ('тринадцять',), 4: ('чотирнадцять',), 5: ('п\'ятнадцять',), - 6: ('шiстнадцять',), - 7: ('сiмнадцять',), - 8: ('вiсiмнадцять',), + 6: ('шістнадцять',), + 7: ('сімнадцять',), + 8: ('вісімнадцять',), 9: ('дев\'ятнадцять',), } @@ -64,61 +86,642 @@ 3: ('тридцять',), 4: ('сорок',), 5: ('п\'ятдесят',), - 6: ('шiстдесят',), - 7: ('сiмдесят',), - 8: ('вiсiмдесят',), + 6: ('шістдесят',), + 7: ('сімдесят',), + 8: ('вісімдесят',), 9: ('дев\'яносто',), } +TWENTIES_ORDINALS = { + 2: ("двадцятий", "двадцяти"), + 3: ("тридцятий", "тридцяти"), + 4: ("сороковий", "сорока"), + 5: ("п'ятдесятий", "п'ятдесяти"), + 6: ("шістдесятий", "шістдесяти"), + 7: ("сімдесятий", "сімдесяти"), + 8: ("вісімдесятий", "вісімдесяти"), + 9: ("дев'яностий", "дев'яности"), +} + HUNDREDS = { 1: ('сто',), - 2: ('двiстi',), + 2: ('двісті',), 3: ('триста',), 4: ('чотириста',), 5: ('п\'ятсот',), - 6: ('шiстсот',), - 7: ('сiмсот',), - 8: ('вiсiмсот',), + 6: ('шістсот',), + 7: ('сімсот',), + 8: ('вісімсот',), 9: ('дев\'ятсот',), } +HUNDREDS_ORDINALS = { + 1: ("сотий", "сто"), + 2: ("двохсотий", "двохсот"), + 3: ("трьохсотий", "трьохсот"), + 4: ("чотирьохсотий", "чотирьохсот"), + 5: ("п'ятисотий", "п'ятсот"), + 6: ("шестисотий", "шістсот"), + 7: ("семисотий", "сімсот"), + 8: ("восьмисотий", "вісімсот"), + 9: ("дев'ятисотий", "дев'ятсот"), +} + THOUSANDS = { - 1: ('тисяча', 'тисячi', 'тисяч'), # 10^3 - 2: ('мiльйон', 'мiльйони', 'мiльйонiв'), # 10^6 - 3: ('мiльярд', 'мiльярди', 'мiльярдiв'), # 10^9 - 4: ('трильйон', 'трильйони', 'трильйонiв'), # 10^12 - 5: ('квадрильйон', 'квадрильйони', 'квадрильйонiв'), # 10^15 - 6: ('квiнтильйон', 'квiнтильйони', 'квiнтильйонiв'), # 10^18 - 7: ('секстильйон', 'секстильйони', 'секстильйонiв'), # 10^21 - 8: ('септильйон', 'септильйони', 'септильйонiв'), # 10^24 - 9: ('октильйон', 'октильйони', 'октильйонiв'), # 10^27 - 10: ('нонiльйон', 'нонiльйони', 'нонiльйонiв'), # 10^30 + 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 +} + +prefixes_ordinal = { + 1: "тисячний", + 2: "мільйонний", + 3: "мільярдний", + 4: "трильйонний", + 5: "квадрильйонний", + 6: "квінтильйонний", + 7: "секстильйонний", + 8: "септильйонний", + 9: "октильйонний", + 10: "нонільйонний", } +FEMININE_MONEY = ('AOA', 'BAM', 'BDT', 'BWP', 'CZK', 'DKK', + 'ERN', 'HNL', 'HRK', 'IDR', 'INR', 'ISK', + 'JPY', 'KPW', 'KRW', 'LKR', 'MOP', 'MRU', + 'MUR', 'MVR', 'MWK', 'NGN', 'NIO', 'NOK', + 'NPR', 'PKR', 'SCR', 'SEK', 'STN', 'TRY', + 'WST', 'UAH', 'ZMW') +FEMININE_CENTS = ('ALL', 'BDT', 'BGN', 'BYN', 'GHS', 'HRK', + 'ILS', 'INR', 'NPR', 'OMR', 'OMR', 'PKR', + 'RSD', 'RUB', 'UAH') + +GENERIC_DOLLARS = ('долар', 'долари', 'доларів') +GENERIC_CENTS = ('цент', 'центи', 'центів') + class Num2Word_UK(Num2Word_Base): CURRENCY_FORMS = { - 'UAH': ( - ('гривня', 'гривнi', 'гривень'), - ('копiйка', 'копiйки', 'копiйок') + 'AED': ( + ('дирхам', 'дирхами', 'дирхамів'), + ('філс', 'філси', 'філсів') + ), + 'AFN': ( + ('афгані', 'афгані', 'афгані'), + ('пул', 'пули', 'пулів') + ), + 'ALL': ( + ('лек', 'леки', 'леків'), + ('кіндарка', 'кіндарки', 'кіндарок') + ), + 'AMD': ( + ('драм', 'драми', 'драмів'), + ('лум', 'лум', 'лум') + ), + 'ANG': ( + ('гульден', 'гульдени', 'гульденів'), + GENERIC_CENTS + ), + 'AOA': ( + ('кванза', 'кванзи', 'кванз'), + ('сентимо', 'сентимо', 'сентимо') + ), + 'ARS': ( + ('песо', 'песо', 'песо'), + ('сентаво', 'сентаво', 'сентаво') + ), + 'AUD': (GENERIC_DOLLARS, GENERIC_CENTS), + 'AWG': ( + ('флорин', 'флорини', 'флоринів'), + GENERIC_CENTS + ), + 'AZN': ( + ('манат', 'манати', 'манатів'), + ('гяпік', 'гяпіки', 'гяпіків') + ), + 'BAM': ( + ('марка', 'марки', 'марок'), + ('фенінг', 'фенінги', 'фенінгів') + ), + 'BBD': (GENERIC_DOLLARS, GENERIC_CENTS), + 'BDT': ( + ('така', 'таки', 'так'), + ('пойша', 'пойші', 'пойш') + ), + 'BGN': ( + ('лев', 'леви', 'левів'), + ('стотинка', 'стотинки', 'стотинок') + ), + 'BHD': ( + ('динар', 'динари', 'динарів'), + ('філс', 'філси', 'філсів') + ), + 'BIF': ( + ('франк', 'франки', 'франків'), + ('сантим', 'сантими', 'сантимів') + ), + 'BMD': (GENERIC_DOLLARS, GENERIC_CENTS), + 'BND': (GENERIC_DOLLARS, GENERIC_CENTS), + 'BOB': ( + ('болівіано', 'болівіано', 'болівіано'), + ('сентаво', 'сентаво', 'сентаво') + ), + 'BRL': ( + ('реал', 'реали', 'реалів'), + ('сентаво', 'сентаво', 'сентаво') + ), + 'BSD': (GENERIC_DOLLARS, GENERIC_CENTS), + 'BTN': ( + ('нгултрум', 'нгултруми', 'нгултрумів'), + ('четрум', 'четруми', 'четрумів') + ), + 'BWP': ( + ('пула', 'пули', 'пул'), + ('тхебе', 'тхебе', 'тхебе') + ), + 'BYN': ( + ('рубель', 'рублі', 'рублів'), + ('копійка', 'копійки', 'копійок') + ), + 'BZD': (GENERIC_DOLLARS, GENERIC_CENTS), + 'CAD': (GENERIC_DOLLARS, GENERIC_CENTS), + 'CDF': ( + ('франк', 'франки', 'франків'), + ('сантим', 'сантими', 'сантимів') + ), + 'CHF': ( + ('франк', 'франки', 'франків'), + ('сантим', 'сантими', 'сантимів') + ), + 'CLP': ( + ('песо', 'песо', 'песо'), + ('сентаво', 'сентаво', 'сентаво') + ), + 'CNY': ( + ('юань', 'юані', 'юанів'), + ('финь', 'фині', 'финів') + ), + 'COP': ( + ('песо', 'песо', 'песо'), + ('сентаво', 'сентаво', 'сентаво') + ), + 'CRC': ( + ('колон', 'колони', 'колонів'), + ('сентімо', 'сентімо', 'сентімо') + ), + 'CUC': ( + ('песо', 'песо', 'песо'), + ('сентаво', 'сентаво', 'сентаво') + ), + 'CUP': ( + ('песо', 'песо', 'песо'), + ('сентаво', 'сентаво', 'сентаво') + ), + 'CVE': ( + ('ескудо', 'ескудо', 'ескудо'), + ('сентаво', 'сентаво', 'сентаво') + ), + 'CZK': ( + ('крона', 'крони', 'крон'), + ('гелер', 'гелери', 'гелерів') + ), + 'DJF': ( + ('франк', 'франки', 'франків'), + ('сантим', 'сантими', 'сантимів') + ), + 'DKK': ( + ('крона', 'крони', 'крон'), + ('ере', 'ере', 'ере') + ), + 'DOP': ( + ('песо', 'песо', 'песо'), + ('сентаво', 'сентаво', 'сентаво') + ), + 'DZD': ( + ('динар', 'динари', 'динарів'), + ('сантим', 'сантими', 'сантимів') + ), + 'EGP': ( + ('фунт', 'фунти', 'фунтів'), + ('піастр', 'піастри', 'піастрів') + ), + 'ERN': ( + ('накфа', 'накфи', 'накф'), + GENERIC_CENTS + ), + 'ETB': ( + ('бир', 'бири', 'бирів'), + GENERIC_CENTS ), 'EUR': ( - ('євро', 'євро', 'євро'), ('цент', 'центи', 'центiв') + ('євро', 'євро', 'євро'), + GENERIC_CENTS + ), + 'FJD': (GENERIC_DOLLARS, GENERIC_CENTS), + 'FKP': ( + ('фунт', 'фунти', 'фунтів'), + ('пенс', 'пенси', 'пенсів') + ), + 'GBP': ( + ('фунт', 'фунти', 'фунтів'), + ('пенс', 'пенси', 'пенсів') + ), + 'GEL': ( + ('ларі', 'ларі', 'ларі'), + ('тетрі', 'тетрі', 'тетрі') + ), + 'GHS': ( + ('седі', 'седі', 'седі'), + ('песева', 'песеви', 'песев') + ), + 'GIP': ( + ('фунт', 'фунти', 'фунтів'), + ('пенс', 'пенси', 'пенсів') + ), + 'GMD': ( + ('даласі', 'даласі', 'даласі'), + ('бутут', 'бутути', 'бутутів') + ), + 'GNF': ( + ('франк', 'франки', 'франків'), + ('сантим', 'сантими', 'сантимів') + ), + 'GTQ': ( + ('кетсаль', 'кетсалі', 'кетсалів'), + ('сентаво', 'сентаво', 'сентаво') + ), + 'GYD': (GENERIC_DOLLARS, GENERIC_CENTS), + 'HKD': (GENERIC_DOLLARS, GENERIC_CENTS), + 'HNL': ( + ('лемпіра', 'лемпіри', 'лемпір'), + ('сентаво', 'сентаво', 'сентаво') + ), + 'HRK': ( + ('куна', 'куни', 'кун'), + ('ліпа', 'ліпи', 'ліп') + ), + 'HTG': ( + ('гурд', 'гурди', 'гурдів'), + ('сантим', 'сантими', 'сантимів') + ), + 'HUF': ( + ('форинт', 'форинти', 'форинтів'), + ('філлер', 'філлери', 'філлерів') + ), + 'IDR': ( + ('рупія', 'рупії', 'рупій'), + GENERIC_CENTS + ), + 'ILS': ( + ('шекель', 'шекелі', 'шекелів'), + ('агора', 'агори', 'агор') + ), + 'INR': ( + ('рупія', 'рупії', 'рупій'), + ('пайса', 'пайси', 'пайс') + ), + 'IQD': ( + ('динар', 'динари', 'динарів'), + ('філс', 'філси', 'філсів') + ), + 'IRR': ( + ('ріал', 'ріали', 'ріалів'), + ('динар', 'динари', 'динарів') + ), + 'ISK': ( + ('крона', 'крони', 'крон'), + ('ейре', 'ейре', 'ейре') + ), + 'JMD': (GENERIC_DOLLARS, GENERIC_CENTS), + 'JOD': ( + ('динар', 'динари', 'динарів'), + ('філс', 'філси', 'філсів') + ), + 'JPY': ( + ('єна', 'єни', 'єн'), + ('сен', 'сен', 'сен') + ), + 'KES': ( + ('шилінг', 'шилінги', 'шилінгів'), + GENERIC_CENTS + ), + 'KGS': ( + ('сом', 'соми', 'сомів'), + ('тиїн', 'тиїни', 'тиїнів') + ), + 'KHR': ( + ('рієль', 'рієлі', 'рієлів'), + ('су', 'су', 'су') + ), + 'KMF': ( + ('франк', 'франки', 'франків'), + ('сантим', 'сантими', 'сантимів') + ), + 'KPW': ( + ('вона', 'вони', 'вон'), + ('чон', 'чони', 'чонів') + ), + 'KRW': ( + ('вона', 'вони', 'вон'), + ('джеон', 'джеони', 'джеонів') + ), + 'KWD': ( + ('динар', 'динари', 'динарів'), + ('філс', 'філси', 'філсів') + ), + 'KYD': (GENERIC_DOLLARS, GENERIC_CENTS), + 'KZT': ( + ('теньге', 'теньге', 'теньге'), + ('тиїн', 'тиїни', 'тиїнів')), + 'LAK': ( + ('кіп', 'кіпи', 'кіпів'), + ('ат', 'ати', 'атів') + ), + 'LBP': ( + ('фунт', 'фунти', 'фунтів'), + ('піастр', 'піастри', 'піастрів') + ), + 'LKR': ( + ('рупія', 'рупії', 'рупій'), + GENERIC_CENTS + ), + 'LRD': (GENERIC_DOLLARS, GENERIC_CENTS), + 'LSL': ( + ('лоті', 'малоті', 'малоті'), + ('сенте', 'лісенте', 'лісенте') + ), + 'LYD': ( + ('динар', 'динари', 'динарів'), + ('дирхам', 'дирхами', 'дирхамів') + ), + 'MAD': ( + ('дирхам', 'дирхами', 'дирхамів'), + ('сантим', 'сантими', 'сантимів') + ), + 'MDL': ( + ('лей', 'леї', 'леї'), + ('бан', 'бані', 'бані') + ), + 'MGA': ( + ('аріарі', 'аріарі', 'аріарі'), + ('іраймбіланья', 'іраймбіланья', 'іраймбіланья') + ), + 'MKD': ( + ('денар', 'денари', 'денарів'), + ('дені', 'дені', 'дені') + ), + 'MMK': ( + ('к\'ят', 'к\'ят', 'к\'ят'), + ('п\'я', 'п\'я', 'п\'я') + ), + 'MNT': ( + ('тугрик', 'тугрики', 'тугриків'), + ('мунгу', 'мунгу', 'мунгу') + ), + 'MOP': ( + ('патака', 'патакі', 'патак'), + ('аво', 'аво', 'аво') + ), + 'MRU': ( + ('угія', 'угії', 'угій'), + ('хумс', 'хумс', 'хумс') + ), + 'MUR': ( + ('рупія', 'рупії', 'рупій'), + GENERIC_CENTS + ), + 'MVR': ( + ('руфія', 'руфії', 'руфій'), + ('ларі', 'ларі', 'ларі') + ), + 'MWK': ( + ('квача', 'квачі', 'квач'), + ('тамбала', 'тамбала', 'тамбала') + ), + 'MXN': ( + ('песо', 'песо', 'песо'), + ('сентаво', 'сентаво', 'сентаво') + ), + 'MYR': ( + ('рингіт', 'рингіти', 'рингітів'), + GENERIC_CENTS + ), + 'MZN': ( + ('метікал', 'метікали', 'метікалів'), + ('сентаво', 'сентаво', 'сентаво') + ), + 'NAD': (GENERIC_DOLLARS, GENERIC_CENTS), + 'NGN': ( + ('найра', 'найри', 'найр'), + ('кобо', 'кобо', 'кобо') + ), + 'NIO': ( + ('кордоба', 'кордоби', 'кордоб'), + ('сентаво', 'сентаво', 'сентаво') + ), + 'NOK': ( + ('крона', 'крони', 'крон'), + ('ере', 'ере', 'ере') + ), + 'NPR': ( + ('рупія', 'рупії', 'рупій'), + ('пайса', 'пайси', 'пайс') + ), + 'NZD': (GENERIC_DOLLARS, GENERIC_CENTS), + 'OMR': ( + ('ріал', 'ріали', 'ріалів'), + ('байза', 'байзи', 'байз') + ), + 'PAB': ( + ('бальбоа', 'бальбоа', 'бальбоа'), + ('сентесімо', 'сентесімо', 'сентесімо') + ), + 'PEN': ( + ('соль', 'соль', 'соль'), + ('сентімо', 'сентімо', 'сентімо') + ), + 'PGK': ( + ('кіна', 'кіна', 'кіна'), + ('тойя', 'тойя', 'тойя') + ), + 'PHP': ( + ('песо', 'песо', 'песо'), + ('сентаво', 'сентаво', 'сентаво') + ), + 'PKR': ( + ('рупія', 'рупії', 'рупій'), + ('пайса', 'пайси', 'пайс') + ), + 'PLN': ( + ('злотий', 'злоті', 'злотих'), + ('грош', 'гроші', 'грошів') + ), + 'PYG': ( + ('гуарані', 'гуарані', 'гуарані'), + ('сентімо', 'сентімо', 'сентімо') + ), + 'QAR': ( + ('ріал', 'ріали', 'ріалів'), + ('дирхам', 'дирхами', 'дирхамів') + ), + 'RON': ( + ('лей', 'леї', 'леї'), + ('бан', 'бані', 'бані') + ), + 'RSD': ( + ('динар', 'динари', 'динарів'), + ('пара', 'пари', 'пар') + ), + 'RUB': ( + ('рубль', 'рублі', 'рублів'), + ('копійка', 'копійки', 'копійок') + ), + 'RWF': ( + ('франк', 'франки', 'франків'), + ('сантим', 'сантими', 'сантимів') + ), + 'SAR': ( + ('ріал', 'ріали', 'ріалів'), + ('халал', 'халали', 'халалів') + ), + 'SBD': (GENERIC_DOLLARS, GENERIC_CENTS), + 'SCR': ( + ('рупія', 'рупії', 'рупій'), + GENERIC_CENTS + ), + 'SDG': ( + ('фунт', 'фунти', 'фунтів'), + ('піастр', 'піастри', 'піастрів') + ), + 'SEK': ( + ('крона', 'крони', 'крон'), + ('ере', 'ере', 'ере') + ), + 'SGD': (GENERIC_DOLLARS, GENERIC_CENTS), + 'SHP': ( + ('фунт', 'фунти', 'фунтів'), + ('пенс', 'пенси', 'пенсів') + ), + 'SLL': ( + ('леоне', 'леоне', 'леоне'), + GENERIC_CENTS + ), + 'SOS': ( + ('шилінг', 'шилінги', 'шилінгів'), + GENERIC_CENTS + ), + 'SRD': (GENERIC_DOLLARS, GENERIC_CENTS), + 'SSP': ( + ('фунт', 'фунти', 'фунтів'), + ('піастр', 'піастри', 'піастрів') + ), + 'STN': ( + ('добра', 'добри', 'добр'), + ('сентімо', 'сентімо', 'сентімо') + ), + 'SYP': ( + ('фунт', 'фунти', 'фунтів'), + ('піастр', 'піастри', 'піастрів') + ), + 'SZL': ( + ('ліланґені', 'ліланґені', 'ліланґені'), + GENERIC_CENTS + ), + 'THB': ( + ('бат', 'бати', 'батів'), + ('сатанг', 'сатанги', 'сатангів') + ), + 'TJS': ( + ('сомоні', 'сомоні', 'сомоні'), + ('дірам', 'дірами', 'дірамів') + ), + 'TMT': ( + ('манат', 'манати', 'манатів'), + ('тенге', 'тенге', 'тенге') + ), + 'TND': ( + ('динар', 'динари', 'динарів'), + ('міллім', 'мілліми', 'міллімів') + ), + 'TOP': ( + ('паанга', 'паанга', 'паанга'), + ('сеніті', 'сеніті', 'сеніті') + ), + 'TRY': ( + ('ліра', 'ліри', 'лір'), + ('куруш', 'куруші', 'курушів') + ), + 'TTD': (GENERIC_DOLLARS, GENERIC_CENTS), + 'TWD': ( + ('новий долар', 'нові долари', 'нових доларів'), + GENERIC_CENTS + ), + 'TZS': ( + ('шилінг', 'шилінги', 'шилінгів'), + GENERIC_CENTS + ), + 'UAH': ( + ('гривня', 'гривні', 'гривень'), + ('копійка', 'копійки', 'копійок') + ), + 'UGX': ( + ('шилінг', 'шилінги', 'шилінгів'), + GENERIC_CENTS + ), + 'USD': (GENERIC_DOLLARS, GENERIC_CENTS), + 'UYU': ( + ('песо', 'песо', 'песо'), + ('сентесімо', 'сентесімо', 'сентесімо') + ), + 'UZS': ( + ('сум', 'суми', 'сумів'), + ('тиїн', 'тиїни', 'тиїнів') + ), + 'VND': ( + ('донг', 'донги', 'донгів'), + ('су', 'су', 'су') + ), + 'WST': ( + ('тала', 'тали', 'тал'), + ('сене', 'сене', 'сене') + ), + 'XCD': (GENERIC_DOLLARS, GENERIC_CENTS), + 'YER': ( + ('ріал', 'ріали', 'ріалів'), + ('філс', 'філси', 'філсів') + ), + 'ZAR': ( + ('ранд', 'ранди', 'рандів'), + GENERIC_CENTS + ), + 'ZMW': ( + ('квача', 'квачі', 'квач'), + ('нгве', 'нгве', 'нгве') ), } def setup(self): - self.negword = "мiнус" + self.negword = "мінус" self.pointword = "кома" def to_cardinal(self, number): n = str(number).replace(',', '.') if '.' in n: left, right = n.split('.') - return '%s %s %s' % ( + 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, - self._int2word(int(right)) + decimal_part ) else: return self._int2word(int(n)) @@ -136,7 +739,7 @@ def pluralize(self, n, forms): return forms[form] - def _int2word(self, n, feminine=True): + def _int2word(self, n, feminine=False): if n < 0: return ' '.join([self.negword, self._int2word(abs(n))]) @@ -172,8 +775,78 @@ def _int2word(self, n, feminine=True): return ' '.join(words) + def _money_verbose(self, number, currency): + return self._int2word(number, currency in FEMININE_MONEY) + def _cents_verbose(self, number, currency): - return self._int2word(number, currency == 'UAH') + return self._int2word(number, currency in FEMININE_CENTS) + + @staticmethod + def last_fragment_to_ordinal(last, words, level): + n1, n2, n3 = get_digits(last) + last_two = n2*10+n1 + if last_two == 0: + words.append(HUNDREDS_ORDINALS[n3][level]) + elif level == 1 and last == 1: + return + elif last_two < 20: + if level == 0: + if n3 > 0: + words.append(HUNDREDS[n3][0]) + words.append(ONES_ORDINALS[last_two][0]) + else: + last_fragment_string = '' + if n3 > 0: + last_fragment_string += HUNDREDS_ORDINALS[n3][1] + last_fragment_string += ONES_ORDINALS[last_two][1] + words.append(last_fragment_string) + elif last_two % 10 == 0: + if level == 0: + if n3 > 0: + words.append(HUNDREDS[n3][0]) + words.append(TWENTIES_ORDINALS[n2][0]) + else: + last_fragment_string = '' + if n3 > 0: + last_fragment_string += HUNDREDS_ORDINALS[n3][1] + last_fragment_string += TWENTIES_ORDINALS[n2][1] + words.append(last_fragment_string) + else: + if level == 0: + if n3 > 0: + words.append(HUNDREDS[n3][0]) + words.append(TWENTIES[n2][0]) + words.append(ONES_ORDINALS[n1][0]) + else: + last_fragment_string = '' + if n3 > 0: + last_fragment_string += HUNDREDS_ORDINALS[n3][1] + last_fragment_string += TWENTIES_ORDINALS[n2][1] + last_fragment_string += ONES_ORDINALS[n1][1] + words.append(last_fragment_string) def to_ordinal(self, number): - raise NotImplementedError() + self.verify_ordinal(number) + + words = [] + fragments = list(splitbyx(str(number), 3)) + level = 0 + last = fragments[-1] + while last == 0: + level = level + 1 + fragments.pop() + last = fragments[-1] + if len(fragments) > 1: + pre_part = self._int2word(number - (last * 1000 ** level)) + words.append(pre_part) + Num2Word_UK.last_fragment_to_ordinal( + last, + words, + 0 if level == 0 else 1 + ) + output = " ".join(words) + if last == 1 and level > 0 and output != "": + output = output + " " + if level > 0: + output = output + prefixes_ordinal[level] + return output diff --git a/tests/test_cz.py b/tests/test_cz.py index 660919b0..1801e8f7 100644 --- a/tests/test_cz.py +++ b/tests/test_cz.py @@ -32,6 +32,14 @@ def test_cardinal(self): self.assertEqual(num2words(1000, lang='cz'), "tisíc") self.assertEqual(num2words(1001, lang='cz'), "tisíc jedna") self.assertEqual(num2words(2012, lang='cz'), "dva tisíce dvanáct") + self.assertEqual( + num2words(10.02, lang='cz'), + "deset celá nula dva" + ) + self.assertEqual( + num2words(15.007, lang='cz'), + "patnáct celá nula nula sedm" + ) self.assertEqual( num2words(12519.85, lang='cz'), "dvanáct tisíc pětset devatenáct celá osmdesát pět" diff --git a/tests/test_kz.py b/tests/test_kz.py index 68f71f2f..83435640 100644 --- a/tests/test_kz.py +++ b/tests/test_kz.py @@ -44,6 +44,14 @@ def test_to_cardinal_floats(self): self.assertEqual(num2words(100.67, lang="kz"), "жүз бүтін алпыс жеті") self.assertEqual(num2words(0.7, lang="kz"), "нөл бүтін жеті") self.assertEqual(num2words(1.73, lang="kz"), "бір бүтін жетпіс үш") + self.assertEqual( + num2words(10.02, lang='kz'), + "он бүтін нөл екі" + ) + self.assertEqual( + num2words(15.007, lang='kz'), + "он бес бүтін нөл нөл жеті" + ) def test_to_ordinal(self): with self.assertRaises(NotImplementedError): diff --git a/tests/test_lt.py b/tests/test_lt.py index 3c11e4ae..e8ddbb8b 100644 --- a/tests/test_lt.py +++ b/tests/test_lt.py @@ -68,6 +68,14 @@ def test_to_cardinal(self): num2words(-5000.22, lang='lt'), 'minus penki tūkstančiai kablelis dvidešimt du', ) + self.assertEqual( + num2words(10.02, lang='lt'), + "dešimt kablelis nulis du" + ) + self.assertEqual( + num2words(15.007, lang='lt'), + "penkiolika kablelis nulis nulis septyni" + ) def test_to_ordinal(self): # @TODO: implement to_ordinal diff --git a/tests/test_lv.py b/tests/test_lv.py index 754ca621..d0f69d26 100644 --- a/tests/test_lv.py +++ b/tests/test_lv.py @@ -63,6 +63,14 @@ def test_to_cardinal(self): num2words(-5000.22, lang='lv'), 'mīnus pieci tūkstoši komats divdesmit divi', ) + self.assertEqual( + num2words(10.02, lang='lv'), + "desmit komats nulle divi" + ) + self.assertEqual( + num2words(15.007, lang='lv'), + "piecpadsmit komats nulle nulle septiņi" + ) self.assertEqual(num2words(0, lang='lv'), 'nulle') self.assertEqual(num2words(5, lang='lv'), "pieci") diff --git a/tests/test_pl.py b/tests/test_pl.py index a268c269..147a747c 100644 --- a/tests/test_pl.py +++ b/tests/test_pl.py @@ -32,6 +32,14 @@ def test_cardinal(self): self.assertEqual(num2words(1000, lang='pl'), "tysiąc") self.assertEqual(num2words(1001, lang='pl'), "tysiąc jeden") self.assertEqual(num2words(2012, lang='pl'), "dwa tysiące dwanaście") + self.assertEqual( + num2words(10.02, lang='pl'), + "dziesięć przecinek zero dwa" + ) + self.assertEqual( + num2words(15.007, lang='pl'), + "piętnaście przecinek zero zero siedem" + ) self.assertEqual( num2words(12519.85, lang='pl'), "dwanaście tysięcy pięćset dziewiętnaście przecinek " diff --git a/tests/test_ru.py b/tests/test_ru.py index f2415aea..dc479758 100644 --- a/tests/test_ru.py +++ b/tests/test_ru.py @@ -75,6 +75,14 @@ def test_cardinal(self): def test_floating_point(self): self.assertEqual(num2words(5.2, lang='ru'), "пять запятая два") + self.assertEqual( + num2words(10.02, lang='ru'), + "десять запятая ноль два" + ) + self.assertEqual( + num2words(15.007, lang='ru'), + "пятнадцать запятая ноль ноль семь" + ) self.assertEqual( num2words(561.42, lang='ru'), "пятьсот шестьдесят один запятая сорок два" @@ -160,6 +168,10 @@ def test_to_currency(self): num2words(1.0, lang='ru', to='currency', currency='RUB'), 'один рубль, ноль копеек' ) + self.assertEqual( + num2words(1.0, lang='ru', to='currency', currency='UAH'), + 'одна гривна, ноль копеек' + ) self.assertEqual( num2words(1234.56, lang='ru', to='currency', currency='EUR'), 'одна тысяча двести тридцать четыре евро, пятьдесят шесть центов' @@ -168,36 +180,85 @@ def test_to_currency(self): num2words(1234.56, lang='ru', to='currency', currency='RUB'), 'одна тысяча двести тридцать четыре рубля, пятьдесят шесть копеек' ) + self.assertEqual( + num2words(1234.56, lang='ru', to='currency', currency='UAH'), + 'одна тысяча двести тридцать четыре гривны, пятьдесят шесть копеек' + ) self.assertEqual( num2words(10111, lang='ru', to='currency', currency='EUR', separator=' и'), 'сто один евро и одиннадцать центов' ) + self.assertEqual( + num2words(10111, lang='ru', to='currency', currency='RUB', + separator=' и'), + 'сто один рубль и одиннадцать копеек' + ) + self.assertEqual( + num2words(10111, lang='ru', to='currency', currency='UAH', + separator=' и'), + 'сто одна гривна и одиннадцать копеек' + ) + self.assertEqual( + num2words(10121, lang='ru', to='currency', currency='EUR', + separator=' и'), + 'сто один евро и двадцать один цент' + ) self.assertEqual( num2words(10121, lang='ru', to='currency', currency='RUB', separator=' и'), 'сто один рубль и двадцать одна копейка' ) + self.assertEqual( + num2words(10121, lang='ru', to='currency', currency='UAH', + separator=' и'), + 'сто одна гривна и двадцать одна копейка' + ) + self.assertEqual( + num2words(10122, lang='ru', to='currency', currency='EUR', + separator=' и'), + 'сто один евро и двадцать два цента' + ) self.assertEqual( num2words(10122, lang='ru', to='currency', currency='RUB', separator=' и'), 'сто один рубль и двадцать две копейки' ) self.assertEqual( - num2words(10121, lang='ru', to='currency', currency='EUR', + num2words(10122, lang='ru', to='currency', currency='UAH', separator=' и'), - 'сто один евро и двадцать один цент' + 'сто одна гривна и двадцать две копейки' ) self.assertEqual( num2words(-1251985, lang='ru', to='currency', currency='EUR', cents=False), 'минус двенадцать тысяч пятьсот девятнадцать евро, 85 центов' ) + self.assertEqual( + num2words(-1251985, lang='ru', to='currency', currency='RUB', + cents=False), + 'минус двенадцать тысяч пятьсот девятнадцать рублей, 85 копеек' + ) + self.assertEqual( + num2words(-1251985, lang='ru', to='currency', currency='UAH', + cents=False), + 'минус двенадцать тысяч пятьсот девятнадцать гривен, 85 копеек' + ) self.assertEqual( num2words('38.4', lang='ru', to='currency', separator=' и', cents=False, currency='EUR'), "тридцать восемь евро и 40 центов" ) + self.assertEqual( + num2words('38.4', lang='ru', to='currency', separator=' и', + cents=False, currency='RUB'), + "тридцать восемь рублей и 40 копеек" + ) + self.assertEqual( + num2words('38.4', lang='ru', to='currency', separator=' и', + cents=False, currency='UAH'), + "тридцать восемь гривен и 40 копеек" + ) self.assertEqual( num2words('1230.56', lang='ru', to='currency', currency='USD'), 'одна тысяча двести тридцать долларов, пятьдесят шесть центов' diff --git a/tests/test_sr.py b/tests/test_sr.py index c97a0930..50f379b8 100644 --- a/tests/test_sr.py +++ b/tests/test_sr.py @@ -86,6 +86,14 @@ def test_cardinal(self): def test_floating_point(self): self.assertEqual("pet zapeta dva", num2words(5.2, lang='sr')) + self.assertEqual( + num2words(10.02, lang='sr'), + "deset zapeta nula dva" + ) + self.assertEqual( + num2words(15.007, lang='sr'), + "petnaest zapeta nula nula sedam" + ) self.assertEqual( "petsto šezdeset jedan zapeta četrdeset dva", num2words(561.42, lang='sr') diff --git a/tests/test_uk.py b/tests/test_uk.py index 69342120..84fb770a 100644 --- a/tests/test_uk.py +++ b/tests/test_uk.py @@ -21,115 +21,3343 @@ from num2words import num2words +TEST_CASES_CARDINAL = ( + (1, "один"), + (2, "два"), + (3, "три"), + (4, "чотири"), + (5, "п'ять"), + (6, "шість"), + (7, "сім"), + (8, "вісім"), + (9, "дев'ять"), + (10, "десять"), + (10.02, "десять кома нуль два"), + (11, "одинадцять"), + (12, "дванадцять"), + (12.40, "дванадцять кома чотири"), + (13, "тринадцять"), + (14, "чотирнадцять"), + (14.13, "чотирнадцять кома тринадцять"), + (15, "п'ятнадцять"), + (16, "шістнадцять"), + (17, "сімнадцять"), + (17.31, "сімнадцять кома тридцять один"), + (18, "вісімнадцять"), + (19, "дев'ятнадцять"), + (20, "двадцять"), + (21, "двадцять один"), + (21.20, "двадцять один кома два"), + (30, "тридцять"), + (32, "тридцять два"), + (40, "сорок"), + (43, "сорок три"), + (43.007, "сорок три кома нуль нуль сім"), + (50, "п'ятдесят"), + (54, "п'ятдесят чотири"), + (60, "шістдесят"), + (60.059, "шістдесят кома нуль п'ятдесят дев'ять"), + (65, "шістдесят п'ять"), + (70, "сімдесят"), + (76, "сімдесят шість"), + (80, "вісімдесят"), + (87, "вісімдесят сім"), + (90, "дев'яносто"), + (98, "дев'яносто вісім"), + (99, "дев'яносто дев'ять"), + (100, "сто"), + (101, "сто один"), + (199, "сто дев'яносто дев'ять"), + (200, "двісті"), + (203, "двісті три"), + (300, "триста"), + (356, "триста п'ятдесят шість"), + (400, "чотириста"), + (434, "чотириста тридцять чотири"), + (500, "п'ятсот"), + (578, "п'ятсот сімдесят вісім"), + (600, "шістсот"), + (689, "шістсот вісімдесят дев'ять"), + (700, "сімсот"), + (729, "сімсот двадцять дев'ять"), + (800, "вісімсот"), + (894, "вісімсот дев'яносто чотири"), + (900, "дев'ятсот"), + (999, "дев'ятсот дев'яносто дев'ять"), + (1000, "одна тисяча"), + (1001, "одна тисяча один"), + (2012, "дві тисячі дванадцять"), + (12519, "дванадцять тисяч п'ятсот дев'ятнадцять"), + (12519.85, "дванадцять тисяч п'ятсот дев'ятнадцять кома вісімдесят п'ять"), + (-260000, "мінус двісті шістдесят тисяч"), + (1000000, "один мільйон"), + (1000000000, "один мільярд"), + (1234567890, "один мільярд двісті тридцять чотири мільйони " + "п'ятсот шістдесят сім тисяч вісімсот дев'яносто"), + (1000000000000, "один трильйон"), + (1000000000000000, "один квадрильйон"), + (1000000000000000000, "один квінтильйон"), + (1000000000000000000000, "один секстильйон"), + (1000000000000000000000000, "один септильйон"), + (1000000000000000000000000000, "один октильйон"), + (1000000000000000000000000000000, "один нонільйон"), + (215461407892039002157189883901676, + "двісті п'ятнадцять нонільйонів чотириста шістдесят один " + "октильйон чотириста сім септильйонів вісімсот дев'яносто " + "два секстильйони тридцять дев'ять квінтильйонів два " + "квадрильйони сто п'ятдесят сім трильйонів сто вісімдесят " + "дев'ять мільярдів вісімсот вісімдесят три мільйони " + "дев'ятсот одна тисяча шістсот сімдесят шість"), + (719094234693663034822824384220291, + "сімсот дев'ятнадцять нонільйонів дев'яносто чотири октильйони " + "двісті тридцять чотири септильйони шістсот дев'яносто три " + "секстильйони шістсот шістдесят три квінтильйони тридцять " + "чотири квадрильйони вісімсот двадцять два трильйони вісімсот " + "двадцять чотири мільярди триста вісімдесят чотири мільйони " + "двісті двадцять тисяч двісті дев'яносто один") +) + +TEST_CASES_ORDINAL = ( + (1, "перший"), + (2, "другий"), + (3, "третій"), + (4, "четвертий"), + (5, "п'ятий"), + (6, "шостий"), + (7, "сьомий"), + (8, "восьмий"), + (9, "дев'ятий"), + (10, "десятий"), + (11, "одинадцятий"), + (12, "дванадцятий"), + (13, "тринадцятий"), + (14, "чотирнадцятий"), + (15, "п'ятнадцятий"), + (16, "шістнадцятий"), + (17, "сімнадцятий"), + (18, "вісімнадцятий"), + (19, "дев'ятнадцятий"), + (20, "двадцятий"), + (21, "двадцять перший"), + (30, "тридцятий"), + (32, "тридцять другий"), + (40, "сороковий"), + (43, "сорок третій"), + (50, "п'ятдесятий"), + (54, "п'ятдесят четвертий"), + (60, "шістдесятий"), + (65, "шістдесят п'ятий"), + (70, "сімдесятий"), + (76, "сімдесят шостий"), + (80, "вісімдесятий"), + (87, "вісімдесят сьомий"), + (90, "дев'яностий"), + (98, "дев'яносто восьмий"), + (100, "сотий"), + (101, "сто перший"), + (199, "сто дев'яносто дев'ятий"), + (200, "двохсотий"), + (203, "двісті третій"), + (300, "трьохсотий"), + (356, "триста п'ятдесят шостий"), + (400, "чотирьохсотий"), + (434, "чотириста тридцять четвертий"), + (500, "п'ятисотий"), + (578, "п'ятсот сімдесят восьмий"), + (600, "шестисотий"), + (690, "шістсот дев'яностий"), + (700, "семисотий"), + (729, "сімсот двадцять дев'ятий"), + (800, "восьмисотий"), + (894, "вісімсот дев'яносто четвертий"), + (900, "дев'ятисотий"), + (999, "дев'ятсот дев'яносто дев'ятий"), + (1000, "тисячний"), + (1001, "одна тисяча перший"), + (2000, "двохтисячний"), + (2312, "дві тисячі триста дванадцятий"), + (12000, "дванадцятитисячний"), + (25000, "двадцятип'ятитисячний"), + (213000, "двохсоттринадцятитисячний"), + (256000, "двохсотп'ятдесятишеститисячний"), + (260000, "двохсотшістдесятитисячний"), + (1000000, "мільйонний"), + (589000000, "п'ятсотвісімдесятидев'ятимільйонний"), + (1000000000, "мільярдний"), + (1234567890, "один мільярд двісті тридцять чотири мільйони " + "п'ятсот шістдесят сім тисяч вісімсот дев'яностий"), + (1000000000000, "трильйонний"), + (1000000000000000, "квадрильйонний"), + (1000000000000000000, "квінтильйонний"), + (1000000000000000000000, "секстильйонний"), + (1000000000000000000000000, "септильйонний"), + (1000000000000000000000000000, "октильйонний"), + (1000000000000000000000000000000, "нонільйонний"), + (956000000000000000000000000000000, + "дев'ятсотп'ятдесятишестинонільйонний"), +) + +TEST_CASES_TO_CURRENCY_AED = ( + (0.00, "нуль дирхамів, нуль філсів"), + (1.00, "один дирхам, нуль філсів"), + (2.00, "два дирхами, нуль філсів"), + (5.00, "п'ять дирхамів, нуль філсів"), + (11.00, "одинадцять дирхамів, нуль філсів"), + (16.01, "шістнадцять дирхамів, один філс"), + (21.00, "двадцять один дирхам, нуль філсів"), + (37.73, "тридцять сім дирхамів, сімдесят три філси"), + (81.25, "вісімдесят один дирхам, двадцять п'ять філсів"), + (100.00, "сто дирхамів, нуль філсів"), + (101.11, "сто один дирхам, одинадцять філсів"), + (10222, "сто два дирхами, двадцять два філси"), + +) + +TEST_CASES_TO_CURRENCY_AFN = ( + (0.00, "нуль афгані, нуль пулів"), + (1.00, "один афгані, нуль пулів"), + (2.00, "два афгані, нуль пулів"), + (5.00, "п'ять афгані, нуль пулів"), + (11.00, "одинадцять афгані, нуль пулів"), + (16.01, "шістнадцять афгані, один пул"), + (21.00, "двадцять один афгані, нуль пулів"), + (37.73, "тридцять сім афгані, сімдесят три пули"), + (81.25, "вісімдесят один афгані, двадцять п'ять пулів"), + (100.00, "сто афгані, нуль пулів"), + (101.11, "сто один афгані, одинадцять пулів"), + (10222, "сто два афгані, двадцять два пули"), +) + +TEST_CASES_TO_CURRENCY_ALL = ( + (0.00, "нуль леків, нуль кіндарок"), + (1.00, "один лек, нуль кіндарок"), + (2.00, "два леки, нуль кіндарок"), + (5.00, "п'ять леків, нуль кіндарок"), + (11.00, "одинадцять леків, нуль кіндарок"), + (16.01, "шістнадцять леків, одна кіндарка"), + (21.00, "двадцять один лек, нуль кіндарок"), + (37.73, "тридцять сім леків, сімдесят три кіндарки"), + (81.25, "вісімдесят один лек, двадцять п'ять кіндарок"), + (100.00, "сто леків, нуль кіндарок"), + (101.11, "сто один лек, одинадцять кіндарок"), + (10222, "сто два леки, двадцять дві кіндарки"), +) + +TEST_CASES_TO_CURRENCY_AMD = ( + (0.00, "нуль драмів, нуль лум"), + (1.00, "один драм, нуль лум"), + (2.00, "два драми, нуль лум"), + (5.00, "п'ять драмів, нуль лум"), + (11.00, "одинадцять драмів, нуль лум"), + (16.01, "шістнадцять драмів, один лум"), + (21.00, "двадцять один драм, нуль лум"), + (37.73, "тридцять сім драмів, сімдесят три лум"), + (81.25, "вісімдесят один драм, двадцять п'ять лум"), + (100.00, "сто драмів, нуль лум"), + (101.11, "сто один драм, одинадцять лум"), + (10222, "сто два драми, двадцять два лум"), +) + +TEST_CASES_TO_CURRENCY_ANG = ( + (0.00, "нуль гульденів, нуль центів"), + (1.00, "один гульден, нуль центів"), + (2.00, "два гульдени, нуль центів"), + (5.00, "п'ять гульденів, нуль центів"), + (11.00, "одинадцять гульденів, нуль центів"), + (16.01, "шістнадцять гульденів, один цент"), + (21.00, "двадцять один гульден, нуль центів"), + (37.73, "тридцять сім гульденів, сімдесят три центи"), + (81.25, "вісімдесят один гульден, двадцять п'ять центів"), + (100.00, "сто гульденів, нуль центів"), + (101.11, "сто один гульден, одинадцять центів"), + (10222, "сто два гульдени, двадцять два центи"), +) +# +TEST_CASES_TO_CURRENCY_AOA = ( + (0.00, "нуль кванз, нуль сентимо"), + (1.00, "одна кванза, нуль сентимо"), + (2.00, "дві кванзи, нуль сентимо"), + (5.00, "п'ять кванз, нуль сентимо"), + (11.00, "одинадцять кванз, нуль сентимо"), + (16.01, "шістнадцять кванз, один сентимо"), + (21.00, "двадцять одна кванза, нуль сентимо"), + (37.73, "тридцять сім кванз, сімдесят три сентимо"), + (81.25, "вісімдесят одна кванза, двадцять п'ять сентимо"), + (100.00, "сто кванз, нуль сентимо"), + (101.11, "сто одна кванза, одинадцять сентимо"), + (10222, "сто дві кванзи, двадцять два сентимо"), +) +# +TEST_CASES_TO_CURRENCY_ARS = ( + (0.00, "нуль песо, нуль сентаво"), + (1.00, "один песо, нуль сентаво"), + (2.00, "два песо, нуль сентаво"), + (5.00, "п'ять песо, нуль сентаво"), + (11.00, "одинадцять песо, нуль сентаво"), + (16.01, "шістнадцять песо, один сентаво"), + (21.00, "двадцять один песо, нуль сентаво"), + (37.73, "тридцять сім песо, сімдесят три сентаво"), + (81.25, "вісімдесят один песо, двадцять п'ять сентаво"), + (100.00, "сто песо, нуль сентаво"), + (101.11, "сто один песо, одинадцять сентаво"), + (10222, "сто два песо, двадцять два сентаво"), +) +# +TEST_CASES_TO_CURRENCY_AUD = ( + (0.00, "нуль доларів, нуль центів"), + (1.00, "один долар, нуль центів"), + (2.00, "два долари, нуль центів"), + (5.00, "п'ять доларів, нуль центів"), + (11.00, "одинадцять доларів, нуль центів"), + (16.01, "шістнадцять доларів, один цент"), + (21.00, "двадцять один долар, нуль центів"), + (37.73, "тридцять сім доларів, сімдесят три центи"), + (81.25, "вісімдесят один долар, двадцять п'ять центів"), + (100.00, "сто доларів, нуль центів"), + (101.11, "сто один долар, одинадцять центів"), + (10222, "сто два долари, двадцять два центи"), +) +# +TEST_CASES_TO_CURRENCY_AWG = ( + (0.00, "нуль флоринів, нуль центів"), + (1.00, "один флорин, нуль центів"), + (2.00, "два флорини, нуль центів"), + (5.00, "п'ять флоринів, нуль центів"), + (11.00, "одинадцять флоринів, нуль центів"), + (16.01, "шістнадцять флоринів, один цент"), + (21.00, "двадцять один флорин, нуль центів"), + (37.73, "тридцять сім флоринів, сімдесят три центи"), + (81.25, "вісімдесят один флорин, двадцять п'ять центів"), + (100.00, "сто флоринів, нуль центів"), + (101.11, "сто один флорин, одинадцять центів"), + (10222, "сто два флорини, двадцять два центи"), +) +# +TEST_CASES_TO_CURRENCY_AZN = ( + (0.00, "нуль манатів, нуль гяпіків"), + (1.00, "один манат, нуль гяпіків"), + (2.00, "два манати, нуль гяпіків"), + (5.00, "п'ять манатів, нуль гяпіків"), + (11.00, "одинадцять манатів, нуль гяпіків"), + (16.01, "шістнадцять манатів, один гяпік"), + (21.00, "двадцять один манат, нуль гяпіків"), + (37.73, "тридцять сім манатів, сімдесят три гяпіки"), + (81.25, "вісімдесят один манат, двадцять п'ять гяпіків"), + (100.00, "сто манатів, нуль гяпіків"), + (101.11, "сто один манат, одинадцять гяпіків"), + (10222, "сто два манати, двадцять два гяпіки"), +) +# +TEST_CASES_TO_CURRENCY_BAM = ( + (0.00, "нуль марок, нуль фенінгів"), + (1.00, "одна марка, нуль фенінгів"), + (2.00, "дві марки, нуль фенінгів"), + (5.00, "п'ять марок, нуль фенінгів"), + (11.00, "одинадцять марок, нуль фенінгів"), + (16.01, "шістнадцять марок, один фенінг"), + (21.00, "двадцять одна марка, нуль фенінгів"), + (37.73, "тридцять сім марок, сімдесят три фенінги"), + (81.25, "вісімдесят одна марка, двадцять п'ять фенінгів"), + (100.00, "сто марок, нуль фенінгів"), + (101.11, "сто одна марка, одинадцять фенінгів"), + (10222, "сто дві марки, двадцять два фенінги"), +) +# +TEST_CASES_TO_CURRENCY_BBD = ( + (0.00, "нуль доларів, нуль центів"), + (1.00, "один долар, нуль центів"), + (2.00, "два долари, нуль центів"), + (5.00, "п'ять доларів, нуль центів"), + (11.00, "одинадцять доларів, нуль центів"), + (16.01, "шістнадцять доларів, один цент"), + (21.00, "двадцять один долар, нуль центів"), + (37.73, "тридцять сім доларів, сімдесят три центи"), + (81.25, "вісімдесят один долар, двадцять п'ять центів"), + (100.00, "сто доларів, нуль центів"), + (101.11, "сто один долар, одинадцять центів"), + (10222, "сто два долари, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_BDT = ( + (0.00, "нуль так, нуль пойш"), + (1.00, "одна така, нуль пойш"), + (2.00, "дві таки, нуль пойш"), + (5.00, "п'ять так, нуль пойш"), + (11.00, "одинадцять так, нуль пойш"), + (16.01, "шістнадцять так, одна пойша"), + (21.00, "двадцять одна така, нуль пойш"), + (37.73, "тридцять сім так, сімдесят три пойші"), + (81.25, "вісімдесят одна така, двадцять п'ять пойш"), + (100.00, "сто так, нуль пойш"), + (101.11, "сто одна така, одинадцять пойш"), + (10222, "сто дві таки, двадцять дві пойші"), +) + +TEST_CASES_TO_CURRENCY_BGN = ( + (0.00, "нуль левів, нуль стотинок"), + (1.00, "один лев, нуль стотинок"), + (2.00, "два леви, нуль стотинок"), + (5.00, "п'ять левів, нуль стотинок"), + (11.00, "одинадцять левів, нуль стотинок"), + (16.01, "шістнадцять левів, одна стотинка"), + (21.00, "двадцять один лев, нуль стотинок"), + (37.73, "тридцять сім левів, сімдесят три стотинки"), + (81.25, "вісімдесят один лев, двадцять п'ять стотинок"), + (100.00, "сто левів, нуль стотинок"), + (101.11, "сто один лев, одинадцять стотинок"), + (10222, "сто два леви, двадцять дві стотинки"), +) + +TEST_CASES_TO_CURRENCY_BHD = ( + (0.00, "нуль динарів, нуль філсів"), + (1.00, "один динар, нуль філсів"), + (2.00, "два динари, нуль філсів"), + (5.00, "п'ять динарів, нуль філсів"), + (11.00, "одинадцять динарів, нуль філсів"), + (16.01, "шістнадцять динарів, один філс"), + (21.00, "двадцять один динар, нуль філсів"), + (37.73, "тридцять сім динарів, сімдесят три філси"), + (81.25, "вісімдесят один динар, двадцять п'ять філсів"), + (100.00, "сто динарів, нуль філсів"), + (101.11, "сто один динар, одинадцять філсів"), + (10222, "сто два динари, двадцять два філси"), +) + +TEST_CASES_TO_CURRENCY_BIF = ( + (0.00, "нуль франків, нуль сантимів"), + (1.00, "один франк, нуль сантимів"), + (2.00, "два франки, нуль сантимів"), + (5.00, "п'ять франків, нуль сантимів"), + (11.00, "одинадцять франків, нуль сантимів"), + (16.01, "шістнадцять франків, один сантим"), + (21.00, "двадцять один франк, нуль сантимів"), + (37.73, "тридцять сім франків, сімдесят три сантими"), + (81.25, "вісімдесят один франк, двадцять п'ять сантимів"), + (100.00, "сто франків, нуль сантимів"), + (101.11, "сто один франк, одинадцять сантимів"), + (10222, "сто два франки, двадцять два сантими"), +) + +TEST_CASES_TO_CURRENCY_BMD = ( + (0.00, "нуль доларів, нуль центів"), + (1.00, "один долар, нуль центів"), + (2.00, "два долари, нуль центів"), + (5.00, "п'ять доларів, нуль центів"), + (11.00, "одинадцять доларів, нуль центів"), + (16.01, "шістнадцять доларів, один цент"), + (21.00, "двадцять один долар, нуль центів"), + (37.73, "тридцять сім доларів, сімдесят три центи"), + (81.25, "вісімдесят один долар, двадцять п'ять центів"), + (100.00, "сто доларів, нуль центів"), + (101.11, "сто один долар, одинадцять центів"), + (10222, "сто два долари, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_BND = ( + (0.00, "нуль доларів, нуль центів"), + (1.00, "один долар, нуль центів"), + (2.00, "два долари, нуль центів"), + (5.00, "п'ять доларів, нуль центів"), + (11.00, "одинадцять доларів, нуль центів"), + (16.01, "шістнадцять доларів, один цент"), + (21.00, "двадцять один долар, нуль центів"), + (37.73, "тридцять сім доларів, сімдесят три центи"), + (81.25, "вісімдесят один долар, двадцять п'ять центів"), + (100.00, "сто доларів, нуль центів"), + (101.11, "сто один долар, одинадцять центів"), + (10222, "сто два долари, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_BOB = ( + (0.00, "нуль болівіано, нуль сентаво"), + (1.00, "один болівіано, нуль сентаво"), + (2.00, "два болівіано, нуль сентаво"), + (5.00, "п'ять болівіано, нуль сентаво"), + (11.00, "одинадцять болівіано, нуль сентаво"), + (16.01, "шістнадцять болівіано, один сентаво"), + (21.00, "двадцять один болівіано, нуль сентаво"), + (37.73, "тридцять сім болівіано, сімдесят три сентаво"), + (81.25, "вісімдесят один болівіано, двадцять п'ять сентаво"), + (100.00, "сто болівіано, нуль сентаво"), + (101.11, "сто один болівіано, одинадцять сентаво"), + (10222, "сто два болівіано, двадцять два сентаво"), +) + +TEST_CASES_TO_CURRENCY_BRL = ( + (0.00, "нуль реалів, нуль сентаво"), + (1.00, "один реал, нуль сентаво"), + (2.00, "два реали, нуль сентаво"), + (5.00, "п'ять реалів, нуль сентаво"), + (11.00, "одинадцять реалів, нуль сентаво"), + (16.01, "шістнадцять реалів, один сентаво"), + (21.00, "двадцять один реал, нуль сентаво"), + (37.73, "тридцять сім реалів, сімдесят три сентаво"), + (81.25, "вісімдесят один реал, двадцять п'ять сентаво"), + (100.00, "сто реалів, нуль сентаво"), + (101.11, "сто один реал, одинадцять сентаво"), + (10222, "сто два реали, двадцять два сентаво"), +) + +TEST_CASES_TO_CURRENCY_BSD = ( + (0.00, "нуль доларів, нуль центів"), + (1.00, "один долар, нуль центів"), + (2.00, "два долари, нуль центів"), + (5.00, "п'ять доларів, нуль центів"), + (11.00, "одинадцять доларів, нуль центів"), + (16.01, "шістнадцять доларів, один цент"), + (21.00, "двадцять один долар, нуль центів"), + (37.73, "тридцять сім доларів, сімдесят три центи"), + (81.25, "вісімдесят один долар, двадцять п'ять центів"), + (100.00, "сто доларів, нуль центів"), + (101.11, "сто один долар, одинадцять центів"), + (10222, "сто два долари, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_BTN = ( + (0.00, "нуль нгултрумів, нуль четрумів"), + (1.00, "один нгултрум, нуль четрумів"), + (2.00, "два нгултруми, нуль четрумів"), + (5.00, "п'ять нгултрумів, нуль четрумів"), + (11.00, "одинадцять нгултрумів, нуль четрумів"), + (16.01, "шістнадцять нгултрумів, один четрум"), + (21.00, "двадцять один нгултрум, нуль четрумів"), + (37.73, "тридцять сім нгултрумів, сімдесят три четруми"), + (81.25, "вісімдесят один нгултрум, двадцять п'ять четрумів"), + (100.00, "сто нгултрумів, нуль четрумів"), + (101.11, "сто один нгултрум, одинадцять четрумів"), + (10222, "сто два нгултруми, двадцять два четруми"), +) + +TEST_CASES_TO_CURRENCY_BWP = ( + (0.00, "нуль пул, нуль тхебе"), + (1.00, "одна пула, нуль тхебе"), + (2.00, "дві пули, нуль тхебе"), + (5.00, "п'ять пул, нуль тхебе"), + (11.00, "одинадцять пул, нуль тхебе"), + (16.01, "шістнадцять пул, один тхебе"), + (21.00, "двадцять одна пула, нуль тхебе"), + (37.73, "тридцять сім пул, сімдесят три тхебе"), + (81.25, "вісімдесят одна пула, двадцять п'ять тхебе"), + (100.00, "сто пул, нуль тхебе"), + (101.11, "сто одна пула, одинадцять тхебе"), + (10222, "сто дві пули, двадцять два тхебе"), +) + +TEST_CASES_TO_CURRENCY_BYN = ( + (0.00, "нуль рублів, нуль копійок"), + (1.00, "один рубель, нуль копійок"), + (2.00, "два рублі, нуль копійок"), + (5.00, "п'ять рублів, нуль копійок"), + (11.00, "одинадцять рублів, нуль копійок"), + (16.01, "шістнадцять рублів, одна копійка"), + (21.00, "двадцять один рубель, нуль копійок"), + (37.73, "тридцять сім рублів, сімдесят три копійки"), + (81.25, "вісімдесят один рубель, двадцять п'ять копійок"), + (100.00, "сто рублів, нуль копійок"), + (101.11, "сто один рубель, одинадцять копійок"), + (10222, "сто два рублі, двадцять дві копійки"), +) + +TEST_CASES_TO_CURRENCY_BZD = ( + (0.00, "нуль доларів, нуль центів"), + (1.00, "один долар, нуль центів"), + (2.00, "два долари, нуль центів"), + (5.00, "п'ять доларів, нуль центів"), + (11.00, "одинадцять доларів, нуль центів"), + (16.01, "шістнадцять доларів, один цент"), + (21.00, "двадцять один долар, нуль центів"), + (37.73, "тридцять сім доларів, сімдесят три центи"), + (81.25, "вісімдесят один долар, двадцять п'ять центів"), + (100.00, "сто доларів, нуль центів"), + (101.11, "сто один долар, одинадцять центів"), + (10222, "сто два долари, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_CAD = ( + (0.00, "нуль доларів, нуль центів"), + (1.00, "один долар, нуль центів"), + (2.00, "два долари, нуль центів"), + (5.00, "п'ять доларів, нуль центів"), + (11.00, "одинадцять доларів, нуль центів"), + (16.01, "шістнадцять доларів, один цент"), + (21.00, "двадцять один долар, нуль центів"), + (37.73, "тридцять сім доларів, сімдесят три центи"), + (81.25, "вісімдесят один долар, двадцять п'ять центів"), + (100.00, "сто доларів, нуль центів"), + (101.11, "сто один долар, одинадцять центів"), + (10222, "сто два долари, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_CDF = ( + (0.00, "нуль франків, нуль сантимів"), + (1.00, "один франк, нуль сантимів"), + (2.00, "два франки, нуль сантимів"), + (5.00, "п'ять франків, нуль сантимів"), + (11.00, "одинадцять франків, нуль сантимів"), + (16.01, "шістнадцять франків, один сантим"), + (21.00, "двадцять один франк, нуль сантимів"), + (37.73, "тридцять сім франків, сімдесят три сантими"), + (81.25, "вісімдесят один франк, двадцять п'ять сантимів"), + (100.00, "сто франків, нуль сантимів"), + (101.11, "сто один франк, одинадцять сантимів"), + (10222, "сто два франки, двадцять два сантими"), +) + +TEST_CASES_TO_CURRENCY_CHF = ( + (0.00, "нуль франків, нуль сантимів"), + (1.00, "один франк, нуль сантимів"), + (2.00, "два франки, нуль сантимів"), + (5.00, "п'ять франків, нуль сантимів"), + (11.00, "одинадцять франків, нуль сантимів"), + (16.01, "шістнадцять франків, один сантим"), + (21.00, "двадцять один франк, нуль сантимів"), + (37.73, "тридцять сім франків, сімдесят три сантими"), + (81.25, "вісімдесят один франк, двадцять п'ять сантимів"), + (100.00, "сто франків, нуль сантимів"), + (101.11, "сто один франк, одинадцять сантимів"), + (10222, "сто два франки, двадцять два сантими"), +) + +TEST_CASES_TO_CURRENCY_CLP = ( + (0.00, "нуль песо, нуль сентаво"), + (1.00, "один песо, нуль сентаво"), + (2.00, "два песо, нуль сентаво"), + (5.00, "п'ять песо, нуль сентаво"), + (11.00, "одинадцять песо, нуль сентаво"), + (16.01, "шістнадцять песо, один сентаво"), + (21.00, "двадцять один песо, нуль сентаво"), + (37.73, "тридцять сім песо, сімдесят три сентаво"), + (81.25, "вісімдесят один песо, двадцять п'ять сентаво"), + (100.00, "сто песо, нуль сентаво"), + (101.11, "сто один песо, одинадцять сентаво"), + (10222, "сто два песо, двадцять два сентаво"), +) + +TEST_CASES_TO_CURRENCY_CNY = ( + (0.00, "нуль юанів, нуль финів"), + (1.00, "один юань, нуль финів"), + (2.00, "два юані, нуль финів"), + (5.00, "п'ять юанів, нуль финів"), + (11.00, "одинадцять юанів, нуль финів"), + (16.01, "шістнадцять юанів, один финь"), + (21.00, "двадцять один юань, нуль финів"), + (37.73, "тридцять сім юанів, сімдесят три фині"), + (81.25, "вісімдесят один юань, двадцять п'ять финів"), + (100.00, "сто юанів, нуль финів"), + (101.11, "сто один юань, одинадцять финів"), + (10222, "сто два юані, двадцять два фині"), +) + +TEST_CASES_TO_CURRENCY_COP = ( + (0.00, "нуль песо, нуль сентаво"), + (1.00, "один песо, нуль сентаво"), + (2.00, "два песо, нуль сентаво"), + (5.00, "п'ять песо, нуль сентаво"), + (11.00, "одинадцять песо, нуль сентаво"), + (16.01, "шістнадцять песо, один сентаво"), + (21.00, "двадцять один песо, нуль сентаво"), + (37.73, "тридцять сім песо, сімдесят три сентаво"), + (81.25, "вісімдесят один песо, двадцять п'ять сентаво"), + (100.00, "сто песо, нуль сентаво"), + (101.11, "сто один песо, одинадцять сентаво"), + (10222, "сто два песо, двадцять два сентаво"), +) + +TEST_CASES_TO_CURRENCY_CRC = ( + (0.00, "нуль колонів, нуль сентімо"), + (1.00, "один колон, нуль сентімо"), + (2.00, "два колони, нуль сентімо"), + (5.00, "п'ять колонів, нуль сентімо"), + (11.00, "одинадцять колонів, нуль сентімо"), + (16.01, "шістнадцять колонів, один сентімо"), + (21.00, "двадцять один колон, нуль сентімо"), + (37.73, "тридцять сім колонів, сімдесят три сентімо"), + (81.25, "вісімдесят один колон, двадцять п'ять сентімо"), + (100.00, "сто колонів, нуль сентімо"), + (101.11, "сто один колон, одинадцять сентімо"), + (10222, "сто два колони, двадцять два сентімо"), +) + +TEST_CASES_TO_CURRENCY_CUC = ( + (0.00, "нуль песо, нуль сентаво"), + (1.00, "один песо, нуль сентаво"), + (2.00, "два песо, нуль сентаво"), + (5.00, "п'ять песо, нуль сентаво"), + (11.00, "одинадцять песо, нуль сентаво"), + (16.01, "шістнадцять песо, один сентаво"), + (21.00, "двадцять один песо, нуль сентаво"), + (37.73, "тридцять сім песо, сімдесят три сентаво"), + (81.25, "вісімдесят один песо, двадцять п'ять сентаво"), + (100.00, "сто песо, нуль сентаво"), + (101.11, "сто один песо, одинадцять сентаво"), + (10222, "сто два песо, двадцять два сентаво"), +) + +TEST_CASES_TO_CURRENCY_CUP = ( + (0.00, "нуль песо, нуль сентаво"), + (1.00, "один песо, нуль сентаво"), + (2.00, "два песо, нуль сентаво"), + (5.00, "п'ять песо, нуль сентаво"), + (11.00, "одинадцять песо, нуль сентаво"), + (16.01, "шістнадцять песо, один сентаво"), + (21.00, "двадцять один песо, нуль сентаво"), + (37.73, "тридцять сім песо, сімдесят три сентаво"), + (81.25, "вісімдесят один песо, двадцять п'ять сентаво"), + (100.00, "сто песо, нуль сентаво"), + (101.11, "сто один песо, одинадцять сентаво"), + (10222, "сто два песо, двадцять два сентаво"), +) + +TEST_CASES_TO_CURRENCY_CVE = ( + (0.00, "нуль ескудо, нуль сентаво"), + (1.00, "один ескудо, нуль сентаво"), + (2.00, "два ескудо, нуль сентаво"), + (5.00, "п'ять ескудо, нуль сентаво"), + (11.00, "одинадцять ескудо, нуль сентаво"), + (16.01, "шістнадцять ескудо, один сентаво"), + (21.00, "двадцять один ескудо, нуль сентаво"), + (37.73, "тридцять сім ескудо, сімдесят три сентаво"), + (81.25, "вісімдесят один ескудо, двадцять п'ять сентаво"), + (100.00, "сто ескудо, нуль сентаво"), + (101.11, "сто один ескудо, одинадцять сентаво"), + (10222, "сто два ескудо, двадцять два сентаво"), +) + +TEST_CASES_TO_CURRENCY_CZK = ( + (0.00, "нуль крон, нуль гелерів"), + (1.00, "одна крона, нуль гелерів"), + (2.00, "дві крони, нуль гелерів"), + (5.00, "п'ять крон, нуль гелерів"), + (11.00, "одинадцять крон, нуль гелерів"), + (16.01, "шістнадцять крон, один гелер"), + (21.00, "двадцять одна крона, нуль гелерів"), + (37.73, "тридцять сім крон, сімдесят три гелери"), + (81.25, "вісімдесят одна крона, двадцять п'ять гелерів"), + (100.00, "сто крон, нуль гелерів"), + (101.11, "сто одна крона, одинадцять гелерів"), + (10222, "сто дві крони, двадцять два гелери"), +) + +TEST_CASES_TO_CURRENCY_DJF = ( + (0.00, "нуль франків, нуль сантимів"), + (1.00, "один франк, нуль сантимів"), + (2.00, "два франки, нуль сантимів"), + (5.00, "п'ять франків, нуль сантимів"), + (11.00, "одинадцять франків, нуль сантимів"), + (16.01, "шістнадцять франків, один сантим"), + (21.00, "двадцять один франк, нуль сантимів"), + (37.73, "тридцять сім франків, сімдесят три сантими"), + (81.25, "вісімдесят один франк, двадцять п'ять сантимів"), + (100.00, "сто франків, нуль сантимів"), + (101.11, "сто один франк, одинадцять сантимів"), + (10222, "сто два франки, двадцять два сантими"), +) + +TEST_CASES_TO_CURRENCY_DKK = ( + (0.00, "нуль крон, нуль ере"), + (1.00, "одна крона, нуль ере"), + (2.00, "дві крони, нуль ере"), + (5.00, "п'ять крон, нуль ере"), + (11.00, "одинадцять крон, нуль ере"), + (16.01, "шістнадцять крон, один ере"), + (21.00, "двадцять одна крона, нуль ере"), + (37.73, "тридцять сім крон, сімдесят три ере"), + (81.25, "вісімдесят одна крона, двадцять п'ять ере"), + (100.00, "сто крон, нуль ере"), + (101.11, "сто одна крона, одинадцять ере"), + (10222, "сто дві крони, двадцять два ере"), +) + +TEST_CASES_TO_CURRENCY_DOP = ( + (0.00, "нуль песо, нуль сентаво"), + (1.00, "один песо, нуль сентаво"), + (2.00, "два песо, нуль сентаво"), + (5.00, "п'ять песо, нуль сентаво"), + (11.00, "одинадцять песо, нуль сентаво"), + (16.01, "шістнадцять песо, один сентаво"), + (21.00, "двадцять один песо, нуль сентаво"), + (37.73, "тридцять сім песо, сімдесят три сентаво"), + (81.25, "вісімдесят один песо, двадцять п'ять сентаво"), + (100.00, "сто песо, нуль сентаво"), + (101.11, "сто один песо, одинадцять сентаво"), + (10222, "сто два песо, двадцять два сентаво"), +) + +TEST_CASES_TO_CURRENCY_DZD = ( + (0.00, "нуль динарів, нуль сантимів"), + (1.00, "один динар, нуль сантимів"), + (2.00, "два динари, нуль сантимів"), + (5.00, "п'ять динарів, нуль сантимів"), + (11.00, "одинадцять динарів, нуль сантимів"), + (16.01, "шістнадцять динарів, один сантим"), + (21.00, "двадцять один динар, нуль сантимів"), + (37.73, "тридцять сім динарів, сімдесят три сантими"), + (81.25, "вісімдесят один динар, двадцять п'ять сантимів"), + (100.00, "сто динарів, нуль сантимів"), + (101.11, "сто один динар, одинадцять сантимів"), + (10222, "сто два динари, двадцять два сантими"), +) + +TEST_CASES_TO_CURRENCY_EGP = ( + (0.00, "нуль фунтів, нуль піастрів"), + (1.00, "один фунт, нуль піастрів"), + (2.00, "два фунти, нуль піастрів"), + (5.00, "п'ять фунтів, нуль піастрів"), + (11.00, "одинадцять фунтів, нуль піастрів"), + (16.01, "шістнадцять фунтів, один піастр"), + (21.00, "двадцять один фунт, нуль піастрів"), + (37.73, "тридцять сім фунтів, сімдесят три піастри"), + (81.25, "вісімдесят один фунт, двадцять п'ять піастрів"), + (100.00, "сто фунтів, нуль піастрів"), + (101.11, "сто один фунт, одинадцять піастрів"), + (10222, "сто два фунти, двадцять два піастри"), +) + +TEST_CASES_TO_CURRENCY_ERN = ( + (0.00, "нуль накф, нуль центів"), + (1.00, "одна накфа, нуль центів"), + (2.00, "дві накфи, нуль центів"), + (5.00, "п'ять накф, нуль центів"), + (11.00, "одинадцять накф, нуль центів"), + (16.01, "шістнадцять накф, один цент"), + (21.00, "двадцять одна накфа, нуль центів"), + (37.73, "тридцять сім накф, сімдесят три центи"), + (81.25, "вісімдесят одна накфа, двадцять п'ять центів"), + (100.00, "сто накф, нуль центів"), + (101.11, "сто одна накфа, одинадцять центів"), + (10222, "сто дві накфи, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_ETB = ( + (0.00, "нуль бирів, нуль центів"), + (1.00, "один бир, нуль центів"), + (2.00, "два бири, нуль центів"), + (5.00, "п'ять бирів, нуль центів"), + (11.00, "одинадцять бирів, нуль центів"), + (16.01, "шістнадцять бирів, один цент"), + (21.00, "двадцять один бир, нуль центів"), + (37.73, "тридцять сім бирів, сімдесят три центи"), + (81.25, "вісімдесят один бир, двадцять п'ять центів"), + (100.00, "сто бирів, нуль центів"), + (101.11, "сто один бир, одинадцять центів"), + (10222, "сто два бири, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_EUR = ( + (0.00, "нуль євро, нуль центів"), + (1.00, "один євро, нуль центів"), + (2.00, "два євро, нуль центів"), + (5.00, "п'ять євро, нуль центів"), + (11.00, "одинадцять євро, нуль центів"), + (16.01, "шістнадцять євро, один цент"), + (21.00, "двадцять один євро, нуль центів"), + (37.73, "тридцять сім євро, сімдесят три центи"), + (81.25, "вісімдесят один євро, двадцять п'ять центів"), + (100.00, "сто євро, нуль центів"), + (101.11, "сто один євро, одинадцять центів"), + (10222, "сто два євро, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_FJD = ( + (0.00, "нуль доларів, нуль центів"), + (1.00, "один долар, нуль центів"), + (2.00, "два долари, нуль центів"), + (5.00, "п'ять доларів, нуль центів"), + (11.00, "одинадцять доларів, нуль центів"), + (16.01, "шістнадцять доларів, один цент"), + (21.00, "двадцять один долар, нуль центів"), + (37.73, "тридцять сім доларів, сімдесят три центи"), + (81.25, "вісімдесят один долар, двадцять п'ять центів"), + (100.00, "сто доларів, нуль центів"), + (101.11, "сто один долар, одинадцять центів"), + (10222, "сто два долари, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_FKP = ( + (0.00, "нуль фунтів, нуль пенсів"), + (1.00, "один фунт, нуль пенсів"), + (2.00, "два фунти, нуль пенсів"), + (5.00, "п'ять фунтів, нуль пенсів"), + (11.00, "одинадцять фунтів, нуль пенсів"), + (16.01, "шістнадцять фунтів, один пенс"), + (21.00, "двадцять один фунт, нуль пенсів"), + (37.73, "тридцять сім фунтів, сімдесят три пенси"), + (81.25, "вісімдесят один фунт, двадцять п'ять пенсів"), + (100.00, "сто фунтів, нуль пенсів"), + (101.11, "сто один фунт, одинадцять пенсів"), + (10222, "сто два фунти, двадцять два пенси"), +) + +TEST_CASES_TO_CURRENCY_GBP = ( + (0.00, "нуль фунтів, нуль пенсів"), + (1.00, "один фунт, нуль пенсів"), + (2.00, "два фунти, нуль пенсів"), + (5.00, "п'ять фунтів, нуль пенсів"), + (11.00, "одинадцять фунтів, нуль пенсів"), + (16.01, "шістнадцять фунтів, один пенс"), + (21.00, "двадцять один фунт, нуль пенсів"), + (37.73, "тридцять сім фунтів, сімдесят три пенси"), + (81.25, "вісімдесят один фунт, двадцять п'ять пенсів"), + (100.00, "сто фунтів, нуль пенсів"), + (101.11, "сто один фунт, одинадцять пенсів"), + (10222, "сто два фунти, двадцять два пенси"), +) + +TEST_CASES_TO_CURRENCY_GEL = ( + (0.00, "нуль ларі, нуль тетрі"), + (1.00, "один ларі, нуль тетрі"), + (2.00, "два ларі, нуль тетрі"), + (5.00, "п'ять ларі, нуль тетрі"), + (11.00, "одинадцять ларі, нуль тетрі"), + (16.01, "шістнадцять ларі, один тетрі"), + (21.00, "двадцять один ларі, нуль тетрі"), + (37.73, "тридцять сім ларі, сімдесят три тетрі"), + (81.25, "вісімдесят один ларі, двадцять п'ять тетрі"), + (100.00, "сто ларі, нуль тетрі"), + (101.11, "сто один ларі, одинадцять тетрі"), + (10222, "сто два ларі, двадцять два тетрі"), +) + +TEST_CASES_TO_CURRENCY_GHS = ( + (0.00, "нуль седі, нуль песев"), + (1.00, "один седі, нуль песев"), + (2.00, "два седі, нуль песев"), + (5.00, "п'ять седі, нуль песев"), + (11.00, "одинадцять седі, нуль песев"), + (16.01, "шістнадцять седі, одна песева"), + (21.00, "двадцять один седі, нуль песев"), + (37.73, "тридцять сім седі, сімдесят три песеви"), + (81.25, "вісімдесят один седі, двадцять п'ять песев"), + (100.00, "сто седі, нуль песев"), + (101.11, "сто один седі, одинадцять песев"), + (10222, "сто два седі, двадцять дві песеви"), +) + +TEST_CASES_TO_CURRENCY_GIP = ( + (0.00, "нуль фунтів, нуль пенсів"), + (1.00, "один фунт, нуль пенсів"), + (2.00, "два фунти, нуль пенсів"), + (5.00, "п'ять фунтів, нуль пенсів"), + (11.00, "одинадцять фунтів, нуль пенсів"), + (16.01, "шістнадцять фунтів, один пенс"), + (21.00, "двадцять один фунт, нуль пенсів"), + (37.73, "тридцять сім фунтів, сімдесят три пенси"), + (81.25, "вісімдесят один фунт, двадцять п'ять пенсів"), + (100.00, "сто фунтів, нуль пенсів"), + (101.11, "сто один фунт, одинадцять пенсів"), + (10222, "сто два фунти, двадцять два пенси"), +) + +TEST_CASES_TO_CURRENCY_GMD = ( + (0.00, "нуль даласі, нуль бутутів"), + (1.00, "один даласі, нуль бутутів"), + (2.00, "два даласі, нуль бутутів"), + (5.00, "п'ять даласі, нуль бутутів"), + (11.00, "одинадцять даласі, нуль бутутів"), + (16.01, "шістнадцять даласі, один бутут"), + (21.00, "двадцять один даласі, нуль бутутів"), + (37.73, "тридцять сім даласі, сімдесят три бутути"), + (81.25, "вісімдесят один даласі, двадцять п'ять бутутів"), + (100.00, "сто даласі, нуль бутутів"), + (101.11, "сто один даласі, одинадцять бутутів"), + (10222, "сто два даласі, двадцять два бутути"), +) + +TEST_CASES_TO_CURRENCY_GNF = ( + (0.00, "нуль франків, нуль сантимів"), + (1.00, "один франк, нуль сантимів"), + (2.00, "два франки, нуль сантимів"), + (5.00, "п'ять франків, нуль сантимів"), + (11.00, "одинадцять франків, нуль сантимів"), + (16.01, "шістнадцять франків, один сантим"), + (21.00, "двадцять один франк, нуль сантимів"), + (37.73, "тридцять сім франків, сімдесят три сантими"), + (81.25, "вісімдесят один франк, двадцять п'ять сантимів"), + (100.00, "сто франків, нуль сантимів"), + (101.11, "сто один франк, одинадцять сантимів"), + (10222, "сто два франки, двадцять два сантими"), +) + +TEST_CASES_TO_CURRENCY_GTQ = ( + (0.00, "нуль кетсалів, нуль сентаво"), + (1.00, "один кетсаль, нуль сентаво"), + (2.00, "два кетсалі, нуль сентаво"), + (5.00, "п'ять кетсалів, нуль сентаво"), + (11.00, "одинадцять кетсалів, нуль сентаво"), + (16.01, "шістнадцять кетсалів, один сентаво"), + (21.00, "двадцять один кетсаль, нуль сентаво"), + (37.73, "тридцять сім кетсалів, сімдесят три сентаво"), + (81.25, "вісімдесят один кетсаль, двадцять п'ять сентаво"), + (100.00, "сто кетсалів, нуль сентаво"), + (101.11, "сто один кетсаль, одинадцять сентаво"), + (10222, "сто два кетсалі, двадцять два сентаво"), +) + +TEST_CASES_TO_CURRENCY_GYD = ( + (0.00, "нуль доларів, нуль центів"), + (1.00, "один долар, нуль центів"), + (2.00, "два долари, нуль центів"), + (5.00, "п'ять доларів, нуль центів"), + (11.00, "одинадцять доларів, нуль центів"), + (16.01, "шістнадцять доларів, один цент"), + (21.00, "двадцять один долар, нуль центів"), + (37.73, "тридцять сім доларів, сімдесят три центи"), + (81.25, "вісімдесят один долар, двадцять п'ять центів"), + (100.00, "сто доларів, нуль центів"), + (101.11, "сто один долар, одинадцять центів"), + (10222, "сто два долари, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_HKD = ( + (0.00, "нуль доларів, нуль центів"), + (1.00, "один долар, нуль центів"), + (2.00, "два долари, нуль центів"), + (5.00, "п'ять доларів, нуль центів"), + (11.00, "одинадцять доларів, нуль центів"), + (16.01, "шістнадцять доларів, один цент"), + (21.00, "двадцять один долар, нуль центів"), + (37.73, "тридцять сім доларів, сімдесят три центи"), + (81.25, "вісімдесят один долар, двадцять п'ять центів"), + (100.00, "сто доларів, нуль центів"), + (101.11, "сто один долар, одинадцять центів"), + (10222, "сто два долари, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_HNL = ( + (0.00, "нуль лемпір, нуль сентаво"), + (1.00, "одна лемпіра, нуль сентаво"), + (2.00, "дві лемпіри, нуль сентаво"), + (5.00, "п'ять лемпір, нуль сентаво"), + (11.00, "одинадцять лемпір, нуль сентаво"), + (16.01, "шістнадцять лемпір, один сентаво"), + (21.00, "двадцять одна лемпіра, нуль сентаво"), + (37.73, "тридцять сім лемпір, сімдесят три сентаво"), + (81.25, "вісімдесят одна лемпіра, двадцять п'ять сентаво"), + (100.00, "сто лемпір, нуль сентаво"), + (101.11, "сто одна лемпіра, одинадцять сентаво"), + (10222, "сто дві лемпіри, двадцять два сентаво"), +) + +TEST_CASES_TO_CURRENCY_HRK = ( + (0.00, "нуль кун, нуль ліп"), + (1.00, "одна куна, нуль ліп"), + (2.00, "дві куни, нуль ліп"), + (5.00, "п'ять кун, нуль ліп"), + (11.00, "одинадцять кун, нуль ліп"), + (16.01, "шістнадцять кун, одна ліпа"), + (21.00, "двадцять одна куна, нуль ліп"), + (37.73, "тридцять сім кун, сімдесят три ліпи"), + (81.25, "вісімдесят одна куна, двадцять п'ять ліп"), + (100.00, "сто кун, нуль ліп"), + (101.11, "сто одна куна, одинадцять ліп"), + (10222, "сто дві куни, двадцять дві ліпи"), +) + +TEST_CASES_TO_CURRENCY_HTG = ( + (0.00, "нуль гурдів, нуль сантимів"), + (1.00, "один гурд, нуль сантимів"), + (2.00, "два гурди, нуль сантимів"), + (5.00, "п'ять гурдів, нуль сантимів"), + (11.00, "одинадцять гурдів, нуль сантимів"), + (16.01, "шістнадцять гурдів, один сантим"), + (21.00, "двадцять один гурд, нуль сантимів"), + (37.73, "тридцять сім гурдів, сімдесят три сантими"), + (81.25, "вісімдесят один гурд, двадцять п'ять сантимів"), + (100.00, "сто гурдів, нуль сантимів"), + (101.11, "сто один гурд, одинадцять сантимів"), + (10222, "сто два гурди, двадцять два сантими"), +) + +TEST_CASES_TO_CURRENCY_HUF = ( + (0.00, "нуль форинтів, нуль філлерів"), + (1.00, "один форинт, нуль філлерів"), + (2.00, "два форинти, нуль філлерів"), + (5.00, "п'ять форинтів, нуль філлерів"), + (11.00, "одинадцять форинтів, нуль філлерів"), + (16.01, "шістнадцять форинтів, один філлер"), + (21.00, "двадцять один форинт, нуль філлерів"), + (37.73, "тридцять сім форинтів, сімдесят три філлери"), + (81.25, "вісімдесят один форинт, двадцять п'ять філлерів"), + (100.00, "сто форинтів, нуль філлерів"), + (101.11, "сто один форинт, одинадцять філлерів"), + (10222, "сто два форинти, двадцять два філлери"), +) + +TEST_CASES_TO_CURRENCY_IDR = ( + (0.00, "нуль рупій, нуль центів"), + (1.00, "одна рупія, нуль центів"), + (2.00, "дві рупії, нуль центів"), + (5.00, "п'ять рупій, нуль центів"), + (11.00, "одинадцять рупій, нуль центів"), + (16.01, "шістнадцять рупій, один цент"), + (21.00, "двадцять одна рупія, нуль центів"), + (37.73, "тридцять сім рупій, сімдесят три центи"), + (81.25, "вісімдесят одна рупія, двадцять п'ять центів"), + (100.00, "сто рупій, нуль центів"), + (101.11, "сто одна рупія, одинадцять центів"), + (10222, "сто дві рупії, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_ILS = ( + (0.00, "нуль шекелів, нуль агор"), + (1.00, "один шекель, нуль агор"), + (2.00, "два шекелі, нуль агор"), + (5.00, "п'ять шекелів, нуль агор"), + (11.00, "одинадцять шекелів, нуль агор"), + (16.01, "шістнадцять шекелів, одна агора"), + (21.00, "двадцять один шекель, нуль агор"), + (37.73, "тридцять сім шекелів, сімдесят три агори"), + (81.25, "вісімдесят один шекель, двадцять п'ять агор"), + (100.00, "сто шекелів, нуль агор"), + (101.11, "сто один шекель, одинадцять агор"), + (10222, "сто два шекелі, двадцять дві агори"), +) + +TEST_CASES_TO_CURRENCY_INR = ( + (0.00, "нуль рупій, нуль пайс"), + (1.00, "одна рупія, нуль пайс"), + (2.00, "дві рупії, нуль пайс"), + (5.00, "п'ять рупій, нуль пайс"), + (11.00, "одинадцять рупій, нуль пайс"), + (16.01, "шістнадцять рупій, одна пайса"), + (21.00, "двадцять одна рупія, нуль пайс"), + (37.73, "тридцять сім рупій, сімдесят три пайси"), + (81.25, "вісімдесят одна рупія, двадцять п'ять пайс"), + (100.00, "сто рупій, нуль пайс"), + (101.11, "сто одна рупія, одинадцять пайс"), + (10222, "сто дві рупії, двадцять дві пайси"), +) + +TEST_CASES_TO_CURRENCY_IQD = ( + (0.00, "нуль динарів, нуль філсів"), + (1.00, "один динар, нуль філсів"), + (2.00, "два динари, нуль філсів"), + (5.00, "п'ять динарів, нуль філсів"), + (11.00, "одинадцять динарів, нуль філсів"), + (16.01, "шістнадцять динарів, один філс"), + (21.00, "двадцять один динар, нуль філсів"), + (37.73, "тридцять сім динарів, сімдесят три філси"), + (81.25, "вісімдесят один динар, двадцять п'ять філсів"), + (100.00, "сто динарів, нуль філсів"), + (101.11, "сто один динар, одинадцять філсів"), + (10222, "сто два динари, двадцять два філси"), +) + +TEST_CASES_TO_CURRENCY_IRR = ( + (0.00, "нуль ріалів, нуль динарів"), + (1.00, "один ріал, нуль динарів"), + (2.00, "два ріали, нуль динарів"), + (5.00, "п'ять ріалів, нуль динарів"), + (11.00, "одинадцять ріалів, нуль динарів"), + (16.01, "шістнадцять ріалів, один динар"), + (21.00, "двадцять один ріал, нуль динарів"), + (37.73, "тридцять сім ріалів, сімдесят три динари"), + (81.25, "вісімдесят один ріал, двадцять п'ять динарів"), + (100.00, "сто ріалів, нуль динарів"), + (101.11, "сто один ріал, одинадцять динарів"), + (10222, "сто два ріали, двадцять два динари"), +) + +TEST_CASES_TO_CURRENCY_ISK = ( + (0.00, "нуль крон, нуль ейре"), + (1.00, "одна крона, нуль ейре"), + (2.00, "дві крони, нуль ейре"), + (5.00, "п'ять крон, нуль ейре"), + (11.00, "одинадцять крон, нуль ейре"), + (16.01, "шістнадцять крон, один ейре"), + (21.00, "двадцять одна крона, нуль ейре"), + (37.73, "тридцять сім крон, сімдесят три ейре"), + (81.25, "вісімдесят одна крона, двадцять п'ять ейре"), + (100.00, "сто крон, нуль ейре"), + (101.11, "сто одна крона, одинадцять ейре"), + (10222, "сто дві крони, двадцять два ейре"), +) + +TEST_CASES_TO_CURRENCY_JMD = ( + (0.00, "нуль доларів, нуль центів"), + (1.00, "один долар, нуль центів"), + (2.00, "два долари, нуль центів"), + (5.00, "п'ять доларів, нуль центів"), + (11.00, "одинадцять доларів, нуль центів"), + (16.01, "шістнадцять доларів, один цент"), + (21.00, "двадцять один долар, нуль центів"), + (37.73, "тридцять сім доларів, сімдесят три центи"), + (81.25, "вісімдесят один долар, двадцять п'ять центів"), + (100.00, "сто доларів, нуль центів"), + (101.11, "сто один долар, одинадцять центів"), + (10222, "сто два долари, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_JOD = ( + (0.00, "нуль динарів, нуль філсів"), + (1.00, "один динар, нуль філсів"), + (2.00, "два динари, нуль філсів"), + (5.00, "п'ять динарів, нуль філсів"), + (11.00, "одинадцять динарів, нуль філсів"), + (16.01, "шістнадцять динарів, один філс"), + (21.00, "двадцять один динар, нуль філсів"), + (37.73, "тридцять сім динарів, сімдесят три філси"), + (81.25, "вісімдесят один динар, двадцять п'ять філсів"), + (100.00, "сто динарів, нуль філсів"), + (101.11, "сто один динар, одинадцять філсів"), + (10222, "сто два динари, двадцять два філси"), +) + +TEST_CASES_TO_CURRENCY_JPY = ( + (0.00, "нуль єн, нуль сен"), + (1.00, "одна єна, нуль сен"), + (2.00, "дві єни, нуль сен"), + (5.00, "п'ять єн, нуль сен"), + (11.00, "одинадцять єн, нуль сен"), + (16.01, "шістнадцять єн, один сен"), + (21.00, "двадцять одна єна, нуль сен"), + (37.73, "тридцять сім єн, сімдесят три сен"), + (81.25, "вісімдесят одна єна, двадцять п'ять сен"), + (100.00, "сто єн, нуль сен"), + (101.11, "сто одна єна, одинадцять сен"), + (10222, "сто дві єни, двадцять два сен"), +) + +TEST_CASES_TO_CURRENCY_KES = ( + (0.00, "нуль шилінгів, нуль центів"), + (1.00, "один шилінг, нуль центів"), + (2.00, "два шилінги, нуль центів"), + (5.00, "п'ять шилінгів, нуль центів"), + (11.00, "одинадцять шилінгів, нуль центів"), + (16.01, "шістнадцять шилінгів, один цент"), + (21.00, "двадцять один шилінг, нуль центів"), + (37.73, "тридцять сім шилінгів, сімдесят три центи"), + (81.25, "вісімдесят один шилінг, двадцять п'ять центів"), + (100.00, "сто шилінгів, нуль центів"), + (101.11, "сто один шилінг, одинадцять центів"), + (10222, "сто два шилінги, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_KGS = ( + (0.00, "нуль сомів, нуль тиїнів"), + (1.00, "один сом, нуль тиїнів"), + (2.00, "два соми, нуль тиїнів"), + (5.00, "п'ять сомів, нуль тиїнів"), + (11.00, "одинадцять сомів, нуль тиїнів"), + (16.01, "шістнадцять сомів, один тиїн"), + (21.00, "двадцять один сом, нуль тиїнів"), + (37.73, "тридцять сім сомів, сімдесят три тиїни"), + (81.25, "вісімдесят один сом, двадцять п'ять тиїнів"), + (100.00, "сто сомів, нуль тиїнів"), + (101.11, "сто один сом, одинадцять тиїнів"), + (10222, "сто два соми, двадцять два тиїни"), +) + +TEST_CASES_TO_CURRENCY_KHR = ( + (0.00, "нуль рієлів, нуль су"), + (1.00, "один рієль, нуль су"), + (2.00, "два рієлі, нуль су"), + (5.00, "п'ять рієлів, нуль су"), + (11.00, "одинадцять рієлів, нуль су"), + (16.01, "шістнадцять рієлів, один су"), + (21.00, "двадцять один рієль, нуль су"), + (37.73, "тридцять сім рієлів, сімдесят три су"), + (81.25, "вісімдесят один рієль, двадцять п'ять су"), + (100.00, "сто рієлів, нуль су"), + (101.11, "сто один рієль, одинадцять су"), + (10222, "сто два рієлі, двадцять два су"), +) + +TEST_CASES_TO_CURRENCY_KMF = ( + (0.00, "нуль франків, нуль сантимів"), + (1.00, "один франк, нуль сантимів"), + (2.00, "два франки, нуль сантимів"), + (5.00, "п'ять франків, нуль сантимів"), + (11.00, "одинадцять франків, нуль сантимів"), + (16.01, "шістнадцять франків, один сантим"), + (21.00, "двадцять один франк, нуль сантимів"), + (37.73, "тридцять сім франків, сімдесят три сантими"), + (81.25, "вісімдесят один франк, двадцять п'ять сантимів"), + (100.00, "сто франків, нуль сантимів"), + (101.11, "сто один франк, одинадцять сантимів"), + (10222, "сто два франки, двадцять два сантими"), +) + +TEST_CASES_TO_CURRENCY_KPW = ( + (0.00, "нуль вон, нуль чонів"), + (1.00, "одна вона, нуль чонів"), + (2.00, "дві вони, нуль чонів"), + (5.00, "п'ять вон, нуль чонів"), + (11.00, "одинадцять вон, нуль чонів"), + (16.01, "шістнадцять вон, один чон"), + (21.00, "двадцять одна вона, нуль чонів"), + (37.73, "тридцять сім вон, сімдесят три чони"), + (81.25, "вісімдесят одна вона, двадцять п'ять чонів"), + (100.00, "сто вон, нуль чонів"), + (101.11, "сто одна вона, одинадцять чонів"), + (10222, "сто дві вони, двадцять два чони"), +) + +TEST_CASES_TO_CURRENCY_KRW = ( + (0.00, "нуль вон, нуль джеонів"), + (1.00, "одна вона, нуль джеонів"), + (2.00, "дві вони, нуль джеонів"), + (5.00, "п'ять вон, нуль джеонів"), + (11.00, "одинадцять вон, нуль джеонів"), + (16.01, "шістнадцять вон, один джеон"), + (21.00, "двадцять одна вона, нуль джеонів"), + (37.73, "тридцять сім вон, сімдесят три джеони"), + (81.25, "вісімдесят одна вона, двадцять п'ять джеонів"), + (100.00, "сто вон, нуль джеонів"), + (101.11, "сто одна вона, одинадцять джеонів"), + (10222, "сто дві вони, двадцять два джеони"), +) + +TEST_CASES_TO_CURRENCY_KWD = ( + (0.00, "нуль динарів, нуль філсів"), + (1.00, "один динар, нуль філсів"), + (2.00, "два динари, нуль філсів"), + (5.00, "п'ять динарів, нуль філсів"), + (11.00, "одинадцять динарів, нуль філсів"), + (16.01, "шістнадцять динарів, один філс"), + (21.00, "двадцять один динар, нуль філсів"), + (37.73, "тридцять сім динарів, сімдесят три філси"), + (81.25, "вісімдесят один динар, двадцять п'ять філсів"), + (100.00, "сто динарів, нуль філсів"), + (101.11, "сто один динар, одинадцять філсів"), + (10222, "сто два динари, двадцять два філси"), +) + +TEST_CASES_TO_CURRENCY_KYD = ( + (0.00, "нуль доларів, нуль центів"), + (1.00, "один долар, нуль центів"), + (2.00, "два долари, нуль центів"), + (5.00, "п'ять доларів, нуль центів"), + (11.00, "одинадцять доларів, нуль центів"), + (16.01, "шістнадцять доларів, один цент"), + (21.00, "двадцять один долар, нуль центів"), + (37.73, "тридцять сім доларів, сімдесят три центи"), + (81.25, "вісімдесят один долар, двадцять п'ять центів"), + (100.00, "сто доларів, нуль центів"), + (101.11, "сто один долар, одинадцять центів"), + (10222, "сто два долари, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_KZT = ( + (0.00, "нуль теньге, нуль тиїнів"), + (1.00, "один теньге, нуль тиїнів"), + (2.00, "два теньге, нуль тиїнів"), + (5.00, "п'ять теньге, нуль тиїнів"), + (11.00, "одинадцять теньге, нуль тиїнів"), + (16.01, "шістнадцять теньге, один тиїн"), + (21.00, "двадцять один теньге, нуль тиїнів"), + (37.73, "тридцять сім теньге, сімдесят три тиїни"), + (81.25, "вісімдесят один теньге, двадцять п'ять тиїнів"), + (100.00, "сто теньге, нуль тиїнів"), + (101.11, "сто один теньге, одинадцять тиїнів"), + (10222, "сто два теньге, двадцять два тиїни"), +) + +TEST_CASES_TO_CURRENCY_LAK = ( + (0.00, "нуль кіпів, нуль атів"), + (1.00, "один кіп, нуль атів"), + (2.00, "два кіпи, нуль атів"), + (5.00, "п'ять кіпів, нуль атів"), + (11.00, "одинадцять кіпів, нуль атів"), + (16.01, "шістнадцять кіпів, один ат"), + (21.00, "двадцять один кіп, нуль атів"), + (37.73, "тридцять сім кіпів, сімдесят три ати"), + (81.25, "вісімдесят один кіп, двадцять п'ять атів"), + (100.00, "сто кіпів, нуль атів"), + (101.11, "сто один кіп, одинадцять атів"), + (10222, "сто два кіпи, двадцять два ати"), +) + +TEST_CASES_TO_CURRENCY_LBP = ( + (0.00, "нуль фунтів, нуль піастрів"), + (1.00, "один фунт, нуль піастрів"), + (2.00, "два фунти, нуль піастрів"), + (5.00, "п'ять фунтів, нуль піастрів"), + (11.00, "одинадцять фунтів, нуль піастрів"), + (16.01, "шістнадцять фунтів, один піастр"), + (21.00, "двадцять один фунт, нуль піастрів"), + (37.73, "тридцять сім фунтів, сімдесят три піастри"), + (81.25, "вісімдесят один фунт, двадцять п'ять піастрів"), + (100.00, "сто фунтів, нуль піастрів"), + (101.11, "сто один фунт, одинадцять піастрів"), + (10222, "сто два фунти, двадцять два піастри"), +) + +TEST_CASES_TO_CURRENCY_LKR = ( + (0.00, "нуль рупій, нуль центів"), + (1.00, "одна рупія, нуль центів"), + (2.00, "дві рупії, нуль центів"), + (5.00, "п'ять рупій, нуль центів"), + (11.00, "одинадцять рупій, нуль центів"), + (16.01, "шістнадцять рупій, один цент"), + (21.00, "двадцять одна рупія, нуль центів"), + (37.73, "тридцять сім рупій, сімдесят три центи"), + (81.25, "вісімдесят одна рупія, двадцять п'ять центів"), + (100.00, "сто рупій, нуль центів"), + (101.11, "сто одна рупія, одинадцять центів"), + (10222, "сто дві рупії, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_LRD = ( + (0.00, "нуль доларів, нуль центів"), + (1.00, "один долар, нуль центів"), + (2.00, "два долари, нуль центів"), + (5.00, "п'ять доларів, нуль центів"), + (11.00, "одинадцять доларів, нуль центів"), + (16.01, "шістнадцять доларів, один цент"), + (21.00, "двадцять один долар, нуль центів"), + (37.73, "тридцять сім доларів, сімдесят три центи"), + (81.25, "вісімдесят один долар, двадцять п'ять центів"), + (100.00, "сто доларів, нуль центів"), + (101.11, "сто один долар, одинадцять центів"), + (10222, "сто два долари, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_LSL = ( + (0.00, "нуль малоті, нуль лісенте"), + (1.00, "один лоті, нуль лісенте"), + (2.00, "два малоті, нуль лісенте"), + (5.00, "п'ять малоті, нуль лісенте"), + (11.00, "одинадцять малоті, нуль лісенте"), + (16.01, "шістнадцять малоті, один сенте"), + (21.00, "двадцять один лоті, нуль лісенте"), + (37.73, "тридцять сім малоті, сімдесят три лісенте"), + (81.25, "вісімдесят один лоті, двадцять п'ять лісенте"), + (100.00, "сто малоті, нуль лісенте"), + (101.11, "сто один лоті, одинадцять лісенте"), + (10222, "сто два малоті, двадцять два лісенте"), +) + +TEST_CASES_TO_CURRENCY_LYD = ( + (0.00, "нуль динарів, нуль дирхамів"), + (1.00, "один динар, нуль дирхамів"), + (2.00, "два динари, нуль дирхамів"), + (5.00, "п'ять динарів, нуль дирхамів"), + (11.00, "одинадцять динарів, нуль дирхамів"), + (16.01, "шістнадцять динарів, один дирхам"), + (21.00, "двадцять один динар, нуль дирхамів"), + (37.73, "тридцять сім динарів, сімдесят три дирхами"), + (81.25, "вісімдесят один динар, двадцять п'ять дирхамів"), + (100.00, "сто динарів, нуль дирхамів"), + (101.11, "сто один динар, одинадцять дирхамів"), + (10222, "сто два динари, двадцять два дирхами"), +) + +TEST_CASES_TO_CURRENCY_MAD = ( + (0.00, "нуль дирхамів, нуль сантимів"), + (1.00, "один дирхам, нуль сантимів"), + (2.00, "два дирхами, нуль сантимів"), + (5.00, "п'ять дирхамів, нуль сантимів"), + (11.00, "одинадцять дирхамів, нуль сантимів"), + (16.01, "шістнадцять дирхамів, один сантим"), + (21.00, "двадцять один дирхам, нуль сантимів"), + (37.73, "тридцять сім дирхамів, сімдесят три сантими"), + (81.25, "вісімдесят один дирхам, двадцять п'ять сантимів"), + (100.00, "сто дирхамів, нуль сантимів"), + (101.11, "сто один дирхам, одинадцять сантимів"), + (10222, "сто два дирхами, двадцять два сантими"), +) + +TEST_CASES_TO_CURRENCY_MDL = ( + (0.00, "нуль леї, нуль бані"), + (1.00, "один лей, нуль бані"), + (2.00, "два леї, нуль бані"), + (5.00, "п'ять леї, нуль бані"), + (11.00, "одинадцять леї, нуль бані"), + (16.01, "шістнадцять леї, один бан"), + (21.00, "двадцять один лей, нуль бані"), + (37.73, "тридцять сім леї, сімдесят три бані"), + (81.25, "вісімдесят один лей, двадцять п'ять бані"), + (100.00, "сто леї, нуль бані"), + (101.11, "сто один лей, одинадцять бані"), + (10222, "сто два леї, двадцять два бані"), +) + +TEST_CASES_TO_CURRENCY_MGA = ( + (0.00, "нуль аріарі, нуль іраймбіланья"), + (1.00, "один аріарі, нуль іраймбіланья"), + (2.00, "два аріарі, нуль іраймбіланья"), + (5.00, "п'ять аріарі, нуль іраймбіланья"), + (11.00, "одинадцять аріарі, нуль іраймбіланья"), + (16.01, "шістнадцять аріарі, один іраймбіланья"), + (21.00, "двадцять один аріарі, нуль іраймбіланья"), + (37.73, "тридцять сім аріарі, сімдесят три іраймбіланья"), + (81.25, "вісімдесят один аріарі, двадцять п'ять іраймбіланья"), + (100.00, "сто аріарі, нуль іраймбіланья"), + (101.11, "сто один аріарі, одинадцять іраймбіланья"), + (10222, "сто два аріарі, двадцять два іраймбіланья"), +) + +TEST_CASES_TO_CURRENCY_MKD = ( + (0.00, "нуль денарів, нуль дені"), + (1.00, "один денар, нуль дені"), + (2.00, "два денари, нуль дені"), + (5.00, "п'ять денарів, нуль дені"), + (11.00, "одинадцять денарів, нуль дені"), + (16.01, "шістнадцять денарів, один дені"), + (21.00, "двадцять один денар, нуль дені"), + (37.73, "тридцять сім денарів, сімдесят три дені"), + (81.25, "вісімдесят один денар, двадцять п'ять дені"), + (100.00, "сто денарів, нуль дені"), + (101.11, "сто один денар, одинадцять дені"), + (10222, "сто два денари, двадцять два дені"), +) + +TEST_CASES_TO_CURRENCY_MMK = ( + (0.00, "нуль к'ят, нуль п'я"), + (1.00, "один к'ят, нуль п'я"), + (2.00, "два к'ят, нуль п'я"), + (5.00, "п'ять к'ят, нуль п'я"), + (11.00, "одинадцять к'ят, нуль п'я"), + (16.01, "шістнадцять к'ят, один п'я"), + (21.00, "двадцять один к'ят, нуль п'я"), + (37.73, "тридцять сім к'ят, сімдесят три п'я"), + (81.25, "вісімдесят один к'ят, двадцять п'ять п'я"), + (100.00, "сто к'ят, нуль п'я"), + (101.11, "сто один к'ят, одинадцять п'я"), + (10222, "сто два к'ят, двадцять два п'я"), +) + +TEST_CASES_TO_CURRENCY_MNT = ( + (0.00, "нуль тугриків, нуль мунгу"), + (1.00, "один тугрик, нуль мунгу"), + (2.00, "два тугрики, нуль мунгу"), + (5.00, "п'ять тугриків, нуль мунгу"), + (11.00, "одинадцять тугриків, нуль мунгу"), + (16.01, "шістнадцять тугриків, один мунгу"), + (21.00, "двадцять один тугрик, нуль мунгу"), + (37.73, "тридцять сім тугриків, сімдесят три мунгу"), + (81.25, "вісімдесят один тугрик, двадцять п'ять мунгу"), + (100.00, "сто тугриків, нуль мунгу"), + (101.11, "сто один тугрик, одинадцять мунгу"), + (10222, "сто два тугрики, двадцять два мунгу"), +) + +TEST_CASES_TO_CURRENCY_MOP = ( + (0.00, "нуль патак, нуль аво"), + (1.00, "одна патака, нуль аво"), + (2.00, "дві патакі, нуль аво"), + (5.00, "п'ять патак, нуль аво"), + (11.00, "одинадцять патак, нуль аво"), + (16.01, "шістнадцять патак, один аво"), + (21.00, "двадцять одна патака, нуль аво"), + (37.73, "тридцять сім патак, сімдесят три аво"), + (81.25, "вісімдесят одна патака, двадцять п'ять аво"), + (100.00, "сто патак, нуль аво"), + (101.11, "сто одна патака, одинадцять аво"), + (10222, "сто дві патакі, двадцять два аво"), +) + +TEST_CASES_TO_CURRENCY_MRU = ( + (0.00, "нуль угій, нуль хумс"), + (1.00, "одна угія, нуль хумс"), + (2.00, "дві угії, нуль хумс"), + (5.00, "п'ять угій, нуль хумс"), + (11.00, "одинадцять угій, нуль хумс"), + (16.01, "шістнадцять угій, один хумс"), + (21.00, "двадцять одна угія, нуль хумс"), + (37.73, "тридцять сім угій, сімдесят три хумс"), + (81.25, "вісімдесят одна угія, двадцять п'ять хумс"), + (100.00, "сто угій, нуль хумс"), + (101.11, "сто одна угія, одинадцять хумс"), + (10222, "сто дві угії, двадцять два хумс"), +) + +TEST_CASES_TO_CURRENCY_MUR = ( + (0.00, "нуль рупій, нуль центів"), + (1.00, "одна рупія, нуль центів"), + (2.00, "дві рупії, нуль центів"), + (5.00, "п'ять рупій, нуль центів"), + (11.00, "одинадцять рупій, нуль центів"), + (16.01, "шістнадцять рупій, один цент"), + (21.00, "двадцять одна рупія, нуль центів"), + (37.73, "тридцять сім рупій, сімдесят три центи"), + (81.25, "вісімдесят одна рупія, двадцять п'ять центів"), + (100.00, "сто рупій, нуль центів"), + (101.11, "сто одна рупія, одинадцять центів"), + (10222, "сто дві рупії, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_MVR = ( + (0.00, "нуль руфій, нуль ларі"), + (1.00, "одна руфія, нуль ларі"), + (2.00, "дві руфії, нуль ларі"), + (5.00, "п'ять руфій, нуль ларі"), + (11.00, "одинадцять руфій, нуль ларі"), + (16.01, "шістнадцять руфій, один ларі"), + (21.00, "двадцять одна руфія, нуль ларі"), + (37.73, "тридцять сім руфій, сімдесят три ларі"), + (81.25, "вісімдесят одна руфія, двадцять п'ять ларі"), + (100.00, "сто руфій, нуль ларі"), + (101.11, "сто одна руфія, одинадцять ларі"), + (10222, "сто дві руфії, двадцять два ларі"), +) + +TEST_CASES_TO_CURRENCY_MWK = ( + (0.00, "нуль квач, нуль тамбала"), + (1.00, "одна квача, нуль тамбала"), + (2.00, "дві квачі, нуль тамбала"), + (5.00, "п'ять квач, нуль тамбала"), + (11.00, "одинадцять квач, нуль тамбала"), + (16.01, "шістнадцять квач, один тамбала"), + (21.00, "двадцять одна квача, нуль тамбала"), + (37.73, "тридцять сім квач, сімдесят три тамбала"), + (81.25, "вісімдесят одна квача, двадцять п'ять тамбала"), + (100.00, "сто квач, нуль тамбала"), + (101.11, "сто одна квача, одинадцять тамбала"), + (10222, "сто дві квачі, двадцять два тамбала"), +) + +TEST_CASES_TO_CURRENCY_MXN = ( + (0.00, "нуль песо, нуль сентаво"), + (1.00, "один песо, нуль сентаво"), + (2.00, "два песо, нуль сентаво"), + (5.00, "п'ять песо, нуль сентаво"), + (11.00, "одинадцять песо, нуль сентаво"), + (16.01, "шістнадцять песо, один сентаво"), + (21.00, "двадцять один песо, нуль сентаво"), + (37.73, "тридцять сім песо, сімдесят три сентаво"), + (81.25, "вісімдесят один песо, двадцять п'ять сентаво"), + (100.00, "сто песо, нуль сентаво"), + (101.11, "сто один песо, одинадцять сентаво"), + (10222, "сто два песо, двадцять два сентаво"), +) + +TEST_CASES_TO_CURRENCY_MYR = ( + (0.00, "нуль рингітів, нуль центів"), + (1.00, "один рингіт, нуль центів"), + (2.00, "два рингіти, нуль центів"), + (5.00, "п'ять рингітів, нуль центів"), + (11.00, "одинадцять рингітів, нуль центів"), + (16.01, "шістнадцять рингітів, один цент"), + (21.00, "двадцять один рингіт, нуль центів"), + (37.73, "тридцять сім рингітів, сімдесят три центи"), + (81.25, "вісімдесят один рингіт, двадцять п'ять центів"), + (100.00, "сто рингітів, нуль центів"), + (101.11, "сто один рингіт, одинадцять центів"), + (10222, "сто два рингіти, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_MZN = ( + (0.00, "нуль метікалів, нуль сентаво"), + (1.00, "один метікал, нуль сентаво"), + (2.00, "два метікали, нуль сентаво"), + (5.00, "п'ять метікалів, нуль сентаво"), + (11.00, "одинадцять метікалів, нуль сентаво"), + (16.01, "шістнадцять метікалів, один сентаво"), + (21.00, "двадцять один метікал, нуль сентаво"), + (37.73, "тридцять сім метікалів, сімдесят три сентаво"), + (81.25, "вісімдесят один метікал, двадцять п'ять сентаво"), + (100.00, "сто метікалів, нуль сентаво"), + (101.11, "сто один метікал, одинадцять сентаво"), + (10222, "сто два метікали, двадцять два сентаво"), +) + +TEST_CASES_TO_CURRENCY_NAD = ( + (0.00, "нуль доларів, нуль центів"), + (1.00, "один долар, нуль центів"), + (2.00, "два долари, нуль центів"), + (5.00, "п'ять доларів, нуль центів"), + (11.00, "одинадцять доларів, нуль центів"), + (16.01, "шістнадцять доларів, один цент"), + (21.00, "двадцять один долар, нуль центів"), + (37.73, "тридцять сім доларів, сімдесят три центи"), + (81.25, "вісімдесят один долар, двадцять п'ять центів"), + (100.00, "сто доларів, нуль центів"), + (101.11, "сто один долар, одинадцять центів"), + (10222, "сто два долари, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_NGN = ( + (0.00, "нуль найр, нуль кобо"), + (1.00, "одна найра, нуль кобо"), + (2.00, "дві найри, нуль кобо"), + (5.00, "п'ять найр, нуль кобо"), + (11.00, "одинадцять найр, нуль кобо"), + (16.01, "шістнадцять найр, один кобо"), + (21.00, "двадцять одна найра, нуль кобо"), + (37.73, "тридцять сім найр, сімдесят три кобо"), + (81.25, "вісімдесят одна найра, двадцять п'ять кобо"), + (100.00, "сто найр, нуль кобо"), + (101.11, "сто одна найра, одинадцять кобо"), + (10222, "сто дві найри, двадцять два кобо"), +) + +TEST_CASES_TO_CURRENCY_NIO = ( + (0.00, "нуль кордоб, нуль сентаво"), + (1.00, "одна кордоба, нуль сентаво"), + (2.00, "дві кордоби, нуль сентаво"), + (5.00, "п'ять кордоб, нуль сентаво"), + (11.00, "одинадцять кордоб, нуль сентаво"), + (16.01, "шістнадцять кордоб, один сентаво"), + (21.00, "двадцять одна кордоба, нуль сентаво"), + (37.73, "тридцять сім кордоб, сімдесят три сентаво"), + (81.25, "вісімдесят одна кордоба, двадцять п'ять сентаво"), + (100.00, "сто кордоб, нуль сентаво"), + (101.11, "сто одна кордоба, одинадцять сентаво"), + (10222, "сто дві кордоби, двадцять два сентаво"), +) + +TEST_CASES_TO_CURRENCY_NOK = ( + (0.00, "нуль крон, нуль ере"), + (1.00, "одна крона, нуль ере"), + (2.00, "дві крони, нуль ере"), + (5.00, "п'ять крон, нуль ере"), + (11.00, "одинадцять крон, нуль ере"), + (16.01, "шістнадцять крон, один ере"), + (21.00, "двадцять одна крона, нуль ере"), + (37.73, "тридцять сім крон, сімдесят три ере"), + (81.25, "вісімдесят одна крона, двадцять п'ять ере"), + (100.00, "сто крон, нуль ере"), + (101.11, "сто одна крона, одинадцять ере"), + (10222, "сто дві крони, двадцять два ере"), +) + +TEST_CASES_TO_CURRENCY_NPR = ( + (0.00, "нуль рупій, нуль пайс"), + (1.00, "одна рупія, нуль пайс"), + (2.00, "дві рупії, нуль пайс"), + (5.00, "п'ять рупій, нуль пайс"), + (11.00, "одинадцять рупій, нуль пайс"), + (16.01, "шістнадцять рупій, одна пайса"), + (21.00, "двадцять одна рупія, нуль пайс"), + (37.73, "тридцять сім рупій, сімдесят три пайси"), + (81.25, "вісімдесят одна рупія, двадцять п'ять пайс"), + (100.00, "сто рупій, нуль пайс"), + (101.11, "сто одна рупія, одинадцять пайс"), + (10222, "сто дві рупії, двадцять дві пайси"), +) + +TEST_CASES_TO_CURRENCY_NZD = ( + (0.00, "нуль доларів, нуль центів"), + (1.00, "один долар, нуль центів"), + (2.00, "два долари, нуль центів"), + (5.00, "п'ять доларів, нуль центів"), + (11.00, "одинадцять доларів, нуль центів"), + (16.01, "шістнадцять доларів, один цент"), + (21.00, "двадцять один долар, нуль центів"), + (37.73, "тридцять сім доларів, сімдесят три центи"), + (81.25, "вісімдесят один долар, двадцять п'ять центів"), + (100.00, "сто доларів, нуль центів"), + (101.11, "сто один долар, одинадцять центів"), + (10222, "сто два долари, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_OMR = ( + (0.00, "нуль ріалів, нуль байз"), + (1.00, "один ріал, нуль байз"), + (2.00, "два ріали, нуль байз"), + (5.00, "п'ять ріалів, нуль байз"), + (11.00, "одинадцять ріалів, нуль байз"), + (16.01, "шістнадцять ріалів, одна байза"), + (21.00, "двадцять один ріал, нуль байз"), + (37.73, "тридцять сім ріалів, сімдесят три байзи"), + (81.25, "вісімдесят один ріал, двадцять п'ять байз"), + (100.00, "сто ріалів, нуль байз"), + (101.11, "сто один ріал, одинадцять байз"), + (10222, "сто два ріали, двадцять дві байзи"), +) + +TEST_CASES_TO_CURRENCY_PAB = ( + (0.00, "нуль бальбоа, нуль сентесімо"), + (1.00, "один бальбоа, нуль сентесімо"), + (2.00, "два бальбоа, нуль сентесімо"), + (5.00, "п'ять бальбоа, нуль сентесімо"), + (11.00, "одинадцять бальбоа, нуль сентесімо"), + (16.01, "шістнадцять бальбоа, один сентесімо"), + (21.00, "двадцять один бальбоа, нуль сентесімо"), + (37.73, "тридцять сім бальбоа, сімдесят три сентесімо"), + (81.25, "вісімдесят один бальбоа, двадцять п'ять сентесімо"), + (100.00, "сто бальбоа, нуль сентесімо"), + (101.11, "сто один бальбоа, одинадцять сентесімо"), + (10222, "сто два бальбоа, двадцять два сентесімо"), +) + +TEST_CASES_TO_CURRENCY_PEN = ( + (0.00, "нуль соль, нуль сентімо"), + (1.00, "один соль, нуль сентімо"), + (2.00, "два соль, нуль сентімо"), + (5.00, "п'ять соль, нуль сентімо"), + (11.00, "одинадцять соль, нуль сентімо"), + (16.01, "шістнадцять соль, один сентімо"), + (21.00, "двадцять один соль, нуль сентімо"), + (37.73, "тридцять сім соль, сімдесят три сентімо"), + (81.25, "вісімдесят один соль, двадцять п'ять сентімо"), + (100.00, "сто соль, нуль сентімо"), + (101.11, "сто один соль, одинадцять сентімо"), + (10222, "сто два соль, двадцять два сентімо"), +) + +TEST_CASES_TO_CURRENCY_PGK = ( + (0.00, "нуль кіна, нуль тойя"), + (1.00, "один кіна, нуль тойя"), + (2.00, "два кіна, нуль тойя"), + (5.00, "п'ять кіна, нуль тойя"), + (11.00, "одинадцять кіна, нуль тойя"), + (16.01, "шістнадцять кіна, один тойя"), + (21.00, "двадцять один кіна, нуль тойя"), + (37.73, "тридцять сім кіна, сімдесят три тойя"), + (81.25, "вісімдесят один кіна, двадцять п'ять тойя"), + (100.00, "сто кіна, нуль тойя"), + (101.11, "сто один кіна, одинадцять тойя"), + (10222, "сто два кіна, двадцять два тойя"), +) + +TEST_CASES_TO_CURRENCY_PHP = ( + (0.00, "нуль песо, нуль сентаво"), + (1.00, "один песо, нуль сентаво"), + (2.00, "два песо, нуль сентаво"), + (5.00, "п'ять песо, нуль сентаво"), + (11.00, "одинадцять песо, нуль сентаво"), + (16.01, "шістнадцять песо, один сентаво"), + (21.00, "двадцять один песо, нуль сентаво"), + (37.73, "тридцять сім песо, сімдесят три сентаво"), + (81.25, "вісімдесят один песо, двадцять п'ять сентаво"), + (100.00, "сто песо, нуль сентаво"), + (101.11, "сто один песо, одинадцять сентаво"), + (10222, "сто два песо, двадцять два сентаво"), +) + +TEST_CASES_TO_CURRENCY_PKR = ( + (0.00, "нуль рупій, нуль пайс"), + (1.00, "одна рупія, нуль пайс"), + (2.00, "дві рупії, нуль пайс"), + (5.00, "п'ять рупій, нуль пайс"), + (11.00, "одинадцять рупій, нуль пайс"), + (16.01, "шістнадцять рупій, одна пайса"), + (21.00, "двадцять одна рупія, нуль пайс"), + (37.73, "тридцять сім рупій, сімдесят три пайси"), + (81.25, "вісімдесят одна рупія, двадцять п'ять пайс"), + (100.00, "сто рупій, нуль пайс"), + (101.11, "сто одна рупія, одинадцять пайс"), + (10222, "сто дві рупії, двадцять дві пайси"), +) + +TEST_CASES_TO_CURRENCY_PLN = ( + (0.00, "нуль злотих, нуль грошів"), + (1.00, "один злотий, нуль грошів"), + (2.00, "два злоті, нуль грошів"), + (5.00, "п'ять злотих, нуль грошів"), + (11.00, "одинадцять злотих, нуль грошів"), + (16.01, "шістнадцять злотих, один грош"), + (21.00, "двадцять один злотий, нуль грошів"), + (37.73, "тридцять сім злотих, сімдесят три гроші"), + (81.25, "вісімдесят один злотий, двадцять п'ять грошів"), + (100.00, "сто злотих, нуль грошів"), + (101.11, "сто один злотий, одинадцять грошів"), + (10222, "сто два злоті, двадцять два гроші"), +) + +TEST_CASES_TO_CURRENCY_PYG = ( + (0.00, "нуль гуарані, нуль сентімо"), + (1.00, "один гуарані, нуль сентімо"), + (2.00, "два гуарані, нуль сентімо"), + (5.00, "п'ять гуарані, нуль сентімо"), + (11.00, "одинадцять гуарані, нуль сентімо"), + (16.01, "шістнадцять гуарані, один сентімо"), + (21.00, "двадцять один гуарані, нуль сентімо"), + (37.73, "тридцять сім гуарані, сімдесят три сентімо"), + (81.25, "вісімдесят один гуарані, двадцять п'ять сентімо"), + (100.00, "сто гуарані, нуль сентімо"), + (101.11, "сто один гуарані, одинадцять сентімо"), + (10222, "сто два гуарані, двадцять два сентімо"), +) + +TEST_CASES_TO_CURRENCY_QAR = ( + (0.00, "нуль ріалів, нуль дирхамів"), + (1.00, "один ріал, нуль дирхамів"), + (2.00, "два ріали, нуль дирхамів"), + (5.00, "п'ять ріалів, нуль дирхамів"), + (11.00, "одинадцять ріалів, нуль дирхамів"), + (16.01, "шістнадцять ріалів, один дирхам"), + (21.00, "двадцять один ріал, нуль дирхамів"), + (37.73, "тридцять сім ріалів, сімдесят три дирхами"), + (81.25, "вісімдесят один ріал, двадцять п'ять дирхамів"), + (100.00, "сто ріалів, нуль дирхамів"), + (101.11, "сто один ріал, одинадцять дирхамів"), + (10222, "сто два ріали, двадцять два дирхами"), +) + +TEST_CASES_TO_CURRENCY_RON = ( + (0.00, "нуль леї, нуль бані"), + (1.00, "один лей, нуль бані"), + (2.00, "два леї, нуль бані"), + (5.00, "п'ять леї, нуль бані"), + (11.00, "одинадцять леї, нуль бані"), + (16.01, "шістнадцять леї, один бан"), + (21.00, "двадцять один лей, нуль бані"), + (37.73, "тридцять сім леї, сімдесят три бані"), + (81.25, "вісімдесят один лей, двадцять п'ять бані"), + (100.00, "сто леї, нуль бані"), + (101.11, "сто один лей, одинадцять бані"), + (10222, "сто два леї, двадцять два бані"), +) + +TEST_CASES_TO_CURRENCY_RSD = ( + (0.00, "нуль динарів, нуль пар"), + (1.00, "один динар, нуль пар"), + (2.00, "два динари, нуль пар"), + (5.00, "п'ять динарів, нуль пар"), + (11.00, "одинадцять динарів, нуль пар"), + (16.01, "шістнадцять динарів, одна пара"), + (21.00, "двадцять один динар, нуль пар"), + (37.73, "тридцять сім динарів, сімдесят три пари"), + (81.25, "вісімдесят один динар, двадцять п'ять пар"), + (100.00, "сто динарів, нуль пар"), + (101.11, "сто один динар, одинадцять пар"), + (10222, "сто два динари, двадцять дві пари"), +) + +TEST_CASES_TO_CURRENCY_RUB = ( + (0.00, "нуль рублів, нуль копійок"), + (1.00, "один рубль, нуль копійок"), + (2.00, "два рублі, нуль копійок"), + (5.00, "п'ять рублів, нуль копійок"), + (11.00, "одинадцять рублів, нуль копійок"), + (16.01, "шістнадцять рублів, одна копійка"), + (21.00, "двадцять один рубль, нуль копійок"), + (37.73, "тридцять сім рублів, сімдесят три копійки"), + (81.25, "вісімдесят один рубль, двадцять п'ять копійок"), + (100.00, "сто рублів, нуль копійок"), + (101.11, "сто один рубль, одинадцять копійок"), +) + +TEST_CASES_TO_CURRENCY_RWF = ( + (0.00, "нуль франків, нуль сантимів"), + (1.00, "один франк, нуль сантимів"), + (2.00, "два франки, нуль сантимів"), + (5.00, "п'ять франків, нуль сантимів"), + (11.00, "одинадцять франків, нуль сантимів"), + (16.01, "шістнадцять франків, один сантим"), + (21.00, "двадцять один франк, нуль сантимів"), + (37.73, "тридцять сім франків, сімдесят три сантими"), + (81.25, "вісімдесят один франк, двадцять п'ять сантимів"), + (100.00, "сто франків, нуль сантимів"), + (101.11, "сто один франк, одинадцять сантимів"), + (10222, "сто два франки, двадцять два сантими"), +) + +TEST_CASES_TO_CURRENCY_SAR = ( + (0.00, "нуль ріалів, нуль халалів"), + (1.00, "один ріал, нуль халалів"), + (2.00, "два ріали, нуль халалів"), + (5.00, "п'ять ріалів, нуль халалів"), + (11.00, "одинадцять ріалів, нуль халалів"), + (16.01, "шістнадцять ріалів, один халал"), + (21.00, "двадцять один ріал, нуль халалів"), + (37.73, "тридцять сім ріалів, сімдесят три халали"), + (81.25, "вісімдесят один ріал, двадцять п'ять халалів"), + (100.00, "сто ріалів, нуль халалів"), + (101.11, "сто один ріал, одинадцять халалів"), + (10222, "сто два ріали, двадцять два халали"), +) + +TEST_CASES_TO_CURRENCY_SBD = ( + (0.00, "нуль доларів, нуль центів"), + (1.00, "один долар, нуль центів"), + (2.00, "два долари, нуль центів"), + (5.00, "п'ять доларів, нуль центів"), + (11.00, "одинадцять доларів, нуль центів"), + (16.01, "шістнадцять доларів, один цент"), + (21.00, "двадцять один долар, нуль центів"), + (37.73, "тридцять сім доларів, сімдесят три центи"), + (81.25, "вісімдесят один долар, двадцять п'ять центів"), + (100.00, "сто доларів, нуль центів"), + (101.11, "сто один долар, одинадцять центів"), + (10222, "сто два долари, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_SCR = ( + (0.00, "нуль рупій, нуль центів"), + (1.00, "одна рупія, нуль центів"), + (2.00, "дві рупії, нуль центів"), + (5.00, "п'ять рупій, нуль центів"), + (11.00, "одинадцять рупій, нуль центів"), + (16.01, "шістнадцять рупій, один цент"), + (21.00, "двадцять одна рупія, нуль центів"), + (37.73, "тридцять сім рупій, сімдесят три центи"), + (81.25, "вісімдесят одна рупія, двадцять п'ять центів"), + (100.00, "сто рупій, нуль центів"), + (101.11, "сто одна рупія, одинадцять центів"), + (10222, "сто дві рупії, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_SDG = ( + (0.00, "нуль фунтів, нуль піастрів"), + (1.00, "один фунт, нуль піастрів"), + (2.00, "два фунти, нуль піастрів"), + (5.00, "п'ять фунтів, нуль піастрів"), + (11.00, "одинадцять фунтів, нуль піастрів"), + (16.01, "шістнадцять фунтів, один піастр"), + (21.00, "двадцять один фунт, нуль піастрів"), + (37.73, "тридцять сім фунтів, сімдесят три піастри"), + (81.25, "вісімдесят один фунт, двадцять п'ять піастрів"), + (100.00, "сто фунтів, нуль піастрів"), + (101.11, "сто один фунт, одинадцять піастрів"), + (10222, "сто два фунти, двадцять два піастри"), +) + +TEST_CASES_TO_CURRENCY_SEK = ( + (0.00, "нуль крон, нуль ере"), + (1.00, "одна крона, нуль ере"), + (2.00, "дві крони, нуль ере"), + (5.00, "п'ять крон, нуль ере"), + (11.00, "одинадцять крон, нуль ере"), + (16.01, "шістнадцять крон, один ере"), + (21.00, "двадцять одна крона, нуль ере"), + (37.73, "тридцять сім крон, сімдесят три ере"), + (81.25, "вісімдесят одна крона, двадцять п'ять ере"), + (100.00, "сто крон, нуль ере"), + (101.11, "сто одна крона, одинадцять ере"), + (10222, "сто дві крони, двадцять два ере"), +) + +TEST_CASES_TO_CURRENCY_SGD = ( + (0.00, "нуль доларів, нуль центів"), + (1.00, "один долар, нуль центів"), + (2.00, "два долари, нуль центів"), + (5.00, "п'ять доларів, нуль центів"), + (11.00, "одинадцять доларів, нуль центів"), + (16.01, "шістнадцять доларів, один цент"), + (21.00, "двадцять один долар, нуль центів"), + (37.73, "тридцять сім доларів, сімдесят три центи"), + (81.25, "вісімдесят один долар, двадцять п'ять центів"), + (100.00, "сто доларів, нуль центів"), + (101.11, "сто один долар, одинадцять центів"), + (10222, "сто два долари, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_SHP = ( + (0.00, "нуль фунтів, нуль пенсів"), + (1.00, "один фунт, нуль пенсів"), + (2.00, "два фунти, нуль пенсів"), + (5.00, "п'ять фунтів, нуль пенсів"), + (11.00, "одинадцять фунтів, нуль пенсів"), + (16.01, "шістнадцять фунтів, один пенс"), + (21.00, "двадцять один фунт, нуль пенсів"), + (37.73, "тридцять сім фунтів, сімдесят три пенси"), + (81.25, "вісімдесят один фунт, двадцять п'ять пенсів"), + (100.00, "сто фунтів, нуль пенсів"), + (101.11, "сто один фунт, одинадцять пенсів"), + (10222, "сто два фунти, двадцять два пенси"), +) + +TEST_CASES_TO_CURRENCY_SLL = ( + (0.00, "нуль леоне, нуль центів"), + (1.00, "один леоне, нуль центів"), + (2.00, "два леоне, нуль центів"), + (5.00, "п'ять леоне, нуль центів"), + (11.00, "одинадцять леоне, нуль центів"), + (16.01, "шістнадцять леоне, один цент"), + (21.00, "двадцять один леоне, нуль центів"), + (37.73, "тридцять сім леоне, сімдесят три центи"), + (81.25, "вісімдесят один леоне, двадцять п'ять центів"), + (100.00, "сто леоне, нуль центів"), + (101.11, "сто один леоне, одинадцять центів"), + (10222, "сто два леоне, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_SOS = ( + (0.00, "нуль шилінгів, нуль центів"), + (1.00, "один шилінг, нуль центів"), + (2.00, "два шилінги, нуль центів"), + (5.00, "п'ять шилінгів, нуль центів"), + (11.00, "одинадцять шилінгів, нуль центів"), + (16.01, "шістнадцять шилінгів, один цент"), + (21.00, "двадцять один шилінг, нуль центів"), + (37.73, "тридцять сім шилінгів, сімдесят три центи"), + (81.25, "вісімдесят один шилінг, двадцять п'ять центів"), + (100.00, "сто шилінгів, нуль центів"), + (101.11, "сто один шилінг, одинадцять центів"), + (10222, "сто два шилінги, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_SRD = ( + (0.00, "нуль доларів, нуль центів"), + (1.00, "один долар, нуль центів"), + (2.00, "два долари, нуль центів"), + (5.00, "п'ять доларів, нуль центів"), + (11.00, "одинадцять доларів, нуль центів"), + (16.01, "шістнадцять доларів, один цент"), + (21.00, "двадцять один долар, нуль центів"), + (37.73, "тридцять сім доларів, сімдесят три центи"), + (81.25, "вісімдесят один долар, двадцять п'ять центів"), + (100.00, "сто доларів, нуль центів"), + (101.11, "сто один долар, одинадцять центів"), + (10222, "сто два долари, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_SSP = ( + (0.00, "нуль фунтів, нуль піастрів"), + (1.00, "один фунт, нуль піастрів"), + (2.00, "два фунти, нуль піастрів"), + (5.00, "п'ять фунтів, нуль піастрів"), + (11.00, "одинадцять фунтів, нуль піастрів"), + (16.01, "шістнадцять фунтів, один піастр"), + (21.00, "двадцять один фунт, нуль піастрів"), + (37.73, "тридцять сім фунтів, сімдесят три піастри"), + (81.25, "вісімдесят один фунт, двадцять п'ять піастрів"), + (100.00, "сто фунтів, нуль піастрів"), + (101.11, "сто один фунт, одинадцять піастрів"), + (10222, "сто два фунти, двадцять два піастри"), +) + +TEST_CASES_TO_CURRENCY_STN = ( + (0.00, "нуль добр, нуль сентімо"), + (1.00, "одна добра, нуль сентімо"), + (2.00, "дві добри, нуль сентімо"), + (5.00, "п'ять добр, нуль сентімо"), + (11.00, "одинадцять добр, нуль сентімо"), + (16.01, "шістнадцять добр, один сентімо"), + (21.00, "двадцять одна добра, нуль сентімо"), + (37.73, "тридцять сім добр, сімдесят три сентімо"), + (81.25, "вісімдесят одна добра, двадцять п'ять сентімо"), + (100.00, "сто добр, нуль сентімо"), + (101.11, "сто одна добра, одинадцять сентімо"), + (10222, "сто дві добри, двадцять два сентімо"), +) + +TEST_CASES_TO_CURRENCY_SYP = ( + (0.00, "нуль фунтів, нуль піастрів"), + (1.00, "один фунт, нуль піастрів"), + (2.00, "два фунти, нуль піастрів"), + (5.00, "п'ять фунтів, нуль піастрів"), + (11.00, "одинадцять фунтів, нуль піастрів"), + (16.01, "шістнадцять фунтів, один піастр"), + (21.00, "двадцять один фунт, нуль піастрів"), + (37.73, "тридцять сім фунтів, сімдесят три піастри"), + (81.25, "вісімдесят один фунт, двадцять п'ять піастрів"), + (100.00, "сто фунтів, нуль піастрів"), + (101.11, "сто один фунт, одинадцять піастрів"), + (10222, "сто два фунти, двадцять два піастри"), +) + +TEST_CASES_TO_CURRENCY_SZL = ( + (0.00, "нуль ліланґені, нуль центів"), + (1.00, "один ліланґені, нуль центів"), + (2.00, "два ліланґені, нуль центів"), + (5.00, "п'ять ліланґені, нуль центів"), + (11.00, "одинадцять ліланґені, нуль центів"), + (16.01, "шістнадцять ліланґені, один цент"), + (21.00, "двадцять один ліланґені, нуль центів"), + (37.73, "тридцять сім ліланґені, сімдесят три центи"), + (81.25, "вісімдесят один ліланґені, двадцять п'ять центів"), + (100.00, "сто ліланґені, нуль центів"), + (101.11, "сто один ліланґені, одинадцять центів"), + (10222, "сто два ліланґені, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_THB = ( + (0.00, "нуль батів, нуль сатангів"), + (1.00, "один бат, нуль сатангів"), + (2.00, "два бати, нуль сатангів"), + (5.00, "п'ять батів, нуль сатангів"), + (11.00, "одинадцять батів, нуль сатангів"), + (16.01, "шістнадцять батів, один сатанг"), + (21.00, "двадцять один бат, нуль сатангів"), + (37.73, "тридцять сім батів, сімдесят три сатанги"), + (81.25, "вісімдесят один бат, двадцять п'ять сатангів"), + (100.00, "сто батів, нуль сатангів"), + (101.11, "сто один бат, одинадцять сатангів"), + (10222, "сто два бати, двадцять два сатанги"), +) + +TEST_CASES_TO_CURRENCY_TJS = ( + (0.00, "нуль сомоні, нуль дірамів"), + (1.00, "один сомоні, нуль дірамів"), + (2.00, "два сомоні, нуль дірамів"), + (5.00, "п'ять сомоні, нуль дірамів"), + (11.00, "одинадцять сомоні, нуль дірамів"), + (16.01, "шістнадцять сомоні, один дірам"), + (21.00, "двадцять один сомоні, нуль дірамів"), + (37.73, "тридцять сім сомоні, сімдесят три дірами"), + (81.25, "вісімдесят один сомоні, двадцять п'ять дірамів"), + (100.00, "сто сомоні, нуль дірамів"), + (101.11, "сто один сомоні, одинадцять дірамів"), + (10222, "сто два сомоні, двадцять два дірами"), +) + +TEST_CASES_TO_CURRENCY_TMT = ( + (0.00, "нуль манатів, нуль тенге"), + (1.00, "один манат, нуль тенге"), + (2.00, "два манати, нуль тенге"), + (5.00, "п'ять манатів, нуль тенге"), + (11.00, "одинадцять манатів, нуль тенге"), + (16.01, "шістнадцять манатів, один тенге"), + (21.00, "двадцять один манат, нуль тенге"), + (37.73, "тридцять сім манатів, сімдесят три тенге"), + (81.25, "вісімдесят один манат, двадцять п'ять тенге"), + (100.00, "сто манатів, нуль тенге"), + (101.11, "сто один манат, одинадцять тенге"), + (10222, "сто два манати, двадцять два тенге"), +) + +TEST_CASES_TO_CURRENCY_TND = ( + (0.00, "нуль динарів, нуль міллімів"), + (1.00, "один динар, нуль міллімів"), + (2.00, "два динари, нуль міллімів"), + (5.00, "п'ять динарів, нуль міллімів"), + (11.00, "одинадцять динарів, нуль міллімів"), + (16.01, "шістнадцять динарів, один міллім"), + (21.00, "двадцять один динар, нуль міллімів"), + (37.73, "тридцять сім динарів, сімдесят три мілліми"), + (81.25, "вісімдесят один динар, двадцять п'ять міллімів"), + (100.00, "сто динарів, нуль міллімів"), + (101.11, "сто один динар, одинадцять міллімів"), + (10222, "сто два динари, двадцять два мілліми"), +) + +TEST_CASES_TO_CURRENCY_TOP = ( + (0.00, "нуль паанга, нуль сеніті"), + (1.00, "один паанга, нуль сеніті"), + (2.00, "два паанга, нуль сеніті"), + (5.00, "п'ять паанга, нуль сеніті"), + (11.00, "одинадцять паанга, нуль сеніті"), + (16.01, "шістнадцять паанга, один сеніті"), + (21.00, "двадцять один паанга, нуль сеніті"), + (37.73, "тридцять сім паанга, сімдесят три сеніті"), + (81.25, "вісімдесят один паанга, двадцять п'ять сеніті"), + (100.00, "сто паанга, нуль сеніті"), + (101.11, "сто один паанга, одинадцять сеніті"), + (10222, "сто два паанга, двадцять два сеніті"), +) + +TEST_CASES_TO_CURRENCY_TRY = ( + (0.00, "нуль лір, нуль курушів"), + (1.00, "одна ліра, нуль курушів"), + (2.00, "дві ліри, нуль курушів"), + (5.00, "п'ять лір, нуль курушів"), + (11.00, "одинадцять лір, нуль курушів"), + (16.01, "шістнадцять лір, один куруш"), + (21.00, "двадцять одна ліра, нуль курушів"), + (37.73, "тридцять сім лір, сімдесят три куруші"), + (81.25, "вісімдесят одна ліра, двадцять п'ять курушів"), + (100.00, "сто лір, нуль курушів"), + (101.11, "сто одна ліра, одинадцять курушів"), + (10222, "сто дві ліри, двадцять два куруші"), +) + +TEST_CASES_TO_CURRENCY_TTD = ( + (0.00, "нуль доларів, нуль центів"), + (1.00, "один долар, нуль центів"), + (2.00, "два долари, нуль центів"), + (5.00, "п'ять доларів, нуль центів"), + (11.00, "одинадцять доларів, нуль центів"), + (16.01, "шістнадцять доларів, один цент"), + (21.00, "двадцять один долар, нуль центів"), + (37.73, "тридцять сім доларів, сімдесят три центи"), + (81.25, "вісімдесят один долар, двадцять п'ять центів"), + (100.00, "сто доларів, нуль центів"), + (101.11, "сто один долар, одинадцять центів"), + (10222, "сто два долари, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_TWD = ( + (0.00, "нуль нових доларів, нуль центів"), + (1.00, "один новий долар, нуль центів"), + (2.00, "два нові долари, нуль центів"), + (5.00, "п'ять нових доларів, нуль центів"), + (11.00, "одинадцять нових доларів, нуль центів"), + (16.01, "шістнадцять нових доларів, один цент"), + (21.00, "двадцять один новий долар, нуль центів"), + (37.73, "тридцять сім нових доларів, сімдесят три центи"), + (81.25, "вісімдесят один новий долар, двадцять п'ять центів"), + (100.00, "сто нових доларів, нуль центів"), + (101.11, "сто один новий долар, одинадцять центів"), + (10222, "сто два нові долари, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_TZS = ( + (0.00, "нуль шилінгів, нуль центів"), + (1.00, "один шилінг, нуль центів"), + (2.00, "два шилінги, нуль центів"), + (5.00, "п'ять шилінгів, нуль центів"), + (11.00, "одинадцять шилінгів, нуль центів"), + (16.01, "шістнадцять шилінгів, один цент"), + (21.00, "двадцять один шилінг, нуль центів"), + (37.73, "тридцять сім шилінгів, сімдесят три центи"), + (81.25, "вісімдесят один шилінг, двадцять п'ять центів"), + (100.00, "сто шилінгів, нуль центів"), + (101.11, "сто один шилінг, одинадцять центів"), + (10222, "сто два шилінги, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_UAH = ( + (0.00, "нуль гривень, нуль копійок"), + (1.00, "одна гривня, нуль копійок"), + (2.00, "дві гривні, нуль копійок"), + (5.00, "п'ять гривень, нуль копійок"), + (11.00, "одинадцять гривень, нуль копійок"), + (16.01, "шістнадцять гривень, одна копійка"), + (21.00, "двадцять одна гривня, нуль копійок"), + (37.73, "тридцять сім гривень, сімдесят три копійки"), + (81.25, "вісімдесят одна гривня, двадцять п'ять копійок"), + (100.00, "сто гривень, нуль копійок"), + (101.11, "сто одна гривня, одинадцять копійок"), + (10222, "сто дві гривні, двадцять дві копійки"), +) + +TEST_CASES_TO_CURRENCY_UGX = ( + (0.00, "нуль шилінгів, нуль центів"), + (1.00, "один шилінг, нуль центів"), + (2.00, "два шилінги, нуль центів"), + (5.00, "п'ять шилінгів, нуль центів"), + (11.00, "одинадцять шилінгів, нуль центів"), + (16.01, "шістнадцять шилінгів, один цент"), + (21.00, "двадцять один шилінг, нуль центів"), + (37.73, "тридцять сім шилінгів, сімдесят три центи"), + (81.25, "вісімдесят один шилінг, двадцять п'ять центів"), + (100.00, "сто шилінгів, нуль центів"), + (101.11, "сто один шилінг, одинадцять центів"), + (10222, "сто два шилінги, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_USD = ( + (0.00, "нуль доларів, нуль центів"), + (1.00, "один долар, нуль центів"), + (2.00, "два долари, нуль центів"), + (5.00, "п'ять доларів, нуль центів"), + (11.00, "одинадцять доларів, нуль центів"), + (16.01, "шістнадцять доларів, один цент"), + (21.00, "двадцять один долар, нуль центів"), + (37.73, "тридцять сім доларів, сімдесят три центи"), + (81.25, "вісімдесят один долар, двадцять п'ять центів"), + (100.00, "сто доларів, нуль центів"), + (101.11, "сто один долар, одинадцять центів"), + (10222, "сто два долари, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_UYU = ( + (0.00, "нуль песо, нуль сентесімо"), + (1.00, "один песо, нуль сентесімо"), + (2.00, "два песо, нуль сентесімо"), + (5.00, "п'ять песо, нуль сентесімо"), + (11.00, "одинадцять песо, нуль сентесімо"), + (16.01, "шістнадцять песо, один сентесімо"), + (21.00, "двадцять один песо, нуль сентесімо"), + (37.73, "тридцять сім песо, сімдесят три сентесімо"), + (81.25, "вісімдесят один песо, двадцять п'ять сентесімо"), + (100.00, "сто песо, нуль сентесімо"), + (101.11, "сто один песо, одинадцять сентесімо"), + (10222, "сто два песо, двадцять два сентесімо"), +) + +TEST_CASES_TO_CURRENCY_UZS = ( + (0.00, "нуль сумів, нуль тиїнів"), + (1.00, "один сум, нуль тиїнів"), + (2.00, "два суми, нуль тиїнів"), + (5.00, "п'ять сумів, нуль тиїнів"), + (11.00, "одинадцять сумів, нуль тиїнів"), + (16.01, "шістнадцять сумів, один тиїн"), + (21.00, "двадцять один сум, нуль тиїнів"), + (37.73, "тридцять сім сумів, сімдесят три тиїни"), + (81.25, "вісімдесят один сум, двадцять п'ять тиїнів"), + (100.00, "сто сумів, нуль тиїнів"), + (101.11, "сто один сум, одинадцять тиїнів"), + (10222, "сто два суми, двадцять два тиїни"), +) + +TEST_CASES_TO_CURRENCY_VND = ( + (0.00, "нуль донгів, нуль су"), + (1.00, "один донг, нуль су"), + (2.00, "два донги, нуль су"), + (5.00, "п'ять донгів, нуль су"), + (11.00, "одинадцять донгів, нуль су"), + (16.01, "шістнадцять донгів, один су"), + (21.00, "двадцять один донг, нуль су"), + (37.73, "тридцять сім донгів, сімдесят три су"), + (81.25, "вісімдесят один донг, двадцять п'ять су"), + (100.00, "сто донгів, нуль су"), + (101.11, "сто один донг, одинадцять су"), + (10222, "сто два донги, двадцять два су"), +) + +TEST_CASES_TO_CURRENCY_WST = ( + (0.00, "нуль тал, нуль сене"), + (1.00, "одна тала, нуль сене"), + (2.00, "дві тали, нуль сене"), + (5.00, "п'ять тал, нуль сене"), + (11.00, "одинадцять тал, нуль сене"), + (16.01, "шістнадцять тал, один сене"), + (21.00, "двадцять одна тала, нуль сене"), + (37.73, "тридцять сім тал, сімдесят три сене"), + (81.25, "вісімдесят одна тала, двадцять п'ять сене"), + (100.00, "сто тал, нуль сене"), + (101.11, "сто одна тала, одинадцять сене"), + (10222, "сто дві тали, двадцять два сене"), +) + +TEST_CASES_TO_CURRENCY_XCD = ( + (0.00, "нуль доларів, нуль центів"), + (1.00, "один долар, нуль центів"), + (2.00, "два долари, нуль центів"), + (5.00, "п'ять доларів, нуль центів"), + (11.00, "одинадцять доларів, нуль центів"), + (16.01, "шістнадцять доларів, один цент"), + (21.00, "двадцять один долар, нуль центів"), + (37.73, "тридцять сім доларів, сімдесят три центи"), + (81.25, "вісімдесят один долар, двадцять п'ять центів"), + (100.00, "сто доларів, нуль центів"), + (101.11, "сто один долар, одинадцять центів"), + (10222, "сто два долари, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_YER = ( + (0.00, "нуль ріалів, нуль філсів"), + (1.00, "один ріал, нуль філсів"), + (2.00, "два ріали, нуль філсів"), + (5.00, "п'ять ріалів, нуль філсів"), + (11.00, "одинадцять ріалів, нуль філсів"), + (16.01, "шістнадцять ріалів, один філс"), + (21.00, "двадцять один ріал, нуль філсів"), + (37.73, "тридцять сім ріалів, сімдесят три філси"), + (81.25, "вісімдесят один ріал, двадцять п'ять філсів"), + (100.00, "сто ріалів, нуль філсів"), + (101.11, "сто один ріал, одинадцять філсів"), + (10222, "сто два ріали, двадцять два філси"), +) + +TEST_CASES_TO_CURRENCY_ZAR = ( + (0.00, "нуль рандів, нуль центів"), + (1.00, "один ранд, нуль центів"), + (2.00, "два ранди, нуль центів"), + (5.00, "п'ять рандів, нуль центів"), + (11.00, "одинадцять рандів, нуль центів"), + (16.01, "шістнадцять рандів, один цент"), + (21.00, "двадцять один ранд, нуль центів"), + (37.73, "тридцять сім рандів, сімдесят три центи"), + (81.25, "вісімдесят один ранд, двадцять п'ять центів"), + (100.00, "сто рандів, нуль центів"), + (101.11, "сто один ранд, одинадцять центів"), + (10222, "сто два ранди, двадцять два центи"), +) + +TEST_CASES_TO_CURRENCY_ZMW = ( + (0.00, "нуль квач, нуль нгве"), + (1.00, "одна квача, нуль нгве"), + (2.00, "дві квачі, нуль нгве"), + (5.00, "п'ять квач, нуль нгве"), + (11.00, "одинадцять квач, нуль нгве"), + (16.01, "шістнадцять квач, один нгве"), + (21.00, "двадцять одна квача, нуль нгве"), + (37.73, "тридцять сім квач, сімдесят три нгве"), + (81.25, "вісімдесят одна квача, двадцять п'ять нгве"), + (100.00, "сто квач, нуль нгве"), + (101.11, "сто одна квача, одинадцять нгве"), + (10222, "сто дві квачі, двадцять два нгве"), +) + class Num2WordsUKTest(TestCase): def test_to_cardinal(self): - self.maxDiff = None - self.assertEqual(num2words(100, lang='uk'), 'сто') - # self.assertEqual(num2words(101, lang='uk'), 'сто один') - self.assertEqual(num2words(110, lang='uk'), 'сто десять') - self.assertEqual(num2words(115, lang='uk'), "сто п'ятнадцять") - self.assertEqual(num2words(123, lang='uk'), 'сто двадцять три') - self.assertEqual(num2words(1000, lang='uk'), 'одна тисяча') - # self.assertEqual(num2words(1001, lang='uk'), 'одна тисяча один') - self.assertEqual(num2words(2012, lang='uk'), 'двi тисячi дванадцять') - self.assertEqual( - num2words(12519.85, lang='uk'), - "дванадцять тисяч п'ятсот дев'ятнадцять кома вiсiмдесят п'ять") - # self.assertEqual( - # num2words(1234567890, lang='uk'), - # "мiльярд двiстi тридцать чотири мiльйона п'ятсот шiстдесят сiмь " - # "тисяч вiсiмсот дев'яносто") - # self.assertEqual( - # num2words(215461407892039002157189883901676, lang='uk'), - # "двiстi п'ятнадцять нонiльйонiв чотириста шiстдесят один " - # "октильйон чотириста сiм септильйонiв вiсiмсот дев'яносто " - # "два секстильйони тридцять дев'ять квiнтильйонiв два " - # "квадрильйони сто п'ятдесят сiм трильйонiв сто вiсiмдесят " - # "дев'ять мiльярдiв вiсiмсот вiсiмдесят три мiльйона " - # "дев'ятсот одна тисяча шiстсот " - # "сiмдесят шiсть") - # self.assertEqual( - # num2words(719094234693663034822824384220291, lang='uk'), - # "сiмсот дев'ятнадцять нонiльйонiв дев'яносто чотири октильйони " - # "двiстi тридцять чотири септильйони шiстсот дев'яносто три " - # "секстильйони шiстсот шiстдесят три квiнтильйони тридцять " - # "чотири квадрильйони вiсiмсот двадцять два трильйони вiсiмсот " - # "двадцять чотири мiльярди триста вiсiмдесят чотири мiльйона " - # "двiстi двадцять тисяч двiстi дев'яносто один") - - def test_and_join_199(self): - self.assertEqual(num2words(187, lang='uk'), "сто вiсiмдесят сiм") - - def test_cardinal_for_float_number(self): - self.assertEqual( - num2words(12.40, lang='uk'), "дванадцять кома чотири" - ) - self.assertEqual( - num2words(17.31, lang='uk'), "сiмнадцять кома тридцять одна" - ) - self.assertEqual( - num2words(14.13, lang='uk'), "чотирнадцять кома тринадцять" - ) - self.assertEqual( - num2words(12.31, lang='uk'), "дванадцять кома тридцять одна" - ) + for test in TEST_CASES_CARDINAL: + self.assertEqual(num2words(test[0], lang='uk'), test[1]) def test_to_ordinal(self): - # @TODO: implement to_ordinal - with self.assertRaises(NotImplementedError): - num2words(1, lang='uk', to='ordinal') + for test in TEST_CASES_ORDINAL: + self.assertEqual( + num2words(test[0], lang='uk', to='ordinal'), + test[1] + ) def test_to_currency(self): - # self.assertEqual( - # num2words(1.0, lang='uk', to='currency', currency='EUR'), - # "один євро, нуль центiв" - # ) - self.assertEqual( - num2words(1.0, lang='uk', to='currency', currency='UAH'), - "одна гривня, нуль копiйок" - ) - self.assertEqual( - num2words(1234.56, lang='uk', to='currency', currency='EUR'), - "одна тисяча двiстi тридцять чотири євро, п'ятдесят шiсть центiв" - ) - self.assertEqual( - num2words(1234.56, lang='uk', to='currency', currency='UAH'), - "одна тисяча двiстi тридцять чотири гривнi, п'ятдесят шiсть " - "копiйок" - ) - # self.assertEqual( - # num2words(10111, lang='uk', to='currency', currency='EUR', - # separator=u' та'), - # "сто один євро та одинадцять центiв" - # ) - self.assertEqual( - num2words(10121, lang='uk', to='currency', currency='UAH', - separator=u' та'), - "сто одна гривня та двадцять одна копiйка" - ) - self.assertEqual( - num2words(10121, lang='uk', to='currency', currency='UAH', - separator=u' та'), - "сто одна гривня та двадцять одна копiйка" - ) - self.assertEqual( - num2words(10122, lang='uk', to='currency', currency='UAH', - separator=u' та'), - "сто одна гривня та двадцять двi копiйки" - ) - # self.assertEqual( - # num2words(10121, lang='uk', to='currency', currency='EUR', - # separator=u' та'), - # "сто один євро та двадцять один цент" - # ) - self.assertEqual( - num2words(-1251985, lang='uk', to='currency', currency='EUR', - cents=False), - "мiнус дванадцять тисяч п'ятсот дев'ятнадцять євро, 85 центiв" - ) - self.assertEqual( - num2words('38.4', lang='uk', to='currency', separator=' и', - cents=False, currency='EUR'), - "тридцять вiсiм євро и 40 центiв" - ) + for test in TEST_CASES_TO_CURRENCY_AED: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="AED"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_AFN: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="AFN"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_ALL: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="ALL"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_AMD: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="AMD"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_ANG: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="ANG"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_AOA: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="AOA"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_ARS: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="ARS"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_AUD: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="AUD"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_AWG: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="AWG"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_AZN: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="AZN"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_BAM: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="BAM"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_BBD: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="BBD"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_BDT: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="BDT"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_BGN: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="BGN"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_BHD: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="BHD"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_BIF: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="BIF"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_BMD: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="BMD"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_BND: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="BND"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_BOB: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="BOB"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_BRL: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="BRL"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_BSD: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="BSD"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_BTN: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="BTN"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_BWP: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="BWP"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_BYN: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="BYN"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_BZD: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="BZD"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_CAD: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="CAD"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_CDF: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="CDF"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_CHF: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="CHF"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_CLP: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="CLP"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_CNY: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="CNY"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_COP: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="COP"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_CRC: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="CRC"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_CUC: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="CUC"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_CUP: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="CUP"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_CVE: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="CVE"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_CZK: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="CZK"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_DJF: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="DJF"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_DKK: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="DKK"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_DOP: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="DOP"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_DZD: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="DZD"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_EGP: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="EGP"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_ERN: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="ERN"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_ETB: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="ETB"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_EUR: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="EUR"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_FJD: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="FJD"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_FKP: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="FKP"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_GBP: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="GBP"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_GEL: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="GEL"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_GHS: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="GHS"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_GIP: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="GIP"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_GMD: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="GMD"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_GNF: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="GNF"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_GTQ: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="GTQ"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_GYD: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="GYD"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_HKD: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="HKD"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_HNL: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="HNL"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_HRK: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="HRK"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_HTG: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="HTG"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_HUF: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="HUF"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_IDR: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="IDR"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_ILS: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="ILS"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_INR: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="INR"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_IQD: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="IQD"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_IRR: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="IRR"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_ISK: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="ISK"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_JMD: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="JMD"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_JOD: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="JOD"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_JPY: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="JPY"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_KES: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="KES"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_KGS: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="KGS"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_KHR: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="KHR"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_KMF: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="KMF"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_KPW: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="KPW"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_KRW: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="KRW"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_KWD: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="KWD"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_KYD: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="KYD"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_KZT: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="KZT"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_LAK: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="LAK"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_LBP: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="LBP"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_LKR: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="LKR"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_LRD: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="LRD"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_LSL: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="LSL"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_LYD: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="LYD"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_MAD: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="MAD"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_MDL: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="MDL"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_MGA: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="MGA"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_MKD: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="MKD"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_MMK: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="MMK"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_MNT: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="MNT"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_MOP: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="MOP"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_MRU: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="MRU"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_MUR: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="MUR"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_MVR: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="MVR"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_MWK: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="MWK"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_MXN: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="MXN"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_MYR: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="MYR"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_MZN: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="MZN"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_NAD: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="NAD"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_NGN: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="NGN"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_NIO: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="NIO"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_NOK: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="NOK"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_NPR: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="NPR"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_NZD: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="NZD"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_OMR: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="OMR"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_PAB: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="PAB"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_PEN: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="PEN"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_PGK: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="PGK"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_PHP: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="PHP"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_PKR: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="PKR"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_PLN: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="PLN"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_PYG: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="PYG"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_QAR: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="QAR"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_RON: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="RON"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_RSD: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="RSD"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_RUB: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="RUB"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_RWF: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="RWF"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_SAR: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="SAR"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_SBD: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="SBD"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_SCR: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="SCR"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_SDG: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="SDG"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_SEK: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="SEK"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_SGD: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="SGD"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_SHP: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="SHP"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_SLL: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="SLL"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_SOS: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="SOS"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_SRD: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="SRD"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_SSP: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="SSP"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_STN: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="STN"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_SYP: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="SYP"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_SZL: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="SZL"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_THB: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="THB"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_TJS: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="TJS"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_TMT: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="TMT"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_TND: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="TND"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_TOP: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="TOP"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_TRY: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="TRY"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_TTD: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="TTD"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_TWD: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="TWD"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_TZS: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="TZS"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_UAH: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="UAH"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_UGX: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="UGX"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_USD: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="USD"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_UYU: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="UYU"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_UZS: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="UZS"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_VND: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="VND"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_WST: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="WST"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_XCD: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="XCD"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_YER: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="YER"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_ZAR: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="ZAR"), + test[1] + ) + for test in TEST_CASES_TO_CURRENCY_ZMW: + self.assertEqual( + num2words(test[0], lang='uk', to='currency', + currency="ZMW"), + test[1] + ) From b5875b81f7399ec567eb10034172a23c89b8252f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0smail=20Eski?= Date: Tue, 12 Oct 2021 10:09:49 +0300 Subject: [PATCH 073/200] [ADD] to ordinal number for Turkish --- num2words/lang_TR.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/num2words/lang_TR.py b/num2words/lang_TR.py index 7fba8711..59393c29 100644 --- a/num2words/lang_TR.py +++ b/num2words/lang_TR.py @@ -806,6 +806,10 @@ def to_ordinal(self, value): return wrd + def to_ordinal_num(self, value): + self.verify_ordinal(value) + return "%s%s" % (value, self.to_ordinal(value)[-4:]) + def to_splitnum(self, val): float_digits = str(int(val * 10 ** self.precision)) if not int(val) == 0: From 3b27a09a305fa6c4b461cb01667000e6c584ede5 Mon Sep 17 00:00:00 2001 From: ismail eski Date: Wed, 17 Aug 2022 18:09:07 +0300 Subject: [PATCH 074/200] [FIX] /num2words/lang_TR.py:812:1: W293 blank line contains whitespace --- num2words/lang_TR.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/num2words/lang_TR.py b/num2words/lang_TR.py index 59393c29..ee1d6d4c 100644 --- a/num2words/lang_TR.py +++ b/num2words/lang_TR.py @@ -809,7 +809,7 @@ def to_ordinal(self, value): def to_ordinal_num(self, value): self.verify_ordinal(value) return "%s%s" % (value, self.to_ordinal(value)[-4:]) - + def to_splitnum(self, val): float_digits = str(int(val * 10 ** self.precision)) if not int(val) == 0: From 5a8a17d1445943192ec4f16357bd2385763caeb0 Mon Sep 17 00:00:00 2001 From: Marlon Rodriguez Date: Sat, 19 Mar 2022 19:12:19 -0400 Subject: [PATCH 075/200] feat: ci: replace travis by github workflows --- .github/workflows/ci.yml | 45 ++++++++++++++++++++++++++++++++++++++++ .travis.yml | 20 ------------------ requirements-test.txt | 1 + tox.ini | 19 ++++++++++------- 4 files changed, 58 insertions(+), 27 deletions(-) create mode 100644 .github/workflows/ci.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..9bc095e5 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,45 @@ +name: CI + +on: [push, pull_request] + +jobs: + build: + + runs-on: ubuntu-latest + strategy: + matrix: + python-version: [3.6, 3.7, 3.8, 3.9, '3.10'] + + steps: + - uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install tox tox-gh-actions coveralls + pip install -r requirements-test.txt + - name: Test with tox + run: | + tox + - name: Upload coverage data to coveralls.io + run: coveralls --service=github + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + COVERALLS_FLAG_NAME: ${{ matrix.python-version }} + COVERALLS_PARALLEL: true + + coveralls: + name: Indicate completion to coveralls.io + needs: build + runs-on: ubuntu-latest + container: python:3-slim + steps: + - name: Finished + run: | + pip3 install --upgrade coveralls + coveralls --service=github --finish + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index aa600d03..00000000 --- a/.travis.yml +++ /dev/null @@ -1,20 +0,0 @@ -sudo: false -language: python -python: - - "2.7" - - "3.4" - - "3.5" - - "3.6" -matrix: - include: - - { python: 3.6, env: TOXENV=flake8 } - - { python: 3.6, env: TOXENV=isort } - # Py37 requires xenial distrubution and sudo - # See travis-ci/travis-ci#9069 - - { python: 3.7, dist: xenial, sudo: true } - -install: - - pip install tox-travis - - pip install coveralls -script: tox -after_success: if [ -e .coverage ]; then coveralls; fi diff --git a/requirements-test.txt b/requirements-test.txt index 7165ac7e..3d9b3a23 100644 --- a/requirements-test.txt +++ b/requirements-test.txt @@ -1,3 +1,4 @@ +tox flake8 flake8-copyright isort diff --git a/tox.ini b/tox.ini index 11c8f61b..11cf12a3 100644 --- a/tox.ini +++ b/tox.ini @@ -1,8 +1,17 @@ [tox] -envlist = flake8,isort,py27,py34,py35,py36,py37 +envlist = py36,py37,py38,py39,py310,flake8,isort + +[gh-actions] +python = + 3.6: py36 + 3.7: py37 + 3.8: py38 + 3.9: py39 + 3.10: isort, flake8, py310 + [testenv] -passenv = TRAVIS TRAVIS_* +passenv = GITHUB_* deps = coverage delegator.py @@ -25,8 +34,4 @@ deps = isort delegator.py commands = - isort --check-only --recursive --diff num2words tests - -[testenv:py27] -setenv = - PYTHONIOENCODING = UTF-8 + isort --check-only --float-to-top --diff num2words tests From 0b896c5c7d8ec92f57993a050901853c629f6d32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7al?= <11833677+gonsalet@users.noreply.github.com> Date: Wed, 16 Feb 2022 17:09:55 +0100 Subject: [PATCH 076/200] =?UTF-8?q?Orthography=20fixes:=20added=202=20miss?= =?UTF-8?q?ing=20accents=20(dieciseis->diecis=C3=A9is=20;=20dolar->d=C3=B3?= =?UTF-8?q?lar)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- num2words/lang_ES.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/num2words/lang_ES.py b/num2words/lang_ES.py index d6fa77aa..18e6da52 100644 --- a/num2words/lang_ES.py +++ b/num2words/lang_ES.py @@ -21,7 +21,7 @@ from .lang_EU import Num2Word_EU -GENERIC_DOLLARS = ('dolar', 'dólares') +GENERIC_DOLLARS = ('dólar', 'dólares') GENERIC_CENTS = ('centavo', 'centavos') CURRENCIES_UNA = ('SLL', 'SEK', 'NOK', 'CZK', 'DKK', 'ISK', 'SKK', 'GBP', 'CYP', 'EGP', 'FKP', 'GIP', @@ -230,7 +230,7 @@ def setup(self): "veintiséis", "veinticinco", "veinticuatro", "veintitrés", "veintidós", "veintiuno", "veinte", "diecinueve", "dieciocho", "diecisiete", - "dieciseis", "quince", "catorce", "trece", "doce", + "dieciséis", "quince", "catorce", "trece", "doce", "once", "diez", "nueve", "ocho", "siete", "seis", "cinco", "cuatro", "tres", "dos", "uno", "cero"] self.ords = {1: "primer", From a61760bd28faf7894933747e3975d7952197b0d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7al?= <11833677+gonsalet@users.noreply.github.com> Date: Wed, 16 Feb 2022 17:57:46 +0100 Subject: [PATCH 077/200] =?UTF-8?q?Orthography=20fix:=20added=20accent=20v?= =?UTF-8?q?eintiun->veinti=C3=BAn?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- num2words/lang_ES.py | 1 + 1 file changed, 1 insertion(+) diff --git a/num2words/lang_ES.py b/num2words/lang_ES.py index 18e6da52..6291fd7d 100644 --- a/num2words/lang_ES.py +++ b/num2words/lang_ES.py @@ -363,4 +363,5 @@ def to_currency(self, val, currency='EUR', cents=True, separator=' con', list_result[0] = list_result[0].replace("uno", "una") result = " ".join(list_result) result = result.replace("uno", "un") + result = result.replace("veintiun", "veintiún") # correct orthography for this specific case return result From 1cea15170dfde2e3c1df1e38877cc06707bd3351 Mon Sep 17 00:00:00 2001 From: gonzy Date: Wed, 16 Feb 2022 18:03:51 +0100 Subject: [PATCH 078/200] =?UTF-8?q?Orthography=20fixes:=20added=20missing?= =?UTF-8?q?=20accent=20(nuevos=20dolares->nuevos=20d=C3=B3lares);=20fixed?= =?UTF-8?q?=20accents=20in=20test=5Fes.py=20(diecis=C3=A9is,=20d=C3=B3lar,?= =?UTF-8?q?=20d=C3=B3lares,=20veinti=C3=BAn)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- num2words/lang_ES.py | 2 +- tests/test_es.py | 282 +++++++++++++++++++++---------------------- 2 files changed, 142 insertions(+), 142 deletions(-) diff --git a/num2words/lang_ES.py b/num2words/lang_ES.py index 6291fd7d..ba22d131 100644 --- a/num2words/lang_ES.py +++ b/num2words/lang_ES.py @@ -184,7 +184,7 @@ class Num2Word_ES(Num2Word_EU): '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 dolares'), ('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')), diff --git a/tests/test_es.py b/tests/test_es.py index cf3a8c2b..da7ff35a 100644 --- a/tests/test_es.py +++ b/tests/test_es.py @@ -28,7 +28,7 @@ (5.5, 'cinco punto cinco'), (11, 'once'), (12, 'doce'), - (16, 'dieciseis'), + (16, 'dieciséis'), (17.42, 'diecisiete punto cuatro dos'), (19, 'diecinueve'), (20, 'veinte'), @@ -117,7 +117,7 @@ (2.00, 'dos euros con cero céntimos'), (8.00, 'ocho euros con cero céntimos'), (12.00, 'doce euros con cero céntimos'), - (21.00, 'veintiun euros con cero céntimos'), + (21.00, 'veintiún euros con cero céntimos'), (81.25, 'ochenta y un euros con veinticinco céntimos'), (350.90, 'trescientos cincuenta euros con noventa céntimos'), (100.00, 'cien euros con cero céntimos'), @@ -128,18 +128,18 @@ (2.00, 'dos pesetas con cero céntimos'), (8.00, 'ocho pesetas con cero céntimos'), (12.00, 'doce pesetas con cero céntimos'), - (21.00, 'veintiun pesetas con cero céntimos'), + (21.00, 'veintiún pesetas con cero céntimos'), (81.25, 'ochenta y un pesetas con veinticinco céntimos'), (350.90, 'trescientos cincuenta pesetas con noventa céntimos'), (100.00, 'cien pesetas con cero céntimos'), ) TEST_CASES_TO_CURRENCY_USD = ( - (1.00, 'un dolar con cero centavos'), + (1.00, 'un dólar con cero centavos'), (2.00, 'dos dólares con cero centavos'), (8.00, 'ocho dólares con cero centavos'), (12.00, 'doce dólares con cero centavos'), - (21.00, 'veintiun dólares con cero centavos'), + (21.00, 'veintiún dólares con cero centavos'), (81.25, 'ochenta y un dólares con veinticinco centavos'), (350.90, 'trescientos cincuenta dólares con noventa centavos'), (100.00, 'cien dólares con cero centavos'), @@ -150,7 +150,7 @@ (2.00, 'dos soles con cero céntimos'), (8.00, 'ocho soles con cero céntimos'), (12.00, 'doce soles con cero céntimos'), - (21.00, 'veintiun soles con cero céntimos'), + (21.00, 'veintiún soles con cero céntimos'), (81.25, 'ochenta y un soles con veinticinco céntimos'), (350.90, 'trescientos cincuenta soles con noventa céntimos'), (100.00, 'cien soles con cero céntimos'), @@ -161,7 +161,7 @@ (2.00, 'dos colones con cero centavos'), (8.00, 'ocho colones con cero centavos'), (12.00, 'doce colones con cero centavos'), - (21.00, 'veintiun colones con cero centavos'), + (21.00, 'veintiún colones con cero centavos'), (81.25, 'ochenta y un colones con veinticinco centavos'), (350.90, 'trescientos cincuenta colones con noventa centavos'), (100.00, 'cien colones con cero centavos'), @@ -174,7 +174,7 @@ (2.00, 'dos libras con cero pence'), (8.00, 'ocho libras con cero pence'), (12.00, 'doce libras con cero pence'), - (21.00, 'veintiun libras con cero pence'), + (21.00, 'veintiún libras con cero pence'), (81.25, 'ochenta y un libras con veinticinco pence'), (350.90, 'trescientos cincuenta libras con noventa pence'), (100.00, 'cien libras con cero pence'), @@ -187,7 +187,7 @@ (2.00, 'dos rublos con cero kopeykas'), (8.00, 'ocho rublos con cero kopeykas'), (12.00, 'doce rublos con cero kopeykas'), - (21.00, 'veintiun rublos con cero kopeykas'), + (21.00, 'veintiún rublos con cero kopeykas'), (81.25, 'ochenta y un rublos con veinticinco kopeykas'), (350.90, 'trescientos cincuenta rublos con noventa kopeykas'), (100.00, 'cien rublos con cero kopeykas'), @@ -200,7 +200,7 @@ (2.00, 'dos coronas con cero öre'), (8.00, 'ocho coronas con cero öre'), (12.00, 'doce coronas con cero öre'), - (21.00, 'veintiun coronas con cero öre'), + (21.00, 'veintiún coronas con cero öre'), (81.25, 'ochenta y un coronas con veinticinco öre'), (350.90, 'trescientos cincuenta coronas con noventa öre'), (100.00, 'cien coronas con cero öre'), @@ -213,7 +213,7 @@ (2.00, 'dos coronas con cero øre'), (8.00, 'ocho coronas con cero øre'), (12.00, 'doce coronas con cero øre'), - (21.00, 'veintiun coronas con cero øre'), + (21.00, 'veintiún coronas con cero øre'), (81.25, 'ochenta y un coronas con veinticinco øre'), (350.90, 'trescientos cincuenta coronas con noventa øre'), (100.00, 'cien coronas con cero øre'), @@ -226,7 +226,7 @@ (2.00, 'dos zlotys con cero groszy'), (8.00, 'ocho zlotys con cero groszy'), (12.00, 'doce zlotys con cero groszy'), - (21.00, 'veintiun zlotys con cero groszy'), + (21.00, 'veintiún zlotys con cero groszy'), (81.25, 'ochenta y un zlotys con veinticinco groszy'), (350.90, 'trescientos cincuenta zlotys con noventa groszy'), (100.00, 'cien zlotys con cero groszy'), @@ -239,7 +239,7 @@ (2.00, 'dos pesos con cero centavos'), (8.00, 'ocho pesos con cero centavos'), (12.00, 'doce pesos con cero centavos'), - (21.00, 'veintiun pesos con cero centavos'), + (21.00, 'veintiún pesos con cero centavos'), (81.25, 'ochenta y un pesos con veinticinco centavos'), (350.90, 'trescientos cincuenta pesos con noventa centavos'), (100.00, 'cien pesos con cero centavos'), @@ -252,7 +252,7 @@ (2.00, 'dos leus con cero bani'), (8.00, 'ocho leus con cero bani'), (12.00, 'doce leus con cero bani'), - (21.00, 'veintiun leus con cero bani'), + (21.00, 'veintiún leus con cero bani'), (81.25, 'ochenta y un leus con veinticinco bani'), (350.90, 'trescientos cincuenta leus con noventa bani'), (100.00, 'cien leus con cero bani'), @@ -265,7 +265,7 @@ (2.00, 'dos rupias con cero paisas'), (8.00, 'ocho rupias con cero paisas'), (12.00, 'doce rupias con cero paisas'), - (21.00, 'veintiun rupias con cero paisas'), + (21.00, 'veintiún rupias con cero paisas'), (81.25, 'ochenta y un rupias con veinticinco paisas'), (350.90, 'trescientos cincuenta rupias con noventa paisas'), (100.00, 'cien rupias con cero paisas'), @@ -278,7 +278,7 @@ (2.00, 'dos florines con cero fillér'), (8.00, 'ocho florines con cero fillér'), (12.00, 'doce florines con cero fillér'), - (21.00, 'veintiun florines con cero fillér'), + (21.00, 'veintiún florines con cero fillér'), (81.25, 'ochenta y un florines con veinticinco fillér'), (350.90, 'trescientos cincuenta florines con noventa fillér'), (100.00, 'cien florines con cero fillér'), @@ -291,7 +291,7 @@ (2.00, 'dos francos con cero céntimos'), (8.00, 'ocho francos con cero céntimos'), (12.00, 'doce francos con cero céntimos'), - (21.00, 'veintiun francos con cero céntimos'), + (21.00, 'veintiún francos con cero céntimos'), (81.25, 'ochenta y un francos con veinticinco céntimos'), (350.90, 'trescientos cincuenta francos con noventa céntimos'), (100.00, 'cien francos con cero céntimos'), @@ -304,7 +304,7 @@ (2.00, 'dos yuanes con cero jiaos'), (8.00, 'ocho yuanes con cero jiaos'), (12.00, 'doce yuanes con cero jiaos'), - (21.00, 'veintiun yuanes con cero jiaos'), + (21.00, 'veintiún yuanes con cero jiaos'), (81.25, 'ochenta y un yuanes con veinticinco jiaos'), (350.90, 'trescientos cincuenta yuanes con noventa jiaos'), (100.00, 'cien yuanes con cero jiaos'), @@ -317,7 +317,7 @@ (2.00, 'dos coronas con cero haléř'), (8.00, 'ocho coronas con cero haléř'), (12.00, 'doce coronas con cero haléř'), - (21.00, 'veintiun coronas con cero haléř'), + (21.00, 'veintiún coronas con cero haléř'), (81.25, 'ochenta y un coronas con veinticinco haléř'), (350.90, 'trescientos cincuenta coronas con noventa haléř'), (100.00, 'cien coronas con cero haléř'), @@ -330,7 +330,7 @@ (2.00, 'dos córdobas con cero centavos'), (8.00, 'ocho córdobas con cero centavos'), (12.00, 'doce córdobas con cero centavos'), - (21.00, 'veintiun córdobas con cero centavos'), + (21.00, 'veintiún córdobas con cero centavos'), (81.25, 'ochenta y un córdobas con veinticinco centavos'), (350.90, 'trescientos cincuenta córdobas con noventa centavos'), (100.00, 'cien córdobas con cero centavos'), @@ -343,7 +343,7 @@ (2.00, 'dos bolívares con cero céntimos'), (8.00, 'ocho bolívares con cero céntimos'), (12.00, 'doce bolívares con cero céntimos'), - (21.00, 'veintiun bolívares con cero céntimos'), + (21.00, 'veintiún bolívares con cero céntimos'), (81.25, 'ochenta y un bolívares con veinticinco céntimos'), (350.90, 'trescientos cincuenta bolívares con noventa céntimos'), (100.00, 'cien bolívares con cero céntimos'), @@ -356,7 +356,7 @@ (2.00, 'dos reales con cero centavos'), (8.00, 'ocho reales con cero centavos'), (12.00, 'doce reales con cero centavos'), - (21.00, 'veintiun reales con cero centavos'), + (21.00, 'veintiún reales con cero centavos'), (81.25, 'ochenta y un reales con veinticinco centavos'), (350.90, 'trescientos cincuenta reales con noventa centavos'), (100.00, 'cien reales con cero centavos'), @@ -369,7 +369,7 @@ (2.00, 'dos yenes con cero sen'), (8.00, 'ocho yenes con cero sen'), (12.00, 'doce yenes con cero sen'), - (21.00, 'veintiun yenes con cero sen'), + (21.00, 'veintiún yenes con cero sen'), (81.25, 'ochenta y un yenes con veinticinco sen'), (350.90, 'trescientos cincuenta yenes con noventa sen'), (100.00, 'cien yenes con cero sen'), @@ -382,7 +382,7 @@ (2.00, 'dos wones con cero jeon'), (8.00, 'ocho wones con cero jeon'), (12.00, 'doce wones con cero jeon'), - (21.00, 'veintiun wones con cero jeon'), + (21.00, 'veintiún wones con cero jeon'), (81.25, 'ochenta y un wones con veinticinco jeon'), (350.90, 'trescientos cincuenta wones con noventa jeon'), (100.00, 'cien wones con cero jeon'), @@ -395,7 +395,7 @@ (2.00, 'dos wones con cero chon'), (8.00, 'ocho wones con cero chon'), (12.00, 'doce wones con cero chon'), - (21.00, 'veintiun wones con cero chon'), + (21.00, 'veintiún wones con cero chon'), (81.25, 'ochenta y un wones con veinticinco chon'), (350.90, 'trescientos cincuenta wones con noventa chon'), (100.00, 'cien wones con cero chon'), @@ -408,7 +408,7 @@ (2.00, 'dos liras con cero kuruş'), (8.00, 'ocho liras con cero kuruş'), (12.00, 'doce liras con cero kuruş'), - (21.00, 'veintiun liras con cero kuruş'), + (21.00, 'veintiún liras con cero kuruş'), (81.25, 'ochenta y un liras con veinticinco kuruş'), (350.90, 'trescientos cincuenta liras con noventa kuruş'), (100.00, 'cien liras con cero kuruş'), @@ -421,7 +421,7 @@ (2.00, 'dos rands con cero céntimos'), (8.00, 'ocho rands con cero céntimos'), (12.00, 'doce rands con cero céntimos'), - (21.00, 'veintiun rands con cero céntimos'), + (21.00, 'veintiún rands con cero céntimos'), (81.25, 'ochenta y un rands con veinticinco céntimos'), (350.90, 'trescientos cincuenta rands con noventa céntimos'), (100.00, 'cien rands con cero céntimos'), @@ -434,7 +434,7 @@ (2.00, 'dos tenges con cero tïın'), (8.00, 'ocho tenges con cero tïın'), (12.00, 'doce tenges con cero tïın'), - (21.00, 'veintiun tenges con cero tïın'), + (21.00, 'veintiún tenges con cero tïın'), (81.25, 'ochenta y un tenges con veinticinco tïın'), (350.90, 'trescientos cincuenta tenges con noventa tïın'), (100.00, 'cien tenges con cero tïın'), @@ -447,7 +447,7 @@ (2.00, 'dos hryvnias con cero kopiykas'), (8.00, 'ocho hryvnias con cero kopiykas'), (12.00, 'doce hryvnias con cero kopiykas'), - (21.00, 'veintiun hryvnias con cero kopiykas'), + (21.00, 'veintiún hryvnias con cero kopiykas'), (81.25, 'ochenta y un hryvnias con veinticinco kopiykas'), (350.90, 'trescientos cincuenta hryvnias con noventa kopiykas'), (100.00, 'cien hryvnias con cero kopiykas'), @@ -460,7 +460,7 @@ (2.00, 'dos bahts con cero satang'), (8.00, 'ocho bahts con cero satang'), (12.00, 'doce bahts con cero satang'), - (21.00, 'veintiun bahts con cero satang'), + (21.00, 'veintiún bahts con cero satang'), (81.25, 'ochenta y un bahts con veinticinco satang'), (350.90, 'trescientos cincuenta bahts con noventa satang'), (100.00, 'cien bahts con cero satang'), @@ -473,7 +473,7 @@ (2.00, 'dos dirhams con cero fils'), (8.00, 'ocho dirhams con cero fils'), (12.00, 'doce dirhams con cero fils'), - (21.00, 'veintiun dirhams con cero fils'), + (21.00, 'veintiún dirhams con cero fils'), (81.25, 'ochenta y un dirhams con veinticinco fils'), (350.90, 'trescientos cincuenta dirhams con noventa fils'), (100.00, 'cien dirhams con cero fils'), @@ -486,7 +486,7 @@ (2.00, 'dos afghanis con cero puls'), (8.00, 'ocho afghanis con cero puls'), (12.00, 'doce afghanis con cero puls'), - (21.00, 'veintiun afghanis con cero puls'), + (21.00, 'veintiún afghanis con cero puls'), (81.25, 'ochenta y un afghanis con veinticinco puls'), (350.90, 'trescientos cincuenta afghanis con noventa puls'), (100.00, 'cien afghanis con cero puls'), @@ -499,7 +499,7 @@ (2.00, 'dos leke con cero qindarka'), (8.00, 'ocho leke con cero qindarka'), (12.00, 'doce leke con cero qindarka'), - (21.00, 'veintiun leke con cero qindarka'), + (21.00, 'veintiún leke con cero qindarka'), (81.25, 'ochenta y un leke con veinticinco qindarka'), (350.90, 'trescientos cincuenta leke con noventa qindarka'), (100.00, 'cien leke con cero qindarka'), @@ -512,7 +512,7 @@ (2.00, 'dos drams con cero lumas'), (8.00, 'ocho drams con cero lumas'), (12.00, 'doce drams con cero lumas'), - (21.00, 'veintiun drams con cero lumas'), + (21.00, 'veintiún drams con cero lumas'), (81.25, 'ochenta y un drams con veinticinco lumas'), (350.90, 'trescientos cincuenta drams con noventa lumas'), (100.00, 'cien drams con cero lumas'), @@ -525,7 +525,7 @@ (2.00, 'dos florines con cero centavos'), (8.00, 'ocho florines con cero centavos'), (12.00, 'doce florines con cero centavos'), - (21.00, 'veintiun florines con cero centavos'), + (21.00, 'veintiún florines con cero centavos'), (81.25, 'ochenta y un florines con veinticinco centavos'), (350.90, 'trescientos cincuenta florines con noventa centavos'), (100.00, 'cien florines con cero centavos'), @@ -538,7 +538,7 @@ (2.00, 'dos kwanzas con cero céntimos'), (8.00, 'ocho kwanzas con cero céntimos'), (12.00, 'doce kwanzas con cero céntimos'), - (21.00, 'veintiun kwanzas con cero céntimos'), + (21.00, 'veintiún kwanzas con cero céntimos'), (81.25, 'ochenta y un kwanzas con veinticinco céntimos'), (350.90, 'trescientos cincuenta kwanzas con noventa céntimos'), (100.00, 'cien kwanzas con cero céntimos'), @@ -551,7 +551,7 @@ (2.00, 'dos florines con cero centavos'), (8.00, 'ocho florines con cero centavos'), (12.00, 'doce florines con cero centavos'), - (21.00, 'veintiun florines con cero centavos'), + (21.00, 'veintiún florines con cero centavos'), (81.25, 'ochenta y un florines con veinticinco centavos'), (350.90, 'trescientos cincuenta florines con noventa centavos'), (100.00, 'cien florines con cero centavos'), @@ -564,7 +564,7 @@ (2.00, 'dos manat con cero qəpik'), (8.00, 'ocho manat con cero qəpik'), (12.00, 'doce manat con cero qəpik'), - (21.00, 'veintiun manat con cero qəpik'), + (21.00, 'veintiún manat con cero qəpik'), (81.25, 'ochenta y un manat con veinticinco qəpik'), (350.90, 'trescientos cincuenta manat con noventa qəpik'), (100.00, 'cien manat con cero qəpik'), @@ -577,7 +577,7 @@ (2.00, 'dos takas con cero paisas'), (8.00, 'ocho takas con cero paisas'), (12.00, 'doce takas con cero paisas'), - (21.00, 'veintiun takas con cero paisas'), + (21.00, 'veintiún takas con cero paisas'), (81.25, 'ochenta y un takas con veinticinco paisas'), (350.90, 'trescientos cincuenta takas con noventa paisas'), (100.00, 'cien takas con cero paisas'), @@ -590,7 +590,7 @@ (2.00, 'dos leva con cero stotinki'), (8.00, 'ocho leva con cero stotinki'), (12.00, 'doce leva con cero stotinki'), - (21.00, 'veintiun leva con cero stotinki'), + (21.00, 'veintiún leva con cero stotinki'), (81.25, 'ochenta y un leva con veinticinco stotinki'), (350.90, 'trescientos cincuenta leva con noventa stotinki'), (100.00, 'cien leva con cero stotinki'), @@ -603,7 +603,7 @@ (2.00, 'dos dinares con cero fils'), (8.00, 'ocho dinares con cero fils'), (12.00, 'doce dinares con cero fils'), - (21.00, 'veintiun dinares con cero fils'), + (21.00, 'veintiún dinares con cero fils'), (81.25, 'ochenta y un dinares con veinticinco fils'), (350.90, 'trescientos cincuenta dinares con noventa fils'), (100.00, 'cien dinares con cero fils'), @@ -616,7 +616,7 @@ (2.00, 'dos bolivianos con cero centavos'), (8.00, 'ocho bolivianos con cero centavos'), (12.00, 'doce bolivianos con cero centavos'), - (21.00, 'veintiun bolivianos con cero centavos'), + (21.00, 'veintiún bolivianos con cero centavos'), (81.25, 'ochenta y un bolivianos con veinticinco centavos'), (350.90, 'trescientos cincuenta bolivianos con noventa centavos'), (100.00, 'cien bolivianos con cero centavos'), @@ -629,7 +629,7 @@ (2.00, 'dos ngultrum con cero chetrum'), (8.00, 'ocho ngultrum con cero chetrum'), (12.00, 'doce ngultrum con cero chetrum'), - (21.00, 'veintiun ngultrum con cero chetrum'), + (21.00, 'veintiún ngultrum con cero chetrum'), (81.25, 'ochenta y un ngultrum con veinticinco chetrum'), (350.90, 'trescientos cincuenta ngultrum con noventa chetrum'), (100.00, 'cien ngultrum con cero chetrum'), @@ -642,7 +642,7 @@ (2.00, 'dos pulas con cero thebes'), (8.00, 'ocho pulas con cero thebes'), (12.00, 'doce pulas con cero thebes'), - (21.00, 'veintiun pulas con cero thebes'), + (21.00, 'veintiún pulas con cero thebes'), (81.25, 'ochenta y un pulas con veinticinco thebes'), (350.90, 'trescientos cincuenta pulas con noventa thebes'), (100.00, 'cien pulas con cero thebes'), @@ -655,7 +655,7 @@ (2.00, 'dos rublos con cero kópeks'), (8.00, 'ocho rublos con cero kópeks'), (12.00, 'doce rublos con cero kópeks'), - (21.00, 'veintiun rublos con cero kópeks'), + (21.00, 'veintiún rublos con cero kópeks'), (81.25, 'ochenta y un rublos con veinticinco kópeks'), (350.90, 'trescientos cincuenta rublos con noventa kópeks'), (100.00, 'cien rublos con cero kópeks'), @@ -668,7 +668,7 @@ (2.00, 'dos rublos con cero kópeks'), (8.00, 'ocho rublos con cero kópeks'), (12.00, 'doce rublos con cero kópeks'), - (21.00, 'veintiun rublos con cero kópeks'), + (21.00, 'veintiún rublos con cero kópeks'), (81.25, 'ochenta y un rublos con veinticinco kópeks'), (350.90, 'trescientos cincuenta rublos con noventa kópeks'), (100.00, 'cien rublos con cero kópeks'), @@ -677,11 +677,11 @@ ) TEST_CASES_TO_CURRENCY_BZD = ( - (1.00, 'un dolar con cero céntimos'), + (1.00, 'un dólar con cero céntimos'), (2.00, 'dos dólares con cero céntimos'), (8.00, 'ocho dólares con cero céntimos'), (12.00, 'doce dólares con cero céntimos'), - (21.00, 'veintiun dólares con cero céntimos'), + (21.00, 'veintiún dólares con cero céntimos'), (81.25, 'ochenta y un dólares con veinticinco céntimos'), (350.90, 'trescientos cincuenta dólares con noventa céntimos'), (100.00, 'cien dólares con cero céntimos'), @@ -694,7 +694,7 @@ (2.00, 'dos escudos con cero centavos'), (8.00, 'ocho escudos con cero centavos'), (12.00, 'doce escudos con cero centavos'), - (21.00, 'veintiun escudos con cero centavos'), + (21.00, 'veintiún escudos con cero centavos'), (81.25, 'ochenta y un escudos con veinticinco centavos'), (350.90, 'trescientos cincuenta escudos con noventa centavos'), (100.00, 'cien escudos con cero centavos'), @@ -707,7 +707,7 @@ (2.00, 'dos libras con cero céntimos'), (8.00, 'ocho libras con cero céntimos'), (12.00, 'doce libras con cero céntimos'), - (21.00, 'veintiun libras con cero céntimos'), + (21.00, 'veintiún libras con cero céntimos'), (81.25, 'ochenta y un libras con veinticinco céntimos'), (350.90, 'trescientos cincuenta libras con noventa céntimos'), (100.00, 'cien libras con cero céntimos'), @@ -720,7 +720,7 @@ (2.00, 'dos coronas con cero øre'), (8.00, 'ocho coronas con cero øre'), (12.00, 'doce coronas con cero øre'), - (21.00, 'veintiun coronas con cero øre'), + (21.00, 'veintiún coronas con cero øre'), (81.25, 'ochenta y un coronas con veinticinco øre'), (350.90, 'trescientos cincuenta coronas con noventa øre'), (100.00, 'cien coronas con cero øre'), @@ -733,7 +733,7 @@ (2.00, 'dos dinares con cero céntimos'), (8.00, 'ocho dinares con cero céntimos'), (12.00, 'doce dinares con cero céntimos'), - (21.00, 'veintiun dinares con cero céntimos'), + (21.00, 'veintiún dinares con cero céntimos'), (81.25, 'ochenta y un dinares con veinticinco céntimos'), (350.90, 'trescientos cincuenta dinares con noventa céntimos'), (100.00, 'cien dinares con cero céntimos'), @@ -746,7 +746,7 @@ (2.00, 'dos sucres con cero centavos'), (8.00, 'ocho sucres con cero centavos'), (12.00, 'doce sucres con cero centavos'), - (21.00, 'veintiun sucres con cero centavos'), + (21.00, 'veintiún sucres con cero centavos'), (81.25, 'ochenta y un sucres con veinticinco centavos'), (350.90, 'trescientos cincuenta sucres con noventa centavos'), (100.00, 'cien sucres con cero centavos'), @@ -759,7 +759,7 @@ (2.00, 'dos libras con cero piastras'), (8.00, 'ocho libras con cero piastras'), (12.00, 'doce libras con cero piastras'), - (21.00, 'veintiun libras con cero piastras'), + (21.00, 'veintiún libras con cero piastras'), (81.25, 'ochenta y un libras con veinticinco piastras'), (350.90, 'trescientos cincuenta libras con noventa piastras'), (100.00, 'cien libras con cero piastras'), @@ -772,7 +772,7 @@ (2.00, 'dos nakfas con cero céntimos'), (8.00, 'ocho nakfas con cero céntimos'), (12.00, 'doce nakfas con cero céntimos'), - (21.00, 'veintiun nakfas con cero céntimos'), + (21.00, 'veintiún nakfas con cero céntimos'), (81.25, 'ochenta y un nakfas con veinticinco céntimos'), (350.90, 'trescientos cincuenta nakfas con noventa céntimos'), (100.00, 'cien nakfas con cero céntimos'), @@ -785,7 +785,7 @@ (2.00, 'dos birrs con cero céntimos'), (8.00, 'ocho birrs con cero céntimos'), (12.00, 'doce birrs con cero céntimos'), - (21.00, 'veintiun birrs con cero céntimos'), + (21.00, 'veintiún birrs con cero céntimos'), (81.25, 'ochenta y un birrs con veinticinco céntimos'), (350.90, 'trescientos cincuenta birrs con noventa céntimos'), (100.00, 'cien birrs con cero céntimos'), @@ -798,7 +798,7 @@ (2.00, 'dos libras con cero peniques'), (8.00, 'ocho libras con cero peniques'), (12.00, 'doce libras con cero peniques'), - (21.00, 'veintiun libras con cero peniques'), + (21.00, 'veintiún libras con cero peniques'), (81.25, 'ochenta y un libras con veinticinco peniques'), (350.90, 'trescientos cincuenta libras con noventa peniques'), (100.00, 'cien libras con cero peniques'), @@ -811,7 +811,7 @@ (2.00, 'dos laris con cero tetris'), (8.00, 'ocho laris con cero tetris'), (12.00, 'doce laris con cero tetris'), - (21.00, 'veintiun laris con cero tetris'), + (21.00, 'veintiún laris con cero tetris'), (81.25, 'ochenta y un laris con veinticinco tetris'), (350.90, 'trescientos cincuenta laris con noventa tetris'), (100.00, 'cien laris con cero tetris'), @@ -824,7 +824,7 @@ (2.00, 'dos cedis con cero pesewas'), (8.00, 'ocho cedis con cero pesewas'), (12.00, 'doce cedis con cero pesewas'), - (21.00, 'veintiun cedis con cero pesewas'), + (21.00, 'veintiún cedis con cero pesewas'), (81.25, 'ochenta y un cedis con veinticinco pesewas'), (350.90, 'trescientos cincuenta cedis con noventa pesewas'), (100.00, 'cien cedis con cero pesewas'), @@ -837,7 +837,7 @@ (2.00, 'dos dalasis con cero bututs'), (8.00, 'ocho dalasis con cero bututs'), (12.00, 'doce dalasis con cero bututs'), - (21.00, 'veintiun dalasis con cero bututs'), + (21.00, 'veintiún dalasis con cero bututs'), (81.25, 'ochenta y un dalasis con veinticinco bututs'), (350.90, 'trescientos cincuenta dalasis con noventa bututs'), (100.00, 'cien dalasis con cero bututs'), @@ -850,7 +850,7 @@ (2.00, 'dos quetzales con cero centavos'), (8.00, 'ocho quetzales con cero centavos'), (12.00, 'doce quetzales con cero centavos'), - (21.00, 'veintiun quetzales con cero centavos'), + (21.00, 'veintiún quetzales con cero centavos'), (81.25, 'ochenta y un quetzales con veinticinco centavos'), (350.90, 'trescientos cincuenta quetzales con noventa centavos'), (100.00, 'cien quetzales con cero centavos'), @@ -863,7 +863,7 @@ (2.00, 'dos lempiras con cero centavos'), (8.00, 'ocho lempiras con cero centavos'), (12.00, 'doce lempiras con cero centavos'), - (21.00, 'veintiun lempiras con cero centavos'), + (21.00, 'veintiún lempiras con cero centavos'), (81.25, 'ochenta y un lempiras con veinticinco centavos'), (350.90, 'trescientos cincuenta lempiras con noventa centavos'), (100.00, 'cien lempiras con cero centavos'), @@ -876,7 +876,7 @@ (2.00, 'dos kunas con cero lipas'), (8.00, 'ocho kunas con cero lipas'), (12.00, 'doce kunas con cero lipas'), - (21.00, 'veintiun kunas con cero lipas'), + (21.00, 'veintiún kunas con cero lipas'), (81.25, 'ochenta y un kunas con veinticinco lipas'), (350.90, 'trescientos cincuenta kunas con noventa lipas'), (100.00, 'cien kunas con cero lipas'), @@ -889,7 +889,7 @@ (2.00, 'dos gourdes con cero céntimos'), (8.00, 'ocho gourdes con cero céntimos'), (12.00, 'doce gourdes con cero céntimos'), - (21.00, 'veintiun gourdes con cero céntimos'), + (21.00, 'veintiún gourdes con cero céntimos'), (81.25, 'ochenta y un gourdes con veinticinco céntimos'), (350.90, 'trescientos cincuenta gourdes con noventa céntimos'), (100.00, 'cien gourdes con cero céntimos'), @@ -902,7 +902,7 @@ (2.00, 'dos rupias con cero céntimos'), (8.00, 'ocho rupias con cero céntimos'), (12.00, 'doce rupias con cero céntimos'), - (21.00, 'veintiun rupias con cero céntimos'), + (21.00, 'veintiún rupias con cero céntimos'), (81.25, 'ochenta y un rupias con veinticinco céntimos'), (350.90, 'trescientos cincuenta rupias con noventa céntimos'), (100.00, 'cien rupias con cero céntimos'), @@ -915,7 +915,7 @@ (2.00, 'dos séqueles con cero agoras'), (8.00, 'ocho séqueles con cero agoras'), (12.00, 'doce séqueles con cero agoras'), - (21.00, 'veintiun séqueles con cero agoras'), + (21.00, 'veintiún séqueles con cero agoras'), (81.25, 'ochenta y un séqueles con veinticinco agoras'), (350.90, 'trescientos cincuenta séqueles con noventa agoras'), (100.00, 'cien séqueles con cero agoras'), @@ -928,7 +928,7 @@ (2.00, 'dos dinares con cero fils'), (8.00, 'ocho dinares con cero fils'), (12.00, 'doce dinares con cero fils'), - (21.00, 'veintiun dinares con cero fils'), + (21.00, 'veintiún dinares con cero fils'), (81.25, 'ochenta y un dinares con veinticinco fils'), (350.90, 'trescientos cincuenta dinares con noventa fils'), (100.00, 'cien dinares con cero fils'), @@ -941,7 +941,7 @@ (2.00, 'dos riales con cero dinares'), (8.00, 'ocho riales con cero dinares'), (12.00, 'doce riales con cero dinares'), - (21.00, 'veintiun riales con cero dinares'), + (21.00, 'veintiún riales con cero dinares'), (81.25, 'ochenta y un riales con veinticinco dinares'), (350.90, 'trescientos cincuenta riales con noventa dinares'), (100.00, 'cien riales con cero dinares'), @@ -954,7 +954,7 @@ (2.00, 'dos coronas con cero aurar'), (8.00, 'ocho coronas con cero aurar'), (12.00, 'doce coronas con cero aurar'), - (21.00, 'veintiun coronas con cero aurar'), + (21.00, 'veintiún coronas con cero aurar'), (81.25, 'ochenta y un coronas con veinticinco aurar'), (350.90, 'trescientos cincuenta coronas con noventa aurar'), (100.00, 'cien coronas con cero aurar'), @@ -967,7 +967,7 @@ (2.00, 'dos liras con cero céntimos'), (8.00, 'ocho liras con cero céntimos'), (12.00, 'doce liras con cero céntimos'), - (21.00, 'veintiun liras con cero céntimos'), + (21.00, 'veintiún liras con cero céntimos'), (81.25, 'ochenta y un liras con veinticinco céntimos'), (350.90, 'trescientos cincuenta liras con noventa céntimos'), (100.00, 'cien liras con cero céntimos'), @@ -980,7 +980,7 @@ (2.00, 'dos dinares con cero piastras'), (8.00, 'ocho dinares con cero piastras'), (12.00, 'doce dinares con cero piastras'), - (21.00, 'veintiun dinares con cero piastras'), + (21.00, 'veintiún dinares con cero piastras'), (81.25, 'ochenta y un dinares con veinticinco piastras'), (350.90, 'trescientos cincuenta dinares con noventa piastras'), (100.00, 'cien dinares con cero piastras'), @@ -993,7 +993,7 @@ (2.00, 'dos chelines con cero céntimos'), (8.00, 'ocho chelines con cero céntimos'), (12.00, 'doce chelines con cero céntimos'), - (21.00, 'veintiun chelines con cero céntimos'), + (21.00, 'veintiún chelines con cero céntimos'), (81.25, 'ochenta y un chelines con veinticinco céntimos'), (350.90, 'trescientos cincuenta chelines con noventa céntimos'), (100.00, 'cien chelines con cero céntimos'), @@ -1006,7 +1006,7 @@ (2.00, 'dos som con cero tyiyn'), (8.00, 'ocho som con cero tyiyn'), (12.00, 'doce som con cero tyiyn'), - (21.00, 'veintiun som con cero tyiyn'), + (21.00, 'veintiún som con cero tyiyn'), (81.25, 'ochenta y un som con veinticinco tyiyn'), (350.90, 'trescientos cincuenta som con noventa tyiyn'), (100.00, 'cien som con cero tyiyn'), @@ -1019,7 +1019,7 @@ (2.00, 'dos rieles con cero céntimos'), (8.00, 'ocho rieles con cero céntimos'), (12.00, 'doce rieles con cero céntimos'), - (21.00, 'veintiun rieles con cero céntimos'), + (21.00, 'veintiún rieles con cero céntimos'), (81.25, 'ochenta y un rieles con veinticinco céntimos'), (350.90, 'trescientos cincuenta rieles con noventa céntimos'), (100.00, 'cien rieles con cero céntimos'), @@ -1032,7 +1032,7 @@ (2.00, 'dos dinares con cero fils'), (8.00, 'ocho dinares con cero fils'), (12.00, 'doce dinares con cero fils'), - (21.00, 'veintiun dinares con cero fils'), + (21.00, 'veintiún dinares con cero fils'), (81.25, 'ochenta y un dinares con veinticinco fils'), (350.90, 'trescientos cincuenta dinares con noventa fils'), (100.00, 'cien dinares con cero fils'), @@ -1045,7 +1045,7 @@ (2.00, 'dos kips con cero att'), (8.00, 'ocho kips con cero att'), (12.00, 'doce kips con cero att'), - (21.00, 'veintiun kips con cero att'), + (21.00, 'veintiún kips con cero att'), (81.25, 'ochenta y un kips con veinticinco att'), (350.90, 'trescientos cincuenta kips con noventa att'), (100.00, 'cien kips con cero att'), @@ -1058,7 +1058,7 @@ (2.00, 'dos rupias con cero céntimos'), (8.00, 'ocho rupias con cero céntimos'), (12.00, 'doce rupias con cero céntimos'), - (21.00, 'veintiun rupias con cero céntimos'), + (21.00, 'veintiún rupias con cero céntimos'), (81.25, 'ochenta y un rupias con veinticinco céntimos'), (350.90, 'trescientos cincuenta rupias con noventa céntimos'), (100.00, 'cien rupias con cero céntimos'), @@ -1071,7 +1071,7 @@ (2.00, 'dos lotis con cero céntimos'), (8.00, 'ocho lotis con cero céntimos'), (12.00, 'doce lotis con cero céntimos'), - (21.00, 'veintiun lotis con cero céntimos'), + (21.00, 'veintiún lotis con cero céntimos'), (81.25, 'ochenta y un lotis con veinticinco céntimos'), (350.90, 'trescientos cincuenta lotis con noventa céntimos'), (100.00, 'cien lotis con cero céntimos'), @@ -1084,7 +1084,7 @@ (2.00, 'dos litas con cero céntimos'), (8.00, 'ocho litas con cero céntimos'), (12.00, 'doce litas con cero céntimos'), - (21.00, 'veintiun litas con cero céntimos'), + (21.00, 'veintiún litas con cero céntimos'), (81.25, 'ochenta y un litas con veinticinco céntimos'), (350.90, 'trescientos cincuenta litas con noventa céntimos'), (100.00, 'cien litas con cero céntimos'), @@ -1097,7 +1097,7 @@ (2.00, 'dos lats con cero céntimos'), (8.00, 'ocho lats con cero céntimos'), (12.00, 'doce lats con cero céntimos'), - (21.00, 'veintiun lats con cero céntimos'), + (21.00, 'veintiún lats con cero céntimos'), (81.25, 'ochenta y un lats con veinticinco céntimos'), (350.90, 'trescientos cincuenta lats con noventa céntimos'), (100.00, 'cien lats con cero céntimos'), @@ -1110,7 +1110,7 @@ (2.00, 'dos dinares con cero dírhams'), (8.00, 'ocho dinares con cero dírhams'), (12.00, 'doce dinares con cero dírhams'), - (21.00, 'veintiun dinares con cero dírhams'), + (21.00, 'veintiún dinares con cero dírhams'), (81.25, 'ochenta y un dinares con veinticinco dírhams'), (350.90, 'trescientos cincuenta dinares con noventa dírhams'), (100.00, 'cien dinares con cero dírhams'), @@ -1123,7 +1123,7 @@ (2.00, 'dos dirhams con cero céntimos'), (8.00, 'ocho dirhams con cero céntimos'), (12.00, 'doce dirhams con cero céntimos'), - (21.00, 'veintiun dirhams con cero céntimos'), + (21.00, 'veintiún dirhams con cero céntimos'), (81.25, 'ochenta y un dirhams con veinticinco céntimos'), (350.90, 'trescientos cincuenta dirhams con noventa céntimos'), (100.00, 'cien dirhams con cero céntimos'), @@ -1136,7 +1136,7 @@ (2.00, 'dos lei con cero bani'), (8.00, 'ocho lei con cero bani'), (12.00, 'doce lei con cero bani'), - (21.00, 'veintiun lei con cero bani'), + (21.00, 'veintiún lei con cero bani'), (81.25, 'ochenta y un lei con veinticinco bani'), (350.90, 'trescientos cincuenta lei con noventa bani'), (100.00, 'cien lei con cero bani'), @@ -1149,7 +1149,7 @@ (2.00, 'dos ariaris con cero iraimbilanja'), (8.00, 'ocho ariaris con cero iraimbilanja'), (12.00, 'doce ariaris con cero iraimbilanja'), - (21.00, 'veintiun ariaris con cero iraimbilanja'), + (21.00, 'veintiún ariaris con cero iraimbilanja'), (81.25, 'ochenta y un ariaris con veinticinco iraimbilanja'), (350.90, 'trescientos cincuenta ariaris con noventa iraimbilanja'), (100.00, 'cien ariaris con cero iraimbilanja'), @@ -1162,7 +1162,7 @@ (2.00, 'dos denares con cero denis'), (8.00, 'ocho denares con cero denis'), (12.00, 'doce denares con cero denis'), - (21.00, 'veintiun denares con cero denis'), + (21.00, 'veintiún denares con cero denis'), (81.25, 'ochenta y un denares con veinticinco denis'), (350.90, 'trescientos cincuenta denares con noventa denis'), (100.00, 'cien denares con cero denis'), @@ -1175,7 +1175,7 @@ (2.00, 'dos kiats con cero pyas'), (8.00, 'ocho kiats con cero pyas'), (12.00, 'doce kiats con cero pyas'), - (21.00, 'veintiun kiats con cero pyas'), + (21.00, 'veintiún kiats con cero pyas'), (81.25, 'ochenta y un kiats con veinticinco pyas'), (350.90, 'trescientos cincuenta kiats con noventa pyas'), (100.00, 'cien kiats con cero pyas'), @@ -1188,7 +1188,7 @@ (2.00, 'dos tugriks con cero möngö'), (8.00, 'ocho tugriks con cero möngö'), (12.00, 'doce tugriks con cero möngö'), - (21.00, 'veintiun tugriks con cero möngö'), + (21.00, 'veintiún tugriks con cero möngö'), (81.25, 'ochenta y un tugriks con veinticinco möngö'), (350.90, 'trescientos cincuenta tugriks con noventa möngö'), (100.00, 'cien tugriks con cero möngö'), @@ -1201,7 +1201,7 @@ (2.00, 'dos patacas con cero avos'), (8.00, 'ocho patacas con cero avos'), (12.00, 'doce patacas con cero avos'), - (21.00, 'veintiun patacas con cero avos'), + (21.00, 'veintiún patacas con cero avos'), (81.25, 'ochenta y un patacas con veinticinco avos'), (350.90, 'trescientos cincuenta patacas con noventa avos'), (100.00, 'cien patacas con cero avos'), @@ -1214,7 +1214,7 @@ (2.00, 'dos ouguiyas con cero khoums'), (8.00, 'ocho ouguiyas con cero khoums'), (12.00, 'doce ouguiyas con cero khoums'), - (21.00, 'veintiun ouguiyas con cero khoums'), + (21.00, 'veintiún ouguiyas con cero khoums'), (81.25, 'ochenta y un ouguiyas con veinticinco khoums'), (350.90, 'trescientos cincuenta ouguiyas con noventa khoums'), (100.00, 'cien ouguiyas con cero khoums'), @@ -1227,7 +1227,7 @@ (2.00, 'dos ouguiyas con cero khoums'), (8.00, 'ocho ouguiyas con cero khoums'), (12.00, 'doce ouguiyas con cero khoums'), - (21.00, 'veintiun ouguiyas con cero khoums'), + (21.00, 'veintiún ouguiyas con cero khoums'), (81.25, 'ochenta y un ouguiyas con veinticinco khoums'), (350.90, 'trescientos cincuenta ouguiyas con noventa khoums'), (100.00, 'cien ouguiyas con cero khoums'), @@ -1240,7 +1240,7 @@ (2.00, 'dos rupias con cero céntimos'), (8.00, 'ocho rupias con cero céntimos'), (12.00, 'doce rupias con cero céntimos'), - (21.00, 'veintiun rupias con cero céntimos'), + (21.00, 'veintiún rupias con cero céntimos'), (81.25, 'ochenta y un rupias con veinticinco céntimos'), (350.90, 'trescientos cincuenta rupias con noventa céntimos'), (100.00, 'cien rupias con cero céntimos'), @@ -1253,7 +1253,7 @@ (2.00, 'dos rufiyaas con cero laari'), (8.00, 'ocho rufiyaas con cero laari'), (12.00, 'doce rufiyaas con cero laari'), - (21.00, 'veintiun rufiyaas con cero laari'), + (21.00, 'veintiún rufiyaas con cero laari'), (81.25, 'ochenta y un rufiyaas con veinticinco laari'), (350.90, 'trescientos cincuenta rufiyaas con noventa laari'), (100.00, 'cien rufiyaas con cero laari'), @@ -1266,7 +1266,7 @@ (2.00, 'dos kuachas con cero tambalas'), (8.00, 'ocho kuachas con cero tambalas'), (12.00, 'doce kuachas con cero tambalas'), - (21.00, 'veintiun kuachas con cero tambalas'), + (21.00, 'veintiún kuachas con cero tambalas'), (81.25, 'ochenta y un kuachas con veinticinco tambalas'), (350.90, 'trescientos cincuenta kuachas con noventa tambalas'), (100.00, 'cien kuachas con cero tambalas'), @@ -1279,7 +1279,7 @@ (2.00, 'dos ringgit con cero céntimos'), (8.00, 'ocho ringgit con cero céntimos'), (12.00, 'doce ringgit con cero céntimos'), - (21.00, 'veintiun ringgit con cero céntimos'), + (21.00, 'veintiún ringgit con cero céntimos'), (81.25, 'ochenta y un ringgit con veinticinco céntimos'), (350.90, 'trescientos cincuenta ringgit con noventa céntimos'), (100.00, 'cien ringgit con cero céntimos'), @@ -1292,7 +1292,7 @@ (2.00, 'dos metical con cero centavos'), (8.00, 'ocho metical con cero centavos'), (12.00, 'doce metical con cero centavos'), - (21.00, 'veintiun metical con cero centavos'), + (21.00, 'veintiún metical con cero centavos'), (81.25, 'ochenta y un metical con veinticinco centavos'), (350.90, 'trescientos cincuenta metical con noventa centavos'), (100.00, 'cien metical con cero centavos'), @@ -1305,7 +1305,7 @@ (2.00, 'dos nairas con cero kobo'), (8.00, 'ocho nairas con cero kobo'), (12.00, 'doce nairas con cero kobo'), - (21.00, 'veintiun nairas con cero kobo'), + (21.00, 'veintiún nairas con cero kobo'), (81.25, 'ochenta y un nairas con veinticinco kobo'), (350.90, 'trescientos cincuenta nairas con noventa kobo'), (100.00, 'cien nairas con cero kobo'), @@ -1318,7 +1318,7 @@ (2.00, 'dos rupias con cero paisas'), (8.00, 'ocho rupias con cero paisas'), (12.00, 'doce rupias con cero paisas'), - (21.00, 'veintiun rupias con cero paisas'), + (21.00, 'veintiún rupias con cero paisas'), (81.25, 'ochenta y un rupias con veinticinco paisas'), (350.90, 'trescientos cincuenta rupias con noventa paisas'), (100.00, 'cien rupias con cero paisas'), @@ -1331,7 +1331,7 @@ (2.00, 'dos riales con cero baisa'), (8.00, 'ocho riales con cero baisa'), (12.00, 'doce riales con cero baisa'), - (21.00, 'veintiun riales con cero baisa'), + (21.00, 'veintiún riales con cero baisa'), (81.25, 'ochenta y un riales con veinticinco baisa'), (350.90, 'trescientos cincuenta riales con noventa baisa'), (100.00, 'cien riales con cero baisa'), @@ -1344,7 +1344,7 @@ (2.00, 'dos balboas con cero centésimos'), (8.00, 'ocho balboas con cero centésimos'), (12.00, 'doce balboas con cero centésimos'), - (21.00, 'veintiun balboas con cero centésimos'), + (21.00, 'veintiún balboas con cero centésimos'), (81.25, 'ochenta y un balboas con veinticinco centésimos'), (350.90, 'trescientos cincuenta balboas con noventa centésimos'), (100.00, 'cien balboas con cero centésimos'), @@ -1357,7 +1357,7 @@ (2.00, 'dos kinas con cero toea'), (8.00, 'ocho kinas con cero toea'), (12.00, 'doce kinas con cero toea'), - (21.00, 'veintiun kinas con cero toea'), + (21.00, 'veintiún kinas con cero toea'), (81.25, 'ochenta y un kinas con veinticinco toea'), (350.90, 'trescientos cincuenta kinas con noventa toea'), (100.00, 'cien kinas con cero toea'), @@ -1370,7 +1370,7 @@ (2.00, 'dos rupias con cero paisas'), (8.00, 'ocho rupias con cero paisas'), (12.00, 'doce rupias con cero paisas'), - (21.00, 'veintiun rupias con cero paisas'), + (21.00, 'veintiún rupias con cero paisas'), (81.25, 'ochenta y un rupias con veinticinco paisas'), (350.90, 'trescientos cincuenta rupias con noventa paisas'), (100.00, 'cien rupias con cero paisas'), @@ -1383,7 +1383,7 @@ (2.00, 'dos zlotys con cero groszy'), (8.00, 'ocho zlotys con cero groszy'), (12.00, 'doce zlotys con cero groszy'), - (21.00, 'veintiun zlotys con cero groszy'), + (21.00, 'veintiún zlotys con cero groszy'), (81.25, 'ochenta y un zlotys con veinticinco groszy'), (350.90, 'trescientos cincuenta zlotys con noventa groszy'), (100.00, 'cien zlotys con cero groszy'), @@ -1396,7 +1396,7 @@ (2.00, 'dos guaranís con cero céntimos'), (8.00, 'ocho guaranís con cero céntimos'), (12.00, 'doce guaranís con cero céntimos'), - (21.00, 'veintiun guaranís con cero céntimos'), + (21.00, 'veintiún guaranís con cero céntimos'), (81.25, 'ochenta y un guaranís con veinticinco céntimos'), (350.90, 'trescientos cincuenta guaranís con noventa céntimos'), (100.00, 'cien guaranís con cero céntimos'), @@ -1409,7 +1409,7 @@ (2.00, 'dos riales con cero dírhams'), (8.00, 'ocho riales con cero dírhams'), (12.00, 'doce riales con cero dírhams'), - (21.00, 'veintiun riales con cero dírhams'), + (21.00, 'veintiún riales con cero dírhams'), (81.25, 'ochenta y un riales con veinticinco dírhams'), (350.90, 'trescientos cincuenta riales con noventa dírhams'), (100.00, 'cien riales con cero dírhams'), @@ -1422,7 +1422,7 @@ (2.00, 'dos dinares con cero para'), (8.00, 'ocho dinares con cero para'), (12.00, 'doce dinares con cero para'), - (21.00, 'veintiun dinares con cero para'), + (21.00, 'veintiún dinares con cero para'), (81.25, 'ochenta y un dinares con veinticinco para'), (350.90, 'trescientos cincuenta dinares con noventa para'), (100.00, 'cien dinares con cero para'), @@ -1435,7 +1435,7 @@ (2.00, 'dos rublos con cero kopeks'), (8.00, 'ocho rublos con cero kopeks'), (12.00, 'doce rublos con cero kopeks'), - (21.00, 'veintiun rublos con cero kopeks'), + (21.00, 'veintiún rublos con cero kopeks'), (81.25, 'ochenta y un rublos con veinticinco kopeks'), (350.90, 'trescientos cincuenta rublos con noventa kopeks'), (100.00, 'cien rublos con cero kopeks'), @@ -1448,7 +1448,7 @@ (2.00, 'dos riales con cero halalas'), (8.00, 'ocho riales con cero halalas'), (12.00, 'doce riales con cero halalas'), - (21.00, 'veintiun riales con cero halalas'), + (21.00, 'veintiún riales con cero halalas'), (81.25, 'ochenta y un riales con veinticinco halalas'), (350.90, 'trescientos cincuenta riales con noventa halalas'), (100.00, 'cien riales con cero halalas'), @@ -1461,7 +1461,7 @@ (2.00, 'dos rupias con cero céntimos'), (8.00, 'ocho rupias con cero céntimos'), (12.00, 'doce rupias con cero céntimos'), - (21.00, 'veintiun rupias con cero céntimos'), + (21.00, 'veintiún rupias con cero céntimos'), (81.25, 'ochenta y un rupias con veinticinco céntimos'), (350.90, 'trescientos cincuenta rupias con noventa céntimos'), (100.00, 'cien rupias con cero céntimos'), @@ -1474,7 +1474,7 @@ (2.00, 'dos libras con cero peniques'), (8.00, 'ocho libras con cero peniques'), (12.00, 'doce libras con cero peniques'), - (21.00, 'veintiun libras con cero peniques'), + (21.00, 'veintiún libras con cero peniques'), (81.25, 'ochenta y un libras con veinticinco peniques'), (350.90, 'trescientos cincuenta libras con noventa peniques'), (100.00, 'cien libras con cero peniques'), @@ -1487,7 +1487,7 @@ (2.00, 'dos coronas con cero haliers'), (8.00, 'ocho coronas con cero haliers'), (12.00, 'doce coronas con cero haliers'), - (21.00, 'veintiun coronas con cero haliers'), + (21.00, 'veintiún coronas con cero haliers'), (81.25, 'ochenta y un coronas con veinticinco haliers'), (350.90, 'trescientos cincuenta coronas con noventa haliers'), (100.00, 'cien coronas con cero haliers'), @@ -1500,7 +1500,7 @@ (2.00, 'dos leonas con cero céntimos'), (8.00, 'ocho leonas con cero céntimos'), (12.00, 'doce leonas con cero céntimos'), - (21.00, 'veintiun leonas con cero céntimos'), + (21.00, 'veintiún leonas con cero céntimos'), (81.25, 'ochenta y un leonas con veinticinco céntimos'), (350.90, 'trescientos cincuenta leonas con noventa céntimos'), (100.00, 'cien leonas con cero céntimos'), @@ -1513,7 +1513,7 @@ (2.00, 'dos dobras con cero céntimos'), (8.00, 'ocho dobras con cero céntimos'), (12.00, 'doce dobras con cero céntimos'), - (21.00, 'veintiun dobras con cero céntimos'), + (21.00, 'veintiún dobras con cero céntimos'), (81.25, 'ochenta y un dobras con veinticinco céntimos'), (350.90, 'trescientos cincuenta dobras con noventa céntimos'), (100.00, 'cien dobras con cero céntimos'), @@ -1526,7 +1526,7 @@ (2.00, 'dos colones con cero centavos'), (8.00, 'ocho colones con cero centavos'), (12.00, 'doce colones con cero centavos'), - (21.00, 'veintiun colones con cero centavos'), + (21.00, 'veintiún colones con cero centavos'), (81.25, 'ochenta y un colones con veinticinco centavos'), (350.90, 'trescientos cincuenta colones con noventa centavos'), (100.00, 'cien colones con cero centavos'), @@ -1539,7 +1539,7 @@ (2.00, 'dos emalangeni con cero céntimos'), (8.00, 'ocho emalangeni con cero céntimos'), (12.00, 'doce emalangeni con cero céntimos'), - (21.00, 'veintiun emalangeni con cero céntimos'), + (21.00, 'veintiún emalangeni con cero céntimos'), (81.25, 'ochenta y un emalangeni con veinticinco céntimos'), (350.90, 'trescientos cincuenta emalangeni con noventa céntimos'), (100.00, 'cien emalangeni con cero céntimos'), @@ -1552,7 +1552,7 @@ (2.00, 'dos somonis con cero dirames'), (8.00, 'ocho somonis con cero dirames'), (12.00, 'doce somonis con cero dirames'), - (21.00, 'veintiun somonis con cero dirames'), + (21.00, 'veintiún somonis con cero dirames'), (81.25, 'ochenta y un somonis con veinticinco dirames'), (350.90, 'trescientos cincuenta somonis con noventa dirames'), (100.00, 'cien somonis con cero dirames'), @@ -1565,7 +1565,7 @@ (2.00, 'dos manat con cero tenge'), (8.00, 'ocho manat con cero tenge'), (12.00, 'doce manat con cero tenge'), - (21.00, 'veintiun manat con cero tenge'), + (21.00, 'veintiún manat con cero tenge'), (81.25, 'ochenta y un manat con veinticinco tenge'), (350.90, 'trescientos cincuenta manat con noventa tenge'), (100.00, 'cien manat con cero tenge'), @@ -1578,7 +1578,7 @@ (2.00, 'dos dinares con cero milésimos'), (8.00, 'ocho dinares con cero milésimos'), (12.00, 'doce dinares con cero milésimos'), - (21.00, 'veintiun dinares con cero milésimos'), + (21.00, 'veintiún dinares con cero milésimos'), (81.25, 'ochenta y un dinares con veinticinco milésimos'), (350.90, 'trescientos cincuenta dinares con noventa milésimos'), (100.00, 'cien dinares con cero milésimos'), @@ -1591,7 +1591,7 @@ (2.00, 'dos paangas con cero céntimos'), (8.00, 'ocho paangas con cero céntimos'), (12.00, 'doce paangas con cero céntimos'), - (21.00, 'veintiun paangas con cero céntimos'), + (21.00, 'veintiún paangas con cero céntimos'), (81.25, 'ochenta y un paangas con veinticinco céntimos'), (350.90, 'trescientos cincuenta paangas con noventa céntimos'), (100.00, 'cien paangas con cero céntimos'), @@ -1600,17 +1600,17 @@ ) wordamount = "{} {}".format("cuatro mil ciento cincuenta", - "nuevos dolares con ochenta y tres céntimos") + "nuevos dólares con ochenta y tres céntimos") TEST_CASES_TO_CURRENCY_TWD = ( (1.00, 'un nuevo dólar con cero céntimos'), - (2.00, 'dos nuevos dolares con cero céntimos'), - (8.00, 'ocho nuevos dolares con cero céntimos'), - (12.00, 'doce nuevos dolares con cero céntimos'), - (21.00, 'veintiun nuevos dolares con cero céntimos'), - (81.25, 'ochenta y un nuevos dolares con veinticinco céntimos'), - (350.90, 'trescientos cincuenta nuevos dolares con noventa céntimos'), - (100.00, 'cien nuevos dolares con cero céntimos'), + (2.00, 'dos nuevos dólares con cero céntimos'), + (8.00, 'ocho nuevos dólares con cero céntimos'), + (12.00, 'doce nuevos dólares con cero céntimos'), + (21.00, 'veintiún nuevos dólares con cero céntimos'), + (81.25, 'ochenta y un nuevos dólares con veinticinco céntimos'), + (350.90, 'trescientos cincuenta nuevos dólares con noventa céntimos'), + (100.00, 'cien nuevos dólares con cero céntimos'), (4150.83, wordamount), ) @@ -1619,7 +1619,7 @@ (2.00, 'dos chelines con cero céntimos'), (8.00, 'ocho chelines con cero céntimos'), (12.00, 'doce chelines con cero céntimos'), - (21.00, 'veintiun chelines con cero céntimos'), + (21.00, 'veintiún chelines con cero céntimos'), (81.25, 'ochenta y un chelines con veinticinco céntimos'), (350.90, 'trescientos cincuenta chelines con noventa céntimos'), (100.00, 'cien chelines con cero céntimos'), @@ -1632,7 +1632,7 @@ (2.00, 'dos hryvnias con cero kopiykas'), (8.00, 'ocho hryvnias con cero kopiykas'), (12.00, 'doce hryvnias con cero kopiykas'), - (21.00, 'veintiun hryvnias con cero kopiykas'), + (21.00, 'veintiún hryvnias con cero kopiykas'), (81.25, 'ochenta y un hryvnias con veinticinco kopiykas'), (350.90, 'trescientos cincuenta hryvnias con noventa kopiykas'), (100.00, 'cien hryvnias con cero kopiykas'), @@ -1645,7 +1645,7 @@ (2.00, 'dos chelines con cero céntimos'), (8.00, 'ocho chelines con cero céntimos'), (12.00, 'doce chelines con cero céntimos'), - (21.00, 'veintiun chelines con cero céntimos'), + (21.00, 'veintiún chelines con cero céntimos'), (81.25, 'ochenta y un chelines con veinticinco céntimos'), (350.90, 'trescientos cincuenta chelines con noventa céntimos'), (100.00, 'cien chelines con cero céntimos'), @@ -1658,7 +1658,7 @@ (2.00, 'dos pesos con cero centésimos'), (8.00, 'ocho pesos con cero centésimos'), (12.00, 'doce pesos con cero centésimos'), - (21.00, 'veintiun pesos con cero centésimos'), + (21.00, 'veintiún pesos con cero centésimos'), (81.25, 'ochenta y un pesos con veinticinco centésimos'), (350.90, 'trescientos cincuenta pesos con noventa centésimos'), (100.00, 'cien pesos con cero centésimos'), @@ -1671,7 +1671,7 @@ (2.00, 'dos sum con cero tiyin'), (8.00, 'ocho sum con cero tiyin'), (12.00, 'doce sum con cero tiyin'), - (21.00, 'veintiun sum con cero tiyin'), + (21.00, 'veintiún sum con cero tiyin'), (81.25, 'ochenta y un sum con veinticinco tiyin'), (350.90, 'trescientos cincuenta sum con noventa tiyin'), (100.00, 'cien sum con cero tiyin'), @@ -1687,7 +1687,7 @@ (2.00, 'dos bolívares fuertes con cero céntimos'), (8.00, 'ocho bolívares fuertes con cero céntimos'), (12.00, 'doce bolívares fuertes con cero céntimos'), - (21.00, 'veintiun bolívares fuertes con cero céntimos'), + (21.00, 'veintiún bolívares fuertes con cero céntimos'), (81.25, 'ochenta y un bolívares fuertes con veinticinco céntimos'), (350.90, 'trescientos cincuenta bolívares fuertes con noventa céntimos'), (100.00, 'cien bolívares fuertes con cero céntimos'), @@ -1699,7 +1699,7 @@ (2.00, 'dos dongs con cero xu'), (8.00, 'ocho dongs con cero xu'), (12.00, 'doce dongs con cero xu'), - (21.00, 'veintiun dongs con cero xu'), + (21.00, 'veintiún dongs con cero xu'), (81.25, 'ochenta y un dongs con veinticinco xu'), (350.90, 'trescientos cincuenta dongs con noventa xu'), (100.00, 'cien dongs con cero xu'), @@ -1712,7 +1712,7 @@ (2.00, 'dos vatu con cero nenhum'), (8.00, 'ocho vatu con cero nenhum'), (12.00, 'doce vatu con cero nenhum'), - (21.00, 'veintiun vatu con cero nenhum'), + (21.00, 'veintiún vatu con cero nenhum'), (81.25, 'ochenta y un vatu con veinticinco nenhum'), (350.90, 'trescientos cincuenta vatu con noventa nenhum'), (100.00, 'cien vatu con cero nenhum'), @@ -1725,7 +1725,7 @@ (2.00, 'dos tala con cero centavos'), (8.00, 'ocho tala con cero centavos'), (12.00, 'doce tala con cero centavos'), - (21.00, 'veintiun tala con cero centavos'), + (21.00, 'veintiún tala con cero centavos'), (81.25, 'ochenta y un tala con veinticinco centavos'), (350.90, 'trescientos cincuenta tala con noventa centavos'), (100.00, 'cien tala con cero centavos'), @@ -1738,7 +1738,7 @@ (2.00, 'dos francos CFA con cero céntimos'), (8.00, 'ocho francos CFA con cero céntimos'), (12.00, 'doce francos CFA con cero céntimos'), - (21.00, 'veintiun francos CFA con cero céntimos'), + (21.00, 'veintiún francos CFA con cero céntimos'), (81.25, 'ochenta y un francos CFA con veinticinco céntimos'), (350.90, 'trescientos cincuenta francos CFA con noventa céntimos'), (100.00, 'cien francos CFA con cero céntimos'), @@ -1751,7 +1751,7 @@ (2.00, 'dos francos CFP con cero céntimos'), (8.00, 'ocho francos CFP con cero céntimos'), (12.00, 'doce francos CFP con cero céntimos'), - (21.00, 'veintiun francos CFP con cero céntimos'), + (21.00, 'veintiún francos CFP con cero céntimos'), (81.25, 'ochenta y un francos CFP con veinticinco céntimos'), (350.90, 'trescientos cincuenta francos CFP con noventa céntimos'), (100.00, 'cien francos CFP con cero céntimos'), @@ -1764,7 +1764,7 @@ (2.00, 'dos riales con cero fils'), (8.00, 'ocho riales con cero fils'), (12.00, 'doce riales con cero fils'), - (21.00, 'veintiun riales con cero fils'), + (21.00, 'veintiún riales con cero fils'), (81.25, 'ochenta y un riales con veinticinco fils'), (350.90, 'trescientos cincuenta riales con noventa fils'), (100.00, 'cien riales con cero fils'), @@ -1777,7 +1777,7 @@ (2.00, 'dos dinares con cero para'), (8.00, 'ocho dinares con cero para'), (12.00, 'doce dinares con cero para'), - (21.00, 'veintiun dinares con cero para'), + (21.00, 'veintiún dinares con cero para'), (81.25, 'ochenta y un dinares con veinticinco para'), (350.90, 'trescientos cincuenta dinares con noventa para'), (100.00, 'cien dinares con cero para'), @@ -1790,7 +1790,7 @@ (2.00, 'dos kwachas con cero ngwee'), (8.00, 'ocho kwachas con cero ngwee'), (12.00, 'doce kwachas con cero ngwee'), - (21.00, 'veintiun kwachas con cero ngwee'), + (21.00, 'veintiún kwachas con cero ngwee'), (81.25, 'ochenta y un kwachas con veinticinco ngwee'), (350.90, 'trescientos cincuenta kwachas con noventa ngwee'), (100.00, 'cien kwachas con cero ngwee'), @@ -1803,7 +1803,7 @@ (2.00, 'dos zaires con cero makuta'), (8.00, 'ocho zaires con cero makuta'), (12.00, 'doce zaires con cero makuta'), - (21.00, 'veintiun zaires con cero makuta'), + (21.00, 'veintiún zaires con cero makuta'), (81.25, 'ochenta y un zaires con veinticinco makuta'), (350.90, 'trescientos cincuenta zaires con noventa makuta'), (100.00, 'cien zaires con cero makuta'), From 4afc68f233c24e59493391f83b5712e7d443744e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7al?= <11833677+gonsalet@users.noreply.github.com> Date: Wed, 16 Feb 2022 18:25:37 +0100 Subject: [PATCH 079/200] flake8 fix: fixed comment style Fixed: ./num2words/lang_ES.py:366:56: E261 at least two spaces before inline comment ./num2words/lang_ES.py:366:80: E501 line too long (100 > 79 characters) --- num2words/lang_ES.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/num2words/lang_ES.py b/num2words/lang_ES.py index ba22d131..ed66cbe1 100644 --- a/num2words/lang_ES.py +++ b/num2words/lang_ES.py @@ -363,5 +363,6 @@ def to_currency(self, val, currency='EUR', cents=True, separator=' con', list_result[0] = list_result[0].replace("uno", "una") result = " ".join(list_result) result = result.replace("uno", "un") - result = result.replace("veintiun", "veintiún") # correct orthography for this specific case + # correct orthography for the specific case of "veintiún": + result = result.replace("veintiun", "veintiún") return result From fc0c15c4b22d131bee2e7d6c3450cb318475ab30 Mon Sep 17 00:00:00 2001 From: gonzy Date: Wed, 16 Feb 2022 18:52:37 +0100 Subject: [PATCH 080/200] Fixed pound cents: penny->penique, pence->peniques; fixed tests accordingly --- num2words/lang_ES.py | 6 +++--- tests/test_es.py | 20 ++++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/num2words/lang_ES.py b/num2words/lang_ES.py index ed66cbe1..80a630fa 100644 --- a/num2words/lang_ES.py +++ b/num2words/lang_ES.py @@ -39,7 +39,7 @@ class Num2Word_ES(Num2Word_EU): 'CRC': (('colón', 'colones'), GENERIC_CENTS), 'AUD': (GENERIC_DOLLARS, GENERIC_CENTS), 'CAD': (GENERIC_DOLLARS, GENERIC_CENTS), - 'GBP': (('libra', 'libras'), ('penny', 'pence')), + 'GBP': (('libra', 'libras'), ('penique', 'peniques')), 'RUB': (('rublo', 'rublos'), ('kopeyka', 'kopeykas')), 'SEK': (('corona', 'coronas'), ('öre', 'öre')), 'NOK': (('corona', 'coronas'), ('øre', 'øre')), @@ -101,7 +101,7 @@ class Num2Word_ES(Num2Word_EU): 'ERN': (('nakfa', 'nakfas'), ('céntimo', 'céntimos')), 'ETB': (('birr', 'birrs'), ('céntimo', 'céntimos')), 'FJD': (GENERIC_DOLLARS, GENERIC_CENTS), - 'FKP': (('libra', 'libras'), ('penny', 'peniques')), + 'FKP': (('libra', 'libras'), ('penique', 'peniques')), 'GEL': (('lari', 'laris'), ('tetri', 'tetris')), 'GHS': (('cedi', 'cedis'), ('pesewa', 'pesewas')), 'GIP': (('libra', 'libras'), ('penique', 'peniques')), @@ -170,7 +170,7 @@ class Num2Word_ES(Num2Word_EU): 'SCR': (('rupia', 'rupias'), ('céntimo', 'céntimos')), 'SDG': (('libra', 'libras'), ('piastra', 'piastras')), 'SGD': (GENERIC_DOLLARS, ('céntimo', 'céntimos')), - 'SHP': (('libra', 'libras'), ('penny', 'peniques')), + 'SHP': (('libra', 'libras'), ('penique', 'peniques')), 'SKK': (('corona', 'coronas'), ('halier', 'haliers')), 'SLL': (('leona', 'leonas'), ('céntimo', 'céntimos')), 'SRD': (GENERIC_DOLLARS, ('céntimo', 'céntimos')), diff --git a/tests/test_es.py b/tests/test_es.py index da7ff35a..2ac5f124 100644 --- a/tests/test_es.py +++ b/tests/test_es.py @@ -170,16 +170,16 @@ ) TEST_CASES_TO_CURRENCY_GBP = ( - (1.00, 'una libra con cero pence'), - (2.00, 'dos libras con cero pence'), - (8.00, 'ocho libras con cero pence'), - (12.00, 'doce libras con cero pence'), - (21.00, 'veintiún libras con cero pence'), - (81.25, 'ochenta y un libras con veinticinco pence'), - (350.90, 'trescientos cincuenta libras con noventa pence'), - (100.00, 'cien libras con cero pence'), - (4150.83, - 'cuatro mil ciento cincuenta libras con ochenta y tres pence'), + (1.00, 'una libra con cero peniques'), + (2.00, 'dos libras con cero peniques'), + (8.00, 'ocho libras con cero peniques'), + (12.00, 'doce libras con cero peniques'), + (21.00, 'veintiún libras con cero peniques'), + (81.25, 'ochenta y un libras con veinticinco peniques'), + (350.90, 'trescientos cincuenta libras con noventa peniques'), + (100.00, 'cien libras con cero peniques'), + (4150.83, + 'cuatro mil ciento cincuenta libras con ochenta y tres peniques'), ) TEST_CASES_TO_CURRENCY_RUB = ( From 0ee149a4c89c7b432ad62075b35ce89e4e3b1d4e Mon Sep 17 00:00:00 2001 From: gonzy Date: Wed, 16 Feb 2022 18:56:55 +0100 Subject: [PATCH 081/200] Added test covering new fix penny->penique --- tests/test_es.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_es.py b/tests/test_es.py index 2ac5f124..9032354c 100644 --- a/tests/test_es.py +++ b/tests/test_es.py @@ -171,6 +171,7 @@ TEST_CASES_TO_CURRENCY_GBP = ( (1.00, 'una libra con cero peniques'), + (1.01, 'una libra con un penique'), (2.00, 'dos libras con cero peniques'), (8.00, 'ocho libras con cero peniques'), (12.00, 'doce libras con cero peniques'), From d4c979ea52dfdb94e2252f4bdbd790a399b0a24c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7al?= <11833677+gonsalet@users.noreply.github.com> Date: Sun, 6 Mar 2022 00:36:40 +0100 Subject: [PATCH 082/200] =?UTF-8?q?Fixed=20accent=20in=20examples=20("cent?= =?UTF-8?q?imos"->"c=C3=A9ntimos")?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed accent in Spanish examples ("centimos"->"céntimos"), thus making the example consistent with actual current behaviour. --- bin/num2words | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/num2words b/bin/num2words index 068abf25..02cfc69e 100755 --- a/bin/num2words +++ b/bin/num2words @@ -46,7 +46,7 @@ Examples: veinticuatro mil ciento veinte punto uno $num2words 2.14 -l es --to currency - dos euros con catorce centimos + dos euros con catorce céntimos """ from __future__ import print_function, unicode_literals From db5e1d175fedee3240854b0beac2deb88868fc4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gon=C3=A7al=20Garc=C3=A9s=20D=C3=ADaz-Mun=C3=ADo?= <11833677+gonsalet@users.noreply.github.com> Date: Mon, 21 Mar 2022 16:33:07 +0100 Subject: [PATCH 083/200] Fixed accent in Spanish command line examples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixed accent in Spanish command line examples ("centimos"->"céntimos"), thus making the example consistent with actual current behaviour. --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index ab4cf652..282aef23 100644 --- a/README.rst +++ b/README.rst @@ -51,7 +51,7 @@ Command line:: $ num2words 24,120.10 -l es veinticuatro mil ciento veinte punto uno $num2words 2.14 -l es --to currency - dos euros con catorce centimos + dos euros con catorce céntimos In code there's only one function to use:: From 62eba317786396147ded2d9eaa6ac29de573e81b Mon Sep 17 00:00:00 2001 From: gonzy <11833677+gonsalet@users.noreply.github.com> Date: Wed, 23 Mar 2022 04:34:52 +0100 Subject: [PATCH 084/200] lang_ES: improved currency gender handling, improved error messages; test_es: updated accordingly --- num2words/lang_ES.py | 70 +++++++++++++++++----- tests/test_es.py | 137 ++++++++++++++++++++++--------------------- 2 files changed, 124 insertions(+), 83 deletions(-) diff --git a/num2words/lang_ES.py b/num2words/lang_ES.py index 80a630fa..5d086d8b 100644 --- a/num2words/lang_ES.py +++ b/num2words/lang_ES.py @@ -27,7 +27,8 @@ 'SKK', 'GBP', 'CYP', 'EGP', 'FKP', 'GIP', 'LBP', 'SDG', 'SHP', 'SSP', 'SYP', 'INR', 'IDR', 'LKR', 'MUR', 'NPR', 'PKR', 'SCR', - 'ESP') + 'ESP', 'TRY', 'ITL') +CENTS_UNA = ('EGP', 'JOD', 'LBP', 'SDG', 'SSP', 'SYP') class Num2Word_ES(Num2Word_EU): @@ -216,9 +217,13 @@ def setup(self): self.high_numwords = self.gen_high_numwords([], [], lows) self.negword = "menos " self.pointword = "punto" - self.errmsg_nonnum = "Solo números pueden ser convertidos a palabras." + 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 = ( - "Numero muy grande para ser convertido a palabras." + "abs(%s) deber ser inferior a %s." ) self.gender_stem = "o" self.exclude_title = ["y", "menos", "punto"] @@ -352,17 +357,52 @@ def to_currency(self, val, currency='EUR', cents=True, separator=' con', result = super(Num2Word_ES, self).to_currency( val, currency=currency, cents=cents, separator=separator, adjective=adjective) - # Handle exception, in spanish is "un euro" and not "uno euro" - # except in this currencies: leona, corona, - # libra, rupia, lempira, peseta, is 'una' - # but only when it's first word, otherwise - # it's replaced in others words like 'veintiun' + # 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(" con ") + + # "DOLLARS" PART (list_result[0]) + + # Feminine currencies ("una libra", "trescientas libras"...) 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") - # correct orthography for the specific case of "veintiún": - result = result.replace("veintiun", "veintiún") + + # "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 = " con ".join(list_result) + return result diff --git a/tests/test_es.py b/tests/test_es.py index 9032354c..e014b811 100644 --- a/tests/test_es.py +++ b/tests/test_es.py @@ -128,9 +128,9 @@ (2.00, 'dos pesetas con cero céntimos'), (8.00, 'ocho pesetas con cero céntimos'), (12.00, 'doce pesetas con cero céntimos'), - (21.00, 'veintiún pesetas con cero céntimos'), - (81.25, 'ochenta y un pesetas con veinticinco céntimos'), - (350.90, 'trescientos cincuenta pesetas con noventa céntimos'), + (21.00, 'veintiuna pesetas con cero céntimos'), + (81.25, 'ochenta y una pesetas con veinticinco céntimos'), + (350.90, 'trescientas cincuenta pesetas con noventa céntimos'), (100.00, 'cien pesetas con cero céntimos'), ) @@ -175,9 +175,9 @@ (2.00, 'dos libras con cero peniques'), (8.00, 'ocho libras con cero peniques'), (12.00, 'doce libras con cero peniques'), - (21.00, 'veintiún libras con cero peniques'), - (81.25, 'ochenta y un libras con veinticinco peniques'), - (350.90, 'trescientos cincuenta libras con noventa peniques'), + (21.00, 'veintiuna libras con cero peniques'), + (81.25, 'ochenta y una libras con veinticinco peniques'), + (350.90, 'trescientas cincuenta libras con noventa peniques'), (100.00, 'cien libras con cero peniques'), (4150.83, 'cuatro mil ciento cincuenta libras con ochenta y tres peniques'), @@ -201,9 +201,9 @@ (2.00, 'dos coronas con cero öre'), (8.00, 'ocho coronas con cero öre'), (12.00, 'doce coronas con cero öre'), - (21.00, 'veintiún coronas con cero öre'), - (81.25, 'ochenta y un coronas con veinticinco öre'), - (350.90, 'trescientos cincuenta coronas con noventa öre'), + (21.00, 'veintiuna coronas con cero öre'), + (81.25, 'ochenta y una coronas con veinticinco öre'), + (350.90, 'trescientas cincuenta coronas con noventa öre'), (100.00, 'cien coronas con cero öre'), (4150.83, 'cuatro mil ciento cincuenta coronas con ochenta y tres öre'), @@ -214,9 +214,9 @@ (2.00, 'dos coronas con cero øre'), (8.00, 'ocho coronas con cero øre'), (12.00, 'doce coronas con cero øre'), - (21.00, 'veintiún coronas con cero øre'), - (81.25, 'ochenta y un coronas con veinticinco øre'), - (350.90, 'trescientos cincuenta coronas con noventa øre'), + (21.00, 'veintiuna coronas con cero øre'), + (81.25, 'ochenta y una coronas con veinticinco øre'), + (350.90, 'trescientas cincuenta coronas con noventa øre'), (100.00, 'cien coronas con cero øre'), (4150.83, 'cuatro mil ciento cincuenta coronas con ochenta y tres øre'), @@ -266,9 +266,9 @@ (2.00, 'dos rupias con cero paisas'), (8.00, 'ocho rupias con cero paisas'), (12.00, 'doce rupias con cero paisas'), - (21.00, 'veintiún rupias con cero paisas'), - (81.25, 'ochenta y un rupias con veinticinco paisas'), - (350.90, 'trescientos cincuenta rupias con noventa paisas'), + (21.00, 'veintiuna rupias con cero paisas'), + (81.25, 'ochenta y una rupias con veinticinco paisas'), + (350.90, 'trescientas cincuenta rupias con noventa paisas'), (100.00, 'cien rupias con cero paisas'), (4150.83, 'cuatro mil ciento cincuenta rupias con ochenta y tres paisas'), @@ -318,9 +318,9 @@ (2.00, 'dos coronas con cero haléř'), (8.00, 'ocho coronas con cero haléř'), (12.00, 'doce coronas con cero haléř'), - (21.00, 'veintiún coronas con cero haléř'), - (81.25, 'ochenta y un coronas con veinticinco haléř'), - (350.90, 'trescientos cincuenta coronas con noventa haléř'), + (21.00, 'veintiuna coronas con cero haléř'), + (81.25, 'ochenta y una coronas con veinticinco haléř'), + (350.90, 'trescientas cincuenta coronas con noventa haléř'), (100.00, 'cien coronas con cero haléř'), (4150.83, 'cuatro mil ciento cincuenta coronas con ochenta y tres haléř'), @@ -405,13 +405,13 @@ ) TEST_CASES_TO_CURRENCY_TRY = ( - (1.00, 'un lira con cero kuruş'), + (1.00, 'una lira con cero kuruş'), (2.00, 'dos liras con cero kuruş'), (8.00, 'ocho liras con cero kuruş'), (12.00, 'doce liras con cero kuruş'), - (21.00, 'veintiún liras con cero kuruş'), - (81.25, 'ochenta y un liras con veinticinco kuruş'), - (350.90, 'trescientos cincuenta liras con noventa kuruş'), + (21.00, 'veintiuna liras con cero kuruş'), + (81.25, 'ochenta y una liras con veinticinco kuruş'), + (350.90, 'trescientas cincuenta liras con noventa kuruş'), (100.00, 'cien liras con cero kuruş'), (4150.83, 'cuatro mil ciento cincuenta liras con ochenta y tres kuruş'), @@ -708,9 +708,9 @@ (2.00, 'dos libras con cero céntimos'), (8.00, 'ocho libras con cero céntimos'), (12.00, 'doce libras con cero céntimos'), - (21.00, 'veintiún libras con cero céntimos'), - (81.25, 'ochenta y un libras con veinticinco céntimos'), - (350.90, 'trescientos cincuenta libras con noventa céntimos'), + (21.00, 'veintiuna libras con cero céntimos'), + (81.25, 'ochenta y una libras con veinticinco céntimos'), + (350.90, 'trescientas cincuenta libras con noventa céntimos'), (100.00, 'cien libras con cero céntimos'), (4150.83, 'cuatro mil ciento cincuenta libras con ochenta y tres céntimos'), @@ -721,9 +721,9 @@ (2.00, 'dos coronas con cero øre'), (8.00, 'ocho coronas con cero øre'), (12.00, 'doce coronas con cero øre'), - (21.00, 'veintiún coronas con cero øre'), - (81.25, 'ochenta y un coronas con veinticinco øre'), - (350.90, 'trescientos cincuenta coronas con noventa øre'), + (21.00, 'veintiuna coronas con cero øre'), + (81.25, 'ochenta y una coronas con veinticinco øre'), + (350.90, 'trescientas cincuenta coronas con noventa øre'), (100.00, 'cien coronas con cero øre'), (4150.83, 'cuatro mil ciento cincuenta coronas con ochenta y tres øre'), @@ -760,9 +760,10 @@ (2.00, 'dos libras con cero piastras'), (8.00, 'ocho libras con cero piastras'), (12.00, 'doce libras con cero piastras'), - (21.00, 'veintiún libras con cero piastras'), - (81.25, 'ochenta y un libras con veinticinco piastras'), - (350.90, 'trescientos cincuenta libras con noventa piastras'), + (21.00, 'veintiuna libras con cero piastras'), + (81.21, 'ochenta y una libras con veintiuna piastras'), + (81.25, 'ochenta y una libras con veinticinco piastras'), + (350.90, 'trescientas cincuenta libras con noventa piastras'), (100.00, 'cien libras con cero piastras'), (4150.83, 'cuatro mil ciento cincuenta libras con ochenta y tres piastras'), @@ -799,9 +800,9 @@ (2.00, 'dos libras con cero peniques'), (8.00, 'ocho libras con cero peniques'), (12.00, 'doce libras con cero peniques'), - (21.00, 'veintiún libras con cero peniques'), - (81.25, 'ochenta y un libras con veinticinco peniques'), - (350.90, 'trescientos cincuenta libras con noventa peniques'), + (21.00, 'veintiuna libras con cero peniques'), + (81.25, 'ochenta y una libras con veinticinco peniques'), + (350.90, 'trescientas cincuenta libras con noventa peniques'), (100.00, 'cien libras con cero peniques'), (4150.83, 'cuatro mil ciento cincuenta libras con ochenta y tres peniques'), @@ -903,9 +904,9 @@ (2.00, 'dos rupias con cero céntimos'), (8.00, 'ocho rupias con cero céntimos'), (12.00, 'doce rupias con cero céntimos'), - (21.00, 'veintiún rupias con cero céntimos'), - (81.25, 'ochenta y un rupias con veinticinco céntimos'), - (350.90, 'trescientos cincuenta rupias con noventa céntimos'), + (21.00, 'veintiuna rupias con cero céntimos'), + (81.25, 'ochenta y una rupias con veinticinco céntimos'), + (350.90, 'trescientas cincuenta rupias con noventa céntimos'), (100.00, 'cien rupias con cero céntimos'), (4150.83, 'cuatro mil ciento cincuenta rupias con ochenta y tres céntimos'), @@ -955,22 +956,22 @@ (2.00, 'dos coronas con cero aurar'), (8.00, 'ocho coronas con cero aurar'), (12.00, 'doce coronas con cero aurar'), - (21.00, 'veintiún coronas con cero aurar'), - (81.25, 'ochenta y un coronas con veinticinco aurar'), - (350.90, 'trescientos cincuenta coronas con noventa aurar'), + (21.00, 'veintiuna coronas con cero aurar'), + (81.25, 'ochenta y una coronas con veinticinco aurar'), + (350.90, 'trescientas cincuenta coronas con noventa aurar'), (100.00, 'cien coronas con cero aurar'), (4150.83, 'cuatro mil ciento cincuenta coronas con ochenta y tres aurar'), ) TEST_CASES_TO_CURRENCY_ITL = ( - (1.00, 'un lira con cero céntimos'), + (1.00, 'una lira con cero céntimos'), (2.00, 'dos liras con cero céntimos'), (8.00, 'ocho liras con cero céntimos'), (12.00, 'doce liras con cero céntimos'), - (21.00, 'veintiún liras con cero céntimos'), - (81.25, 'ochenta y un liras con veinticinco céntimos'), - (350.90, 'trescientos cincuenta liras con noventa céntimos'), + (21.00, 'veintiuna liras con cero céntimos'), + (81.25, 'ochenta y una liras con veinticinco céntimos'), + (350.90, 'trescientas cincuenta liras con noventa céntimos'), (100.00, 'cien liras con cero céntimos'), (4150.83, 'cuatro mil ciento cincuenta liras con ochenta y tres céntimos'), @@ -1059,9 +1060,9 @@ (2.00, 'dos rupias con cero céntimos'), (8.00, 'ocho rupias con cero céntimos'), (12.00, 'doce rupias con cero céntimos'), - (21.00, 'veintiún rupias con cero céntimos'), - (81.25, 'ochenta y un rupias con veinticinco céntimos'), - (350.90, 'trescientos cincuenta rupias con noventa céntimos'), + (21.00, 'veintiuna rupias con cero céntimos'), + (81.25, 'ochenta y una rupias con veinticinco céntimos'), + (350.90, 'trescientas cincuenta rupias con noventa céntimos'), (100.00, 'cien rupias con cero céntimos'), (4150.83, 'cuatro mil ciento cincuenta rupias con ochenta y tres céntimos'), @@ -1241,9 +1242,9 @@ (2.00, 'dos rupias con cero céntimos'), (8.00, 'ocho rupias con cero céntimos'), (12.00, 'doce rupias con cero céntimos'), - (21.00, 'veintiún rupias con cero céntimos'), - (81.25, 'ochenta y un rupias con veinticinco céntimos'), - (350.90, 'trescientos cincuenta rupias con noventa céntimos'), + (21.00, 'veintiuna rupias con cero céntimos'), + (81.25, 'ochenta y una rupias con veinticinco céntimos'), + (350.90, 'trescientas cincuenta rupias con noventa céntimos'), (100.00, 'cien rupias con cero céntimos'), (4150.83, 'cuatro mil ciento cincuenta rupias con ochenta y tres céntimos'), @@ -1319,9 +1320,9 @@ (2.00, 'dos rupias con cero paisas'), (8.00, 'ocho rupias con cero paisas'), (12.00, 'doce rupias con cero paisas'), - (21.00, 'veintiún rupias con cero paisas'), - (81.25, 'ochenta y un rupias con veinticinco paisas'), - (350.90, 'trescientos cincuenta rupias con noventa paisas'), + (21.00, 'veintiuna rupias con cero paisas'), + (81.25, 'ochenta y una rupias con veinticinco paisas'), + (350.90, 'trescientas cincuenta rupias con noventa paisas'), (100.00, 'cien rupias con cero paisas'), (4150.83, 'cuatro mil ciento cincuenta rupias con ochenta y tres paisas'), @@ -1371,9 +1372,9 @@ (2.00, 'dos rupias con cero paisas'), (8.00, 'ocho rupias con cero paisas'), (12.00, 'doce rupias con cero paisas'), - (21.00, 'veintiún rupias con cero paisas'), - (81.25, 'ochenta y un rupias con veinticinco paisas'), - (350.90, 'trescientos cincuenta rupias con noventa paisas'), + (21.00, 'veintiuna rupias con cero paisas'), + (81.25, 'ochenta y una rupias con veinticinco paisas'), + (350.90, 'trescientas cincuenta rupias con noventa paisas'), (100.00, 'cien rupias con cero paisas'), (4150.83, 'cuatro mil ciento cincuenta rupias con ochenta y tres paisas'), @@ -1462,9 +1463,9 @@ (2.00, 'dos rupias con cero céntimos'), (8.00, 'ocho rupias con cero céntimos'), (12.00, 'doce rupias con cero céntimos'), - (21.00, 'veintiún rupias con cero céntimos'), - (81.25, 'ochenta y un rupias con veinticinco céntimos'), - (350.90, 'trescientos cincuenta rupias con noventa céntimos'), + (21.00, 'veintiuna rupias con cero céntimos'), + (81.25, 'ochenta y una rupias con veinticinco céntimos'), + (350.90, 'trescientas cincuenta rupias con noventa céntimos'), (100.00, 'cien rupias con cero céntimos'), (4150.83, 'cuatro mil ciento cincuenta rupias con ochenta y tres céntimos'), @@ -1475,9 +1476,9 @@ (2.00, 'dos libras con cero peniques'), (8.00, 'ocho libras con cero peniques'), (12.00, 'doce libras con cero peniques'), - (21.00, 'veintiún libras con cero peniques'), - (81.25, 'ochenta y un libras con veinticinco peniques'), - (350.90, 'trescientos cincuenta libras con noventa peniques'), + (21.00, 'veintiuna libras con cero peniques'), + (81.25, 'ochenta y una libras con veinticinco peniques'), + (350.90, 'trescientas cincuenta libras con noventa peniques'), (100.00, 'cien libras con cero peniques'), (4150.83, 'cuatro mil ciento cincuenta libras con ochenta y tres peniques'), @@ -1488,9 +1489,9 @@ (2.00, 'dos coronas con cero haliers'), (8.00, 'ocho coronas con cero haliers'), (12.00, 'doce coronas con cero haliers'), - (21.00, 'veintiún coronas con cero haliers'), - (81.25, 'ochenta y un coronas con veinticinco haliers'), - (350.90, 'trescientos cincuenta coronas con noventa haliers'), + (21.00, 'veintiuna coronas con cero haliers'), + (81.25, 'ochenta y una coronas con veinticinco haliers'), + (350.90, 'trescientas cincuenta coronas con noventa haliers'), (100.00, 'cien coronas con cero haliers'), (4150.83, 'cuatro mil ciento cincuenta coronas con ochenta y tres haliers'), @@ -1501,9 +1502,9 @@ (2.00, 'dos leonas con cero céntimos'), (8.00, 'ocho leonas con cero céntimos'), (12.00, 'doce leonas con cero céntimos'), - (21.00, 'veintiún leonas con cero céntimos'), - (81.25, 'ochenta y un leonas con veinticinco céntimos'), - (350.90, 'trescientos cincuenta leonas con noventa céntimos'), + (21.00, 'veintiuna leonas con cero céntimos'), + (81.25, 'ochenta y una leonas con veinticinco céntimos'), + (350.90, 'trescientas cincuenta leonas con noventa céntimos'), (100.00, 'cien leonas con cero céntimos'), (4150.83, 'cuatro mil ciento cincuenta leonas con ochenta y tres céntimos'), From 12e8402da4138f4bf4ab52cb985d5166518f8a2f Mon Sep 17 00:00:00 2001 From: gonzy <11833677+gonsalet@users.noreply.github.com> Date: Thu, 24 Mar 2022 00:37:53 +0100 Subject: [PATCH 085/200] Improved currency gender handling, now splitting 'dollars' and 'cents' parts on --- num2words/lang_ES.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/num2words/lang_ES.py b/num2words/lang_ES.py index 5d086d8b..de2d1e13 100644 --- a/num2words/lang_ES.py +++ b/num2words/lang_ES.py @@ -367,7 +367,7 @@ def to_currency(self, val, currency='EUR', cents=True, separator=' con', # Source: https://www.rae.es/dpd/una (section 2.2) # split "dollars" part from "cents" part - list_result = result.split(" con ") + list_result = result.split(separator + " ") # "DOLLARS" PART (list_result[0]) @@ -403,6 +403,6 @@ def to_currency(self, val, currency='EUR', cents=True, separator=' con', list_result[1] = list_result[1].replace("uno", "un") # join back "dollars" part with "cents" part - result = " con ".join(list_result) + result = (separator + " ").join(list_result) return result From b8a215a9916346f732a0176fc7277b6333a0a77d Mon Sep 17 00:00:00 2001 From: gonzy <11833677+gonsalet@users.noreply.github.com> Date: Thu, 24 Mar 2022 00:54:22 +0100 Subject: [PATCH 086/200] Added tests for every currency gender combination (dollars, cents) --- tests/test_es.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test_es.py b/tests/test_es.py index e014b811..68a14e0f 100644 --- a/tests/test_es.py +++ b/tests/test_es.py @@ -114,6 +114,7 @@ TEST_CASES_TO_CURRENCY = ( (1.00, 'un euro con cero céntimos'), + (1.01, 'un euro con un céntimo'), (2.00, 'dos euros con cero céntimos'), (8.00, 'ocho euros con cero céntimos'), (12.00, 'doce euros con cero céntimos'), @@ -125,6 +126,7 @@ TEST_CASES_TO_CURRENCY_ESP = ( (1.00, 'una peseta con cero céntimos'), + (1.01, 'una peseta con un céntimo'), (2.00, 'dos pesetas con cero céntimos'), (8.00, 'ocho pesetas con cero céntimos'), (12.00, 'doce pesetas con cero céntimos'), From 2cb98d3af1097d75e795c0fd67bdd8037d2b5339 Mon Sep 17 00:00:00 2001 From: Marlon Rodriguez Garcia Date: Wed, 3 Aug 2022 14:49:06 -0400 Subject: [PATCH 087/200] Added new release --- CHANGES.rst | 28 ++++++++++++++++++++++++++++ README.rst | 2 +- bin/num2words | 2 +- num2words/lang_KO.py | 2 +- setup.py | 10 +++++++--- 5 files changed, 38 insertions(+), 6 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 298f9db9..9f3a7b24 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,6 +1,34 @@ Changelog ========= +Version 0.5.11 -- 2022/08/03 +---------------------------- + +* Add KZT and UAH currencies to lang RU (#264) +* Add es_NI currency (#276) +* Update .gitignore to add .eggs/ directory (#280) +* Fix Hebrew support (#289) +* Update test_tr.py to increase coverage (#298) +* Add ordinal 12,345 to ES test suite to increase coverage (#287) +* Add simple tests for lang_DK.py (#286) +* Add testcase for lang_EN.py (#288) +* Add more tests to base.py (#283) +* Fixed misspelling of 21 (cardinal and ordinal number) in IT language (#270) +* Romanian issues 259 (#260) +* Adding Language Support for Telugu / Bug Fix in Kannada (#263) +* Add support of Kazakh language (KZ) (#306) +* Update README.rst (#307) +* Added support for Hungarian language (#310) +* [UPD] Readme file (#363) +* [ADD] num2words: add traslation to spanish of several currencies (#356) +* added swedish language including test cases (#352) +* Remove dupplicated line in lang_PT_BR (#355) +* Fix ordinal_num output for Dutch (NL) (#369) +* Polishordinals (#367) +* [tr] return Turkish 0 ordinal and cardinal (#347) +* Improve Ukrainian support and minor fixes in CZ, KZ, LT, LV, PL, RU, SR languages (#400) +* feat: ci: replace travis by github workflows (#448) +* [ES] Added missing accents ("dieciséis", "dólar", "dólares", "veintiún"), improved currency gender handling, fixed pound cent names (#443) Version 0.5.10 -- 2019/05/12 ---------------------------- diff --git a/README.rst b/README.rst index 282aef23..9978a20f 100644 --- a/README.rst +++ b/README.rst @@ -1,5 +1,5 @@ num2words library - Convert numbers to words in multiple languages -========================================================== +================================================================== .. image:: https://img.shields.io/pypi/v/num2words.svg :target: https://pypi.python.org/pypi/num2words diff --git a/bin/num2words b/bin/num2words index 02cfc69e..2a20b225 100755 --- a/bin/num2words +++ b/bin/num2words @@ -55,7 +55,7 @@ import sys from docopt import docopt import num2words -__version__ = "0.5.10" +__version__ = "0.5.11" __license__ = "LGPL" diff --git a/num2words/lang_KO.py b/num2words/lang_KO.py index e4e01b5b..65f4531e 100644 --- a/num2words/lang_KO.py +++ b/num2words/lang_KO.py @@ -93,7 +93,7 @@ def merge(self, lpair, rpair): def to_ordinal(self, value): self.verify_ordinal(value) - if(value == 1): + if value == 1: return "첫 번째" outwords = self.to_cardinal(value).split(" ") lastwords = outwords[-1].split("백") diff --git a/setup.py b/setup.py index fbc34f7b..3565f62d 100644 --- a/setup.py +++ b/setup.py @@ -27,8 +27,11 @@ 'Intended Audience :: Developers', 'License :: OSI Approved :: GNU Library or Lesser General Public License ' '(LGPL)', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', 'Topic :: Software Development :: Internationalization', 'Topic :: Software Development :: Libraries :: Python Modules', 'Topic :: Software Development :: Localization', @@ -61,11 +64,12 @@ def find_version(fname): version=find_version("bin/num2words"), description='Modules to convert numbers to words. Easily extensible.', long_description=LONG_DESC, + long_description_content_type="text/markdown", license='LGPL', author='Taro Ogawa ', author_email='tos@users.sourceforge.net', maintainer='Savoir-faire Linux inc.', - maintainer_email='istvan.szalai@savoirfairelinux.com', + maintainer_email='support@savoirfairelinux.com', keywords=' number word numbers words convert conversion i18n ' 'localisation localization internationalisation ' 'internationalization', From f2acbc2873bb7791857c77b9836357215d064e15 Mon Sep 17 00:00:00 2001 From: Marlon Rodriguez Garcia Date: Thu, 4 Aug 2022 12:10:25 -0400 Subject: [PATCH 088/200] Add new check to base --- tests/test_base.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/test_base.py b/tests/test_base.py index bd9cbd13..6500db6e 100644 --- a/tests/test_base.py +++ b/tests/test_base.py @@ -58,3 +58,8 @@ def test_is_title(self): self.base.title("one"), "One" ) + self.base.exclude_title.append('one') + self.assertEqual( + self.base.title("one"), + "one" + ) From 112e91c35a9da5075190fa948dd635515187d230 Mon Sep 17 00:00:00 2001 From: gshekler Date: Sat, 3 Oct 2020 15:02:49 +0300 Subject: [PATCH 089/200] fix pluralize --- num2words/lang_HE.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/num2words/lang_HE.py b/num2words/lang_HE.py index 34b2ec8a..2b96dc1b 100644 --- a/num2words/lang_HE.py +++ b/num2words/lang_HE.py @@ -81,11 +81,7 @@ def pluralize(n, forms): - # gettext implementation: - # (n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2) - - form = 0 if (n % 10 == 1 and n % 100 != 11) else 1 if n != 0 else 2 - + form = 1 if n == 0 else 0 if n == 1 else 1 return forms[form] @@ -151,6 +147,9 @@ def to_cardinal(self, number): def to_ordinal(self, number): raise NotImplementedError() + def pluralize(self, n, forms): + return pluralize(n, forms) + if __name__ == '__main__': yo = Num2Word_HE() From 07ea1baca273101156cc2fb3c273eb34c502fbe1 Mon Sep 17 00:00:00 2001 From: gshekler Date: Sat, 3 Oct 2020 15:03:43 +0300 Subject: [PATCH 090/200] implement currency for HE --- num2words/lang_HE.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/num2words/lang_HE.py b/num2words/lang_HE.py index 2b96dc1b..f9871925 100644 --- a/num2words/lang_HE.py +++ b/num2words/lang_HE.py @@ -136,11 +136,13 @@ def n2w(n): return int2word(int(n)) -def to_currency(n, currency='EUR', cents=True, separator=','): - raise NotImplementedError() - - class Num2Word_HE(Num2Word_Base): + CURRENCY_FORMS = { + 'NIS': (('שקל', 'שקלים'), ('אגורה', 'אגורות')), + 'EUR': (('אירו', 'אירו'), ('סנט', 'סנט')), + 'USD': (('דולר', 'דולרים'), ('סנט', 'סנט')), + } + def to_cardinal(self, number): return n2w(number) @@ -150,6 +152,14 @@ def to_ordinal(self, number): def pluralize(self, n, forms): return pluralize(n, forms) + def to_currency(self, val, currency='NIS', cents=True, separator=' ו', + adjective=False): + result = super(Num2Word_HE, self).to_currency( + val, currency=currency, cents=cents, separator=separator, + adjective=adjective) + # In Hebrew the separator is along with the following word + return result.replace(" ו ", " ו") + if __name__ == '__main__': yo = Num2Word_HE() From f820ee5ec1d92c9196679e8cc966323eeb697956 Mon Sep 17 00:00:00 2001 From: gshekler Date: Sat, 3 Oct 2020 15:03:57 +0300 Subject: [PATCH 091/200] add unit tests --- tests/test_he.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/tests/test_he.py b/tests/test_he.py index 206d7cc5..5a17694e 100644 --- a/tests/test_he.py +++ b/tests/test_he.py @@ -20,6 +20,7 @@ from unittest import TestCase from num2words import num2words +from num2words.lang_HE import Num2Word_HE class Num2WordsHETest(TestCase): @@ -71,3 +72,39 @@ def test_1000_to_9999(self): self.assertEqual( num2words(6870, lang="he"), u'ששת אלפים שמונה מאות ושבעים' ) + + def test_pluralize(self): + n = Num2Word_HE() + cr1, cr2 = n.CURRENCY_FORMS['NIS'] + self.assertEqual(n.pluralize(1, cr1), 'שקל') + self.assertEqual(n.pluralize(2, cr1), 'שקלים') + self.assertEqual(n.pluralize(1, cr2), 'אגורה') + self.assertEqual(n.pluralize(2, cr2), 'אגורות') + + cr1, cr2 = n.CURRENCY_FORMS['USD'] + self.assertEqual(n.pluralize(1, cr1), 'דולר') + self.assertEqual(n.pluralize(2, cr1), 'דולרים') + self.assertEqual(n.pluralize(1, cr2), 'סנט') + self.assertEqual(n.pluralize(2, cr2), 'סנט') + + def test_currency_(self): + n = Num2Word_HE() + self.assertEqual(n.to_currency(20.0 ,currency='NIS'), 'עשרים שקלים ואפס אגורות') + self.assertEqual(n.to_currency(100.0 ,currency='NIS'), 'מאה שקלים ואפס אגורות') + self.assertEqual(n.to_currency(100.50 ,currency='NIS'), 'מאה שקלים וחמישים אגורות') + + def test_to_cardinal(self): + n = Num2Word_HE() + self.assertEqual(n.to_cardinal(1500), u'אלף וחמש מאות') + + +class Num2WordsHETestNotImplementedMethofs(TestCase): + n = Num2Word_HE() + + def test_to_ordinal(self): + with self.assertRaises(NotImplementedError): + self.n.to_ordinal('1') + + def test_large_number(self): + with self.assertRaises(NotImplementedError): + num2words(2000000, lang="he") From 7993ca5023a7a24ef8d2aeed62aa98fa7c59744d Mon Sep 17 00:00:00 2001 From: gshekler Date: Sat, 3 Oct 2020 15:14:21 +0300 Subject: [PATCH 092/200] typo --- tests/test_he.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_he.py b/tests/test_he.py index 5a17694e..688bbf04 100644 --- a/tests/test_he.py +++ b/tests/test_he.py @@ -87,7 +87,7 @@ def test_pluralize(self): self.assertEqual(n.pluralize(1, cr2), 'סנט') self.assertEqual(n.pluralize(2, cr2), 'סנט') - def test_currency_(self): + def test_to_currency(self): n = Num2Word_HE() self.assertEqual(n.to_currency(20.0 ,currency='NIS'), 'עשרים שקלים ואפס אגורות') self.assertEqual(n.to_currency(100.0 ,currency='NIS'), 'מאה שקלים ואפס אגורות') From c11927b353d111ed6609b57fd9f43e47e6424d54 Mon Sep 17 00:00:00 2001 From: Gabriel Shekler <46564521+gs202@users.noreply.github.com> Date: Sat, 6 Aug 2022 13:51:57 +0300 Subject: [PATCH 093/200] fix flake issues --- tests/test_he.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tests/test_he.py b/tests/test_he.py index 688bbf04..2ce6797a 100644 --- a/tests/test_he.py +++ b/tests/test_he.py @@ -89,9 +89,15 @@ def test_pluralize(self): def test_to_currency(self): n = Num2Word_HE() - self.assertEqual(n.to_currency(20.0 ,currency='NIS'), 'עשרים שקלים ואפס אגורות') - self.assertEqual(n.to_currency(100.0 ,currency='NIS'), 'מאה שקלים ואפס אגורות') - self.assertEqual(n.to_currency(100.50 ,currency='NIS'), 'מאה שקלים וחמישים אגורות') + self.assertEqual( + n.to_currency(20.0, currency='NIS'), 'עשרים שקלים ואפס אגורות' + ) + self.assertEqual( + (n.to_currency(100.0, currency='NIS'), 'מאה שקלים ואפס אגורות' + ) + self.assertEqual( + (n.to_currency(100.50, currency='NIS'), 'מאה שקלים וחמישים אגורות' + ) def test_to_cardinal(self): n = Num2Word_HE() From b01c44e33cc4bfe75042ca9461adaf556be85b63 Mon Sep 17 00:00:00 2001 From: Gabriel Shekler <46564521+gs202@users.noreply.github.com> Date: Sat, 6 Aug 2022 13:53:14 +0300 Subject: [PATCH 094/200] typo --- tests/test_he.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_he.py b/tests/test_he.py index 2ce6797a..e50a6a22 100644 --- a/tests/test_he.py +++ b/tests/test_he.py @@ -93,10 +93,10 @@ def test_to_currency(self): n.to_currency(20.0, currency='NIS'), 'עשרים שקלים ואפס אגורות' ) self.assertEqual( - (n.to_currency(100.0, currency='NIS'), 'מאה שקלים ואפס אגורות' + n.to_currency(100.0, currency='NIS'), 'מאה שקלים ואפס אגורות' ) self.assertEqual( - (n.to_currency(100.50, currency='NIS'), 'מאה שקלים וחמישים אגורות' + n.to_currency(100.50, currency='NIS'), 'מאה שקלים וחמישים אגורות' ) def test_to_cardinal(self): From 9f59c5c8940f01095c80e94d8c26a0916e110a52 Mon Sep 17 00:00:00 2001 From: hamidreza kalbasi Date: Wed, 16 Dec 2020 21:11:52 +0330 Subject: [PATCH 095/200] add basic farsi support --- README.rst | 1 + num2words/__init__.py | 3 +- num2words/lang_FA.py | 165 ++++++++++++++++++++++++++++++++++++++++++ tests/test_fa.py | 85 ++++++++++++++++++++++ 4 files changed, 253 insertions(+), 1 deletion(-) create mode 100644 num2words/lang_FA.py create mode 100644 tests/test_fa.py diff --git a/README.rst b/README.rst index 9978a20f..04145315 100644 --- a/README.rst +++ b/README.rst @@ -86,6 +86,7 @@ Besides the numerical argument, there are two main optional arguments. * ``es_CO`` (Spanish - Colombia) * ``es_VE`` (Spanish - Venezuela) * ``eu`` (EURO) +* ``fa`` (Farsi) * ``fi`` (Finnish) * ``fr`` (French) * ``fr_CH`` (French - Switzerland) diff --git a/num2words/__init__.py b/num2words/__init__.py index a8c47370..19090545 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -18,7 +18,7 @@ from __future__ import unicode_literals from . import (lang_AR, lang_CZ, lang_DE, lang_DK, lang_EN, lang_EN_IN, - lang_ES, lang_ES_CO, lang_ES_NI, lang_ES_VE, lang_FI, lang_FR, + lang_ES, lang_ES_CO, 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_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, @@ -30,6 +30,7 @@ 'cz': lang_CZ.Num2Word_CZ(), 'en': lang_EN.Num2Word_EN(), 'en_IN': lang_EN_IN.Num2Word_EN_IN(), + '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(), diff --git a/num2words/lang_FA.py b/num2words/lang_FA.py new file mode 100644 index 00000000..9e232a79 --- /dev/null +++ b/num2words/lang_FA.py @@ -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. +# Copyright (c) 2018, Abdullah Alhazmy, Alhazmy13. All Rights Reserved. +# Copyright (c) 2020, Hamidreza Kalbasi. 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 re +from decimal import Decimal +from math import floor + +farsiOnes = [ + "", "یک", "دو", "سه", "چهار", "پنج", "شش", "هفت", "هشت", + "نه", + "ده", + "یازده", + "دوازده", + "سیزده", + "چهارده", + "پونزده", + "شونزده", + "هیفده", + "هیجده", + "نوزده", +] + +farsiTens = [ + "", + "ده", + "بیست", + "سی", + "چهل", + "پنجاه", + "شصت", + "هفتاد", + "هشتاد", + "نود", +] + +farsiHundreds = [ + "", + "صد", + "دویست", + "سیصد", + "چهارصد", + "پانصد", + "ششصد", + "هفتصد", + "هشتصد", + "نهصد", +] + +farsiBig = [ + '', + ' هزار', + ' میلیون', + " میلیارد", + ' تریلیون', + " تریلیارد", +] + +farsiFrac = ["", "دهم", "صدم"] +farsiFracBig = ["", "هزارم", "میلیونیم", "میلیاردیم"] + +farsiSeperator = ' و ' + +class Num2Word_FA(object): + errmsg_too_big = "Too large" + max_num = 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(math.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 (res == ''): + res = yx + else: + res = yx + farsiSeperator + return res + + def fractional(self, number, l): + if (number == 5): + return "نیم" + x = self.cardinalPos(number) + ld3, lm3 = divmod(l, 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) + + def to_ordinal_num(self, value): + return str(value)+"م" + + def to_cardinal(self, number): + if number < 0: + return "منفی " + self.to_cardinal(-number) + if (number == 0): + return "صفر" + x, y, l = self.float2tuple(number) + if y == 0: + return self.cardinalPos(x) + if x == 0: + return self.fractional(y, l) + return self.cardinalPos(x) + farsiSeperator + self.fractional(y, l) \ No newline at end of file diff --git a/tests/test_fa.py b/tests/test_fa.py new file mode 100644 index 00000000..dbe9574c --- /dev/null +++ b/tests/test_fa.py @@ -0,0 +1,85 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. +# Copyright (c) 2020, Hamidreza Kalbasi. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + +from unittest import TestCase + +from num2words import num2words + + +class Num2WordsFATest(TestCase): + def test_and_join_199(self): + self.assertEqual(num2words(199, lang='fa'), "صد و نود و نه") + + def test_ordinal(self): + self.assertEqual( + num2words(0, lang='fa', to='ordinal'), + 'صفرم' + ) + self.assertEqual( + num2words(1, lang='fa', to='ordinal'), + 'یکم' + ) + self.assertEqual( + num2words(13, lang='fa', to='ordinal'), + 'سیزدهم' + ) + self.assertEqual( + num2words(23, lang='fa', to='ordinal'), + 'بیست و سوم' + ) + self.assertEqual( + num2words(12, lang='fa', to='ordinal'), + 'دوازدهم' + ) + self.assertEqual( + num2words(113, lang='fa', to='ordinal'), + 'صد و سیزدهم' + ) + self.assertEqual( + num2words(103, lang='fa', to='ordinal'), + 'صد و سوم' + ) + + def test_cardinal(self): + self.assertEqual(num2words(130000, lang='fa'), "صد و سی هزار") + self.assertEqual(num2words(242, lang='fa'), "دویست و چهل و دو") + + + + def test_ordinal_num(self): + self.assertEqual(num2words(10, lang='fa', to='ordinal_num'), '10م') + self.assertEqual(num2words(21, lang='fa', to='ordinal_num'), '21م') + self.assertEqual(num2words(102, lang='fa', to='ordinal_num'), '102م') + self.assertEqual(num2words(73, lang='fa', to='ordinal_num'), '73م') + + def test_cardinal_for_float_number(self): + self.assertEqual(num2words(12.5, lang='fa'), "دوازده و نیم") + self.assertEqual(num2words(0.75, lang='fa'), "هفتاد و پنج صدم") + self.assertEqual(num2words(12.51, lang='fa'), "دوازده و پنجاه و یک صدم") + self.assertEqual(num2words(12.53, lang='fa'), "دوازده و پنجاه و سه صدم") + self.assertEqual(num2words(12.59, lang='fa'), "دوازده و پنجاه و نه صدم") + self.assertEqual(num2words(0.000001, lang='fa'), "یک میلیونیم") + + def test_overflow(self): + with self.assertRaises(OverflowError): + num2words("1000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000") From bbd9de8299aa6d390e2d897c8c7b7cd60142e293 Mon Sep 17 00:00:00 2001 From: hamidreza kalbasi Date: Sun, 24 Jan 2021 10:10:24 +0330 Subject: [PATCH 096/200] fix test coverage --- num2words/lang_FA.py | 4 +++- tests/test_fa.py | 18 +++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/num2words/lang_FA.py b/num2words/lang_FA.py index 9e232a79..ca7004ca 100644 --- a/num2words/lang_FA.py +++ b/num2words/lang_FA.py @@ -123,10 +123,12 @@ def cardinalPos(self, number): if (y == 0): continue yx = self.cardinal3(y) + b + if b == ' هزار' and y == 1: + yx = 'هزار' if (res == ''): res = yx else: - res = yx + farsiSeperator + res = yx + farsiSeperator + res return res def fractional(self, number, l): diff --git a/tests/test_fa.py b/tests/test_fa.py index dbe9574c..4082e7f1 100644 --- a/tests/test_fa.py +++ b/tests/test_fa.py @@ -58,8 +58,24 @@ def test_ordinal(self): def test_cardinal(self): self.assertEqual(num2words(130000, lang='fa'), "صد و سی هزار") self.assertEqual(num2words(242, lang='fa'), "دویست و چهل و دو") + self.assertEqual(num2words(800, lang='fa'), "هشتصد") + self.assertEqual(num2words(-203, lang='fa'), "منفی دویست و سه") + self.assertEqual( + num2words(1234567890, lang='fa'), + "یک میلیارد و دویست و سی و چهار میلیون و پانصد و شصت و هفت هزار و هشتصد و نود" + ) + + def test_year(self): + self.assertEqual(num2words(1398, lang='fa', to='year'), "هزار و سیصد و نود و هشت") + self.assertEqual(num2words(1399, lang='fa', to='year'), "هزار و سیصد و نود و نه") + self.assertEqual(num2words(1400, lang='fa', to='year'), "هزار و چهارصد") - + def test_currency(self): + self.assertEqual(num2words(1000, lang='fa', to='currency'), 'هزار تومان') + self.assertEqual( + num2words(1500000, lang='fa', to='currency'), + 'یک میلیون و پانصد هزار تومان' + ) def test_ordinal_num(self): self.assertEqual(num2words(10, lang='fa', to='ordinal_num'), '10م') From a1f0392beb8f976e1e1e444d2d668600f95b4390 Mon Sep 17 00:00:00 2001 From: hamidreza kalbasi Date: Sun, 24 Jan 2021 10:30:06 +0330 Subject: [PATCH 097/200] remove unneccery if --- num2words/lang_FA.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/num2words/lang_FA.py b/num2words/lang_FA.py index ca7004ca..9c5ff749 100644 --- a/num2words/lang_FA.py +++ b/num2words/lang_FA.py @@ -90,14 +90,7 @@ def float2tuple(self, value): 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)) + post = int(math.floor(post)) return pre, post, self.precision From 3d2fa184cfbfca6443998a572d1ac8181b2626c7 Mon Sep 17 00:00:00 2001 From: hamidreza kalbasi Date: Mon, 25 Jan 2021 00:14:05 +0330 Subject: [PATCH 098/200] try fix test failure --- num2words/lang_FA.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/num2words/lang_FA.py b/num2words/lang_FA.py index 9c5ff749..f49b5f35 100644 --- a/num2words/lang_FA.py +++ b/num2words/lang_FA.py @@ -90,8 +90,14 @@ def float2tuple(self, value): self.precision = abs(Decimal(str(value)).as_tuple().exponent) post = abs(value - pre) * 10**self.precision - post = int(math.floor(post)) - + 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 From 464f9ed7afd347dcb6b7e71a17fb4deed3138526 Mon Sep 17 00:00:00 2001 From: hamidreza kalbasi Date: Mon, 25 Jan 2021 10:34:01 +0330 Subject: [PATCH 099/200] fix flake8 problems --- num2words/lang_FA.py | 17 ++++++++--------- tests/test_fa.py | 26 +++++++++++++++++--------- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/num2words/lang_FA.py b/num2words/lang_FA.py index f49b5f35..96e9e526 100644 --- a/num2words/lang_FA.py +++ b/num2words/lang_FA.py @@ -17,7 +17,6 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA -import re from decimal import Decimal from math import floor @@ -76,6 +75,7 @@ farsiSeperator = ' و ' + class Num2Word_FA(object): errmsg_too_big = "Too large" max_num = 10 ** 36 @@ -100,7 +100,6 @@ def float2tuple(self, value): post = int(floor(post)) return pre, post, self.precision - def cardinal3(self, number): if (number < 19): return farsiOnes[number] @@ -108,12 +107,12 @@ def cardinal3(self, number): x, y = divmod(number, 10) if y == 0: return farsiTens[x] - return farsiTens[x] + farsiSeperator + farsiOnes[y] + 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 = '' @@ -130,11 +129,11 @@ def cardinalPos(self, number): res = yx + farsiSeperator + res return res - def fractional(self, number, l): + def fractional(self, number, level): if (number == 5): return "نیم" x = self.cardinalPos(number) - ld3, lm3 = divmod(l, 3) + ld3, lm3 = divmod(level, 3) ltext = (farsiFrac[lm3] + " " + farsiFracBig[ld3]).strip() return x + " " + ltext @@ -158,9 +157,9 @@ def to_cardinal(self, number): return "منفی " + self.to_cardinal(-number) if (number == 0): return "صفر" - x, y, l = self.float2tuple(number) + x, y, level = self.float2tuple(number) if y == 0: return self.cardinalPos(x) if x == 0: - return self.fractional(y, l) - return self.cardinalPos(x) + farsiSeperator + self.fractional(y, l) \ No newline at end of file + return self.fractional(y, level) + return self.cardinalPos(x) + farsiSeperator + self.fractional(y, level) diff --git a/tests/test_fa.py b/tests/test_fa.py index 4082e7f1..9a9c4ead 100644 --- a/tests/test_fa.py +++ b/tests/test_fa.py @@ -62,16 +62,21 @@ def test_cardinal(self): self.assertEqual(num2words(-203, lang='fa'), "منفی دویست و سه") self.assertEqual( num2words(1234567890, lang='fa'), - "یک میلیارد و دویست و سی و چهار میلیون و پانصد و شصت و هفت هزار و هشتصد و نود" + "یک میلیارد و دویست و سی و چهار میلیون و" + " پانصد و شصت و هفت هزار و هشتصد و نود" ) def test_year(self): - self.assertEqual(num2words(1398, lang='fa', to='year'), "هزار و سیصد و نود و هشت") - self.assertEqual(num2words(1399, lang='fa', to='year'), "هزار و سیصد و نود و نه") - self.assertEqual(num2words(1400, lang='fa', to='year'), "هزار و چهارصد") - + self.assertEqual(num2words(1398, lang='fa', to='year'), + "هزار و سیصد و نود و هشت") + self.assertEqual(num2words(1399, lang='fa', to='year'), + "هزار و سیصد و نود و نه") + self.assertEqual( + num2words(1400, lang='fa', to='year'), "هزار و چهارصد") + def test_currency(self): - self.assertEqual(num2words(1000, lang='fa', to='currency'), 'هزار تومان') + self.assertEqual( + num2words(1000, lang='fa', to='currency'), 'هزار تومان') self.assertEqual( num2words(1500000, lang='fa', to='currency'), 'یک میلیون و پانصد هزار تومان' @@ -86,9 +91,12 @@ def test_ordinal_num(self): def test_cardinal_for_float_number(self): self.assertEqual(num2words(12.5, lang='fa'), "دوازده و نیم") self.assertEqual(num2words(0.75, lang='fa'), "هفتاد و پنج صدم") - self.assertEqual(num2words(12.51, lang='fa'), "دوازده و پنجاه و یک صدم") - self.assertEqual(num2words(12.53, lang='fa'), "دوازده و پنجاه و سه صدم") - self.assertEqual(num2words(12.59, lang='fa'), "دوازده و پنجاه و نه صدم") + self.assertEqual(num2words(12.51, lang='fa'), + "دوازده و پنجاه و یک صدم") + self.assertEqual(num2words(12.53, lang='fa'), + "دوازده و پنجاه و سه صدم") + self.assertEqual(num2words(12.59, lang='fa'), + "دوازده و پنجاه و نه صدم") self.assertEqual(num2words(0.000001, lang='fa'), "یک میلیونیم") def test_overflow(self): From 4e6a5732482d6d17536e2d4d6c91e3f8d867c928 Mon Sep 17 00:00:00 2001 From: Katsuya Iida Date: Fri, 20 Aug 2021 17:29:01 +0900 Subject: [PATCH 100/200] =?UTF-8?q?Support=20Japanese=20Reiwa=20(=E4=BB=A4?= =?UTF-8?q?=E5=92=8C/=E3=82=8C=E3=81=84=E3=82=8F)=20era.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- num2words/lang_JA.py | 1 + tests/test_ja.py | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/num2words/lang_JA.py b/num2words/lang_JA.py index 58a29460..1e0e6222 100644 --- a/num2words/lang_JA.py +++ b/num2words/lang_JA.py @@ -335,6 +335,7 @@ def rendaku_merge_pairs(lpair, rpair): (1912, ("大正", "たいしょう")), (1926, ("昭和", "しょうわ")), (1989, ("平成", "へいせい")), + (2019, ("令和", "れいわ")), ] diff --git a/tests/test_ja.py b/tests/test_ja.py index eaac20b7..42da1445 100644 --- a/tests/test_ja.py +++ b/tests/test_ja.py @@ -163,6 +163,21 @@ def test_currency(self): "はちじゅうきゅうえん") def test_year(self): + self.assertEqual(n2j(2021, to="year"), "令和三年") + self.assertEqual(n2j(2021, to="year", reading=True), + "れいわさんねん") + self.assertEqual(n2j(2021, to="year", reading="arabic"), + "令和3年") + self.assertEqual(n2j(2019, to="year"), "令和元年") + self.assertEqual(n2j(2019, to="year", reading=True), + "れいわがんねん") + self.assertEqual(n2j(2019, to="year", reading="arabic"), + "令和1年") + self.assertEqual(n2j(2018, to="year"), "平成三十年") + self.assertEqual(n2j(2018, to="year", reading=True), + "へいせいさんじゅうねん") + self.assertEqual(n2j(2018, to="year", reading="arabic"), + "平成30年") self.assertEqual(n2j(2017, to="year"), "平成二十九年") self.assertEqual(n2j(2017, to="year", reading=True), "へいせいにじゅうくねん") @@ -176,8 +191,6 @@ def test_year(self): "にせんねん") self.assertEqual(n2j(645, to="year"), "大化元年") self.assertEqual(n2j(645, to="year", reading=True), "たいかがんねん") - self.assertEqual(n2j(645, to="year"), "大化元年") - self.assertEqual(n2j(645, to="year", reading=True), "たいかがんねん") self.assertEqual(n2j(-99, to="year", era=False), "紀元前九十九年") self.assertEqual(n2j(-99, to="year", era=False, reading=True), "きげんぜんきゅうじゅうくねん") From 5d1e3c7d1aaad9e8df0796a547fe0c7ea2fe2c23 Mon Sep 17 00:00:00 2001 From: Marlon Rodriguez Garcia <47992153+mrodriguezg1991@users.noreply.github.com> Date: Thu, 4 Aug 2022 16:17:58 -0400 Subject: [PATCH 101/200] Update __init__.py remove space --- num2words/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/num2words/__init__.py b/num2words/__init__.py index 19090545..ee54e5cf 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -24,7 +24,7 @@ lang_NL, lang_NO, lang_PL, lang_PT, lang_PT_BR, lang_RO, lang_RU, lang_SL, lang_SR, lang_SV, lang_TE, lang_TH, lang_TR, lang_UK, lang_VI) - + CONVERTER_CLASSES = { 'ar': lang_AR.Num2Word_AR(), 'cz': lang_CZ.Num2Word_CZ(), From 16229a31a485e415b8e5c58a3951b7a089dbb1f2 Mon Sep 17 00:00:00 2001 From: Eyosiyas Bereketab Date: Sun, 7 Aug 2022 22:19:49 +0300 Subject: [PATCH 102/200] Add Amharic language --- num2words/lang_AM.py | 107 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 num2words/lang_AM.py diff --git a/num2words/lang_AM.py b/num2words/lang_AM.py new file mode 100644 index 00000000..5d1e7bb2 --- /dev/null +++ b/num2words/lang_AM.py @@ -0,0 +1,107 @@ +# -*- 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): + 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 + "ሊዮን" + + 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 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) + 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_currency(self, val, currency='ብር', cents=True, separator='.', + adjective=False): + 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) \ + .replace(' ', '') From 4355e11637359439609528f6c2f201375857b037 Mon Sep 17 00:00:00 2001 From: Eyosiyas Bereketab Date: Sun, 7 Aug 2022 22:30:30 +0300 Subject: [PATCH 103/200] Update init for Amharic language --- num2words/__init__.py | 15 ++++++++------- tests/test_am.py | 23 +++++++++++++++++++++++ 2 files changed, 31 insertions(+), 7 deletions(-) create mode 100644 tests/test_am.py diff --git a/num2words/__init__.py b/num2words/__init__.py index ee54e5cf..baba5bdd 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -18,15 +18,16 @@ from __future__ import unicode_literals from . import (lang_AR, lang_CZ, lang_DE, lang_DK, lang_EN, lang_EN_IN, - lang_ES, lang_ES_CO, 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_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_SL, lang_SR, lang_SV, lang_TE, lang_TH, lang_TR, - lang_UK, lang_VI) - + lang_ES, lang_ES_CO, 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_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_SL, lang_SR, lang_SV, lang_TE, lang_TH, + lang_TR, lang_UK, lang_VI, lang_AM) + CONVERTER_CLASSES = { 'ar': lang_AR.Num2Word_AR(), + 'am': lang_AM.Num2Word_AM(), 'cz': lang_CZ.Num2Word_CZ(), 'en': lang_EN.Num2Word_EN(), 'en_IN': lang_EN_IN.Num2Word_EN_IN(), diff --git a/tests/test_am.py b/tests/test_am.py new file mode 100644 index 00000000..1a8436cf --- /dev/null +++ b/tests/test_am.py @@ -0,0 +1,23 @@ +# -*- 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 unittest import TestCase + +from num2words import num2words + + +class Num2WordsAMTest(TestCase): From 736db5149e25c3b575c45113c69a7d4dfd3a031a Mon Sep 17 00:00:00 2001 From: Eyosiyas Bereketab Date: Sun, 7 Aug 2022 22:34:49 +0300 Subject: [PATCH 104/200] Update Amharic language --- num2words/lang_AM.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/num2words/lang_AM.py b/num2words/lang_AM.py index 5d1e7bb2..6e4f2f92 100644 --- a/num2words/lang_AM.py +++ b/num2words/lang_AM.py @@ -67,9 +67,9 @@ def merge(self, lpair, rpair): if lnum == 1 and rnum < 100: return (rtext, rnum) elif 100 > lnum > rnum: - return ("%s-%s" % (ltext, rtext), lnum + rnum) + return ("%s %s" % (ltext, rtext), lnum + rnum) elif lnum >= 100 > rnum: - return ("%s እና %s" % (ltext, rtext), lnum + rnum) + return ("%s %s" % (ltext, rtext), lnum + rnum) elif rnum > lnum: return ("%s %s" % (ltext, rtext), lnum * rnum) return ("%s, %s" % (ltext, rtext), lnum + rnum) @@ -86,7 +86,7 @@ def to_ordinal(self, value): lastword = lastword[:-1] + "ie" lastword += "th" lastwords[-1] = self.title(lastword) - outwords[-1] = "-".join(lastwords) + outwords[-1] = " ".join(lastwords) return " ".join(outwords) def to_ordinal_num(self, value): From 770cd6d1d53abbb3c497a8db1e07c9a4e395e6e9 Mon Sep 17 00:00:00 2001 From: Eyosiyas Bereketab Date: Sun, 7 Aug 2022 23:02:25 +0300 Subject: [PATCH 105/200] Add Amharic currency form --- num2words/lang_AM.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/num2words/lang_AM.py b/num2words/lang_AM.py index 6e4f2f92..024e3e1e 100644 --- a/num2words/lang_AM.py +++ b/num2words/lang_AM.py @@ -21,6 +21,8 @@ class Num2Word_AM(lang_EU.Num2Word_EU): + CURRENCY_FORMS = {'ETB': (('ብር', 'ብር'), ('ሳንቲም', 'ሳንቲም'))} + def set_high_numwords(self, high): max = 3 + 3 * len(high) for word, n in zip(high, range(max, 3, -3)): @@ -93,8 +95,8 @@ def to_ordinal_num(self, value): self.verify_ordinal(value) return "%s%s" % (value, self.to_ordinal(value)[-2:]) - def to_currency(self, val, currency='ብር', cents=True, separator='.', - adjective=False): + 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) From a5a812d4210147a9255a935a2188469b6afa18c7 Mon Sep 17 00:00:00 2001 From: Eyosiyas Bereketab Date: Sun, 7 Aug 2022 23:06:48 +0300 Subject: [PATCH 106/200] Add test cases --- num2words/lang_AM.py | 3 +-- tests/test_am.py | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/num2words/lang_AM.py b/num2words/lang_AM.py index 024e3e1e..40725592 100644 --- a/num2words/lang_AM.py +++ b/num2words/lang_AM.py @@ -105,5 +105,4 @@ def to_currency(self, val, currency='ብር', cents=True, separator=' ከ', 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) \ - .replace(' ', '') + return self.to_splitnum(val, hightxt="መቶ", longval=longval) diff --git a/tests/test_am.py b/tests/test_am.py index 1a8436cf..6c479553 100644 --- a/tests/test_am.py +++ b/tests/test_am.py @@ -21,3 +21,46 @@ class Num2WordsAMTest(TestCase): + def test_and_join_199(self): + self.assertEqual(num2words(199, lang='am'), "አንድ መቶ ዘጠና ዘጠኝ") + + def test_ordinal(self): + self.assertEqual( + num2words(1, lang='am', to='ordinal'), + 'አንደኛ' + ) + self.assertEqual( + num2words(13, lang='am', to='ordinal'), + 'አሥራ ሦስተኛ' + ) + self.assertEqual( + num2words(22, lang='am', to='ordinal'), + 'ሃያ ሁለተኛ' + ) + + def test_to_currency(self): + self.assertEqual( + num2words('38.4', lang='am', to='currency', cents=False, currency='ETB'), + "ሠላሳ ስምንት ብር ከ 40 ሳንቲም" + ) + self.assertEqual( + num2words('0', lang='am', to='currency', separator=' እና', cents=True, currency='ETB'), + "ዜሮ ብር እና ዜሮ ሳንቲም" + ) + + self.assertEqual( + num2words('1.50', lang='am', to='currency', cents=True, currency='ETB'), + "አንድ ብር ከ አምሳ ሳንቲም" + ) + + def test_to_year(self): + self.assertEqual(num2words(1990, lang='am', to='year'), + 'አሥራ ዘጠኝ መቶ ዘጠና') + self.assertEqual(num2words(5555, lang='am', to='year'), + 'አምሳ አምስት መቶ አምሳ አምስት') + self.assertEqual(num2words(2017, lang='am', to='year'), + 'ሁለት ሺህ አሥራ ሰባት') + self.assertEqual(num2words(1066, lang='am', to='year'), + 'አንድ ሺህ ስድሳ ስድስት') + self.assertEqual(num2words(1865, lang='am', to='year'), + 'አሥራ ስምንት መቶ ስድሳ አምስት') From 5948065b368fa4c21f6f25a9cde5c46d61e7f17a Mon Sep 17 00:00:00 2001 From: Eyosiyas Bereketab Date: Tue, 9 Aug 2022 11:14:40 +0300 Subject: [PATCH 107/200] Fix flake 8 requirements in python3.1 and increase test coverage. --- num2words/__init__.py | 16 ++++++++-------- num2words/lang_AM.py | 2 +- tests/test_am.py | 31 +++++++++++++++++++++++++------ 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/num2words/__init__.py b/num2words/__init__.py index baba5bdd..dc422200 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -17,17 +17,17 @@ from __future__ import unicode_literals -from . import (lang_AR, lang_CZ, lang_DE, lang_DK, lang_EN, lang_EN_IN, - lang_ES, lang_ES_CO, 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_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_SL, lang_SR, lang_SV, lang_TE, lang_TH, - lang_TR, lang_UK, lang_VI, lang_AM) +from . import (lang_AM, lang_AR, lang_CZ, lang_DE, lang_DK, lang_EN, + lang_EN_IN, lang_ES, lang_ES_CO, 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_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_SL, lang_SR, lang_SV, lang_TE, + lang_TH, lang_TR, lang_UK, lang_VI) CONVERTER_CLASSES = { - 'ar': lang_AR.Num2Word_AR(), 'am': lang_AM.Num2Word_AM(), + 'ar': lang_AR.Num2Word_AR(), 'cz': lang_CZ.Num2Word_CZ(), 'en': lang_EN.Num2Word_EN(), 'en_IN': lang_EN_IN.Num2Word_EN_IN(), diff --git a/num2words/lang_AM.py b/num2words/lang_AM.py index 40725592..4e40bda7 100644 --- a/num2words/lang_AM.py +++ b/num2words/lang_AM.py @@ -93,7 +93,7 @@ def to_ordinal(self, value): def to_ordinal_num(self, value): self.verify_ordinal(value) - return "%s%s" % (value, self.to_ordinal(value)[-2:]) + return "%s%s" % (value, self.to_ordinal(value)[-1:]) def to_currency(self, val, currency='ብር', cents=True, separator=' ከ', adjective=True): diff --git a/tests/test_am.py b/tests/test_am.py index 6c479553..a3dc95da 100644 --- a/tests/test_am.py +++ b/tests/test_am.py @@ -38,19 +38,38 @@ def test_ordinal(self): 'ሃያ ሁለተኛ' ) + def test_ordinal_num(self): + self.assertEqual(num2words(10, lang='am', to='ordinal_num'), '10ኛ') + self.assertEqual(num2words(21, lang='am', to='ordinal_num'), '21ኛ') + self.assertEqual(num2words(102, lang='am', to='ordinal_num'), '102ኛ') + + def test_cardinal_for_float_number(self): + self.assertEqual(num2words(12.5, lang='am'), "አሥራ ሁለት ነጥብ አምስት") + self.assertEqual(num2words(12.51, lang='am'), "አሥራ ሁለት ነጥብ አምስት አንድ") + self.assertEqual(num2words(12.53, lang='am'), "አሥራ ሁለት ነጥብ አምስት ሦስት") + + def test_overflow(self): + with self.assertRaises(OverflowError): + num2words("1000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000", lang='am') + def test_to_currency(self): self.assertEqual( - num2words('38.4', lang='am', to='currency', cents=False, currency='ETB'), - "ሠላሳ ስምንት ብር ከ 40 ሳንቲም" + num2words('38.4', lang='am', to='currency', cents=False, + currency='ETB'), "ሠላሳ ስምንት ብር ከ 40 ሳንቲም" ) self.assertEqual( - num2words('0', lang='am', to='currency', separator=' እና', cents=True, currency='ETB'), - "ዜሮ ብር እና ዜሮ ሳንቲም" + num2words('0', lang='am', to='currency', separator=' እና', + cents=True, currency='ETB'), "ዜሮ ብር እና ዜሮ ሳንቲም" ) self.assertEqual( - num2words('1.50', lang='am', to='currency', cents=True, currency='ETB'), - "አንድ ብር ከ አምሳ ሳንቲም" + num2words('1.50', lang='am', to='currency', cents=True, + currency='ETB'), "አንድ ብር ከ አምሳ ሳንቲም" ) def test_to_year(self): From 83203ed98e512765b75ca604a3480a82d513d99f Mon Sep 17 00:00:00 2001 From: Eyosiyas Bereketab Date: Tue, 9 Aug 2022 17:00:56 +0300 Subject: [PATCH 108/200] Fix line too long __init__.py --- num2words/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/num2words/__init__.py b/num2words/__init__.py index dc422200..86f1b63a 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -22,8 +22,8 @@ lang_FA, lang_FI, lang_FR, lang_FR_BE, lang_FR_CH, lang_FR_DZ, lang_HE, lang_HU, lang_ID, 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_SL, lang_SR, lang_SV, lang_TE, - lang_TH, lang_TR, lang_UK, lang_VI) + lang_PT_BR, lang_RO, lang_RU, lang_SL, lang_SR, lang_SV, + lang_TE, lang_TH, lang_TR, lang_UK, lang_VI) CONVERTER_CLASSES = { 'am': lang_AM.Num2Word_AM(), From 8ed54f332d9a2044642b1947ab554cdb52c2f768 Mon Sep 17 00:00:00 2001 From: Eyosiyas Bereketab Date: Tue, 9 Aug 2022 21:13:53 +0300 Subject: [PATCH 109/200] Update Amharic language support --- README.rst | 3 +- num2words/lang_AM.py | 122 ++++++++++++++++++++++++++----------------- tests/test_am.py | 37 +++++++------ 3 files changed, 98 insertions(+), 64 deletions(-) diff --git a/README.rst b/README.rst index 04145315..7b9b487e 100644 --- a/README.rst +++ b/README.rst @@ -76,6 +76,7 @@ Besides the numerical argument, there are two main optional arguments. **lang:** The language in which to convert the number. Supported values are: * ``en`` (English, default) +* ``am`` (Amharic) * ``ar`` (Arabic) * ``cz`` (Czech) * ``de`` (German) @@ -149,4 +150,4 @@ added Lithuanian support, but didn't take over maintenance of the project. I am thus basing myself on Marius Grigaitis' improvements and re-publishing ``pynum2word`` as ``num2words``. -Virgil Dupras, Savoir-faire Linux +Virgil Dupras, Savoir-faire Linux \ No newline at end of file diff --git a/num2words/lang_AM.py b/num2words/lang_AM.py index 4e40bda7..3efd9c25 100644 --- a/num2words/lang_AM.py +++ b/num2words/lang_AM.py @@ -23,45 +23,73 @@ class Num2Word_AM(lang_EU.Num2Word_EU): CURRENCY_FORMS = {'ETB': (('ብር', 'ብር'), ('ሳንቲም', 'ሳንቲም'))} + GIGA_SUFFIX = 'ቢሊዮን' + MEGA_SUFFIX = 'ሚሊዮን' + 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 + "ሊዮን" + 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 = {"አንድ": "አንደኛ", - "ሁለት": "ሁለተኛ", - "ሦስት": "ሦስተኛ", - "አራት": "አራተኛ", - "አምስት": "አምስተኛ", - "ስድስት": "ስድስተኛ", - "ሰባት": "ሰባተኛ", - "ስምንት": "ስምንተኛ", - "ዘጠኝ": "ዘጠነኛ", - "አሥር": "አሥረኛ", - "አሥራ አንድ": "አሥራ አንድ", - "አሥራ ሁለት": "አሥራ ሁለተኛ", - "አሥራ ሦስት": "አሥራ ሦስተኛ", - "አሥራ አራት": "አሥራ አራተኛ", - "አሥራ አምስት": "አሥራ አምስተኛ", - "አሥራ ስድስት": "አሥራ ስድስተኛ", - "አሥራ ሰባት": "አሥራ ሰባተኛ", - "አሥራ ስምንት": "አሥራ ስምንተኛ", - "አሥራ ዘጠኝ": "አሥራ ዘጠነኛ"} + 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 < 0: + value = abs(value) + out = self.negword + + 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 @@ -69,31 +97,31 @@ def merge(self, lpair, rpair): if lnum == 1 and rnum < 100: return (rtext, rnum) elif 100 > lnum > rnum: - return ("%s %s" % (ltext, rtext), lnum + rnum) + return ('%s %s' % (ltext, rtext), lnum + rnum) elif lnum >= 100 > rnum: - return ("%s %s" % (ltext, rtext), lnum + rnum) + return ('%s %s' % (ltext, rtext), lnum + rnum) elif rnum > lnum: - return ("%s %s" % (ltext, rtext), lnum * rnum) - return ("%s, %s" % (ltext, rtext), lnum + rnum) + 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("-") + 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" + if lastword[-1] == 'y': + lastword = lastword[:-1] + 'ie' + lastword += 'th' lastwords[-1] = self.title(lastword) - outwords[-1] = " ".join(lastwords) - return " ".join(outwords) + 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:]) + return '%s%s' % (value, self.to_ordinal(value)[-1:]) def to_currency(self, val, currency='ብር', cents=True, separator=' ከ', adjective=True): @@ -105,4 +133,4 @@ def to_currency(self, val, currency='ብር', cents=True, separator=' ከ', 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) + return self.to_splitnum(val, hightxt='መቶ', longval=longval) diff --git a/tests/test_am.py b/tests/test_am.py index a3dc95da..460ca6e4 100644 --- a/tests/test_am.py +++ b/tests/test_am.py @@ -21,10 +21,15 @@ class Num2WordsAMTest(TestCase): + def test_cardinal(self): + self.assertEqual(num2words(100, lang='am'), 'መቶ') + self.assertEqual(num2words(100000, lang='am'), 'አንድ መቶ ሺህ') + self.assertEqual(num2words(101, lang='am'), 'አንድ መቶ አንድ') + def test_and_join_199(self): - self.assertEqual(num2words(199, lang='am'), "አንድ መቶ ዘጠና ዘጠኝ") + self.assertEqual(num2words(199, lang='am'), 'አንድ መቶ ዘጠና ዘጠኝ') - def test_ordinal(self): + def test_to_ordinal(self): self.assertEqual( num2words(1, lang='am', to='ordinal'), 'አንደኛ' @@ -38,38 +43,38 @@ def test_ordinal(self): 'ሃያ ሁለተኛ' ) - def test_ordinal_num(self): + def test_to_ordinal_num(self): self.assertEqual(num2words(10, lang='am', to='ordinal_num'), '10ኛ') self.assertEqual(num2words(21, lang='am', to='ordinal_num'), '21ኛ') self.assertEqual(num2words(102, lang='am', to='ordinal_num'), '102ኛ') def test_cardinal_for_float_number(self): - self.assertEqual(num2words(12.5, lang='am'), "አሥራ ሁለት ነጥብ አምስት") - self.assertEqual(num2words(12.51, lang='am'), "አሥራ ሁለት ነጥብ አምስት አንድ") - self.assertEqual(num2words(12.53, lang='am'), "አሥራ ሁለት ነጥብ አምስት ሦስት") + self.assertEqual(num2words(12.5, lang='am'), 'አሥራ ሁለት ነጥብ አምስት') + self.assertEqual(num2words(12.51, lang='am'), 'አሥራ ሁለት ነጥብ አምስት አንድ') + self.assertEqual(num2words(12.53, lang='am'), 'አሥራ ሁለት ነጥብ አምስት ሦስት') - def test_overflow(self): + def test_to_overflow(self): with self.assertRaises(OverflowError): - num2words("1000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000" - "0000000000000000000000000000000000000000000000000000000" - "00000000000000000000000000000000", lang='am') + num2words('1000000000000000000000000000000000000000000000000000000' + '0000000000000000000000000000000000000000000000000000000' + '0000000000000000000000000000000000000000000000000000000' + '0000000000000000000000000000000000000000000000000000000' + '0000000000000000000000000000000000000000000000000000000' + '00000000000000000000000000000000', lang='am') def test_to_currency(self): self.assertEqual( num2words('38.4', lang='am', to='currency', cents=False, - currency='ETB'), "ሠላሳ ስምንት ብር ከ 40 ሳንቲም" + currency='ETB'), 'ሠላሳ ስምንት ብር ከ 40 ሳንቲም' ) self.assertEqual( num2words('0', lang='am', to='currency', separator=' እና', - cents=True, currency='ETB'), "ዜሮ ብር እና ዜሮ ሳንቲም" + cents=True, currency='ETB'), 'ዜሮ ብር እና ዜሮ ሳንቲም' ) self.assertEqual( num2words('1.50', lang='am', to='currency', cents=True, - currency='ETB'), "አንድ ብር ከ አምሳ ሳንቲም" + currency='ETB'), 'አንድ ብር ከ አምሳ ሳንቲም' ) def test_to_year(self): From 5bfcebd9fb32bb2c6b946e4270624aa4045bfe11 Mon Sep 17 00:00:00 2001 From: Drew Echerd Date: Fri, 2 Jul 2021 17:00:13 +0500 Subject: [PATCH 110/200] Added Tajik language support --- README.rst | 1 + num2words/__init__.py | 1 + num2words/lang_TG.py | 149 ++++++++++++++++++++++++++++++++++++++++++ tests/test_tg.py | 104 +++++++++++++++++++++++++++++ 4 files changed, 255 insertions(+) create mode 100644 num2words/lang_TG.py create mode 100644 tests/test_tg.py diff --git a/README.rst b/README.rst index 7b9b487e..2a8f99f4 100644 --- a/README.rst +++ b/README.rst @@ -113,6 +113,7 @@ Besides the numerical argument, there are two main optional arguments. * ``ro`` (Romanian) * ``ru`` (Russian) * ``te`` (Telugu) +* ``tg`` (Tajik) * ``tr`` (Turkish) * ``th`` (Thai) * ``vi`` (Vietnamese) diff --git a/num2words/__init__.py b/num2words/__init__.py index 86f1b63a..1bc70943 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -62,6 +62,7 @@ '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(), diff --git a/num2words/lang_TG.py b/num2words/lang_TG.py new file mode 100644 index 00000000..cc0bf497 --- /dev/null +++ b/num2words/lang_TG.py @@ -0,0 +1,149 @@ +# -*- 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 + +GENERIC_DOLLARS = ("доллар", "доллар") +GENERIC_CENTS = ("сент", "сент") + + +class Num2Word_TG(lang_EU.Num2Word_EU): + CURRENCY_FORMS = { + # repalced by EUR + "EUR": (("евро", "евро"), GENERIC_CENTS), + # replaced by EUR + "USD": (GENERIC_DOLLARS, GENERIC_CENTS), + "RUB": (("рубл", "рубл"), ("копейк", "копейк")), + "TJS": (("сомонӣ", "сомонӣ"), ("дирам", "дирам")), + } + + 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 + + elif self.MEGA_SUFFIX: + self.cards[10 ** n] = word + self.MEGA_SUFFIX + + def setup(self): + super(Num2Word_TG, self).setup() + + lows = ["квинт", "квадр", "тр", "м", "м"] + self.high_numwords = self.gen_high_numwords([], [], lows) + self.negword = "минус " + self.pointword = "нуқта" + self.exclude_title = ["ва", "минус", "нуқта"] + + self.mid_numwords = [ + (1000, "ҳазор"), + (100, "сад"), + (90, "навад"), + (80, "ҳаштод"), + (70, "ҳафтод"), + (60, "шаст"), + (50, "панҷоҳ"), + (40, "чил"), + (30, "си"), + ] + self.low_numwords = [ + "бист", + "нуздаҳ", + "ҳаждаҳ", + "ҳабдаҳ", + "шонздаҳ", + "понздаҳ", + "чордаҳ", + "сенздаҳ", + "дувоздаҳ", + "ёздаҳ", + "даҳ", + "нӯҳ", + "ҳашт", + "ҳафт", + "шаш", + "панҷ", + "чор", + "се", + "ду", + "як", + "сифр", + ] + + 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 = self.negword + + 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: + if ltext == "си": + return ("%sю %s" % (ltext, rtext), lnum + rnum) + elif ltext == "панҷоҳ": + return ("панҷову %s" % (rtext), lnum + rnum) + else: + return ("%sу %s" % (ltext, rtext), lnum + rnum) + elif lnum >= 100 > rnum: + return ("%sу %s" % (ltext, rtext), lnum + rnum) + elif rnum > lnum: + if ltext == "яксад" and rtext not in self.low_numwords: + return ("сад %s" % (rtext), lnum * rnum) + if rtext == "сад": + return ("%s%s" % (ltext, rtext), lnum * rnum) + else: + return ("%s %s" % (ltext, rtext), lnum * rnum) + return ("%sу %s" % (ltext, rtext), lnum + rnum) + + def to_ordinal(self, value): + self.verify_ordinal(value) + cardinal = self.to_cardinal(value) + outwords = cardinal.split(" ") + lastword = outwords[-1] + if lastword in ["ду", "се", "си"]: + return "%sюм" % (cardinal) + else: + return "%sум" % (cardinal) + + def to_ordinal_num(self, value): + self.verify_ordinal(value) + return "%s%s" % (value, self.to_ordinal(value)[-2:]) diff --git a/tests/test_tg.py b/tests/test_tg.py new file mode 100644 index 00000000..2caa9cf1 --- /dev/null +++ b/tests/test_tg.py @@ -0,0 +1,104 @@ +# -*- 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 unittest import TestCase + +from num2words import num2words + + +class Num2WordsTGTest(TestCase): + def test_cardinal(self): + self.assertEqual(num2words(100, lang="tg"), "сад") + self.assertEqual(num2words(101, lang="tg"), "яксаду як") + self.assertEqual(num2words(110, lang="tg"), "яксаду даҳ") + self.assertEqual(num2words(115, lang="tg"), "яксаду понздаҳ") + self.assertEqual(num2words(123, lang="tg"), "яксаду бисту се") + self.assertEqual(num2words(1000, lang="tg"), "як ҳазор") + self.assertEqual(num2words(1001, lang="tg"), "як ҳазору як") + self.assertEqual(num2words(2012, lang="tg"), "ду ҳазору дувоздаҳ") + self.assertEqual( + num2words(12519.85, lang="tg"), + "дувоздаҳ ҳазору панҷсаду нуздаҳ нуқта ҳашт панҷ", + ) + + self.assertEqual( + num2words(1234567890, lang="tg"), + "як миллиарду дусаду сию чор миллиону панҷсаду шасту ҳафт ҳазору " + "ҳаштсаду навад", + ) + self.assertEqual(num2words(5, lang="tg"), "панҷ") + self.assertEqual(num2words(-1, lang="tg"), "минус як") + self.assertEqual(num2words(-15, lang="tg"), "минус понздаҳ") + self.assertEqual(num2words(-100, lang="tg"), "минус сад") + + def test_to_ordinal(self): + self.assertEqual(num2words(1, lang="tg", to="ordinal"), "якум") + self.assertEqual(num2words(2, lang="tg", to="ordinal"), "дуюм") + self.assertEqual(num2words(3, lang="tg", to="ordinal"), "сеюм") + self.assertEqual(num2words(30, lang="tg", to="ordinal"), "сиюм") + + self.assertEqual(num2words(13, lang="tg", to="ordinal"), "сенздаҳум") + self.assertEqual(num2words(20, lang="tg", to="ordinal"), "бистум") + self.assertEqual(num2words(23, lang="tg", to="ordinal"), "бисту сеюм") + self.assertEqual(num2words(100, lang="tg", to="ordinal"), "садум") + self.assertEqual(num2words(136, lang="tg", to="ordinal"), + "яксаду сию шашум") + self.assertEqual(num2words(500, lang="tg", to="ordinal"), "панҷсадум") + self.assertEqual( + num2words(1000, lang="tg", to="ordinal"), "як ҳазорум" + ) + self.assertEqual( + num2words(1001, lang="tg", to="ordinal"), "як ҳазору якум" + ) + self.assertEqual( + num2words(2000, lang="tg", to="ordinal"), "ду ҳазорум" + ) + self.assertEqual( + num2words(1000000, lang="tg", to="ordinal"), "як миллионум" + ) + self.assertEqual( + num2words(1000000000, lang="tg", to="ordinal"), "як миллиардум" + ) + + def test_to_currency(self): + self.assertEqual( + num2words(1.0, lang="tg", to="currency", currency="EUR"), + "як евро, сифр сент", + ) + self.assertEqual( + num2words(1.0, lang="tg", to="currency", currency="TJS"), + "як сомонӣ, сифр дирам", + ) + self.assertEqual( + num2words(1234.56, lang="tg", to="currency", currency="TJS"), + "як ҳазору дусаду сию чор сомонӣ, панҷову шаш дирам", + ) + self.assertEqual( + num2words(1234.56, lang="tg", to="currency", currency="RUB"), + "як ҳазору дусаду сию чор рубл, панҷову шаш копейк", + ) + self.assertEqual( + num2words(12519.85, lang="tg", to="currency", currency="TJS", + cents=False), + "дувоздаҳ ҳазору панҷсаду нуздаҳ сомонӣ, 85 дирам", + ) + self.assertEqual( + num2words("1230.56", lang="tg", to="currency", currency="USD"), + "як ҳазору дусаду си доллар, панҷову шаш сент", + ) \ No newline at end of file From af97683fdc972e262e6f5b5c0e95059b2a19d156 Mon Sep 17 00:00:00 2001 From: Drew Echerd Date: Fri, 2 Jul 2021 18:51:22 +0500 Subject: [PATCH 111/200] Added test for OverflowError and ordinal_num --- tests/test_tg.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/test_tg.py b/tests/test_tg.py index 2caa9cf1..a846d701 100644 --- a/tests/test_tg.py +++ b/tests/test_tg.py @@ -24,7 +24,10 @@ class Num2WordsTGTest(TestCase): def test_cardinal(self): + with self.assertRaises(OverflowError): + num2words(1000000000000000000000000, lang='tg') self.assertEqual(num2words(100, lang="tg"), "сад") + self.assertEqual(num2words(100000, lang="tg"), "сад ҳазор") self.assertEqual(num2words(101, lang="tg"), "яксаду як") self.assertEqual(num2words(110, lang="tg"), "яксаду даҳ") self.assertEqual(num2words(115, lang="tg"), "яксаду понздаҳ") @@ -101,4 +104,9 @@ def test_to_currency(self): self.assertEqual( num2words("1230.56", lang="tg", to="currency", currency="USD"), "як ҳазору дусаду си доллар, панҷову шаш сент", + ) + + def test_to_ordinal_num(self): + self.assertEqual( + num2words("100", lang="tg", to="ordinal_num"), "100ум", ) \ No newline at end of file From beb3326bbca5fbf3a28404567c71a5151bcf996d Mon Sep 17 00:00:00 2001 From: Drew Echerd Date: Fri, 2 Jul 2021 22:29:28 +0500 Subject: [PATCH 112/200] Added MEGA_SUFFIX and GIGA_SUFFIX tests --- num2words/lang_TG.py | 3 ++- tests/test_tg.py | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/num2words/lang_TG.py b/num2words/lang_TG.py index cc0bf497..8a028d58 100644 --- a/num2words/lang_TG.py +++ b/num2words/lang_TG.py @@ -43,7 +43,7 @@ def set_high_numwords(self, high): if n == 9: self.cards[10 ** n] = word + self.GIGA_SUFFIX - elif self.MEGA_SUFFIX: + else: self.cards[10 ** n] = word + self.MEGA_SUFFIX def setup(self): @@ -147,3 +147,4 @@ def to_ordinal(self, value): def to_ordinal_num(self, value): self.verify_ordinal(value) return "%s%s" % (value, self.to_ordinal(value)[-2:]) + diff --git a/tests/test_tg.py b/tests/test_tg.py index a846d701..482913be 100644 --- a/tests/test_tg.py +++ b/tests/test_tg.py @@ -45,6 +45,9 @@ def test_cardinal(self): "як миллиарду дусаду сию чор миллиону панҷсаду шасту ҳафт ҳазору " "ҳаштсаду навад", ) + self.assertEqual(num2words(1000000, lang="tg"), "як миллион") + self.assertEqual(num2words(1000000000, lang="tg"), "як миллиард") + self.assertEqual(num2words(1000000000000, lang="tg"), "як триллион") self.assertEqual(num2words(5, lang="tg"), "панҷ") self.assertEqual(num2words(-1, lang="tg"), "минус як") self.assertEqual(num2words(-15, lang="tg"), "минус понздаҳ") From 7bf80d5dd73cf6f2b228cc5cd2258cd0bc02d235 Mon Sep 17 00:00:00 2001 From: Drew Echerd Date: Tue, 9 Aug 2022 09:57:58 -0400 Subject: [PATCH 113/200] Fixed flake8 errors --- num2words/lang_TG.py | 1 - tests/test_tg.py | 19 +++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/num2words/lang_TG.py b/num2words/lang_TG.py index 8a028d58..48291a26 100644 --- a/num2words/lang_TG.py +++ b/num2words/lang_TG.py @@ -147,4 +147,3 @@ def to_ordinal(self, value): def to_ordinal_num(self, value): self.verify_ordinal(value) return "%s%s" % (value, self.to_ordinal(value)[-2:]) - diff --git a/tests/test_tg.py b/tests/test_tg.py index 482913be..53a49e4f 100644 --- a/tests/test_tg.py +++ b/tests/test_tg.py @@ -25,7 +25,7 @@ class Num2WordsTGTest(TestCase): def test_cardinal(self): with self.assertRaises(OverflowError): - num2words(1000000000000000000000000, lang='tg') + num2words(1000000000000000000000000, lang="tg") self.assertEqual(num2words(100, lang="tg"), "сад") self.assertEqual(num2words(100000, lang="tg"), "сад ҳазор") self.assertEqual(num2words(101, lang="tg"), "яксаду як") @@ -63,8 +63,9 @@ def test_to_ordinal(self): self.assertEqual(num2words(20, lang="tg", to="ordinal"), "бистум") self.assertEqual(num2words(23, lang="tg", to="ordinal"), "бисту сеюм") self.assertEqual(num2words(100, lang="tg", to="ordinal"), "садум") - self.assertEqual(num2words(136, lang="tg", to="ordinal"), - "яксаду сию шашум") + self.assertEqual( + num2words(136, lang="tg", to="ordinal"), "яксаду сию шашум" + ) self.assertEqual(num2words(500, lang="tg", to="ordinal"), "панҷсадум") self.assertEqual( num2words(1000, lang="tg", to="ordinal"), "як ҳазорум" @@ -100,16 +101,18 @@ def test_to_currency(self): "як ҳазору дусаду сию чор рубл, панҷову шаш копейк", ) self.assertEqual( - num2words(12519.85, lang="tg", to="currency", currency="TJS", - cents=False), + num2words( + 12519.85, lang="tg", to="currency", currency="TJS", cents=False + ), "дувоздаҳ ҳазору панҷсаду нуздаҳ сомонӣ, 85 дирам", ) self.assertEqual( num2words("1230.56", lang="tg", to="currency", currency="USD"), "як ҳазору дусаду си доллар, панҷову шаш сент", ) - + def test_to_ordinal_num(self): self.assertEqual( - num2words("100", lang="tg", to="ordinal_num"), "100ум", - ) \ No newline at end of file + num2words("100", lang="tg", to="ordinal_num"), + "100ум", + ) From a7442708fabe210555356fb4c0ac9fc7ae9a92ff Mon Sep 17 00:00:00 2001 From: Eyosiyas Bereketab Date: Tue, 9 Aug 2022 21:19:56 +0300 Subject: [PATCH 114/200] Update __init__.py --- num2words/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/num2words/__init__.py b/num2words/__init__.py index 1bc70943..3c9171a8 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -23,7 +23,7 @@ lang_HE, lang_HU, lang_ID, 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_SL, lang_SR, lang_SV, - lang_TE, lang_TH, lang_TR, lang_UK, lang_VI) + lang_TE, lang_TG, lang_TH, lang_TR, lang_UK, lang_VI) CONVERTER_CLASSES = { 'am': lang_AM.Num2Word_AM(), From 2ca98971e1d51e3449e32314ca0342e5776506d4 Mon Sep 17 00:00:00 2001 From: Eyosiyas Bereketab Date: Wed, 10 Aug 2022 09:34:03 +0300 Subject: [PATCH 115/200] Add additional test case --- num2words/lang_AM.py | 19 ++++++------------- tests/test_am.py | 4 ++++ 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/num2words/lang_AM.py b/num2words/lang_AM.py index 3efd9c25..77922db3 100644 --- a/num2words/lang_AM.py +++ b/num2words/lang_AM.py @@ -60,7 +60,7 @@ def setup(self): 'ስምንት': 'ስምንተኛ', 'ዘጠኝ': 'ዘጠነኛ', 'አሥር': 'አሥረኛ', - 'አሥራ አንድ': 'አሥራ አንድ', + 'አሥራ አንድ': 'አሥራ አንደኛ', 'አሥራ ሁለት': 'አሥራ ሁለተኛ', 'አሥራ ሦስት': 'አሥራ ሦስተኛ', 'አሥራ አራት': 'አሥራ አራተኛ', @@ -77,10 +77,6 @@ def to_cardinal(self, value): 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)) @@ -95,14 +91,13 @@ def merge(self, lpair, rpair): ltext, lnum = lpair rtext, rnum = rpair if lnum == 1 and rnum < 100: - return (rtext, rnum) + return rtext, rnum elif 100 > lnum > rnum: - return ('%s %s' % (ltext, rtext), lnum + rnum) + return '%s %s' % (ltext, rtext), lnum + rnum elif lnum >= 100 > rnum: - return ('%s %s' % (ltext, rtext), lnum + rnum) + return '%s %s' % (ltext, rtext), lnum + rnum elif rnum > lnum: - return ('%s %s' % (ltext, rtext), lnum * rnum) - return ('%s, %s' % (ltext, rtext), lnum + rnum) + return '%s %s' % (ltext, rtext), lnum * rnum def to_ordinal(self, value): self.verify_ordinal(value) @@ -112,9 +107,7 @@ def to_ordinal(self, value): try: lastword = self.ords[lastword] except KeyError: - if lastword[-1] == 'y': - lastword = lastword[:-1] + 'ie' - lastword += 'th' + lastword += 'ኛ' lastwords[-1] = self.title(lastword) outwords[-1] = ' '.join(lastwords) return ' '.join(outwords) diff --git a/tests/test_am.py b/tests/test_am.py index 460ca6e4..58709c37 100644 --- a/tests/test_am.py +++ b/tests/test_am.py @@ -42,6 +42,10 @@ def test_to_ordinal(self): num2words(22, lang='am', to='ordinal'), 'ሃያ ሁለተኛ' ) + self.assertEqual( + num2words(10000, lang='am', to='ordinal'), + 'አሥር ሺህኛ' + ) def test_to_ordinal_num(self): self.assertEqual(num2words(10, lang='am', to='ordinal_num'), '10ኛ') From 084ace67cbffa193857ef4bed73290b598a63f4c Mon Sep 17 00:00:00 2001 From: "potapov.s" Date: Tue, 2 Nov 2021 12:59:24 +0300 Subject: [PATCH 116/200] - add uzs for ru and en --- num2words/lang_EU.py | 6 ++++-- num2words/lang_RU.py | 3 +++ tests/test_en.py | 6 ++++++ tests/test_ru.py | 5 +++++ 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/num2words/lang_EU.py b/num2words/lang_EU.py index 09d39c15..529547a9 100644 --- a/num2words/lang_EU.py +++ b/num2words/lang_EU.py @@ -43,7 +43,8 @@ class Num2Word_EU(Num2Word_Base): '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')) + 'HUF': (('forint', 'forint'), ('fillér', 'fillér')), + 'UZS': (('sum', 'sums'), ('tiyin', 'tiyins')) } CURRENCY_ADJECTIVES = { @@ -56,7 +57,8 @@ class Num2Word_EU(Num2Word_Base): 'MXN': 'Mexican', 'RON': 'Romanian', 'INR': 'Indian', - 'HUF': 'Hungarian' + 'HUF': 'Hungarian', + 'UZS': 'Uzbekistan' } GIGA_SUFFIX = "illiard" diff --git a/num2words/lang_RU.py b/num2words/lang_RU.py index 8e6c875b..166169c2 100644 --- a/num2words/lang_RU.py +++ b/num2words/lang_RU.py @@ -113,6 +113,9 @@ class Num2Word_RU(Num2Word_Base): 'KZT': ( ('тенге', 'тенге', 'тенге'), ('тиын', 'тиына', 'тиынов') ), + 'UZS': ( + ('сум', 'сума', 'сумов'), ('тийин', 'тийина', 'тийинов') + ), } def setup(self): diff --git a/tests/test_en.py b/tests/test_en.py index 6234ac98..e763841c 100644 --- a/tests/test_en.py +++ b/tests/test_en.py @@ -131,6 +131,12 @@ def test_to_currency(self): "four pesos and one cent" ) + self.assertEqual( + num2words('2000.00', lang='en', to='currency', separator=' and', + cents=True, currency='UZS'), + "two thousand sums and zero tiyins" + ) + def test_to_year(self): # issue 141 # "e2 e2" diff --git a/tests/test_ru.py b/tests/test_ru.py index dc479758..85d6dc3e 100644 --- a/tests/test_ru.py +++ b/tests/test_ru.py @@ -272,3 +272,8 @@ def test_to_currency(self): 'одна тысяча двести тридцать четыре доллара, пятьдесят шесть ' 'центов' ) + self.assertEqual( + num2words(10122, lang='ru', to='currency', currency='UZS', + separator=' и'), + 'сто один сум и двадцать два тийина' + ) From d1fe26961cff366c4788e0c4b0f1ae5f4b0d73fb Mon Sep 17 00:00:00 2001 From: cyriaka90 Date: Mon, 9 Nov 2020 18:16:22 +0100 Subject: [PATCH 117/200] fix Polish twenties --- num2words/lang_PL.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/num2words/lang_PL.py b/num2words/lang_PL.py index 1fb1fdcd..ec7e6a22 100644 --- a/num2words/lang_PL.py +++ b/num2words/lang_PL.py @@ -80,7 +80,7 @@ 6: ('sześćdziesiąt',), 7: ('siedemdziesiąt',), 8: ('osiemdziesiąt',), - 9: ('dziewięćdzisiąt',), + 9: ('dziewięćdziesiąt',), } TWENTIES_ORDINALS = { From 5878cd07fe1d691ea94149aba014ebbd2eefb4af Mon Sep 17 00:00:00 2001 From: cyriaka90 Date: Mon, 9 Nov 2020 18:26:47 +0100 Subject: [PATCH 118/200] adapt polish tests --- tests/test_pl.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/test_pl.py b/tests/test_pl.py index 147a747c..cf6e18ad 100644 --- a/tests/test_pl.py +++ b/tests/test_pl.py @@ -52,7 +52,7 @@ def test_cardinal(self): self.assertEqual( num2words(1234567890, lang='pl'), "miliard dwieście trzydzieści cztery miliony pięćset " - "sześćdziesiąt siedem tysięcy osiemset dziewięćdzisiąt" + "sześćdziesiąt siedem tysięcy osiemset dziewięćdziesiąt" ) self.assertEqual( num2words(10000000001000000100000, lang='pl'), @@ -62,20 +62,20 @@ def test_cardinal(self): num2words(215461407892039002157189883901676, lang='pl'), "dwieście piętnaście kwintylionów czterysta sześćdziesiąt jeden " "kwadryliardów czterysta siedem kwadrylionów osiemset " - "dziewięćdzisiąt dwa tryliardy trzydzieści dziewięć trylionów " + "dziewięćdziesiąt dwa tryliardy trzydzieści dziewięć trylionów " "dwa biliardy sto pięćdziesiąt siedem bilionów sto osiemdziesiąt " "dziewięć miliardów osiemset osiemdziesiąt trzy miliony " "dziewięćset jeden tysięcy sześćset siedemdziesiąt sześć" ) self.assertEqual( num2words(719094234693663034822824384220291, lang='pl'), - "siedemset dziewiętnaście kwintylionów dziewięćdzisiąt cztery " + "siedemset dziewiętnaście kwintylionów dziewięćdziesiąt cztery " "kwadryliardy dwieście trzydzieści cztery kwadryliony sześćset " - "dziewięćdzisiąt trzy tryliardy sześćset sześćdziesiąt trzy " + "dziewięćdziesiąt trzy tryliardy sześćset sześćdziesiąt trzy " "tryliony trzydzieści cztery biliardy osiemset dwadzieścia dwa " "biliony osiemset dwadzieścia cztery miliardy trzysta " "osiemdziesiąt cztery miliony dwieście dwadzieścia " - "tysięcy dwieście dziewięćdzisiąt jeden" + "tysięcy dwieście dziewięćdziesiąt jeden" ) self.assertEqual( num2words( From e4b75bb00d2fa55522995563e00eb08b78887546 Mon Sep 17 00:00:00 2001 From: cyriaka90 Date: Tue, 16 Aug 2022 14:58:50 +0200 Subject: [PATCH 119/200] increase Polish test coverage --- tests/test_pl.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/test_pl.py b/tests/test_pl.py index cf6e18ad..08ef0394 100644 --- a/tests/test_pl.py +++ b/tests/test_pl.py @@ -24,11 +24,13 @@ class Num2WordsPLTest(TestCase): def test_cardinal(self): + self.assertEqual(num2words(90, lang='pl'), "dziewięćdziesiąt") self.assertEqual(num2words(100, lang='pl'), "sto") self.assertEqual(num2words(101, lang='pl'), "sto jeden") self.assertEqual(num2words(110, lang='pl'), "sto dziesięć") self.assertEqual(num2words(115, lang='pl'), "sto piętnaście") self.assertEqual(num2words(123, lang='pl'), "sto dwadzieścia trzy") + self.assertEqual(num2words(400, lang='pl'), "czterysta") self.assertEqual(num2words(1000, lang='pl'), "tysiąc") self.assertEqual(num2words(1001, lang='pl'), "tysiąc jeden") self.assertEqual(num2words(2012, lang='pl'), "dwa tysiące dwanaście") @@ -94,6 +96,9 @@ def test_to_ordinal(self): self.assertEqual(num2words(100, lang='pl', to='ordinal'), "setny") self.assertEqual( num2words(101, lang='pl', to='ordinal'), "sto pierwszy") + self.assertEqual(num2words(120, lang='pl', to='ordinal'), + "sto dwudziesty") + self.assertEqual(num2words(20, lang='pl', to='ordinal'), "dwudziesty") self.assertEqual(num2words(121, lang='pl', to='ordinal'), "sto dwudziesty pierwszy") self.assertEqual( @@ -118,6 +123,10 @@ def test_to_ordinal(self): self.assertEqual(num2words(1000000, lang='pl', to='ordinal'), "milionowy") + def test_to_ordinal_error(self): + with self.assertRaises(NotImplementedError): + num2words(1.5, lang='pl', to='ordinal') + def test_currency(self): self.assertEqual( num2words(1.0, lang='pl', to='currency', currency='EUR'), From 3dda6ee22e5278fa9621f9fb37dc8de2e5dc230d Mon Sep 17 00:00:00 2001 From: Sergio Zanchetta Date: Sun, 16 Jan 2022 00:52:24 +0100 Subject: [PATCH 120/200] Add to_currency and CURRENCY_FORMS for italian --- num2words/lang_IT.py | 119 +++++++++++++++++++++++++++---------------- 1 file changed, 76 insertions(+), 43 deletions(-) diff --git a/num2words/lang_IT.py b/num2words/lang_IT.py index 6966d730..d532f7f4 100644 --- a/num2words/lang_IT.py +++ b/num2words/lang_IT.py @@ -16,6 +16,8 @@ from __future__ import unicode_literals +from .lang_EU import Num2Word_EU + # Globals # ------- @@ -43,57 +45,27 @@ ] -# 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 +GENERIC_DOLLARS = ('dollaro', 'dollari') +GENERIC_CENTS = ('centesimo', 'centesimi') +CURRENCIES_UNA = ('GBP') # Main class # ========== -class Num2Word_IT: +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 @@ -206,3 +178,64 @@ def to_ordinal(self, number): 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 From 593435f21a675e317ee42fb3b2717bdd95eb43c4 Mon Sep 17 00:00:00 2001 From: Sergio Zanchetta Date: Sun, 16 Jan 2022 12:07:43 +0100 Subject: [PATCH 121/200] Add tests for italian language currencies --- tests/test_it.py | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/tests/test_it.py b/tests/test_it.py index 348f4ed8..9023355f 100644 --- a/tests/test_it.py +++ b/tests/test_it.py @@ -21,6 +21,36 @@ from num2words import num2words +TEST_CASES_TO_CURRENCY_EUR = ( + (1.00, 'un euro e zero centesimi'), + (2.01, 'due euro e un centesimo'), + (8.10, 'otto euro e dieci centesimi'), + (12.26, 'dodici euro e ventisei centesimi'), + (21.29, 'ventun euro e ventinove centesimi'), + (81.25, 'ottantun euro e venticinque centesimi'), + (100.00, 'cento euro e zero centesimi'), +) + +TEST_CASES_TO_CURRENCY_USD = ( + (1.00, 'un dollaro e zero centesimi'), + (2.01, 'due dollari e un centesimo'), + (8.10, 'otto dollari e dieci centesimi'), + (12.26, 'dodici dollari e ventisei centesimi'), + (21.29, 'ventun dollari e ventinove centesimi'), + (81.25, 'ottantun dollari e venticinque centesimi'), + (100.00, 'cento dollari e zero centesimi'), +) + +TEST_CASES_TO_CURRENCY_GBP = ( + (1.00, 'una sterlina e zero penny'), + (2.01, 'due sterline e un penny'), + (8.10, 'otto sterline e dieci penny'), + (12.26, 'dodici sterline e ventisei penny'), + (21.29, 'ventun sterline e ventinove penny'), + (81.25, 'ottantun sterline e venticinque penny'), + (100.00, 'cento sterline e zero penny'), +) + class Num2WordsITTest(TestCase): maxDiff = None @@ -240,3 +270,24 @@ def test_with_decimals(self): self.assertAlmostEqual( num2words(1.1, lang="it"), "uno virgola uno" ) + + def test_currency_eur(self): + for test in TEST_CASES_TO_CURRENCY_EUR: + self.assertEqual( + num2words(test[0], lang='it', to='currency', currency='EUR'), + test[1] + ) + + def test_currency_usd(self): + for test in TEST_CASES_TO_CURRENCY_USD: + self.assertEqual( + num2words(test[0], lang='it', to='currency', currency='USD'), + test[1] + ) + + def test_currency_gbp(self): + for test in TEST_CASES_TO_CURRENCY_GBP: + self.assertEqual( + num2words(test[0], lang='it', to='currency', currency='GBP'), + test[1] + ) From 44a2b7cc2db2de0e71416982fbb2e5477ec44ebf Mon Sep 17 00:00:00 2001 From: ismail eski Date: Wed, 17 Aug 2022 19:11:37 +0300 Subject: [PATCH 122/200] [TEST] ordinal_num test --- tests/test_tr.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/test_tr.py b/tests/test_tr.py index 84252624..2da70010 100644 --- a/tests/test_tr.py +++ b/tests/test_tr.py @@ -183,6 +183,10 @@ def test_tr(self): "expected": u"yüzbirmilyaryüzbirmilyononbirbinonvirgüliki"}, {"test": 101101011010.2, "to": "cardinal", "expected": u"yüzbirmilyaryüzbirmilyononbirbinonvirgülyirmi"} + {"test": 10, "to": "ordinal_num", "expected": u"10uncu"} + {"test": 1, "to": "ordinal_num","expected": u"1inci"} + {"test": 3, "to": "ordinal_num","expected": u"3üncü"} + {"test": 6, "to": "ordinal_num","expected": u"6ıncı"} ] for casedata in testcases: From 75eec68f3ed8d7f6ec9e316ec994a98d879ad166 Mon Sep 17 00:00:00 2001 From: Antoine Planchot Date: Fri, 14 May 2021 22:31:46 +0200 Subject: [PATCH 123/200] Added support for Esperanto numbers. --- num2words/__init__.py | 1 + num2words/lang_EO.py | 130 +++++++++++++++++++++++++++++ tests/test_eo.py | 190 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 321 insertions(+) create mode 100644 num2words/lang_EO.py create mode 100644 tests/test_eo.py diff --git a/num2words/__init__.py b/num2words/__init__.py index 3c9171a8..acff85c9 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -38,6 +38,7 @@ '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_NI': lang_ES_NI.Num2Word_ES_NI(), diff --git a/num2words/lang_EO.py b/num2words/lang_EO.py new file mode 100644 index 00000000..473e74d1 --- /dev/null +++ b/num2words/lang_EO.py @@ -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." + ) + 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] diff --git a/tests/test_eo.py b/tests/test_eo.py new file mode 100644 index 00000000..64076cee --- /dev/null +++ b/tests/test_eo.py @@ -0,0 +1,190 @@ +# -*- 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 unicode_literals + +from unittest import TestCase + +from num2words import num2words + +TEST_CASES_CARDINAL = ( + (1, "unu"), + (2, "du"), + (3, "tri"), + (5.5, "kvin komo kvin"), + (11, "dek unu"), + (12, "dek du"), + (16, "dek ses"), + (17.42, "dek sep komo kvar du"), + (19, "dek naŭ"), + (20, "dudek"), + (21, "dudek unu"), + (26, "dudek ses"), + (27.312, "dudek sep komo tri unu du"), + (28, "dudek ok"), + (30, "tridek"), + (31, "tridek unu"), + (40, "kvardek"), + (44, "kvardek kvar"), + (50, "kvindek"), + (53.486, "kvindek tri komo kvar ok ses"), + (55, "kvindek kvin"), + (60, "sesdek"), + (67, "sesdek sep"), + (70, "sepdek"), + (79, "sepdek naŭ"), + (89, "okdek naŭ"), + (95, "naŭdek kvin"), + (100, "cent"), + (101, "cent unu"), + (199, "cent naŭdek naŭ"), + (203, "ducent tri"), + (287, "ducent okdek sep"), + (300.42, "tricent komo kvar du"), + (356, "tricent kvindek ses"), + (400, "kvarcent"), + (434, "kvarcent tridek kvar"), + (578, "kvincent sepdek ok"), + (689, "sescent okdek naŭ"), + (729, "sepcent dudek naŭ"), + (894, "okcent naŭdek kvar"), + (999, "naŭcent naŭdek naŭ"), + (1000, "mil"), + (1001, "mil unu"), + (1097, "mil naŭdek sep"), + (1104, "mil cent kvar"), + (1243, "mil ducent kvardek tri"), + (2385, "du mil tricent okdek kvin"), + (3766, "tri mil sepcent sesdek ses"), + (4196, "kvar mil cent naŭdek ses"), + (4196.42, "kvar mil cent naŭdek ses komo kvar du"), + (5846, "kvin mil okcent kvardek ses"), + (6459, "ses mil kvarcent kvindek naŭ"), + (7232, "sep mil ducent tridek du"), + (8569, "ok mil kvincent sesdek naŭ"), + (9539, "naŭ mil kvincent tridek naŭ"), + (1000000, "unu miliono"), + (1000001, "unu miliono unu"), + (4000000, "kvar milionoj"), + (4000004, "kvar milionoj kvar"), + (4300000, "kvar milionoj tricent mil"), + (80000000, "okdek milionoj"), + (300000000, "tricent milionoj"), + (10000000000000, "dek bilionoj"), + (10000000000010, "dek bilionoj dek"), + (100000000000000, "cent bilionoj"), + (1000000000000000000, "unu triliono"), + (1000000000000000000000, "unu triliardo"), + (10000000000000000000000000, "dek kvarilionoj") +) + +TEST_CASES_ORDINAL = ( + (1, "unua"), + (8, "oka"), + (12, "dek dua"), + (14, "dek kvara"), + (28, "dudek oka"), + (100, "centa"), + (1000, "mila"), + (1000000, "unu miliona"), + (1000000000000000, "unu biliarda"), + (1000000000000000000, "unu triliona") +) + +TEST_CASES_ORDINAL_NUM = ( + (1, "1a"), + (8, "8a"), + (11, "11a"), + (12, "12a"), + (14, "14a"), + (21, "21a"), + (28, "28a"), + (100, "100a"), + (101, "101a"), + (1000, "1000a"), + (1000000, "1000000a") +) + +TEST_CASES_TO_CURRENCY_EUR = ( + (1.00, "unu eŭro kaj nul centimo"), + (2.01, "du eŭroj kaj unu centimo"), + (8.10, "ok eŭroj kaj dek centimoj"), + (12.26, "dek du eŭroj kaj dudek ses centimoj"), + (21.29, "dudek unu eŭroj kaj dudek naŭ centimoj"), + (81.25, "okdek unu eŭroj kaj dudek kvin centimoj"), + (100.00, "cent eŭroj kaj nul centimo"), +) + +TEST_CASES_TO_CURRENCY_FRF = ( + (1.00, "unu franko kaj nul centimo"), + (2.01, "du frankoj kaj unu centimo"), + (8.10, "ok frankoj kaj dek centimoj"), + (12.27, "dek du frankoj kaj dudek sep centimoj"), + (21.29, "dudek unu frankoj kaj dudek naŭ centimoj"), + (81.25, "okdek unu frankoj kaj dudek kvin centimoj"), + (100.00, "cent frankoj kaj nul centimo"), +) + +TEST_CASES_TO_CURRENCY_USD = ( + (1.00, "unu dolaro kaj nul cendo"), + (2.01, "du dolaroj kaj unu cendo"), + (8.10, "ok dolaroj kaj dek cendoj"), + (12.26, "dek du dolaroj kaj dudek ses cendoj"), + (21.29, "dudek unu dolaroj kaj dudek naŭ cendoj"), + (81.25, "okdek unu dolaroj kaj dudek kvin cendoj"), + (100.00, "cent dolaroj kaj nul cendo"), +) + + +class Num2WordsEOTest(TestCase): + def test_number(self): + for test in TEST_CASES_CARDINAL: + self.assertEqual(num2words(test[0], lang="eo"), test[1]) + + def test_ordinal(self): + for test in TEST_CASES_ORDINAL: + self.assertEqual( + num2words(test[0], lang="eo", ordinal=True), + test[1] + ) + + def test_ordinal_num(self): + for test in TEST_CASES_ORDINAL_NUM: + self.assertEqual( + num2words(test[0], lang="eo", to="ordinal_num"), + test[1] + ) + + def test_currency_eur(self): + for test in TEST_CASES_TO_CURRENCY_EUR: + self.assertEqual( + num2words(test[0], lang="eo", to="currency", currency="EUR"), + test[1] + ) + + def test_currency_frf(self): + for test in TEST_CASES_TO_CURRENCY_FRF: + self.assertEqual( + num2words(test[0], lang="eo", to="currency", currency="FRF"), + test[1] + ) + + def test_currency_usd(self): + for test in TEST_CASES_TO_CURRENCY_USD: + self.assertEqual( + num2words(test[0], lang="eo", to="currency", currency="USD"), + test[1] + ) From 7109e16e73cdc28b8ad48b8e4cb8ed13e8e62195 Mon Sep 17 00:00:00 2001 From: ismail eski Date: Wed, 17 Aug 2022 19:56:11 +0300 Subject: [PATCH 124/200] [TEST] ordinal_num test --- tests/test_tr.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_tr.py b/tests/test_tr.py index 2da70010..d01ba060 100644 --- a/tests/test_tr.py +++ b/tests/test_tr.py @@ -182,10 +182,10 @@ def test_tr(self): {"test": 101101011010.02, "to": "cardinal", "expected": u"yüzbirmilyaryüzbirmilyononbirbinonvirgüliki"}, {"test": 101101011010.2, "to": "cardinal", - "expected": u"yüzbirmilyaryüzbirmilyononbirbinonvirgülyirmi"} - {"test": 10, "to": "ordinal_num", "expected": u"10uncu"} - {"test": 1, "to": "ordinal_num","expected": u"1inci"} - {"test": 3, "to": "ordinal_num","expected": u"3üncü"} + "expected": u"yüzbirmilyaryüzbirmilyononbirbinonvirgülyirmi"}, + {"test": 10, "to": "ordinal_num", "expected": u"10uncu"}, + {"test": 1, "to": "ordinal_num","expected": u"1inci"}, + {"test": 3, "to": "ordinal_num","expected": u"3üncü"}, {"test": 6, "to": "ordinal_num","expected": u"6ıncı"} ] From b6a80e0e2a381cc830effc964fcc2119e201bdbc Mon Sep 17 00:00:00 2001 From: ismail eski Date: Thu, 18 Aug 2022 18:48:10 +0300 Subject: [PATCH 125/200] [FIX] E231 missing whitespace after ',' --- tests/test_tr.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_tr.py b/tests/test_tr.py index d01ba060..e1aefba5 100644 --- a/tests/test_tr.py +++ b/tests/test_tr.py @@ -184,9 +184,9 @@ def test_tr(self): {"test": 101101011010.2, "to": "cardinal", "expected": u"yüzbirmilyaryüzbirmilyononbirbinonvirgülyirmi"}, {"test": 10, "to": "ordinal_num", "expected": u"10uncu"}, - {"test": 1, "to": "ordinal_num","expected": u"1inci"}, - {"test": 3, "to": "ordinal_num","expected": u"3üncü"}, - {"test": 6, "to": "ordinal_num","expected": u"6ıncı"} + {"test": 1, "to": "ordinal_num", "expected": u"1inci"}, + {"test": 3, "to": "ordinal_num", "expected": u"3üncü"}, + {"test": 6, "to": "ordinal_num", "expected": u"6ıncı"} ] for casedata in testcases: From 2ee06aa086cc609f48d4869725213da874315dc2 Mon Sep 17 00:00:00 2001 From: Willem Van Onsem Date: Thu, 18 Aug 2022 18:59:35 +0200 Subject: [PATCH 126/200] reformatting --- num2words/__init__.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/num2words/__init__.py b/num2words/__init__.py index acff85c9..fb9f7e91 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -18,12 +18,13 @@ from __future__ import unicode_literals from . import (lang_AM, lang_AR, lang_CZ, lang_DE, lang_DK, lang_EN, - lang_EN_IN, lang_ES, lang_ES_CO, 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_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_SL, lang_SR, lang_SV, - lang_TE, lang_TG, lang_TH, lang_TR, lang_UK, lang_VI) + lang_EN_IN, lang_EO, lang_ES, lang_ES_CO, 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_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_SL, + lang_SR, lang_SV, lang_TE, lang_TG, lang_TH, lang_TR, lang_UK, + lang_VI) CONVERTER_CLASSES = { 'am': lang_AM.Num2Word_AM(), From 0865ac247e10ece70fb1d330f69d751624e14cb7 Mon Sep 17 00:00:00 2001 From: Marlon Rodriguez Date: Fri, 19 Aug 2022 10:28:08 -0400 Subject: [PATCH 127/200] new release --- CHANGES.rst | 19 +++++++++++++++++-- bin/num2words | 4 ++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 9f3a7b24..4a1d1e1d 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,6 +1,21 @@ Changelog ========= +Version 0.5.12 -- 2022/08/19 +---------------------------- + +* Support Japanese Reiwa (令和/れいわ) era. (#412) +* Add basic farsi support (#354) +* Added Tajik language support (#406) +* Fix Amharic language support (#465) +* Fix Hebrew pluralize and implement to_currency (#330) +* Add support to translate some currencies in italian language (#434) +* Fix Polish twenties (#345) +* Add uzs for ru and en (#422) +* Added support for Esperanto numbers. (#387) +* [ADD] to ordinal number for Turkish (#468) +* Fix zeroth in Dutch to nulde fixing (#326) + Version 0.5.11 -- 2022/08/03 ---------------------------- @@ -77,9 +92,9 @@ Version 0.5.7 -- 2018/06/27 * Add Finnish localization. (#170) * Add Japanese localization. (#171) * Add belgian-french localization. (#151) -* Add Czech localization. (#154) +* Add Czech localization. (#154) * Add Thai localization. (#139) -* Improve English localization. (#144) +* Improve English localization. (#144) * Improve Spanish localization. (#167) * Improve Italian localization. (#143) * Improve documentation. (#155, #145, #174) diff --git a/bin/num2words b/bin/num2words index 2a20b225..26990c01 100755 --- a/bin/num2words +++ b/bin/num2words @@ -34,7 +34,7 @@ Options: -t --to= Output converter [default: cardinal]. -h --help Show this message. -v --version Show version. - + Examples: $ num2words 10001 ten thousand and one @@ -55,7 +55,7 @@ import sys from docopt import docopt import num2words -__version__ = "0.5.11" +__version__ = "0.5.12" __license__ = "LGPL" From 3ffdbec8e0bad4fe740500404aa8446ad4a9e5a8 Mon Sep 17 00:00:00 2001 From: Yunus Emre Geldegul Date: Fri, 19 Aug 2022 23:37:53 +0300 Subject: [PATCH 128/200] #454: [tr] fix negative number problem --- num2words/lang_TR.py | 48 +++++++++++++++++++++++++------------------- tests/test_tr.py | 6 +++++- 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/num2words/lang_TR.py b/num2words/lang_TR.py index ee1d6d4c..2f20dd66 100644 --- a/num2words/lang_TR.py +++ b/num2words/lang_TR.py @@ -124,11 +124,17 @@ def to_cardinal(self, value): if not int(value) == value: return self.to_cardinal_float(value) + + if str(value).startswith("-"): + pre_word, value = self.negword, float(str(value)[1:]) + else: + pre_word, value = "", float(value) + self.to_splitnum(value) if self.order_of_last_zero_digit >= len(self.integers_to_read[0]): # number like 00 and all 0s and even more, raise error - return wrd + return "%s%s" % (pre_word, wrd) if self.total_triplets_to_read == 1: if self.total_digits_outside_triplets == 2: @@ -137,7 +143,7 @@ def to_cardinal(self, value): wrd += self.CARDINAL_TENS.get( self.integers_to_read[0][0], "" ) - return wrd + return "%s%s" % (pre_word, wrd) if self.order_of_last_zero_digit == 0: # number like xy, read cardinal xy and return wrd += self.CARDINAL_TENS.get( @@ -146,7 +152,7 @@ def to_cardinal(self, value): wrd += self.CARDINAL_ONES.get( self.integers_to_read[0][1], "" ) - return wrd + return "%s%s" % (pre_word, wrd) if self.total_digits_outside_triplets == 1: if self.order_of_last_zero_digit == 0: @@ -156,7 +162,7 @@ def to_cardinal(self, value): ) if self.integers_to_read[0][0] == "0": return self.ZERO - return wrd + return "%s%s" % (pre_word, wrd) if self.total_digits_outside_triplets == 0: if self.order_of_last_zero_digit == 2: @@ -165,7 +171,7 @@ def to_cardinal(self, value): self.integers_to_read[0][0], "" ) wrd += self.CARDINAL_HUNDRED[0] - return wrd + return "%s%s" % (pre_word, wrd) if self.order_of_last_zero_digit == 1: # number like xy0, read cardinal xy0 and return wrd += self.HUNDREDS.get( @@ -175,7 +181,7 @@ def to_cardinal(self, value): wrd += self.CARDINAL_TENS.get( self.integers_to_read[0][1], "" ) - return wrd + return "%s%s" % (pre_word, wrd) if self.order_of_last_zero_digit == 0: # number like xyz, read cardinal xyz and return wrd += self.HUNDREDS.get( @@ -188,7 +194,7 @@ def to_cardinal(self, value): wrd += self.CARDINAL_ONES.get( self.integers_to_read[0][2], "" ) - return wrd + return "%s%s" % (pre_word, wrd) if self.total_triplets_to_read >= 2: if self.total_digits_outside_triplets == 2: @@ -202,7 +208,7 @@ def to_cardinal(self, value): wrd += self.CARDINAL_TRIPLETS[ self.total_triplets_to_read - 1 ] - return wrd + return "%s%s" % (pre_word, wrd) if self.order_of_last_zero_digit == len( self.integers_to_read[0]) - 2: # number like xy and all 0s, read cardinal xy 0..0 @@ -216,7 +222,7 @@ def to_cardinal(self, value): wrd += self.CARDINAL_TRIPLETS[ self.total_triplets_to_read - 1 ] - return wrd + return "%s%s" % (pre_word, wrd) if self.order_of_last_zero_digit < len( self.integers_to_read[0]) - 2: # number like xy and others, read cardinal xy n..n @@ -244,7 +250,7 @@ def to_cardinal(self, value): wrd += self.CARDINAL_TRIPLETS[ self.total_triplets_to_read - 1 ] - return wrd + return "%s%s" % (pre_word, wrd) if self.order_of_last_zero_digit < len( self.integers_to_read[0]) - 1: # number like x and others, read cardinal x n..n @@ -268,7 +274,7 @@ def to_cardinal(self, value): wrd += self.CARDINAL_TRIPLETS[ self.total_triplets_to_read - 1 ] - return wrd + return "%s%s" % (pre_word, wrd) if self.order_of_last_zero_digit == len( self.integers_to_read[0]) - 2: # number like xy0 and all 0s, read cardinal xy0 0..0 @@ -283,7 +289,7 @@ def to_cardinal(self, value): wrd += self.CARDINAL_TRIPLETS[ self.total_triplets_to_read - 1 ] - return wrd + return "%s%s" % (pre_word, wrd) if self.order_of_last_zero_digit == len( self.integers_to_read[0]) - 3: # number like xyz and all 0s, read cardinal xyz 0..0 @@ -299,7 +305,7 @@ def to_cardinal(self, value): wrd += self.CARDINAL_TRIPLETS[ self.total_triplets_to_read - 1 ] - return wrd + return "%s%s" % (pre_word, wrd) if self.order_of_last_zero_digit < len( self.integers_to_read[0]) - 3: # number like xyz and all others, read cardinal xyz n..n @@ -339,11 +345,11 @@ def to_cardinal(self, value): last_read_digit_order) - 1: if i == 1: wrd += self.CARDINAL_HUNDRED[0] - return wrd + return "%s%s" % (pre_word, wrd) elif i > 1: wrd += self.CARDINAL_HUNDRED[0] wrd += self.CARDINAL_TRIPLETS[i - 1] - return wrd + return "%s%s" % (pre_word, wrd) else: wrd += self.CARDINAL_HUNDRED[0] @@ -357,14 +363,14 @@ def to_cardinal(self, value): self.integers_to_read[0][ last_read_digit_order + 1], "" ) - return wrd + return "%s%s" % (pre_word, wrd) elif i > 1: wrd += self.CARDINAL_TENS.get( self.integers_to_read[0][ last_read_digit_order + 1], "" ) wrd += self.CARDINAL_TRIPLETS[i - 1] - return wrd + return "%s%s" % (pre_word, wrd) else: wrd += self.CARDINAL_TENS.get( self.integers_to_read[0][ @@ -381,7 +387,7 @@ def to_cardinal(self, value): self.integers_to_read[0][ last_read_digit_order + 2], "" ) - return wrd + return "%s%s" % (pre_word, wrd) if i == 2: if not self.integers_to_read[0][ last_read_digit_order: @@ -398,14 +404,14 @@ def to_cardinal(self, value): last_read_digit_order + 2], "" ) wrd += self.CARDINAL_TRIPLETS[i - 1] - return wrd + return "%s%s" % (pre_word, wrd) if i > 2: wrd += self.CARDINAL_ONES.get( self.integers_to_read[0][ last_read_digit_order + 2], "" ) wrd += self.CARDINAL_TRIPLETS[i - 1] - return wrd + return "%s%s" % (pre_word, wrd) else: if not self.integers_to_read[0][ last_read_digit_order: @@ -435,7 +441,7 @@ def to_cardinal(self, value): wrd += self.CARDINAL_TRIPLETS[i - 1] - return wrd + return "%s%s" % (pre_word, wrd) def to_cardinal_float(self, value): self.to_splitnum(value) diff --git a/tests/test_tr.py b/tests/test_tr.py index e1aefba5..59c88c79 100644 --- a/tests/test_tr.py +++ b/tests/test_tr.py @@ -186,7 +186,11 @@ def test_tr(self): {"test": 10, "to": "ordinal_num", "expected": u"10uncu"}, {"test": 1, "to": "ordinal_num", "expected": u"1inci"}, {"test": 3, "to": "ordinal_num", "expected": u"3üncü"}, - {"test": 6, "to": "ordinal_num", "expected": u"6ıncı"} + {"test": 6, "to": "ordinal_num", "expected": u"6ıncı"}, + {"test": -5, "to": "cardinal", "expected": u"eksibeş"}, + {"test": -55, "to": "cardinal", "expected": u"eksiellibeş"}, + {"test": -576, "to": "cardinal", "expected": u"eksibeşyüzyetmişaltı"}, + {"test": -3, "to": "currency", "expected": u"eksiüçlira"}, ] for casedata in testcases: From ddf6a88af61e6c8357884583be5e7ee0073f8323 Mon Sep 17 00:00:00 2001 From: Yunus Emre Geldegul Date: Fri, 19 Aug 2022 23:51:30 +0300 Subject: [PATCH 129/200] #454: [tr] fix flake8 E501 problem --- tests/test_tr.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_tr.py b/tests/test_tr.py index 59c88c79..da7bacd8 100644 --- a/tests/test_tr.py +++ b/tests/test_tr.py @@ -189,7 +189,8 @@ def test_tr(self): {"test": 6, "to": "ordinal_num", "expected": u"6ıncı"}, {"test": -5, "to": "cardinal", "expected": u"eksibeş"}, {"test": -55, "to": "cardinal", "expected": u"eksiellibeş"}, - {"test": -576, "to": "cardinal", "expected": u"eksibeşyüzyetmişaltı"}, + {"test": -576, "to": "cardinal", + "expected": u"eksibeşyüzyetmişaltı"}, {"test": -3, "to": "currency", "expected": u"eksiüçlira"}, ] From a7d095c97db49c9583af02655676f6c1d82332f5 Mon Sep 17 00:00:00 2001 From: Yunus Emre Geldegul Date: Fri, 19 Aug 2022 23:56:14 +0300 Subject: [PATCH 130/200] #454: [tr] fix flake8 E128 --- tests/test_tr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_tr.py b/tests/test_tr.py index da7bacd8..4a341af1 100644 --- a/tests/test_tr.py +++ b/tests/test_tr.py @@ -190,7 +190,7 @@ def test_tr(self): {"test": -5, "to": "cardinal", "expected": u"eksibeş"}, {"test": -55, "to": "cardinal", "expected": u"eksiellibeş"}, {"test": -576, "to": "cardinal", - "expected": u"eksibeşyüzyetmişaltı"}, + "expected": u"eksibeşyüzyetmişaltı"}, {"test": -3, "to": "currency", "expected": u"eksiüçlira"}, ] From 9e6cdac35d6ece1f075d7880c006e334bfc4edcd Mon Sep 17 00:00:00 2001 From: George Date: Wed, 5 Oct 2022 13:17:52 +0100 Subject: [PATCH 131/200] removed hyphen between tens and units --- num2words/lang_NO.py | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/num2words/lang_NO.py b/num2words/lang_NO.py index 0fb43e43..56bc8db8 100644 --- a/num2words/lang_NO.py +++ b/num2words/lang_NO.py @@ -50,8 +50,7 @@ def setup(self): "tolv", "elleve", "ti", "ni", "\xe5tte", "syv", "seks", "fem", "fire", "tre", "to", "en", "null"] - self.ords = {"en": "f\xf8rste", - "to": "andre", + self.ords_pl = {"to": "andre", "tre": "tredje", "fire": "fjerde", "fem": "femte", @@ -62,7 +61,15 @@ def setup(self): "ti": "tiende", "elleve": "ellevte", "tolv": "tolvte", + "fjorten": "fjortende", + "femten": "femtende", + "seksten": "sekstende", + "sytten": "syttende", + "atten": "attende", + "nitten": "nittende", "tjue": "tjuende"} + # this needs to be done separately to not block 13-19 to_ordinal (as they all end with "-en") + self.ords_sg = {"en": "f\xf8rste"} def merge(self, lpair, rpair): ltext, lnum = lpair @@ -70,7 +77,7 @@ def merge(self, lpair, rpair): if lnum == 1 and rnum < 100: return (rtext, rnum) elif 100 > lnum > rnum: - return ("%s-%s" % (ltext, rtext), lnum + rnum) + return ("%s%s" % (ltext, rtext), lnum + rnum) elif lnum >= 100 > rnum: return ("%s og %s" % (ltext, rtext), lnum + rnum) elif rnum > lnum: @@ -79,19 +86,16 @@ def merge(self, lpair, rpair): def to_ordinal(self, value): self.verify_ordinal(value) - outwords = self.to_cardinal(value).split(" ") - lastwords = outwords[-1].split("-") - lastword = lastwords[-1].lower() - try: - lastword = self.ords[lastword] - except KeyError: - if lastword[-2:] == "ti": - lastword = lastword + "ende" - else: - lastword += "de" - lastwords[-1] = self.title(lastword) - outwords[-1] = "".join(lastwords) - return " ".join(outwords) + outword = self.to_cardinal(value) + for key in self.ords_pl: + if outword.endswith(key): + outword = outword[:len(outword) - len(key)] + self.ords_pl[key] + break + for key in self.ords_sg: + if outword.endswith(key): + outword = outword[:len(outword) - len(key)] + self.ords_sg[key] + break + return outword def to_ordinal_num(self, value): self.verify_ordinal(value) From 720e3ca53199be3758a1b7b34015b6bbf99ce8d1 Mon Sep 17 00:00:00 2001 From: George Date: Wed, 5 Oct 2022 13:18:16 +0100 Subject: [PATCH 132/200] corrected ordinal_num --- num2words/lang_NO.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/num2words/lang_NO.py b/num2words/lang_NO.py index 56bc8db8..eca8499c 100644 --- a/num2words/lang_NO.py +++ b/num2words/lang_NO.py @@ -99,7 +99,7 @@ def to_ordinal(self, value): def to_ordinal_num(self, value): self.verify_ordinal(value) - return "%s%s" % (value, self.to_ordinal(value)[-2:]) + return str(value) + "." def to_year(self, val, longval=True): if not (val // 100) % 10: From f123eba1c463012687bc4ae3b67eaf0673b196e3 Mon Sep 17 00:00:00 2001 From: George Date: Wed, 5 Oct 2022 13:32:09 +0100 Subject: [PATCH 133/200] fixed NO currency --- num2words/lang_NO.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/num2words/lang_NO.py b/num2words/lang_NO.py index eca8499c..f82d4a59 100644 --- a/num2words/lang_NO.py +++ b/num2words/lang_NO.py @@ -23,6 +23,7 @@ class Num2Word_NO(lang_EU.Num2Word_EU): GIGA_SUFFIX = "illard" MEGA_SUFFIX = "illion" + CURRENCY_FORMS = {'NOK': (('krone', 'kroner'), ('øre', 'øre'))} def set_high_numwords(self, high): cap = 3 + 6 * len(high) @@ -107,6 +108,12 @@ def to_year(self, val, longval=True): return self.to_splitnum(val, hightxt="hundre", jointxt="og", longval=longval) - def to_currency(self, val, longval=True): - return self.to_splitnum(val, hightxt="krone/r", lowtxt="\xf8re/r", - jointxt="og", longval=longval, cents=True) + def to_currency(self, val, currency='NOK', cents=True, separator=' og', + adjective=False): + result = super(Num2Word_NO, self).to_currency( + val, currency=currency, cents=cents, separator=separator, + adjective=adjective) + + # do not print "og null øre" + result = result.replace(' og null øre', '') + return result From 5b388796600b5b62d9a2571ae9f04ca3b1070bc0 Mon Sep 17 00:00:00 2001 From: George Date: Wed, 5 Oct 2022 13:33:04 +0100 Subject: [PATCH 134/200] removed comma from word form of large numbers --- num2words/lang_NO.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/num2words/lang_NO.py b/num2words/lang_NO.py index f82d4a59..f14360fd 100644 --- a/num2words/lang_NO.py +++ b/num2words/lang_NO.py @@ -83,7 +83,7 @@ def merge(self, lpair, rpair): return ("%s og %s" % (ltext, rtext), lnum + rnum) elif rnum > lnum: return ("%s %s" % (ltext, rtext), lnum * rnum) - return ("%s, %s" % (ltext, rtext), lnum + rnum) + return ("%s %s" % (ltext, rtext), lnum + rnum) def to_ordinal(self, value): self.verify_ordinal(value) From 2d5b795e0231abee8f7ccd2e53c387bfc0c19975 Mon Sep 17 00:00:00 2001 From: George Date: Wed, 5 Oct 2022 13:33:13 +0100 Subject: [PATCH 135/200] added Norwegian test cases --- tests/test_no.py | 73 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 tests/test_no.py diff --git a/tests/test_no.py b/tests/test_no.py new file mode 100644 index 00000000..06f40886 --- /dev/null +++ b/tests/test_no.py @@ -0,0 +1,73 @@ +# 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 unittest import TestCase + +from num2words import num2words + + +class Num2WordsNOTest(TestCase): + def test_cardinal(self): + self.assertEqual(num2words(0, to="cardinal", lang="no"), "null") + self.assertEqual(num2words(1, to="cardinal", lang="no"), "en") + self.assertEqual(num2words(3, to="cardinal", lang="no"), "tre") + self.assertEqual(num2words(5, to="cardinal", lang="no"), "fem") + self.assertEqual(num2words(18, to="cardinal", lang="no"), "atten") + self.assertEqual(num2words(45, to="cardinal", lang="no"), "førtifem") + self.assertEqual(num2words(92, to="cardinal", lang="no"), "nittito") + self.assertEqual(num2words(1345, to="cardinal", lang="no"), + "en tusen tre hundre og førtifem") + self.assertEqual(num2words(4435, to="cardinal", lang="no"), + "fire tusen fire hundre og trettifem") + self.assertEqual(num2words(1004435, to="cardinal", lang="no"), + "en million fire tusen fire hundre og trettifem") + self.assertEqual(num2words(4335000, to="cardinal", lang="no"), + "fire million tre hundre og trettifem tusen") + self.assertEqual(num2words(14004535, to="cardinal", lang="no"), + "fjorten million fire tusen fem hundre og trettifem") + self.assertEqual(num2words(1.5, to="cardinal", lang="no"), "en komma fem") + + def test_ordinal(self): + self.assertEqual(num2words(1, to="ordinal", lang="no"), "første") + self.assertEqual(num2words(5, to="ordinal", lang="no"), "femte") + self.assertEqual(num2words(10, to="ordinal", lang="no"), "tiende") + self.assertEqual(num2words(14, to="ordinal", lang="no"), "fjortende") + self.assertEqual(num2words(30, to="ordinal", lang="no"),"trettiende") + self.assertEqual(num2words(32, to="ordinal", lang="no"),"trettiandre") + self.assertEqual(num2words(1435, to="ordinal", lang="no"), + "en tusen fire hundre og trettifemte") + + def test_ordinal_num(self): + self.assertEqual(num2words(1, to="ordinal_num", lang="no"), "1.") + self.assertEqual(num2words(5, to="ordinal_num", lang="no"), "5.") + self.assertEqual(num2words(10, to="ordinal_num", lang="no"), "10.") + self.assertEqual(num2words(14, to="ordinal_num", lang="no"), "14.") + self.assertEqual(num2words(32, to="ordinal_num", lang="no"), "32.") + + def test_year(self): + self.assertEqual(num2words(1835, to="year", lang="no"), "atten hundre og trettifem") + self.assertEqual(num2words(2015, to="year", lang="no"), "to tusen og femten") + + def test_currency(self): + self.assertEqual(num2words(1.00, to="currency", lang="no"), "en krone") + self.assertEqual(num2words(2.00, to="currency", lang="no"), "to kroner") + self.assertEqual(num2words(2.50, to="currency", lang="no"), "to kroner og femti øre") + self.assertEqual(num2words(135.00, to="currency", lang="no"), "en hundre og trettifem kroner") + self.assertEqual(num2words(135.59, to="currency", lang="no"), "en hundre og trettifem kroner og femtini øre") + From 4596667c08969912cbf3dc758edb5e390ccd1938 Mon Sep 17 00:00:00 2001 From: George Date: Wed, 5 Oct 2022 17:21:38 +0100 Subject: [PATCH 136/200] formatting --- num2words/lang_NO.py | 40 ++++++++++++++++++++-------------------- tests/test_no.py | 32 +++++++++++++++++++------------- 2 files changed, 39 insertions(+), 33 deletions(-) diff --git a/num2words/lang_NO.py b/num2words/lang_NO.py index f14360fd..8c0c56f8 100644 --- a/num2words/lang_NO.py +++ b/num2words/lang_NO.py @@ -52,24 +52,24 @@ def setup(self): "syv", "seks", "fem", "fire", "tre", "to", "en", "null"] self.ords_pl = {"to": "andre", - "tre": "tredje", - "fire": "fjerde", - "fem": "femte", - "seks": "sjette", - "syv": "syvende", - "\xe5tte": "\xe5ttende", - "ni": "niende", - "ti": "tiende", - "elleve": "ellevte", - "tolv": "tolvte", - "fjorten": "fjortende", - "femten": "femtende", - "seksten": "sekstende", - "sytten": "syttende", - "atten": "attende", - "nitten": "nittende", - "tjue": "tjuende"} - # this needs to be done separately to not block 13-19 to_ordinal (as they all end with "-en") + "tre": "tredje", + "fire": "fjerde", + "fem": "femte", + "seks": "sjette", + "syv": "syvende", + "\xe5tte": "\xe5ttende", + "ni": "niende", + "ti": "tiende", + "elleve": "ellevte", + "tolv": "tolvte", + "fjorten": "fjortende", + "femten": "femtende", + "seksten": "sekstende", + "sytten": "syttende", + "atten": "attende", + "nitten": "nittende", + "tjue": "tjuende"} + # this needs to be done separately to not block 13-19 to_ordinal self.ords_sg = {"en": "f\xf8rste"} def merge(self, lpair, rpair): @@ -113,7 +113,7 @@ def to_currency(self, val, currency='NOK', cents=True, separator=' og', result = super(Num2Word_NO, self).to_currency( val, currency=currency, cents=cents, separator=separator, adjective=adjective) - - # do not print "og null øre" + + # do not print "og null øre" result = result.replace(' og null øre', '') return result diff --git a/tests/test_no.py b/tests/test_no.py index 06f40886..16fad888 100644 --- a/tests/test_no.py +++ b/tests/test_no.py @@ -41,18 +41,19 @@ def test_cardinal(self): "fire million tre hundre og trettifem tusen") self.assertEqual(num2words(14004535, to="cardinal", lang="no"), "fjorten million fire tusen fem hundre og trettifem") - self.assertEqual(num2words(1.5, to="cardinal", lang="no"), "en komma fem") - + self.assertEqual(num2words(1.5, to="cardinal", lang="no"), + "en komma fem") + def test_ordinal(self): self.assertEqual(num2words(1, to="ordinal", lang="no"), "første") self.assertEqual(num2words(5, to="ordinal", lang="no"), "femte") self.assertEqual(num2words(10, to="ordinal", lang="no"), "tiende") self.assertEqual(num2words(14, to="ordinal", lang="no"), "fjortende") - self.assertEqual(num2words(30, to="ordinal", lang="no"),"trettiende") - self.assertEqual(num2words(32, to="ordinal", lang="no"),"trettiandre") + self.assertEqual(num2words(30, to="ordinal", lang="no"), "trettiende") + self.assertEqual(num2words(32, to="ordinal", lang="no"), "trettiandre") self.assertEqual(num2words(1435, to="ordinal", lang="no"), "en tusen fire hundre og trettifemte") - + def test_ordinal_num(self): self.assertEqual(num2words(1, to="ordinal_num", lang="no"), "1.") self.assertEqual(num2words(5, to="ordinal_num", lang="no"), "5.") @@ -61,13 +62,18 @@ def test_ordinal_num(self): self.assertEqual(num2words(32, to="ordinal_num", lang="no"), "32.") def test_year(self): - self.assertEqual(num2words(1835, to="year", lang="no"), "atten hundre og trettifem") - self.assertEqual(num2words(2015, to="year", lang="no"), "to tusen og femten") - + self.assertEqual(num2words(1835, to="year", lang="no"), + "atten hundre og trettifem") + self.assertEqual(num2words(2015, to="year", lang="no"), + "to tusen og femten") + def test_currency(self): self.assertEqual(num2words(1.00, to="currency", lang="no"), "en krone") - self.assertEqual(num2words(2.00, to="currency", lang="no"), "to kroner") - self.assertEqual(num2words(2.50, to="currency", lang="no"), "to kroner og femti øre") - self.assertEqual(num2words(135.00, to="currency", lang="no"), "en hundre og trettifem kroner") - self.assertEqual(num2words(135.59, to="currency", lang="no"), "en hundre og trettifem kroner og femtini øre") - + self.assertEqual(num2words(2.00, to="currency", lang="no"), + "to kroner") + self.assertEqual(num2words(2.50, to="currency", lang="no"), + "to kroner og femti øre") + self.assertEqual(num2words(135.00, to="currency", lang="no"), + "en hundre og trettifem kroner") + self.assertEqual(num2words(135.59, to="currency", lang="no"), + "en hundre og trettifem kroner og femtini øre") From b6ebdac6e4b55deea11a4e3fe735adca1f5b64d7 Mon Sep 17 00:00:00 2001 From: George Date: Wed, 12 Oct 2022 18:05:19 +0100 Subject: [PATCH 137/200] further ordinal coverage --- num2words/lang_NO.py | 5 ++++- tests/test_no.py | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/num2words/lang_NO.py b/num2words/lang_NO.py index 8c0c56f8..b4d33380 100644 --- a/num2words/lang_NO.py +++ b/num2words/lang_NO.py @@ -68,7 +68,10 @@ def setup(self): "sytten": "syttende", "atten": "attende", "nitten": "nittende", - "tjue": "tjuende"} + "tjue": "tjuende", + "hundre": "hundrede", + "tusen": "tusende", + "million": "millionte"} # this needs to be done separately to not block 13-19 to_ordinal self.ords_sg = {"en": "f\xf8rste"} diff --git a/tests/test_no.py b/tests/test_no.py index 16fad888..92ed8603 100644 --- a/tests/test_no.py +++ b/tests/test_no.py @@ -51,8 +51,12 @@ def test_ordinal(self): self.assertEqual(num2words(14, to="ordinal", lang="no"), "fjortende") self.assertEqual(num2words(30, to="ordinal", lang="no"), "trettiende") self.assertEqual(num2words(32, to="ordinal", lang="no"), "trettiandre") + self.assertEqual(num2words(100, to="ordinal", lang="no"), "en hundrede") + self.assertEqual(num2words(1000, to="ordinal", lang="no"), "en tusende") self.assertEqual(num2words(1435, to="ordinal", lang="no"), "en tusen fire hundre og trettifemte") + self.assertEqual(num2words(1000000, to="ordinal", lang="no"), + "en millionte") def test_ordinal_num(self): self.assertEqual(num2words(1, to="ordinal_num", lang="no"), "1.") From f58d9540a7622b0fb0e7939761fe4d040aa645fb Mon Sep 17 00:00:00 2001 From: George Date: Thu, 13 Oct 2022 10:01:57 +0100 Subject: [PATCH 138/200] new test linting --- tests/test_no.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/test_no.py b/tests/test_no.py index 92ed8603..1b29061b 100644 --- a/tests/test_no.py +++ b/tests/test_no.py @@ -51,8 +51,10 @@ def test_ordinal(self): self.assertEqual(num2words(14, to="ordinal", lang="no"), "fjortende") self.assertEqual(num2words(30, to="ordinal", lang="no"), "trettiende") self.assertEqual(num2words(32, to="ordinal", lang="no"), "trettiandre") - self.assertEqual(num2words(100, to="ordinal", lang="no"), "en hundrede") - self.assertEqual(num2words(1000, to="ordinal", lang="no"), "en tusende") + self.assertEqual(num2words(100, to="ordinal", lang="no"), + "en hundrede") + self.assertEqual(num2words(1000, to="ordinal", lang="no"), + "en tusende") self.assertEqual(num2words(1435, to="ordinal", lang="no"), "en tusen fire hundre og trettifemte") self.assertEqual(num2words(1000000, to="ordinal", lang="no"), From 6a26a0b9686cdfc8cba683238277919cb79bf8a0 Mon Sep 17 00:00:00 2001 From: Sergei Ruzki Date: Tue, 8 Nov 2022 14:11:15 +0100 Subject: [PATCH 139/200] [FIX]flake8 for 3.10 line length fix --- num2words/lang_PL.py | 11 ++++++++++- num2words/lang_RU.py | 3 ++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/num2words/lang_PL.py b/num2words/lang_PL.py index a692f23f..92ff9678 100644 --- a/num2words/lang_PL.py +++ b/num2words/lang_PL.py @@ -156,7 +156,16 @@ class Num2Word_PL(Num2Word_Base): ('euro', 'euro', 'euro'), ('cent', 'centy', 'centów') ), 'USD': ( - ('dolar amerykański', 'dolary amerykańskie', 'dolarów amerykańskich'), ('cent', 'centy', 'centów') + ( + 'dolar amerykański', + 'dolary amerykańskie', + 'dolarów amerykańskich' + ), + ( + 'cent', + 'centy', + 'centów' + ) ), } diff --git a/num2words/lang_RU.py b/num2words/lang_RU.py index 77fe441f..b521cfed 100644 --- a/num2words/lang_RU.py +++ b/num2words/lang_RU.py @@ -114,7 +114,8 @@ class Num2Word_RU(Num2Word_Base): ('тенге', 'тенге', 'тенге'), ('тиын', 'тиына', 'тиынов') ), 'BYN': ( - ('белорусский рубль', 'белорусских рубля', 'белорусских рублей'), ('копейка', 'копейки', 'копеек') + ('белорусский рубль', 'белорусских рубля', 'белорусских рублей'), + ('копейка', 'копейки', 'копеек') ), 'UZS': ( ('сум', 'сума', 'сумов'), ('тийин', 'тийина', 'тийинов') From 4d300317e990b4ca9859a27646e8cc1b9732686e Mon Sep 17 00:00:00 2001 From: eyaler Date: Fri, 25 Nov 2022 14:57:59 +0100 Subject: [PATCH 140/200] changed ktiv haser to ktiv male (long form when not using diacritics) --- num2words/lang_HE.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/num2words/lang_HE.py b/num2words/lang_HE.py index f9871925..9e08ebad 100644 --- a/num2words/lang_HE.py +++ b/num2words/lang_HE.py @@ -25,8 +25,8 @@ ONES = { 1: (u'אחת',), - 2: (u'שתים',), - 3: (u'שלש',), + 2: (u'שתיים',), + 3: (u'שלוש',), 4: (u'ארבע',), 5: (u'חמש',), 6: (u'שש',), @@ -39,7 +39,7 @@ 0: (u'עשר',), 1: (u'אחת עשרה',), 2: (u'שתים עשרה',), - 3: (u'שלש עשרה',), + 3: (u'שלוש עשרה',), 4: (u'ארבע עשרה',), 5: (u'חמש עשרה',), 6: (u'שש עשרה',), @@ -50,10 +50,10 @@ TWENTIES = { 2: (u'עשרים',), - 3: (u'שלשים',), + 3: (u'שלושים',), 4: (u'ארבעים',), 5: (u'חמישים',), - 6: (u'ששים',), + 6: (u'שישים',), 7: (u'שבעים',), 8: (u'שמונים',), 9: (u'תשעים',), @@ -68,7 +68,7 @@ THOUSANDS = { 1: (u'אלף',), 2: (u'אלפיים',), - 3: (u'שלשת אלפים',), + 3: (u'שלושת אלפים',), 4: (u'ארבעת אלפים',), 5: (u'חמשת אלפים',), 6: (u'ששת אלפים',), From 36a025b498046720daf81caf171322af03b2cc4c Mon Sep 17 00:00:00 2001 From: eyaler Date: Fri, 2 Dec 2022 13:43:16 +0000 Subject: [PATCH 141/200] change hebrew spelling from biblical and short-form (ktiv haser) to modern long-form (ktiv male); add hebrew gender; and hebrew ordinals; add hebrew decimal fraction and negative; fix hebrew word order for singular; fix hebrew currency names; fix global double space after minus; fix tests --- bin/num2words | 6 +- num2words/base.py | 6 +- num2words/lang_HE.py | 173 +++++++++++++++++++++++++++++++------------ tests/test_cli.py | 8 +- tests/test_en.py | 6 ++ tests/test_he.py | 77 ++++++++++++------- 6 files changed, 193 insertions(+), 83 deletions(-) diff --git a/bin/num2words b/bin/num2words index 26990c01..06ff0443 100755 --- a/bin/num2words +++ b/bin/num2words @@ -76,13 +76,13 @@ def main(): sys.stdout.write(os.linesep) sys.exit(0) if args["--list-converters"]: - for lang in get_converters(): - sys.stdout.write(lang) + for cvt in get_converters(): + sys.stdout.write(cvt) sys.stdout.write(os.linesep) sys.exit(0) try: words = num2words.num2words(args[''], lang=args['--lang'], to=args['--to']) - sys.stdout.write(words+os.linesep) + sys.stdout.write(words + os.linesep) sys.exit(0) except Exception as err: sys.stderr.write(str(args[''])) diff --git a/num2words/base.py b/num2words/base.py index 0929cb93..243045ff 100644 --- a/num2words/base.py +++ b/num2words/base.py @@ -94,7 +94,7 @@ 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, num_str[1:] + return '%s ' % self.negword.strip(), num_str[1:] return '', num_str def str_to_number(self, value): @@ -109,7 +109,7 @@ def to_cardinal(self, value): out = "" if value < 0: value = abs(value) - out = self.negword + out = "%s " % self.negword.strip() if value >= self.MAXVAL: raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL)) @@ -292,7 +292,7 @@ def to_currency(self, val, currency='EUR', cents=True, separator=',', if adjective and currency in self.CURRENCY_ADJECTIVES: cr1 = prefix_currency(self.CURRENCY_ADJECTIVES[currency], cr1) - minus_str = "%s " % self.negword if is_negative else "" + 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) diff --git a/num2words/lang_HE.py b/num2words/lang_HE.py index 9e08ebad..fb49c7f1 100644 --- a/num2words/lang_HE.py +++ b/num2words/lang_HE.py @@ -19,33 +19,36 @@ from __future__ import print_function, unicode_literals from .base import Num2Word_Base +from .compat import to_s +from .currency import parse_currency_parts, prefix_currency from .utils import get_digits, splitbyx + ZERO = (u'אפס',) ONES = { - 1: (u'אחת',), - 2: (u'שתיים',), - 3: (u'שלוש',), - 4: (u'ארבע',), - 5: (u'חמש',), - 6: (u'שש',), - 7: (u'שבע',), - 8: (u'שמונה',), - 9: (u'תשע',), + 1: (u'אחת', u'אחד', u'ראשונה', u'ראשון'), + 2: (u'שתיים', u'שניים', u'שנייה', u'שני'), + 3: (u'שלוש', u'שלושה', u'שלישית', u'שלישי'), + 4: (u'ארבע', u'ארבעה', u'רביעית', u'רביעי'), + 5: (u'חמש', u'חמישה', u'חמישית', u'חמישי'), + 6: (u'שש', u'שישה', u'שישית', u'שישי'), + 7: (u'שבע', u'שבעה', u'שביעית', u'שביעי'), + 8: (u'שמונה', u'שמונה', u'שמינית', u'שמיני'), + 9: (u'תשע', u'תשעה', u'תשיעית', u'תשיעי'), } TENS = { - 0: (u'עשר',), - 1: (u'אחת עשרה',), - 2: (u'שתים עשרה',), - 3: (u'שלוש עשרה',), - 4: (u'ארבע עשרה',), - 5: (u'חמש עשרה',), - 6: (u'שש עשרה',), - 7: (u'שבע עשרה',), - 8: (u'שמונה עשרה',), - 9: (u'תשע עשרה',), + 0: (u'עשר', u'עשרה', u'עשירית', u'עשירי'), + 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'תשעה עשר'), } TWENTIES = { @@ -79,14 +82,11 @@ AND = u'ו' +MAXVAL = 10000 -def pluralize(n, forms): - form = 1 if n == 0 else 0 if n == 1 else 1 - return forms[form] - - -def int2word(n): - if n > 9999: # doesn't yet work for numbers this big +def int2word(n, gender='f', ordinal=False): + assert n == int(n) + if n >= MAXVAL: # doesn't yet work for numbers this big raise NotImplementedError() if n == 0: @@ -118,47 +118,126 @@ def int2word(n): words.append(TWENTIES[n2][0]) if n2 == 1: - words.append(TENS[n1][0]) + words.append(TENS[n1][(gender == 'm') + ordinal*(not n1)]) elif n1 > 0 and not (i > 0 and x == 1): - words.append(ONES[n1][0]) + words.append(ONES[n1][(gender == 'm') + ordinal*(x < 11)]) if i > 0: words.append(THOUSANDS[i][0]) - # source: https://hebrew-academy.org.il/2017/01/30/ו-החיבור-במספרים/ + # source: 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 if len(words) > 1: words[-1] = AND + words[-1] return ' '.join(words) -def n2w(n): - return int2word(int(n)) - - class Num2Word_HE(Num2Word_Base): CURRENCY_FORMS = { - 'NIS': (('שקל', 'שקלים'), ('אגורה', 'אגורות')), - 'EUR': (('אירו', 'אירו'), ('סנט', 'סנט')), - 'USD': (('דולר', 'דולרים'), ('סנט', 'סנט')), + 'ILS': ((u'שקל', u'שקלים'), (u'אגורה', u'אגורות')), + 'EUR': ((u'אירו', u'אירו'), (u'סנט', u'סנטים')), + 'USD': ((u'דולר', u'דולרים'), (u'סנט', u'סנטים')), } - def to_cardinal(self, number): - return n2w(number) + CURRENCY_GENDERS = { + 'ILS': ('m', 'f'), + 'EUR': ('m', 'm'), + 'USD': ('m', 'm'), + } - def to_ordinal(self, number): - raise NotImplementedError() + 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'): + try: + assert int(value) == value + except (ValueError, TypeError, AssertionError): + return self.to_cardinal_float(value, gender) # 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/ + + 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, ordinal=False) + + def to_ordinal(self, value, gender='m'): + self.verify_ordinal(value) + out = int2word(int(value), gender, ordinal=True) + if value == 0 or value > 10: + out = 'ה' + out + return out def pluralize(self, n, forms): - return pluralize(n, forms) + assert n == int(n) + form = 0 if n == 1 else 1 + return forms[form] + - def to_currency(self, val, currency='NIS', cents=True, separator=' ו', + def to_currency(self, val, currency='ILS', cents=True, separator=' ' + AND, adjective=False): - result = super(Num2Word_HE, self).to_currency( - val, currency=currency, cents=cents, separator=separator, - adjective=adjective) - # In Hebrew the separator is along with the following word - return result.replace(" ו ", " ו") + 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__)) + + 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) + cents_str = self.to_cardinal(right, gender=gender2) \ + if cents else self._cents_terse(right, currency) + + strings = [ + minus_str, + money_str, + self.pluralize(left, cr1), + separator, + cents_str, + self.pluralize(right, cr2) + ] + if left == 1: + strings[1], strings[2] = strings[2], strings[1] + if right == 1: + strings[4], strings[5] = strings[5], strings[4] + return u'%s%s %s%s%s %s' % tuple(strings) # In Hebrew the separator is along with the following word if __name__ == '__main__': diff --git a/tests/test_cli.py b/tests/test_cli.py index a85b1250..79610cb7 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -59,12 +59,12 @@ def test_cli_list_langs(self): output = self.cli.run_cmd('--list-languages') self.assertEqual( sorted(list(num2words.CONVERTER_CLASSES.keys())), - output.out.strip().split(os.linesep) + [out for out in output.out.strip().splitlines() if out] ) output = self.cli.run_cmd('-L') self.assertEqual( sorted(list(num2words.CONVERTER_CLASSES.keys())), - output.out.strip().split(os.linesep) + [out for out in output.out.strip().splitlines() if out] ) def test_cli_list_converters(self): @@ -73,12 +73,12 @@ def test_cli_list_converters(self): output = self.cli.run_cmd('--list-converters') self.assertEqual( sorted(list(num2words.CONVERTES_TYPES)), - output.out.strip().split(os.linesep) + [out for out in output.out.strip().splitlines() if out] ) output = self.cli.run_cmd('-C') self.assertEqual( sorted(list(num2words.CONVERTES_TYPES)), - output.out.strip().split(os.linesep) + [out for out in output.out.strip().splitlines() if out] ) def test_cli_default_lang(self): diff --git a/tests/test_en.py b/tests/test_en.py index e763841c..de934717 100644 --- a/tests/test_en.py +++ b/tests/test_en.py @@ -95,6 +95,12 @@ def test_to_currency(self): "one dollar and one cent" ) + self.assertEqual( + num2words('1.01', lang='en', to='currency', separator=' and', + cents=True, currency='USD'), + "one dollar and one cent" + ) + self.assertEqual( num2words('4778.00', lang='en', to='currency', separator=' and', cents=True, currency='USD', adjective=True), diff --git a/tests/test_he.py b/tests/test_he.py index e50a6a22..82a2aeeb 100644 --- a/tests/test_he.py +++ b/tests/test_he.py @@ -31,25 +31,25 @@ def test_0(self): def test_1_to_10(self): self.assertEqual(num2words(1, lang="he"), u'אחת') - self.assertEqual(num2words(2, lang="he"), u'שתים') + self.assertEqual(num2words(2, lang="he"), u'שתיים') self.assertEqual(num2words(7, lang="he"), u'שבע') self.assertEqual(num2words(10, lang="he"), u'עשר') def test_11_to_19(self): self.assertEqual(num2words(11, lang="he"), u'אחת עשרה') - self.assertEqual(num2words(13, lang="he"), u'שלש עשרה') + self.assertEqual(num2words(13, lang="he"), u'שלוש עשרה') self.assertEqual(num2words(15, lang="he"), u'חמש עשרה') self.assertEqual(num2words(16, lang="he"), u'שש עשרה') self.assertEqual(num2words(19, lang="he"), u'תשע עשרה') def test_20_to_99(self): self.assertEqual(num2words(20, lang="he"), u'עשרים') - self.assertEqual(num2words(23, lang="he"), u'עשרים ושלש') + self.assertEqual(num2words(23, lang="he"), u'עשרים ושלוש') self.assertEqual(num2words(28, lang="he"), u'עשרים ושמונה') - self.assertEqual(num2words(31, lang="he"), u'שלשים ואחת') + self.assertEqual(num2words(31, lang="he"), u'שלושים ואחת') self.assertEqual(num2words(40, lang="he"), u'ארבעים') - self.assertEqual(num2words(66, lang="he"), u'ששים ושש') - self.assertEqual(num2words(92, lang="he"), u'תשעים ושתים') + self.assertEqual(num2words(66, lang="he"), u'שישים ושש') + self.assertEqual(num2words(92, lang="he"), u'תשעים ושתיים') def test_100_to_999(self): self.assertEqual(num2words(100, lang="he"), u'מאה') @@ -65,7 +65,7 @@ def test_1000_to_9999(self): self.assertEqual(num2words(1001, lang="he"), u'אלף ואחת') self.assertEqual(num2words(1500, lang="he"), u'אלף וחמש מאות') self.assertEqual( - num2words(7378, lang="he"), u'שבעת אלפים שלש מאות שבעים ושמונה' + num2words(7378, lang="he"), u'שבעת אלפים שלוש מאות שבעים ושמונה' ) self.assertEqual(num2words(2000, lang="he"), u'אלפיים') self.assertEqual(num2words(2100, lang="he"), u'אלפיים ומאה') @@ -75,42 +75,67 @@ def test_1000_to_9999(self): def test_pluralize(self): n = Num2Word_HE() - cr1, cr2 = n.CURRENCY_FORMS['NIS'] - self.assertEqual(n.pluralize(1, cr1), 'שקל') - self.assertEqual(n.pluralize(2, cr1), 'שקלים') - self.assertEqual(n.pluralize(1, cr2), 'אגורה') - self.assertEqual(n.pluralize(2, cr2), 'אגורות') + cr1, cr2 = n.CURRENCY_FORMS['ILS'] + self.assertEqual(n.pluralize(1, cr1), u'שקל') + self.assertEqual(n.pluralize(2, cr1), u'שקלים') + self.assertEqual(n.pluralize(1, cr2), u'אגורה') + self.assertEqual(n.pluralize(2, cr2), u'אגורות') cr1, cr2 = n.CURRENCY_FORMS['USD'] - self.assertEqual(n.pluralize(1, cr1), 'דולר') - self.assertEqual(n.pluralize(2, cr1), 'דולרים') - self.assertEqual(n.pluralize(1, cr2), 'סנט') - self.assertEqual(n.pluralize(2, cr2), 'סנט') + self.assertEqual(n.pluralize(1, cr1), u'דולר') + self.assertEqual(n.pluralize(2, cr1), u'דולרים') + self.assertEqual(n.pluralize(1, cr2), u'סנט') + self.assertEqual(n.pluralize(2, cr2), u'סנטים') def test_to_currency(self): n = Num2Word_HE() self.assertEqual( - n.to_currency(20.0, currency='NIS'), 'עשרים שקלים ואפס אגורות' + n.to_currency(20.0, currency='ILS'), u'עשרים שקלים ואפס אגורות' ) self.assertEqual( - n.to_currency(100.0, currency='NIS'), 'מאה שקלים ואפס אגורות' + n.to_currency(100.0, currency='ILS'), u'מאה שקלים ואפס אגורות' ) self.assertEqual( - n.to_currency(100.50, currency='NIS'), 'מאה שקלים וחמישים אגורות' + n.to_currency(100.50, currency='ILS'), u'מאה שקלים וחמישים אגורות' + ) + self.assertEqual( + n.to_currency(101.51, currency='ILS'), u'מאה ואחד שקלים וחמישים ואחת אגורות' + ) + self.assertEqual( + n.to_currency(-101.51, currency='ILS'), u'מינוס מאה ואחד שקלים וחמישים ואחת אגורות' + ) + self.assertEqual( + n.to_currency(1.01, currency='ILS'), u'שקל אחד ואגורה אחת' + ) + self.assertEqual( + n.to_currency(-1.01, currency='ILS'), u'מינוס שקל אחד ואגורה אחת' ) def test_to_cardinal(self): n = Num2Word_HE() self.assertEqual(n.to_cardinal(1500), u'אלף וחמש מאות') - - -class Num2WordsHETestNotImplementedMethofs(TestCase): - n = Num2Word_HE() + self.assertEqual(n.to_cardinal(1501), u'אלף חמש מאות ואחת') def test_to_ordinal(self): - with self.assertRaises(NotImplementedError): - self.n.to_ordinal('1') + n = Num2Word_HE() + self.assertEqual(n.to_ordinal(1500), u'האלף וחמש מאות') + self.assertEqual(n.to_ordinal(1501), u'האלף חמש מאות ואחד') + + def test_cardinal_for_float_number(self): + self.assertEqual(num2words(12.5, lang='he'), u'שתים עשרה נקודה חמש') + self.assertEqual(num2words(12.51, lang='he'), u'שתים עשרה נקודה חמש אחת') + self.assertEqual(num2words(12.53, lang='he'), u'שתים עשרה נקודה חמש שלוש') + self.assertEqual(num2words(12.59, lang='he'), u'שתים עשרה נקודה חמש תשע') + self.assertEqual(num2words(12.5, lang='he', gender='m'), u'שנים עשר נקודה חמש') + self.assertEqual(num2words(12.51, lang='he', gender='m'), u'שנים עשר נקודה חמש אחת') + self.assertEqual(num2words(12.53, lang='he', gender='m'), u'שנים עשר נקודה חמש שלוש') + self.assertEqual(num2words(12.59, lang='he', gender='m'), u'שנים עשר נקודה חמש תשע') + self.assertEqual(num2words(12.594132, lang='he', gender='m'), u'שנים עשר נקודה חמש תשע ארבע אחת שלוש שתיים') + + +class Num2WordsHETestNotImplementedMethods(TestCase): + n = Num2Word_HE() def test_large_number(self): - with self.assertRaises(NotImplementedError): + with self.assertRaises(OverflowError): num2words(2000000, lang="he") From e617d26fac6dc3a259669238787c1cfc9f91e5c4 Mon Sep 17 00:00:00 2001 From: eyaler Date: Fri, 2 Dec 2022 13:56:31 +0000 Subject: [PATCH 142/200] remove duplicate test --- tests/test_en.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/test_en.py b/tests/test_en.py index de934717..e763841c 100644 --- a/tests/test_en.py +++ b/tests/test_en.py @@ -95,12 +95,6 @@ def test_to_currency(self): "one dollar and one cent" ) - self.assertEqual( - num2words('1.01', lang='en', to='currency', separator=' and', - cents=True, currency='USD'), - "one dollar and one cent" - ) - self.assertEqual( num2words('4778.00', lang='en', to='currency', separator=' and', cents=True, currency='USD', adjective=True), From 16f2641fcef666c460c72b9753463fb546ccc566 Mon Sep 17 00:00:00 2001 From: eyaler Date: Fri, 2 Dec 2022 14:31:40 +0000 Subject: [PATCH 143/200] add definite ordinals; fix ordinal bugs; add more ordinal tests --- num2words/lang_HE.py | 31 +++++++++++++++++++------------ tests/test_he.py | 12 ++++++++++++ 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/num2words/lang_HE.py b/num2words/lang_HE.py index fb49c7f1..30841e3f 100644 --- a/num2words/lang_HE.py +++ b/num2words/lang_HE.py @@ -82,14 +82,19 @@ AND = u'ו' +DEF = u'ה' + MAXVAL = 10000 -def int2word(n, gender='f', ordinal=False): + +def int2word(n, gender='f', ordinal=False, definite=False): assert n == int(n) if n >= MAXVAL: # doesn't yet work for numbers this big raise NotImplementedError() if n == 0: + if ordinal: + return DEF + ZERO[0] return ZERO[0] words = [] @@ -118,9 +123,9 @@ def int2word(n, gender='f', ordinal=False): words.append(TWENTIES[n2][0]) if n2 == 1: - words.append(TENS[n1][(gender == 'm') + ordinal*(not n1)]) + words.append(TENS[n1][(gender == 'm') + 2*ordinal*(not n1)]) elif n1 > 0 and not (i > 0 and x == 1): - words.append(ONES[n1][(gender == 'm') + ordinal*(x < 11)]) + words.append(ONES[n1][(gender == 'm') + 2*ordinal*(x < 11)]) if i > 0: words.append(THOUSANDS[i][0]) @@ -129,6 +134,9 @@ def int2word(n, gender='f', ordinal=False): if len(words) > 1: words[-1] = AND + words[-1] + if ordinal and (n > 10 or definite): + words[0] = DEF + words[0] + return ' '.join(words) @@ -173,12 +181,11 @@ def to_cardinal_float(self, value, gender='f'): return " ".join(out) - def to_cardinal(self, value, gender='f'): try: assert int(value) == value except (ValueError, TypeError, AssertionError): - return self.to_cardinal_float(value, gender) # 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/ + return self.to_cardinal_float(value, gender=gender) # 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/ out = "" if value < 0: @@ -188,21 +195,21 @@ def to_cardinal(self, value, gender='f'): if value >= self.MAXVAL: raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL)) - return out + int2word(int(value), gender, ordinal=False) + return out + int2word(int(value), gender=gender, ordinal=False) - def to_ordinal(self, value, gender='m'): + def to_ordinal(self, value, gender='m', definite=False): self.verify_ordinal(value) - out = int2word(int(value), gender, ordinal=True) - if value == 0 or value > 10: - out = 'ה' + out - return out + + if value >= self.MAXVAL: + raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL)) + + return int2word(int(value), gender=gender, ordinal=True, definite=definite) def pluralize(self, n, forms): assert n == int(n) form = 0 if n == 1 else 1 return forms[form] - def to_currency(self, val, currency='ILS', cents=True, separator=' ' + AND, adjective=False): left, right, is_negative = parse_currency_parts(val) diff --git a/tests/test_he.py b/tests/test_he.py index 82a2aeeb..b5afc6ee 100644 --- a/tests/test_he.py +++ b/tests/test_he.py @@ -120,6 +120,15 @@ def test_to_ordinal(self): n = Num2Word_HE() self.assertEqual(n.to_ordinal(1500), u'האלף וחמש מאות') self.assertEqual(n.to_ordinal(1501), u'האלף חמש מאות ואחד') + self.assertEqual(n.to_ordinal(1501, definite=True), u'האלף חמש מאות ואחד') + self.assertEqual(n.to_ordinal(1), u'ראשון') + self.assertEqual(n.to_ordinal(1, definite=True), u'הראשון') + self.assertEqual(n.to_ordinal(1, gender='f'), u'ראשונה') + self.assertEqual(n.to_ordinal(1, gender='f', definite=True), u'הראשונה') + self.assertEqual(n.to_ordinal(0), u'האפס') + self.assertEqual(n.to_ordinal(0, definite=True), u'האפס') + self.assertEqual(n.to_ordinal(0, gender='f'), u'האפס') + self.assertEqual(n.to_ordinal(0, gender='f', definite=True), u'האפס') def test_cardinal_for_float_number(self): self.assertEqual(num2words(12.5, lang='he'), u'שתים עשרה נקודה חמש') @@ -139,3 +148,6 @@ class Num2WordsHETestNotImplementedMethods(TestCase): def test_large_number(self): with self.assertRaises(OverflowError): num2words(2000000, lang="he") + + with self.assertRaises(OverflowError): + num2words(2000000, lang="he", ordinal=True) From f8776dd3690268576c2c9c8fa1962714d659d0c5 Mon Sep 17 00:00:00 2001 From: eyaler Date: Fri, 2 Dec 2022 15:36:39 +0000 Subject: [PATCH 144/200] allow to prefer singular forms --- num2words/lang_HE.py | 12 +++++++----- tests/test_he.py | 24 ++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/num2words/lang_HE.py b/num2words/lang_HE.py index 30841e3f..2af2dda3 100644 --- a/num2words/lang_HE.py +++ b/num2words/lang_HE.py @@ -205,13 +205,15 @@ def to_ordinal(self, value, gender='m', definite=False): return int2word(int(value), gender=gender, ordinal=True, definite=definite) - def pluralize(self, n, forms): + def pluralize(self, n, forms, currency=None, is_negative=False, prefer_singular=False): assert n == int(n) - form = 0 if n == 1 else 1 + form = 1 + if n == 1 or prefer_singular and (n > 10 or n == 0 or is_negative or currency != 'ILS'): + form = 0 return forms[form] def to_currency(self, val, currency='ILS', cents=True, separator=' ' + AND, - adjective=False): + adjective=False, prefer_singular=False, prefer_singular_cents=False): left, right, is_negative = parse_currency_parts(val) try: @@ -235,10 +237,10 @@ def to_currency(self, val, currency='ILS', cents=True, separator=' ' + AND, strings = [ minus_str, money_str, - self.pluralize(left, cr1), + self.pluralize(left, cr1, currency=currency, is_negative=is_negative, prefer_singular=prefer_singular), separator, cents_str, - self.pluralize(right, cr2) + self.pluralize(right, cr2, currency=currency, is_negative=is_negative, prefer_singular=prefer_singular_cents) ] if left == 1: strings[1], strings[2] = strings[2], strings[1] diff --git a/tests/test_he.py b/tests/test_he.py index b5afc6ee..5ac39903 100644 --- a/tests/test_he.py +++ b/tests/test_he.py @@ -104,12 +104,36 @@ def test_to_currency(self): self.assertEqual( n.to_currency(-101.51, currency='ILS'), u'מינוס מאה ואחד שקלים וחמישים ואחת אגורות' ) + self.assertEqual( + n.to_currency(-101.51, currency='ILS', prefer_singular=True), u'מינוס מאה ואחד שקל וחמישים ואחת אגורות' + ) + self.assertEqual( + n.to_currency(-101.51, currency='ILS', prefer_singular_cents=True), u'מינוס מאה ואחד שקלים וחמישים ואחת אגורה' + ) + self.assertEqual( + n.to_currency(-101.51, currency='ILS', prefer_singular=True, prefer_singular_cents=True), u'מינוס מאה ואחד שקל וחמישים ואחת אגורה' + ) + self.assertEqual( + n.to_currency(5.05, currency='ILS', prefer_singular=True, prefer_singular_cents=True), u'חמישה שקלים וחמש אגורות' + ) self.assertEqual( n.to_currency(1.01, currency='ILS'), u'שקל אחד ואגורה אחת' ) self.assertEqual( n.to_currency(-1.01, currency='ILS'), u'מינוס שקל אחד ואגורה אחת' ) + self.assertEqual( + n.to_currency(5.05, currency='USD'), u'חמישה דולרים וחמישה סנטים' + ) + self.assertEqual( + n.to_currency(5.05, currency='USD', prefer_singular=True), u'חמישה דולר וחמישה סנטים' + ) + self.assertEqual( + n.to_currency(5.05, currency='USD', prefer_singular_cents=True), u'חמישה דולרים וחמישה סנט' + ) + self.assertEqual( + n.to_currency(5.05, currency='USD', prefer_singular=True, prefer_singular_cents=True), u'חמישה דולר וחמישה סנט' + ) def test_to_cardinal(self): n = Num2Word_HE() From 8f27e6ad02d90fe61086c4328b846762a97b4cde Mon Sep 17 00:00:00 2001 From: eyaler Date: Fri, 2 Dec 2022 16:39:40 +0000 Subject: [PATCH 145/200] support kwargs for old ordinal interface --- num2words/__init__.py | 2 +- tests/test_he.py | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/num2words/__init__.py b/num2words/__init__.py index fb9f7e91..e30fd01e 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -90,7 +90,7 @@ def num2words(number, ordinal=False, lang='en', to='cardinal', **kwargs): # backwards compatible if ordinal: - return converter.to_ordinal(number) + to = 'ordinal' if to not in CONVERTES_TYPES: raise NotImplementedError() diff --git a/tests/test_he.py b/tests/test_he.py index 5ac39903..aef17063 100644 --- a/tests/test_he.py +++ b/tests/test_he.py @@ -139,6 +139,8 @@ def test_to_cardinal(self): n = Num2Word_HE() self.assertEqual(n.to_cardinal(1500), u'אלף וחמש מאות') self.assertEqual(n.to_cardinal(1501), u'אלף חמש מאות ואחת') + self.assertEqual(num2words(1, lang='he'), u'אחת') + self.assertEqual(num2words(1, lang='he', gender='m'), u'אחד') def test_to_ordinal(self): n = Num2Word_HE() @@ -153,6 +155,10 @@ def test_to_ordinal(self): self.assertEqual(n.to_ordinal(0, definite=True), u'האפס') self.assertEqual(n.to_ordinal(0, gender='f'), u'האפס') self.assertEqual(n.to_ordinal(0, gender='f', definite=True), u'האפס') + self.assertEqual(num2words(1, ordinal=True, lang='he'), u'ראשון') + self.assertEqual(num2words(1, ordinal=True, lang='he', gender='f'), u'ראשונה') + self.assertEqual(num2words(1, ordinal=True, lang='he', definite=True), u'הראשון') + self.assertEqual(num2words(1, ordinal=True, lang='he', gender='f', definite=True), u'הראשונה') def test_cardinal_for_float_number(self): self.assertEqual(num2words(12.5, lang='he'), u'שתים עשרה נקודה חמש') From 04c0765b995f9c249eab8def61285b1c4722263f Mon Sep 17 00:00:00 2001 From: eyaler Date: Fri, 2 Dec 2022 17:47:14 +0000 Subject: [PATCH 146/200] raised maxval to 1,000,000 --- num2words/lang_HE.py | 29 ++++++++++++++++------------- tests/test_he.py | 35 ++++++++++++++++++++++++++++++++--- 2 files changed, 48 insertions(+), 16 deletions(-) diff --git a/num2words/lang_HE.py b/num2words/lang_HE.py index 2af2dda3..addf3c5c 100644 --- a/num2words/lang_HE.py +++ b/num2words/lang_HE.py @@ -78,13 +78,14 @@ 7: (u'שבעת אלפים',), 8: (u'שמונת אלפים',), 9: (u'תשעת אלפים',), + 10: (u'עשרת אלפים',), } AND = u'ו' DEF = u'ה' -MAXVAL = 10000 +MAXVAL = 1000000 def int2word(n, gender='f', ordinal=False, definite=False): @@ -109,10 +110,6 @@ def int2word(n, gender='f', ordinal=False, definite=False): n1, n2, n3 = get_digits(x) - if i > 0: - words.append(THOUSANDS[n1][0]) - continue - if n3 > 0: if n3 <= 2: words.append(HUNDRED[n3][0]) @@ -122,17 +119,23 @@ def int2word(n, gender='f', ordinal=False, definite=False): if n2 > 1: words.append(TWENTIES[n2][0]) - if n2 == 1: - words.append(TENS[n1][(gender == 'm') + 2*ordinal*(not n1)]) - elif n1 > 0 and not (i > 0 and x == 1): - words.append(ONES[n1][(gender == 'm') + 2*ordinal*(x < 11)]) + if i == 0 or x > 10: + if n2 == 1: + words.append( + TENS[n1][(gender == 'm' or i > 0) + 2 * ordinal * (not n1)]) + elif n1 > 0: + words.append( + ONES[n1][(gender == 'm' or i > 0) + 2 * ordinal * (x < 11)]) if i > 0: - words.append(THOUSANDS[i][0]) + if x < 11: + words.append(THOUSANDS[x][0]) + else: + words[-1] = words[-1] + ' ' + THOUSANDS[1][0] - # source: 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 - if len(words) > 1: - words[-1] = AND + words[-1] + # source: 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 + if len(words) > 1: + words[-1] = AND + words[-1] if ordinal and (n > 10 or definite): words[0] = DEF + words[0] diff --git a/tests/test_he.py b/tests/test_he.py index aef17063..27785822 100644 --- a/tests/test_he.py +++ b/tests/test_he.py @@ -64,14 +64,41 @@ def test_1000_to_9999(self): self.assertEqual(num2words(1000, lang="he"), u'אלף') self.assertEqual(num2words(1001, lang="he"), u'אלף ואחת') self.assertEqual(num2words(1500, lang="he"), u'אלף וחמש מאות') - self.assertEqual( - num2words(7378, lang="he"), u'שבעת אלפים שלוש מאות שבעים ושמונה' - ) self.assertEqual(num2words(2000, lang="he"), u'אלפיים') self.assertEqual(num2words(2100, lang="he"), u'אלפיים ומאה') self.assertEqual( num2words(6870, lang="he"), u'ששת אלפים שמונה מאות ושבעים' ) + self.assertEqual( + num2words(7378, lang="he"), u'שבעת אלפים שלוש מאות שבעים ושמונה' + ) + self.assertEqual( + num2words(9999, lang="he"), u'תשעת אלפים תשע מאות תשעים ותשע' + ) + + def test_10000_to_99999(self): + self.assertEqual(num2words(10000, lang="he"), u'עשרת אלפים') + self.assertEqual(num2words(10001, lang="he"), u'עשרת אלפים ואחת') + self.assertEqual(num2words(10999, lang="he"), u'עשרת אלפים תשע מאות תשעים ותשע') + self.assertEqual(num2words(11000, lang="he"), u'אחד עשר אלף') + self.assertEqual(num2words(15000, lang="he"), u'חמישה עשר אלף') + self.assertEqual(num2words(20000, lang="he"), u'עשרים אלף') + self.assertEqual(num2words(21000, lang="he"), u'עשרים ואחד אלף') + self.assertEqual(num2words(68700, lang="he"), u'שישים ושמונה אלף ושבע מאות') + self.assertEqual(num2words(73781, lang="he"), u'שבעים ושלושה אלף שבע מאות שמונים ואחת') + self.assertEqual(num2words(99999, lang="he"), u'תשעים ותשעה אלף תשע מאות תשעים ותשע') + + def test_100000_to_999999(self): + self.assertEqual(num2words(100000, lang="he"), u'מאה אלף') + self.assertEqual(num2words(100001, lang="he"), u'מאה אלף ואחת') + self.assertEqual(num2words(199999, lang="he"), u'מאה תשעים ותשעה אלף תשע מאות תשעים ותשע') + self.assertEqual(num2words(110000, lang="he"), u'מאה ועשרה אלף') + self.assertEqual(num2words(150000, lang="he"), u'מאה וחמישים אלף') + self.assertEqual(num2words(200000, lang="he"), u'מאתיים אלף') + self.assertEqual(num2words(210000, lang="he"), u'מאתיים ועשרה אלף') + self.assertEqual(num2words(687000, lang="he"), u'שש מאות שמונים ושבעה אלף') + self.assertEqual(num2words(737812, lang="he"), u'שבע מאות שלושים ושבעה אלף שמונה מאות ושתים עשרה') + self.assertEqual(num2words(999999, lang="he"), u'תשע מאות תשעים ותשעה אלף תשע מאות תשעים ותשע') def test_pluralize(self): n = Num2Word_HE() @@ -155,6 +182,8 @@ def test_to_ordinal(self): self.assertEqual(n.to_ordinal(0, definite=True), u'האפס') self.assertEqual(n.to_ordinal(0, gender='f'), u'האפס') self.assertEqual(n.to_ordinal(0, gender='f', definite=True), u'האפס') + self.assertEqual(n.to_ordinal(999999), u'התשע מאות תשעים ותשעה אלף תשע מאות תשעים ותשעה') + self.assertEqual(n.to_ordinal(999999, gender='f'), u'התשע מאות תשעים ותשעה אלף תשע מאות תשעים ותשע') self.assertEqual(num2words(1, ordinal=True, lang='he'), u'ראשון') self.assertEqual(num2words(1, ordinal=True, lang='he', gender='f'), u'ראשונה') self.assertEqual(num2words(1, ordinal=True, lang='he', definite=True), u'הראשון') From b487f3e22cd56d1f729b5d9ce34d9a88fd51db91 Mon Sep 17 00:00:00 2001 From: eyaler Date: Sat, 3 Dec 2022 14:56:59 +0000 Subject: [PATCH 147/200] raised maxval to 1e15; added construct forms --- num2words/lang_HE.py | 102 ++++++++++++++++++++++++------------------- tests/test_he.py | 87 +++++++++++++++++++++++++++++++++++- 2 files changed, 142 insertions(+), 47 deletions(-) diff --git a/num2words/lang_HE.py b/num2words/lang_HE.py index addf3c5c..535f9ecc 100644 --- a/num2words/lang_HE.py +++ b/num2words/lang_HE.py @@ -27,28 +27,22 @@ ZERO = (u'אפס',) ONES = { - 1: (u'אחת', u'אחד', u'ראשונה', u'ראשון'), - 2: (u'שתיים', u'שניים', u'שנייה', u'שני'), - 3: (u'שלוש', u'שלושה', u'שלישית', u'שלישי'), - 4: (u'ארבע', u'ארבעה', u'רביעית', u'רביעי'), - 5: (u'חמש', u'חמישה', u'חמישית', u'חמישי'), - 6: (u'שש', u'שישה', u'שישית', u'שישי'), - 7: (u'שבע', u'שבעה', u'שביעית', u'שביעי'), - 8: (u'שמונה', u'שמונה', u'שמינית', u'שמיני'), - 9: (u'תשע', u'תשעה', u'תשיעית', u'תשיעי'), + 1: (u'אחת', u'אחד', u'אחת', u'אחד', u'ראשונה', u'ראשון'), + 2: (u'שתיים', u'שניים', u'שתי', u'שני', u'שנייה', u'שני'), + 3: (u'שלוש', u'שלושה', u'שלוש', u'שלושת', u'שלישית', u'שלישי'), + 4: (u'ארבע', u'ארבעה', u'ארבע', u'ארבעת', u'רביעית', u'רביעי'), + 5: (u'חמש', u'חמישה', u'חמש', u'חמשת', u'חמישית', u'חמישי'), + 6: (u'שש', u'שישה', u'שש', u'ששת', u'שישית', u'שישי'), + 7: (u'שבע', u'שבעה', u'שבע', u'שבעת', u'שביעית', u'שביעי'), + 8: (u'שמונה', u'שמונה', u'שמונה', u'שמונת', u'שמינית', u'שמיני'), + 9: (u'תשע', u'תשעה', u'תשע', u'תשעת', u'תשיעית', u'תשיעי'), } TENS = { - 0: (u'עשר', u'עשרה', u'עשירית', u'עשירי'), + 0: (u'עשר', u'עשרה', u'עשר', u'עשרת', u'עשירית', u'עשירי'), 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'תשעה עשר'), + 3: (u'עשרה', u'עשר'), } TWENTIES = { @@ -63,7 +57,7 @@ } HUNDRED = { - 1: (u'מאה',), + 1: (u'מאה', u'מאת'), 2: (u'מאתיים',), 3: (u'מאות',) } @@ -71,27 +65,26 @@ THOUSANDS = { 1: (u'אלף',), 2: (u'אלפיים',), - 3: (u'שלושת אלפים',), - 4: (u'ארבעת אלפים',), - 5: (u'חמשת אלפים',), - 6: (u'ששת אלפים',), - 7: (u'שבעת אלפים',), - 8: (u'שמונת אלפים',), - 9: (u'תשעת אלפים',), - 10: (u'עשרת אלפים',), + 3: (u'אלפים', 'אלפי'), +} + +LARGE = { + 1: (u'מיליון', u'מיליוני'), + 2: (u'מיליארד', u'מיליארדי'), + 3: (u'טריליון', u'טריליוני') } AND = u'ו' DEF = u'ה' -MAXVAL = 1000000 +MAXVAL = int(1e15) -def int2word(n, gender='f', ordinal=False, definite=False): +def int2word(n, gender='f', construct=False, ordinal=False, definite=False): assert n == int(n) - if n >= MAXVAL: # doesn't yet work for numbers this big - raise NotImplementedError() + if n >= MAXVAL: + raise OverflowError('abs(%s) must be less than %s.' % (n, MAXVAL)) if n == 0: if ordinal: @@ -111,7 +104,9 @@ def int2word(n, gender='f', ordinal=False, definite=False): n1, n2, n3 = get_digits(x) if n3 > 0: - if n3 <= 2: + if construct and i == 0 and x == 100: + words.append(HUNDRED[n3][1]) + elif n3 <= 2: words.append(HUNDRED[n3][0]) else: words.append(ONES[n3][0] + ' ' + HUNDRED[3][0]) @@ -121,17 +116,34 @@ def int2word(n, gender='f', ordinal=False, definite=False): if i == 0 or x > 10: if n2 == 1: - words.append( - TENS[n1][(gender == 'm' or i > 0) + 2 * ordinal * (not n1)]) + if n1 <= 2: + words.append( + TENS[n1][(gender == 'm' or i > 0) + 2*(construct > ordinal and n1 == 0) + 4*ordinal*(n1 == 0)]) + else: + words.append( + ONES[n1][(gender == 'm' or i > 0)] + ' ' + TENS[3][(gender == 'f' and i > 0)]) elif n1 > 0: words.append( - ONES[n1][(gender == 'm' or i > 0) + 2 * ordinal * (x < 11)]) + ONES[n1][(gender == 'm' or i > 0) + 2*(construct > ordinal and i == 0) + 4*ordinal*(x < 11)]) - if i > 0: - if x < 11: - words.append(THOUSANDS[x][0]) - else: + if i == 1: + if x >= 11: words[-1] = words[-1] + ' ' + THOUSANDS[1][0] + elif n1 == 0: + words.append(TENS[n1][3] + ' ' + THOUSANDS[3][construct and n % 1000 == 0]) + elif n1 <= 2: + words.append(THOUSANDS[n1][0]) + else: + words.append(ONES[n1][3] + ' ' + THOUSANDS[3][construct and n % 1000 == 0]) + elif i > 1: + if x >= 11: + words[-1] = words[-1] + ' ' + LARGE[i-1][construct and n % 1000**i == 0] + elif n1 == 0: + words.append(TENS[n1][1 + 2*(construct and n % 1000**i == 0)] + ' ' + LARGE[i-1][construct and n % 1000**i == 0]) + elif n1 == 1: + words.append(LARGE[i-1][0]) + else: + words.append(ONES[n1][1 + 2*(construct and n % 1000**i == 0 or x == 2)] + ' ' + LARGE[i-1][construct and n % 1000**i == 0]) # source: 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 if len(words) > 1: @@ -159,8 +171,8 @@ class Num2Word_HE(Num2Word_Base): def setup(self): super(Num2Word_HE, self).setup() - self.negword = u"מינוס" - self.pointword = u"נקודה" + self.negword = u'מינוס' + self.pointword = u'נקודה' self.MAXVAL = MAXVAL def to_cardinal_float(self, value, gender='f'): @@ -182,9 +194,9 @@ def to_cardinal_float(self, value, gender='f'): curr = int(post[i]) out.append(to_s(self.to_cardinal(curr))) - return " ".join(out) + return ' '.join(out) - def to_cardinal(self, value, gender='f'): + def to_cardinal(self, value, gender='f', construct=False): try: assert int(value) == value except (ValueError, TypeError, AssertionError): @@ -198,7 +210,7 @@ def to_cardinal(self, value, gender='f'): if value >= self.MAXVAL: raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL)) - return out + int2word(int(value), gender=gender, ordinal=False) + return out + int2word(int(value), gender=gender, construct=construct, ordinal=False) def to_ordinal(self, value, gender='m', definite=False): self.verify_ordinal(value) @@ -233,8 +245,8 @@ def to_currency(self, val, currency='ILS', cents=True, separator=' ' + AND, except KeyError: gender1 = gender2 = '' - money_str = self.to_cardinal(left, gender=gender1) - cents_str = self.to_cardinal(right, gender=gender2) \ + money_str = self.to_cardinal(left, gender=gender1, construct=left == 2) + cents_str = self.to_cardinal(right, gender=gender2, construct=right == 2) \ if cents else self._cents_terse(right, currency) strings = [ diff --git a/tests/test_he.py b/tests/test_he.py index 27785822..9aabcec0 100644 --- a/tests/test_he.py +++ b/tests/test_he.py @@ -37,7 +37,9 @@ def test_1_to_10(self): def test_11_to_19(self): self.assertEqual(num2words(11, lang="he"), u'אחת עשרה') + self.assertEqual(num2words(11, lang="he", gender='m'), u'אחד עשר') self.assertEqual(num2words(13, lang="he"), u'שלוש עשרה') + self.assertEqual(num2words(13, lang="he", construct=True), u'שלוש עשרה') self.assertEqual(num2words(15, lang="he"), u'חמש עשרה') self.assertEqual(num2words(16, lang="he"), u'שש עשרה') self.assertEqual(num2words(19, lang="he"), u'תשע עשרה') @@ -53,19 +55,31 @@ def test_20_to_99(self): def test_100_to_999(self): self.assertEqual(num2words(100, lang="he"), u'מאה') + self.assertEqual(num2words(100, lang="he", construct=True), u'מאת') self.assertEqual(num2words(111, lang="he"), u'מאה ואחת עשרה') + self.assertEqual(num2words(111, lang="he", construct=True), u'מאה ואחת עשרה') self.assertEqual(num2words(150, lang="he"), u'מאה וחמישים') self.assertEqual(num2words(196, lang="he"), u'מאה תשעים ושש') self.assertEqual(num2words(200, lang="he"), u'מאתיים') + self.assertEqual(num2words(200, lang="he", construct=True), u'מאתיים') self.assertEqual(num2words(210, lang="he"), u'מאתיים ועשר') self.assertEqual(num2words(701, lang="he"), u'שבע מאות ואחת') def test_1000_to_9999(self): self.assertEqual(num2words(1000, lang="he"), u'אלף') + self.assertEqual(num2words(1000, lang="he", construct=True), u'אלף') self.assertEqual(num2words(1001, lang="he"), u'אלף ואחת') self.assertEqual(num2words(1500, lang="he"), u'אלף וחמש מאות') self.assertEqual(num2words(2000, lang="he"), u'אלפיים') + self.assertEqual(num2words(2000, lang="he", construct=True), u'אלפיים') + self.assertEqual(num2words(2002, lang="he"), u'אלפיים ושתיים') + self.assertEqual(num2words(2002, lang="he", construct=True), u'אלפיים ושתי') self.assertEqual(num2words(2100, lang="he"), u'אלפיים ומאה') + self.assertEqual(num2words(2100, lang="he", construct=True), u'אלפיים ומאת') + self.assertEqual(num2words(3000, lang="he"), u'שלושת אלפים') + self.assertEqual(num2words(3000, lang="he", construct=True), u'שלושת אלפי') + self.assertEqual(num2words(3001, lang="he"), u'שלושת אלפים ואחת') + self.assertEqual(num2words(3001, lang="he", construct=True), u'שלושת אלפים ואחת') self.assertEqual( num2words(6870, lang="he"), u'ששת אלפים שמונה מאות ושבעים' ) @@ -78,11 +92,14 @@ def test_1000_to_9999(self): def test_10000_to_99999(self): self.assertEqual(num2words(10000, lang="he"), u'עשרת אלפים') + self.assertEqual(num2words(10000, lang="he", construct=True), u'עשרת אלפי') self.assertEqual(num2words(10001, lang="he"), u'עשרת אלפים ואחת') + self.assertEqual(num2words(10001, lang="he", construct=True), u'עשרת אלפים ואחת') self.assertEqual(num2words(10999, lang="he"), u'עשרת אלפים תשע מאות תשעים ותשע') self.assertEqual(num2words(11000, lang="he"), u'אחד עשר אלף') self.assertEqual(num2words(15000, lang="he"), u'חמישה עשר אלף') self.assertEqual(num2words(20000, lang="he"), u'עשרים אלף') + self.assertEqual(num2words(20000, lang="he", construct=True), u'עשרים אלף') self.assertEqual(num2words(21000, lang="he"), u'עשרים ואחד אלף') self.assertEqual(num2words(68700, lang="he"), u'שישים ושמונה אלף ושבע מאות') self.assertEqual(num2words(73781, lang="he"), u'שבעים ושלושה אלף שבע מאות שמונים ואחת') @@ -90,6 +107,7 @@ def test_10000_to_99999(self): def test_100000_to_999999(self): self.assertEqual(num2words(100000, lang="he"), u'מאה אלף') + self.assertEqual(num2words(100000, lang="he", construct=True), u'מאה אלף') self.assertEqual(num2words(100001, lang="he"), u'מאה אלף ואחת') self.assertEqual(num2words(199999, lang="he"), u'מאה תשעים ותשעה אלף תשע מאות תשעים ותשע') self.assertEqual(num2words(110000, lang="he"), u'מאה ועשרה אלף') @@ -97,9 +115,65 @@ def test_100000_to_999999(self): self.assertEqual(num2words(200000, lang="he"), u'מאתיים אלף') self.assertEqual(num2words(210000, lang="he"), u'מאתיים ועשרה אלף') self.assertEqual(num2words(687000, lang="he"), u'שש מאות שמונים ושבעה אלף') + self.assertEqual(num2words(687000, lang="he", construct=True), u'שש מאות שמונים ושבעה אלף') self.assertEqual(num2words(737812, lang="he"), u'שבע מאות שלושים ושבעה אלף שמונה מאות ושתים עשרה') self.assertEqual(num2words(999999, lang="he"), u'תשע מאות תשעים ותשעה אלף תשע מאות תשעים ותשע') + def test_1000000_to_999999999999999(self): + self.assertEqual(num2words(1000000, lang="he"), u'מיליון') + self.assertEqual(num2words(1000000, lang="he", construct=True), u'מיליון') + self.assertEqual(num2words(1000002, lang="he"), u'מיליון ושתיים') + self.assertEqual(num2words(1000002, lang="he", construct=True), u'מיליון ושתי') + self.assertEqual(num2words(2000000, lang="he"), u'שני מיליון') + self.assertEqual(num2words(2000000, lang="he", construct=True), u'שני מיליוני') + self.assertEqual(num2words(3000000, lang="he"), u'שלושה מיליון') + self.assertEqual(num2words(3000000, lang="he", construct=True), u'שלושת מיליוני') + self.assertEqual(num2words(3000002, lang="he"), u'שלושה מיליון ושתיים') + self.assertEqual(num2words(3000002, lang="he", construct=True), u'שלושה מיליון ושתי') + self.assertEqual(num2words(10000000, lang="he"), u'עשרה מיליון') + self.assertEqual(num2words(10000000, lang="he", construct=True), 'עשרת מיליוני') + self.assertEqual(num2words(11000000, lang="he"), u'אחד עשר מיליון') + self.assertEqual(num2words(11000000, lang="he", construct=True), 'אחד עשר מיליוני') + + self.assertEqual(num2words(1000000000, lang="he"), u'מיליארד') + self.assertEqual(num2words(1000000000, lang="he", construct=True), u'מיליארד') + self.assertEqual(num2words(1000000002, lang="he"), u'מיליארד ושתיים') + self.assertEqual(num2words(1000000002, lang="he", construct=True), u'מיליארד ושתי') + self.assertEqual(num2words(2000000000, lang="he"), u'שני מיליארד') + self.assertEqual(num2words(2000000000, lang="he", construct=True), u'שני מיליארדי') + self.assertEqual(num2words(3000000000, lang="he"), u'שלושה מיליארד') + self.assertEqual(num2words(3000000000, lang="he", construct=True), u'שלושת מיליארדי') + self.assertEqual(num2words(3000000002, lang="he"), u'שלושה מיליארד ושתיים') + self.assertEqual(num2words(3000000002, lang="he", construct=True), u'שלושה מיליארד ושתי') + self.assertEqual(num2words(10000000000, lang="he"), u'עשרה מיליארד') + self.assertEqual(num2words(10000000000, lang="he", construct=True), 'עשרת מיליארדי') + self.assertEqual(num2words(10000000002, lang="he"), u'עשרה מיליארד ושתיים') + self.assertEqual(num2words(10000000002, lang="he", construct=True), 'עשרה מיליארד ושתי') + self.assertEqual(num2words(11000000000, lang="he"), u'אחד עשר מיליארד') + self.assertEqual(num2words(11000000000, lang="he", construct=True), 'אחד עשר מיליארדי') + + self.assertEqual(num2words(1000000000000, lang="he"), u'טריליון') + self.assertEqual(num2words(1000000000000, lang="he", construct=True), u'טריליון') + self.assertEqual(num2words(1000000000002, lang="he"), u'טריליון ושתיים') + self.assertEqual(num2words(1000000000002, lang="he", construct=True), u'טריליון ושתי') + self.assertEqual(num2words(2000000000000, lang="he"), u'שני טריליון') + self.assertEqual(num2words(2000000000000, lang="he", construct=True), u'שני טריליוני') + self.assertEqual(num2words(3000000000000, lang="he"), u'שלושה טריליון') + self.assertEqual(num2words(3000000000000, lang="he", construct=True), u'שלושת טריליוני') + self.assertEqual(num2words(3000000000002, lang="he"), u'שלושה טריליון ושתיים') + self.assertEqual(num2words(3000000000002, lang="he", construct=True), u'שלושה טריליון ושתי') + self.assertEqual(num2words(10000000000000, lang="he"), u'עשרה טריליון') + self.assertEqual(num2words(10000000000000, lang="he", construct=True), 'עשרת טריליוני') + self.assertEqual(num2words(10000000000002, lang="he"), u'עשרה טריליון ושתיים') + self.assertEqual(num2words(10000000000002, lang="he", construct=True), 'עשרה טריליון ושתי') + self.assertEqual(num2words(11000000000000, lang="he"), u'אחד עשר טריליון') + self.assertEqual(num2words(11000000000000, lang="he", construct=True), 'אחד עשר טריליוני') + + self.assertEqual(num2words(999999999999999, lang="he"), u'תשע מאות תשעים ותשעה טריליון תשע מאות תשעים ותשעה מיליארד תשע מאות תשעים ותשעה מיליון תשע מאות תשעים ותשעה אלף תשע מאות תשעים ותשע') + self.assertEqual(num2words(999999999999999, lang="he", gender='m'), u'תשע מאות תשעים ותשעה טריליון תשע מאות תשעים ותשעה מיליארד תשע מאות תשעים ותשעה מיליון תשע מאות תשעים ותשעה אלף תשע מאות תשעים ותשעה') + self.assertEqual(num2words(999999999999999, lang="he", construct=True), u'תשע מאות תשעים ותשעה טריליון תשע מאות תשעים ותשעה מיליארד תשע מאות תשעים ותשעה מיליון תשע מאות תשעים ותשעה אלף תשע מאות תשעים ותשע') + self.assertEqual(num2words(999999999999999, lang="he", gender='m', construct=True), u'תשע מאות תשעים ותשעה טריליון תשע מאות תשעים ותשעה מיליארד תשע מאות תשעים ותשעה מיליון תשע מאות תשעים ותשעה אלף תשע מאות תשעים ותשעת') + def test_pluralize(self): n = Num2Word_HE() cr1, cr2 = n.CURRENCY_FORMS['ILS'] @@ -149,6 +223,15 @@ def test_to_currency(self): self.assertEqual( n.to_currency(-1.01, currency='ILS'), u'מינוס שקל אחד ואגורה אחת' ) + self.assertEqual( + n.to_currency(2.02, currency='ILS'), u'שני שקלים ושתי אגורות' + ) + self.assertEqual( + n.to_currency(1002.02, currency='ILS'), u'אלף ושניים שקלים ושתי אגורות' + ) + self.assertEqual( + n.to_currency(1000002.02, currency='ILS'), u'מיליון ושניים שקלים ושתי אגורות' + ) self.assertEqual( n.to_currency(5.05, currency='USD'), u'חמישה דולרים וחמישה סנטים' ) @@ -206,7 +289,7 @@ class Num2WordsHETestNotImplementedMethods(TestCase): def test_large_number(self): with self.assertRaises(OverflowError): - num2words(2000000, lang="he") + num2words(2e15, lang="he") with self.assertRaises(OverflowError): - num2words(2000000, lang="he", ordinal=True) + num2words(2e15, lang="he", ordinal=True) From 16468d3e96ffc510ab33bfccaaa6ca75febe9dfc Mon Sep 17 00:00:00 2001 From: eyaler Date: Sat, 3 Dec 2022 15:04:11 +0000 Subject: [PATCH 148/200] do not allow singular form for plural negatives --- num2words/lang_HE.py | 6 +++--- tests/test_he.py | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/num2words/lang_HE.py b/num2words/lang_HE.py index 535f9ecc..4fd92bb6 100644 --- a/num2words/lang_HE.py +++ b/num2words/lang_HE.py @@ -223,7 +223,7 @@ def to_ordinal(self, value, gender='m', definite=False): def pluralize(self, n, forms, currency=None, is_negative=False, prefer_singular=False): assert n == int(n) form = 1 - if n == 1 or prefer_singular and (n > 10 or n == 0 or is_negative or currency != 'ILS'): + if n == 1 or prefer_singular and (abs(n) > 10 or n == 0 or currency != 'ILS'): form = 0 return forms[form] @@ -252,10 +252,10 @@ def to_currency(self, val, currency='ILS', cents=True, separator=' ' + AND, strings = [ minus_str, money_str, - self.pluralize(left, cr1, currency=currency, is_negative=is_negative, prefer_singular=prefer_singular), + self.pluralize(left, cr1, currency=currency, prefer_singular=prefer_singular), separator, cents_str, - self.pluralize(right, cr2, currency=currency, is_negative=is_negative, prefer_singular=prefer_singular_cents) + self.pluralize(right, cr2, currency=currency, prefer_singular=prefer_singular_cents) ] if left == 1: strings[1], strings[2] = strings[2], strings[1] diff --git a/tests/test_he.py b/tests/test_he.py index 9aabcec0..5b186390 100644 --- a/tests/test_he.py +++ b/tests/test_he.py @@ -217,6 +217,9 @@ def test_to_currency(self): self.assertEqual( n.to_currency(5.05, currency='ILS', prefer_singular=True, prefer_singular_cents=True), u'חמישה שקלים וחמש אגורות' ) + self.assertEqual( + n.to_currency(-5.05, currency='ILS', prefer_singular=True, prefer_singular_cents=True), u'מינוס חמישה שקלים וחמש אגורות' + ) self.assertEqual( n.to_currency(1.01, currency='ILS'), u'שקל אחד ואגורה אחת' ) From 52d7b0236def3f965e064f2eabf0c8f0401c5a99 Mon Sep 17 00:00:00 2001 From: eyaler Date: Sat, 3 Dec 2022 15:06:29 +0000 Subject: [PATCH 149/200] do not allow singular form for plural negatives --- num2words/lang_HE.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/num2words/lang_HE.py b/num2words/lang_HE.py index 4fd92bb6..c121d5d0 100644 --- a/num2words/lang_HE.py +++ b/num2words/lang_HE.py @@ -20,7 +20,7 @@ from .base import Num2Word_Base from .compat import to_s -from .currency import parse_currency_parts, prefix_currency +from .currency import parse_currency_parts from .utils import get_digits, splitbyx @@ -220,7 +220,7 @@ def to_ordinal(self, value, gender='m', definite=False): return int2word(int(value), gender=gender, ordinal=True, definite=definite) - def pluralize(self, n, forms, currency=None, is_negative=False, prefer_singular=False): + 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) > 10 or n == 0 or currency != 'ILS'): From 23a9fd4141d15c5c6f318a597c0c982067166365 Mon Sep 17 00:00:00 2001 From: eyaler Date: Sat, 3 Dec 2022 15:43:59 +0000 Subject: [PATCH 150/200] maxval=1e66 --- num2words/lang_HE.py | 21 +++++++++++++++++++-- tests/test_he.py | 8 ++++---- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/num2words/lang_HE.py b/num2words/lang_HE.py index c121d5d0..66fa1eee 100644 --- a/num2words/lang_HE.py +++ b/num2words/lang_HE.py @@ -71,14 +71,31 @@ LARGE = { 1: (u'מיליון', u'מיליוני'), 2: (u'מיליארד', u'מיליארדי'), - 3: (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(1e15) +MAXVAL = int(1e66) def int2word(n, gender='f', construct=False, ordinal=False, definite=False): diff --git a/tests/test_he.py b/tests/test_he.py index 5b186390..24110f9b 100644 --- a/tests/test_he.py +++ b/tests/test_he.py @@ -74,12 +74,12 @@ def test_1000_to_9999(self): self.assertEqual(num2words(2000, lang="he", construct=True), u'אלפיים') self.assertEqual(num2words(2002, lang="he"), u'אלפיים ושתיים') self.assertEqual(num2words(2002, lang="he", construct=True), u'אלפיים ושתי') - self.assertEqual(num2words(2100, lang="he"), u'אלפיים ומאה') - self.assertEqual(num2words(2100, lang="he", construct=True), u'אלפיים ומאת') self.assertEqual(num2words(3000, lang="he"), u'שלושת אלפים') self.assertEqual(num2words(3000, lang="he", construct=True), u'שלושת אלפי') self.assertEqual(num2words(3001, lang="he"), u'שלושת אלפים ואחת') self.assertEqual(num2words(3001, lang="he", construct=True), u'שלושת אלפים ואחת') + self.assertEqual(num2words(3100, lang="he"), u'שלושת אלפים ומאה') + self.assertEqual(num2words(3100, lang="he", construct=True), u'שלושת אלפים ומאת') self.assertEqual( num2words(6870, lang="he"), u'ששת אלפים שמונה מאות ושבעים' ) @@ -292,7 +292,7 @@ class Num2WordsHETestNotImplementedMethods(TestCase): def test_large_number(self): with self.assertRaises(OverflowError): - num2words(2e15, lang="he") + num2words(2e66, lang="he") with self.assertRaises(OverflowError): - num2words(2e15, lang="he", ordinal=True) + num2words(2e66, lang="he", ordinal=True) From 78c45c622a0c528aec94bb17e4fe05bc30bab5ca Mon Sep 17 00:00:00 2001 From: eyaler Date: Sat, 3 Dec 2022 16:53:16 +0000 Subject: [PATCH 151/200] fixed bug in gender of TENS --- num2words/lang_HE.py | 2 +- tests/test_he.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/num2words/lang_HE.py b/num2words/lang_HE.py index 66fa1eee..4510eefe 100644 --- a/num2words/lang_HE.py +++ b/num2words/lang_HE.py @@ -138,7 +138,7 @@ def int2word(n, gender='f', construct=False, ordinal=False, definite=False): TENS[n1][(gender == 'm' or i > 0) + 2*(construct > ordinal and n1 == 0) + 4*ordinal*(n1 == 0)]) else: words.append( - ONES[n1][(gender == 'm' or i > 0)] + ' ' + TENS[3][(gender == 'f' and i > 0)]) + ONES[n1][(gender == 'm' or i > 0)] + ' ' + TENS[3][(gender == 'm' or i > 0)]) elif n1 > 0: words.append( ONES[n1][(gender == 'm' or i > 0) + 2*(construct > ordinal and i == 0) + 4*ordinal*(x < 11)]) diff --git a/tests/test_he.py b/tests/test_he.py index 24110f9b..07b47528 100644 --- a/tests/test_he.py +++ b/tests/test_he.py @@ -42,6 +42,7 @@ def test_11_to_19(self): self.assertEqual(num2words(13, lang="he", construct=True), u'שלוש עשרה') self.assertEqual(num2words(15, lang="he"), u'חמש עשרה') self.assertEqual(num2words(16, lang="he"), u'שש עשרה') + self.assertEqual(num2words(16, lang="he", gender='m'), u'שישה עשר') self.assertEqual(num2words(19, lang="he"), u'תשע עשרה') def test_20_to_99(self): @@ -98,6 +99,7 @@ def test_10000_to_99999(self): self.assertEqual(num2words(10999, lang="he"), u'עשרת אלפים תשע מאות תשעים ותשע') self.assertEqual(num2words(11000, lang="he"), u'אחד עשר אלף') self.assertEqual(num2words(15000, lang="he"), u'חמישה עשר אלף') + self.assertEqual(num2words(15000, lang="he", gender='m'), u'חמישה עשר אלף') self.assertEqual(num2words(20000, lang="he"), u'עשרים אלף') self.assertEqual(num2words(20000, lang="he", construct=True), u'עשרים אלף') self.assertEqual(num2words(21000, lang="he"), u'עשרים ואחד אלף') From 1466c6221e4efb12866122473a3a2c4e62f4e0e0 Mon Sep 17 00:00:00 2001 From: eyaler Date: Sat, 3 Dec 2022 17:32:08 +0000 Subject: [PATCH 152/200] simplify code, add more tests, add makaf for cents_terse --- num2words/lang_HE.py | 23 ++++++++++++++--------- tests/test_he.py | 7 +++++++ 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/num2words/lang_HE.py b/num2words/lang_HE.py index 4510eefe..79edd440 100644 --- a/num2words/lang_HE.py +++ b/num2words/lang_HE.py @@ -40,9 +40,8 @@ TENS = { 0: (u'עשר', u'עשרה', u'עשר', u'עשרת', u'עשירית', u'עשירי'), - 1: (u'אחת עשרה', u'אחד עשר'), + 1: (u'עשרה', u'עשר'), 2: (u'שתים עשרה', u'שנים עשר'), - 3: (u'עשרה', u'עשר'), } TWENTIES = { @@ -95,6 +94,8 @@ DEF = u'ה' +MAKAF = '-' + MAXVAL = int(1e66) @@ -133,12 +134,12 @@ def int2word(n, gender='f', construct=False, ordinal=False, definite=False): if i == 0 or x > 10: if n2 == 1: - if n1 <= 2: + if n1 in (0, 2): words.append( - TENS[n1][(gender == 'm' or i > 0) + 2*(construct > ordinal and n1 == 0) + 4*ordinal*(n1 == 0)]) + TENS[n1][gender == 'm' or i > 0]) else: words.append( - ONES[n1][(gender == 'm' or i > 0)] + ' ' + TENS[3][(gender == 'm' or i > 0)]) + ONES[n1][(gender == 'm' or i > 0)] + ' ' + TENS[1][(gender == 'm' or i > 0)]) elif n1 > 0: words.append( ONES[n1][(gender == 'm' or i > 0) + 2*(construct > ordinal and i == 0) + 4*ordinal*(x < 11)]) @@ -147,7 +148,7 @@ def int2word(n, gender='f', construct=False, ordinal=False, definite=False): if x >= 11: words[-1] = words[-1] + ' ' + THOUSANDS[1][0] elif n1 == 0: - words.append(TENS[n1][3] + ' ' + THOUSANDS[3][construct and n % 1000 == 0]) + words.append(TENS[0][3] + ' ' + THOUSANDS[3][construct and n % 1000 == 0]) elif n1 <= 2: words.append(THOUSANDS[n1][0]) else: @@ -156,7 +157,7 @@ def int2word(n, gender='f', construct=False, ordinal=False, definite=False): if x >= 11: words[-1] = words[-1] + ' ' + LARGE[i-1][construct and n % 1000**i == 0] elif n1 == 0: - words.append(TENS[n1][1 + 2*(construct and n % 1000**i == 0)] + ' ' + LARGE[i-1][construct and n % 1000**i == 0]) + words.append(TENS[0][1 + 2*(construct and n % 1000**i == 0)] + ' ' + LARGE[i-1][construct and n % 1000**i == 0]) elif n1 == 1: words.append(LARGE[i-1][0]) else: @@ -263,8 +264,12 @@ def to_currency(self, val, currency='ILS', cents=True, separator=' ' + AND, gender1 = gender2 = '' money_str = self.to_cardinal(left, gender=gender1, construct=left == 2) - cents_str = self.to_cardinal(right, gender=gender2, construct=right == 2) \ - if cents else self._cents_terse(right, currency) + if cents: + cents_str = self.to_cardinal(right, gender=gender2, construct=right == 2) + else: + cents_str = self._cents_terse(right, currency) + if separator.split()[-1] == AND: + separator += MAKAF strings = [ minus_str, diff --git a/tests/test_he.py b/tests/test_he.py index 07b47528..db48e1f5 100644 --- a/tests/test_he.py +++ b/tests/test_he.py @@ -222,6 +222,9 @@ def test_to_currency(self): self.assertEqual( n.to_currency(-5.05, currency='ILS', prefer_singular=True, prefer_singular_cents=True), u'מינוס חמישה שקלים וחמש אגורות' ) + self.assertEqual( + n.to_currency(-5.05, currency='ILS', cents=False), u'מינוס חמישה שקלים ו-05 אגורות' + ) self.assertEqual( n.to_currency(1.01, currency='ILS'), u'שקל אחד ואגורה אחת' ) @@ -266,6 +269,10 @@ def test_to_ordinal(self): self.assertEqual(n.to_ordinal(1, definite=True), u'הראשון') self.assertEqual(n.to_ordinal(1, gender='f'), u'ראשונה') self.assertEqual(n.to_ordinal(1, gender='f', definite=True), u'הראשונה') + self.assertEqual(n.to_ordinal(17), u'השבעה עשר') + self.assertEqual(n.to_ordinal(17, definite=True), u'השבעה עשר') + self.assertEqual(n.to_ordinal(17, gender='f'), u'השבע עשרה') + self.assertEqual(n.to_ordinal(17, gender='f', definite=True), u'השבע עשרה') self.assertEqual(n.to_ordinal(0), u'האפס') self.assertEqual(n.to_ordinal(0, definite=True), u'האפס') self.assertEqual(n.to_ordinal(0, gender='f'), u'האפס') From 2a3dad27afde52092abe2c0b887ad58898339b36 Mon Sep 17 00:00:00 2001 From: eyaler Date: Sat, 3 Dec 2022 19:15:58 +0000 Subject: [PATCH 153/200] fixed maxval to be percise --- num2words/lang_HE.py | 2 +- tests/test_he.py | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/num2words/lang_HE.py b/num2words/lang_HE.py index 79edd440..a0457449 100644 --- a/num2words/lang_HE.py +++ b/num2words/lang_HE.py @@ -96,7 +96,7 @@ MAKAF = '-' -MAXVAL = int(1e66) +MAXVAL = int('1' + '0'*66) def int2word(n, gender='f', construct=False, ordinal=False, definite=False): diff --git a/tests/test_he.py b/tests/test_he.py index db48e1f5..a12657f2 100644 --- a/tests/test_he.py +++ b/tests/test_he.py @@ -295,13 +295,13 @@ def test_cardinal_for_float_number(self): self.assertEqual(num2words(12.59, lang='he', gender='m'), u'שנים עשר נקודה חמש תשע') self.assertEqual(num2words(12.594132, lang='he', gender='m'), u'שנים עשר נקודה חמש תשע ארבע אחת שלוש שתיים') + def test_overflow(self): + n = Num2Word_HE() + num2words(n.MAXVAL - 1, lang="he") + num2words(n.MAXVAL - 1, ordinal=True, lang="he") -class Num2WordsHETestNotImplementedMethods(TestCase): - n = Num2Word_HE() - - def test_large_number(self): with self.assertRaises(OverflowError): - num2words(2e66, lang="he") + num2words(n.MAXVAL, lang="he") with self.assertRaises(OverflowError): - num2words(2e66, lang="he", ordinal=True) + num2words(n.MAXVAL, lang="he", ordinal=True) From a840c5ac27f0645c1ea8d8d3baf34781f890f421 Mon Sep 17 00:00:00 2001 From: eyaler Date: Sat, 3 Dec 2022 21:50:42 +0000 Subject: [PATCH 154/200] factorize to allow memoization --- num2words/lang_HE.py | 98 +++++++++++++++++++++++--------------------- 1 file changed, 52 insertions(+), 46 deletions(-) diff --git a/num2words/lang_HE.py b/num2words/lang_HE.py index a0457449..1a62000a 100644 --- a/num2words/lang_HE.py +++ b/num2words/lang_HE.py @@ -99,6 +99,54 @@ MAXVAL = int('1' + '0'*66) +def chunk2word(n, i, x, gender='f', construct=False, ordinal=False): + words = [] + n1, n2, n3 = get_digits(x) + + if n3 > 0: + if construct and i == 0 and x == 100: + words.append(HUNDRED[n3][1]) + elif n3 <= 2: + words.append(HUNDRED[n3][0]) + else: + words.append(ONES[n3][0] + ' ' + HUNDRED[3][0]) + + if n2 > 1: + words.append(TWENTIES[n2][0]) + + if i == 0 or x >= 11: + if n2 == 1: + if n1 in (0, 2): + words.append(TENS[n1][gender == 'm' or i > 0]) + else: + words.append(ONES[n1][(gender == 'm' or i > 0)] + ' ' + TENS[1][(gender == 'm' or i > 0)]) + elif n1 > 0: + words.append(ONES[n1][(gender == 'm' or i > 0) + 2*(construct > ordinal and i == 0) + 4*ordinal*(x < 11)]) + + if i == 1: + if x >= 11: + words[-1] = words[-1] + ' ' + THOUSANDS[1][0] + elif n1 == 0: + words.append(TENS[0][3] + ' ' + THOUSANDS[3][construct and n % 1000**i == 0]) + elif n1 <= 2: + words.append(THOUSANDS[n1][0]) + else: + words.append(ONES[n1][3] + ' ' + THOUSANDS[3][construct and n % 1000**i== 0]) + + elif i > 1: + if x >= 11: + words[-1] = words[-1] + ' ' + LARGE[i - 1][ + construct and n % 1000**i == 0] + elif n1 == 0: + words.append(TENS[0][1 + 2*(construct and n % 1000**i == 0)] + ' ' + LARGE[i - 1][construct and n % 1000**i == 0]) + elif n1 == 1: + words.append(LARGE[i - 1][0]) + else: + words.append(ONES[n1][1 + 2*(construct and n % 1000**i == 0 or x == 2)] + ' ' + LARGE[i - 1][construct and n % 1000**i == 0]) + + return words + + def int2word(n, gender='f', construct=False, ordinal=False, definite=False): assert n == int(n) if n >= MAXVAL: @@ -119,55 +167,13 @@ def int2word(n, gender='f', construct=False, ordinal=False, definite=False): if x == 0: continue - n1, n2, n3 = get_digits(x) - - if n3 > 0: - if construct and i == 0 and x == 100: - words.append(HUNDRED[n3][1]) - elif n3 <= 2: - words.append(HUNDRED[n3][0]) - else: - words.append(ONES[n3][0] + ' ' + HUNDRED[3][0]) - - if n2 > 1: - words.append(TWENTIES[n2][0]) - - if i == 0 or x > 10: - if n2 == 1: - if n1 in (0, 2): - words.append( - TENS[n1][gender == 'm' or i > 0]) - else: - words.append( - ONES[n1][(gender == 'm' or i > 0)] + ' ' + TENS[1][(gender == 'm' or i > 0)]) - elif n1 > 0: - words.append( - ONES[n1][(gender == 'm' or i > 0) + 2*(construct > ordinal and i == 0) + 4*ordinal*(x < 11)]) - - if i == 1: - if x >= 11: - words[-1] = words[-1] + ' ' + THOUSANDS[1][0] - elif n1 == 0: - words.append(TENS[0][3] + ' ' + THOUSANDS[3][construct and n % 1000 == 0]) - elif n1 <= 2: - words.append(THOUSANDS[n1][0]) - else: - words.append(ONES[n1][3] + ' ' + THOUSANDS[3][construct and n % 1000 == 0]) - elif i > 1: - if x >= 11: - words[-1] = words[-1] + ' ' + LARGE[i-1][construct and n % 1000**i == 0] - elif n1 == 0: - words.append(TENS[0][1 + 2*(construct and n % 1000**i == 0)] + ' ' + LARGE[i-1][construct and n % 1000**i == 0]) - elif n1 == 1: - words.append(LARGE[i-1][0]) - else: - words.append(ONES[n1][1 + 2*(construct and n % 1000**i == 0 or x == 2)] + ' ' + LARGE[i-1][construct and n % 1000**i == 0]) + words += chunk2word(n, i, x, gender=gender, construct=construct, ordinal=ordinal) # source: 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 if len(words) > 1: words[-1] = AND + words[-1] - if ordinal and (n > 10 or definite): + if ordinal and (n >= 11 or definite): words[0] = DEF + words[0] return ' '.join(words) @@ -202,7 +208,7 @@ def to_cardinal_float(self, value, gender='f'): pre, post = self.float2tuple(float(value)) post = str(post) - post = '0' * (self.precision - len(post)) + post + post = '0'*(self.precision - len(post)) + post out = [self.to_cardinal(pre, gender=gender)] if self.precision: @@ -241,7 +247,7 @@ def to_ordinal(self, value, gender='m', definite=False): 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) > 10 or n == 0 or currency != 'ILS'): + if n == 1 or prefer_singular and (abs(n) >= 11 or n == 0 or currency != 'ILS'): form = 0 return forms[form] From c27ff99ce3013782c5735dac8bcf9533f7b7e623 Mon Sep 17 00:00:00 2001 From: eyaler Date: Sun, 4 Dec 2022 05:08:19 +0000 Subject: [PATCH 155/200] simplify code;add makaf parameter (just for terse) --- num2words/lang_HE.py | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/num2words/lang_HE.py b/num2words/lang_HE.py index 1a62000a..6a559e1f 100644 --- a/num2words/lang_HE.py +++ b/num2words/lang_HE.py @@ -55,7 +55,7 @@ 9: (u'תשעים',), } -HUNDRED = { +HUNDREDS = { 1: (u'מאה', u'מאת'), 2: (u'מאתיים',), 3: (u'מאות',) @@ -94,55 +94,54 @@ DEF = u'ה' -MAKAF = '-' - MAXVAL = int('1' + '0'*66) -def chunk2word(n, i, x, gender='f', construct=False, ordinal=False): +def chunk2word(i, x, is_last, gender='f', construct=False, ordinal=False): words = [] n1, n2, n3 = get_digits(x) if n3 > 0: if construct and i == 0 and x == 100: - words.append(HUNDRED[n3][1]) + words.append(HUNDREDS[n3][1]) elif n3 <= 2: - words.append(HUNDRED[n3][0]) + words.append(HUNDREDS[n3][0]) else: - words.append(ONES[n3][0] + ' ' + HUNDRED[3][0]) + 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 if n2 == 1: if n1 in (0, 2): - words.append(TENS[n1][gender == 'm' or i > 0]) + words.append(TENS[n1][male]) else: - words.append(ONES[n1][(gender == 'm' or i > 0)] + ' ' + TENS[1][(gender == 'm' or i > 0)]) + words.append(ONES[n1][male] + ' ' + TENS[1][male]) elif n1 > 0: - words.append(ONES[n1][(gender == 'm' or i > 0) + 2*(construct > ordinal and i == 0) + 4*ordinal*(x < 11)]) + words.append(ONES[n1][male + 2*(construct > ordinal and i == 0) + 4*ordinal*(x < 11)]) if i == 1: if x >= 11: words[-1] = words[-1] + ' ' + THOUSANDS[1][0] elif n1 == 0: - words.append(TENS[0][3] + ' ' + THOUSANDS[3][construct and n % 1000**i == 0]) + words.append(TENS[0][3] + ' ' + THOUSANDS[3][construct and is_last]) elif n1 <= 2: words.append(THOUSANDS[n1][0]) else: - words.append(ONES[n1][3] + ' ' + THOUSANDS[3][construct and n % 1000**i== 0]) + words.append(ONES[n1][3] + ' ' + THOUSANDS[3][construct and is_last]) elif i > 1: if x >= 11: words[-1] = words[-1] + ' ' + LARGE[i - 1][ - construct and n % 1000**i == 0] + construct and is_last] elif n1 == 0: - words.append(TENS[0][1 + 2*(construct and n % 1000**i == 0)] + ' ' + LARGE[i - 1][construct and n % 1000**i == 0]) + words.append(TENS[0][1 + 2*(construct and is_last)] + ' ' + LARGE[i - 1][construct and is_last]) elif n1 == 1: words.append(LARGE[i - 1][0]) else: - words.append(ONES[n1][1 + 2*(construct and n % 1000**i == 0 or x == 2)] + ' ' + LARGE[i - 1][construct and n % 1000**i == 0]) + words.append(ONES[n1][1 + 2*(construct and is_last or x == 2)] + ' ' + LARGE[i - 1][construct and is_last]) return words @@ -167,7 +166,8 @@ def int2word(n, gender='f', construct=False, ordinal=False, definite=False): if x == 0: continue - words += chunk2word(n, i, x, gender=gender, construct=construct, ordinal=ordinal) + is_last = n % 1000**i == 0 + words += chunk2word(i, x, is_last, gender=gender, construct=construct, ordinal=ordinal) # source: 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 if len(words) > 1: @@ -192,9 +192,12 @@ class Num2Word_HE(Num2Word_Base): '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 @@ -275,7 +278,7 @@ def to_currency(self, val, currency='ILS', cents=True, separator=' ' + AND, else: cents_str = self._cents_terse(right, currency) if separator.split()[-1] == AND: - separator += MAKAF + separator += self.makaf strings = [ minus_str, @@ -289,7 +292,7 @@ def to_currency(self, val, currency='ILS', cents=True, separator=' ' + AND, strings[1], strings[2] = strings[2], strings[1] if right == 1: strings[4], strings[5] = strings[5], strings[4] - return u'%s%s %s%s%s %s' % tuple(strings) # In Hebrew the separator is along with the following word + return u'%s%s %s%s%s %s' % tuple(strings) # In Hebrew the separator is along with the following word if __name__ == '__main__': From 8b679c0150afe091c0169f85a6e1e08d3a54f030 Mon Sep 17 00:00:00 2001 From: eyaler Date: Sat, 17 Dec 2022 20:47:45 +0000 Subject: [PATCH 156/200] fixed errors in construct and ordinal above 11. added ordinal plural forms --- num2words/lang_HE.py | 49 ++++++++++++++++------------- tests/test_he.py | 75 +++++++++++++++++++++++++++++++++++++------- 2 files changed, 91 insertions(+), 33 deletions(-) diff --git a/num2words/lang_HE.py b/num2words/lang_HE.py index 6a559e1f..947f1c71 100644 --- a/num2words/lang_HE.py +++ b/num2words/lang_HE.py @@ -27,19 +27,19 @@ ZERO = (u'אפס',) ONES = { - 1: (u'אחת', u'אחד', u'אחת', u'אחד', u'ראשונה', u'ראשון'), - 2: (u'שתיים', u'שניים', u'שתי', u'שני', u'שנייה', u'שני'), - 3: (u'שלוש', u'שלושה', u'שלוש', u'שלושת', u'שלישית', u'שלישי'), - 4: (u'ארבע', u'ארבעה', u'ארבע', u'ארבעת', u'רביעית', u'רביעי'), - 5: (u'חמש', u'חמישה', u'חמש', u'חמשת', u'חמישית', u'חמישי'), - 6: (u'שש', u'שישה', u'שש', u'ששת', u'שישית', u'שישי'), - 7: (u'שבע', u'שבעה', u'שבע', u'שבעת', u'שביעית', u'שביעי'), - 8: (u'שמונה', u'שמונה', u'שמונה', u'שמונת', u'שמינית', u'שמיני'), - 9: (u'תשע', u'תשעה', u'תשע', u'תשעת', u'תשיעית', u'תשיעי'), + 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'עשירי'), + 0: (u'עשר', u'עשרה', u'עשר', u'עשרת', u'עשירית', u'עשירי', u'עשיריות', u'עשיריים'), 1: (u'עשרה', u'עשר'), 2: (u'שתים עשרה', u'שנים עשר'), } @@ -97,12 +97,12 @@ MAXVAL = int('1' + '0'*66) -def chunk2word(i, x, is_last, gender='f', construct=False, ordinal=False): +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 i == 0 and x == 100: + if construct and n == 100: words.append(HUNDREDS[n3][1]) elif n3 <= 2: words.append(HUNDREDS[n3][0]) @@ -114,13 +114,18 @@ def chunk2word(i, x, is_last, gender='f', construct=False, ordinal=False): 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 in (0, 2): + 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 + 2*(construct > ordinal and i == 0) + 4*ordinal*(x < 11)]) + words.append(ONES[n1][male + cop]) + + is_last = n % 1000 ** i == 0 if i == 1: if x >= 11: @@ -134,8 +139,7 @@ def chunk2word(i, x, is_last, gender='f', construct=False, ordinal=False): elif i > 1: if x >= 11: - words[-1] = words[-1] + ' ' + LARGE[i - 1][ - construct and is_last] + words[-1] = words[-1] + ' ' + LARGE[i - 1][construct and is_last] elif n1 == 0: words.append(TENS[0][1 + 2*(construct and is_last)] + ' ' + LARGE[i - 1][construct and is_last]) elif n1 == 1: @@ -146,8 +150,10 @@ def chunk2word(i, x, is_last, gender='f', construct=False, ordinal=False): return words -def int2word(n, gender='f', construct=False, ordinal=False, definite=False): +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)) @@ -166,8 +172,7 @@ def int2word(n, gender='f', construct=False, ordinal=False, definite=False): if x == 0: continue - is_last = n % 1000**i == 0 - words += chunk2word(i, x, is_last, gender=gender, construct=construct, ordinal=ordinal) + words += chunk2word(n, i, x, gender=gender, construct=construct, ordinal=ordinal, plural=plural) # source: 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 if len(words) > 1: @@ -237,15 +242,15 @@ def to_cardinal(self, value, gender='f', construct=False): if value >= self.MAXVAL: raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL)) - return out + int2word(int(value), gender=gender, construct=construct, ordinal=False) + return out + int2word(int(value), gender=gender, construct=construct) - def to_ordinal(self, value, gender='m', definite=False): + 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) + 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) diff --git a/tests/test_he.py b/tests/test_he.py index a12657f2..b1e5dea2 100644 --- a/tests/test_he.py +++ b/tests/test_he.py @@ -34,6 +34,7 @@ def test_1_to_10(self): self.assertEqual(num2words(2, lang="he"), u'שתיים') self.assertEqual(num2words(7, lang="he"), u'שבע') self.assertEqual(num2words(10, lang="he"), u'עשר') + self.assertEqual(num2words(10, lang="he", gender='m', construct=True), u'עשרת') def test_11_to_19(self): self.assertEqual(num2words(11, lang="he"), u'אחת עשרה') @@ -43,11 +44,15 @@ def test_11_to_19(self): self.assertEqual(num2words(15, lang="he"), u'חמש עשרה') self.assertEqual(num2words(16, lang="he"), u'שש עשרה') self.assertEqual(num2words(16, lang="he", gender='m'), u'שישה עשר') + self.assertEqual(num2words(16, lang="he", gender='m', construct=True), u'שישה עשר') self.assertEqual(num2words(19, lang="he"), u'תשע עשרה') def test_20_to_99(self): self.assertEqual(num2words(20, lang="he"), u'עשרים') self.assertEqual(num2words(23, lang="he"), u'עשרים ושלוש') + self.assertEqual(num2words(23, lang="he", gender='m'), u'עשרים ושלושה') + self.assertEqual(num2words(23, lang="he", construct=True), u'עשרים ושלוש') + self.assertEqual(num2words(23, lang="he", gender='m', construct=True), u'עשרים ושלושה') self.assertEqual(num2words(28, lang="he"), u'עשרים ושמונה') self.assertEqual(num2words(31, lang="he"), u'שלושים ואחת') self.assertEqual(num2words(40, lang="he"), u'ארבעים') @@ -61,6 +66,8 @@ def test_100_to_999(self): self.assertEqual(num2words(111, lang="he", construct=True), u'מאה ואחת עשרה') self.assertEqual(num2words(150, lang="he"), u'מאה וחמישים') self.assertEqual(num2words(196, lang="he"), u'מאה תשעים ושש') + self.assertEqual(num2words(196, lang="he", gender='m'), u'מאה תשעים ושישה') + self.assertEqual(num2words(196, lang="he", gender='m', construct=True), u'מאה תשעים ושישה') self.assertEqual(num2words(200, lang="he"), u'מאתיים') self.assertEqual(num2words(200, lang="he", construct=True), u'מאתיים') self.assertEqual(num2words(210, lang="he"), u'מאתיים ועשר') @@ -70,17 +77,26 @@ def test_1000_to_9999(self): self.assertEqual(num2words(1000, lang="he"), u'אלף') self.assertEqual(num2words(1000, lang="he", construct=True), u'אלף') self.assertEqual(num2words(1001, lang="he"), u'אלף ואחת') + self.assertEqual(num2words(1002, lang="he"), u'אלף ושתיים') + self.assertEqual(num2words(1002, lang="he", gender='m'), u'אלף ושניים') + self.assertEqual(num2words(1002, lang="he", gender='m', construct=True), u'אלף ושניים') + self.assertEqual(num2words(1003, lang="he"), u'אלף ושלוש') + self.assertEqual(num2words(1003, lang="he", gender='m'), u'אלף ושלושה') + self.assertEqual(num2words(1003, lang="he", gender='m', construct=True), u'אלף ושלושה') + self.assertEqual(num2words(1010, lang="he"), u'אלף ועשר') + self.assertEqual(num2words(1010, lang="he", gender='m'), u'אלף ועשרה') + self.assertEqual(num2words(1010, lang="he", gender='m', construct=True), u'אלף ועשרה') self.assertEqual(num2words(1500, lang="he"), u'אלף וחמש מאות') self.assertEqual(num2words(2000, lang="he"), u'אלפיים') self.assertEqual(num2words(2000, lang="he", construct=True), u'אלפיים') self.assertEqual(num2words(2002, lang="he"), u'אלפיים ושתיים') - self.assertEqual(num2words(2002, lang="he", construct=True), u'אלפיים ושתי') + self.assertEqual(num2words(2002, lang="he", construct=True), u'אלפיים ושתיים') self.assertEqual(num2words(3000, lang="he"), u'שלושת אלפים') self.assertEqual(num2words(3000, lang="he", construct=True), u'שלושת אלפי') self.assertEqual(num2words(3001, lang="he"), u'שלושת אלפים ואחת') self.assertEqual(num2words(3001, lang="he", construct=True), u'שלושת אלפים ואחת') self.assertEqual(num2words(3100, lang="he"), u'שלושת אלפים ומאה') - self.assertEqual(num2words(3100, lang="he", construct=True), u'שלושת אלפים ומאת') + self.assertEqual(num2words(3100, lang="he", construct=True), u'שלושת אלפים ומאה') self.assertEqual( num2words(6870, lang="he"), u'ששת אלפים שמונה מאות ושבעים' ) @@ -103,6 +119,8 @@ def test_10000_to_99999(self): self.assertEqual(num2words(20000, lang="he"), u'עשרים אלף') self.assertEqual(num2words(20000, lang="he", construct=True), u'עשרים אלף') self.assertEqual(num2words(21000, lang="he"), u'עשרים ואחד אלף') + self.assertEqual(num2words(25000, lang="he"), u'עשרים וחמישה אלף') + self.assertEqual(num2words(25000, lang="he", construct=True), u'עשרים וחמישה אלף') self.assertEqual(num2words(68700, lang="he"), u'שישים ושמונה אלף ושבע מאות') self.assertEqual(num2words(73781, lang="he"), u'שבעים ושלושה אלף שבע מאות שמונים ואחת') self.assertEqual(num2words(99999, lang="he"), u'תשעים ותשעה אלף תשע מאות תשעים ותשע') @@ -125,13 +143,13 @@ def test_1000000_to_999999999999999(self): self.assertEqual(num2words(1000000, lang="he"), u'מיליון') self.assertEqual(num2words(1000000, lang="he", construct=True), u'מיליון') self.assertEqual(num2words(1000002, lang="he"), u'מיליון ושתיים') - self.assertEqual(num2words(1000002, lang="he", construct=True), u'מיליון ושתי') + self.assertEqual(num2words(1000002, lang="he", construct=True), u'מיליון ושתיים') self.assertEqual(num2words(2000000, lang="he"), u'שני מיליון') self.assertEqual(num2words(2000000, lang="he", construct=True), u'שני מיליוני') self.assertEqual(num2words(3000000, lang="he"), u'שלושה מיליון') self.assertEqual(num2words(3000000, lang="he", construct=True), u'שלושת מיליוני') self.assertEqual(num2words(3000002, lang="he"), u'שלושה מיליון ושתיים') - self.assertEqual(num2words(3000002, lang="he", construct=True), u'שלושה מיליון ושתי') + self.assertEqual(num2words(3000002, lang="he", construct=True), u'שלושה מיליון ושתיים') self.assertEqual(num2words(10000000, lang="he"), u'עשרה מיליון') self.assertEqual(num2words(10000000, lang="he", construct=True), 'עשרת מיליוני') self.assertEqual(num2words(11000000, lang="he"), u'אחד עשר מיליון') @@ -140,41 +158,41 @@ def test_1000000_to_999999999999999(self): self.assertEqual(num2words(1000000000, lang="he"), u'מיליארד') self.assertEqual(num2words(1000000000, lang="he", construct=True), u'מיליארד') self.assertEqual(num2words(1000000002, lang="he"), u'מיליארד ושתיים') - self.assertEqual(num2words(1000000002, lang="he", construct=True), u'מיליארד ושתי') + self.assertEqual(num2words(1000000002, lang="he", construct=True), u'מיליארד ושתיים') self.assertEqual(num2words(2000000000, lang="he"), u'שני מיליארד') self.assertEqual(num2words(2000000000, lang="he", construct=True), u'שני מיליארדי') self.assertEqual(num2words(3000000000, lang="he"), u'שלושה מיליארד') self.assertEqual(num2words(3000000000, lang="he", construct=True), u'שלושת מיליארדי') self.assertEqual(num2words(3000000002, lang="he"), u'שלושה מיליארד ושתיים') - self.assertEqual(num2words(3000000002, lang="he", construct=True), u'שלושה מיליארד ושתי') + self.assertEqual(num2words(3000000002, lang="he", construct=True), u'שלושה מיליארד ושתיים') self.assertEqual(num2words(10000000000, lang="he"), u'עשרה מיליארד') self.assertEqual(num2words(10000000000, lang="he", construct=True), 'עשרת מיליארדי') self.assertEqual(num2words(10000000002, lang="he"), u'עשרה מיליארד ושתיים') - self.assertEqual(num2words(10000000002, lang="he", construct=True), 'עשרה מיליארד ושתי') + self.assertEqual(num2words(10000000002, lang="he", construct=True), 'עשרה מיליארד ושתיים') self.assertEqual(num2words(11000000000, lang="he"), u'אחד עשר מיליארד') self.assertEqual(num2words(11000000000, lang="he", construct=True), 'אחד עשר מיליארדי') self.assertEqual(num2words(1000000000000, lang="he"), u'טריליון') self.assertEqual(num2words(1000000000000, lang="he", construct=True), u'טריליון') self.assertEqual(num2words(1000000000002, lang="he"), u'טריליון ושתיים') - self.assertEqual(num2words(1000000000002, lang="he", construct=True), u'טריליון ושתי') + self.assertEqual(num2words(1000000000002, lang="he", construct=True), u'טריליון ושתיים') self.assertEqual(num2words(2000000000000, lang="he"), u'שני טריליון') self.assertEqual(num2words(2000000000000, lang="he", construct=True), u'שני טריליוני') self.assertEqual(num2words(3000000000000, lang="he"), u'שלושה טריליון') self.assertEqual(num2words(3000000000000, lang="he", construct=True), u'שלושת טריליוני') self.assertEqual(num2words(3000000000002, lang="he"), u'שלושה טריליון ושתיים') - self.assertEqual(num2words(3000000000002, lang="he", construct=True), u'שלושה טריליון ושתי') + self.assertEqual(num2words(3000000000002, lang="he", construct=True), u'שלושה טריליון ושתיים') self.assertEqual(num2words(10000000000000, lang="he"), u'עשרה טריליון') self.assertEqual(num2words(10000000000000, lang="he", construct=True), 'עשרת טריליוני') self.assertEqual(num2words(10000000000002, lang="he"), u'עשרה טריליון ושתיים') - self.assertEqual(num2words(10000000000002, lang="he", construct=True), 'עשרה טריליון ושתי') + self.assertEqual(num2words(10000000000002, lang="he", construct=True), 'עשרה טריליון ושתיים') self.assertEqual(num2words(11000000000000, lang="he"), u'אחד עשר טריליון') self.assertEqual(num2words(11000000000000, lang="he", construct=True), 'אחד עשר טריליוני') self.assertEqual(num2words(999999999999999, lang="he"), u'תשע מאות תשעים ותשעה טריליון תשע מאות תשעים ותשעה מיליארד תשע מאות תשעים ותשעה מיליון תשע מאות תשעים ותשעה אלף תשע מאות תשעים ותשע') self.assertEqual(num2words(999999999999999, lang="he", gender='m'), u'תשע מאות תשעים ותשעה טריליון תשע מאות תשעים ותשעה מיליארד תשע מאות תשעים ותשעה מיליון תשע מאות תשעים ותשעה אלף תשע מאות תשעים ותשעה') self.assertEqual(num2words(999999999999999, lang="he", construct=True), u'תשע מאות תשעים ותשעה טריליון תשע מאות תשעים ותשעה מיליארד תשע מאות תשעים ותשעה מיליון תשע מאות תשעים ותשעה אלף תשע מאות תשעים ותשע') - self.assertEqual(num2words(999999999999999, lang="he", gender='m', construct=True), u'תשע מאות תשעים ותשעה טריליון תשע מאות תשעים ותשעה מיליארד תשע מאות תשעים ותשעה מיליון תשע מאות תשעים ותשעה אלף תשע מאות תשעים ותשעת') + self.assertEqual(num2words(999999999999999, lang="he", gender='m', construct=True), u'תשע מאות תשעים ותשעה טריליון תשע מאות תשעים ותשעה מיליארד תשע מאות תשעים ותשעה מיליון תשע מאות תשעים ותשעה אלף תשע מאות תשעים ותשעה') def test_pluralize(self): n = Num2Word_HE() @@ -262,6 +280,7 @@ def test_to_cardinal(self): def test_to_ordinal(self): n = Num2Word_HE() + self.assertEqual(n.to_ordinal(1001), u'האלף ואחד') self.assertEqual(n.to_ordinal(1500), u'האלף וחמש מאות') self.assertEqual(n.to_ordinal(1501), u'האלף חמש מאות ואחד') self.assertEqual(n.to_ordinal(1501, definite=True), u'האלף חמש מאות ואחד') @@ -269,6 +288,10 @@ def test_to_ordinal(self): self.assertEqual(n.to_ordinal(1, definite=True), u'הראשון') self.assertEqual(n.to_ordinal(1, gender='f'), u'ראשונה') self.assertEqual(n.to_ordinal(1, gender='f', definite=True), u'הראשונה') + self.assertEqual(n.to_ordinal(10), u'עשירי') + self.assertEqual(n.to_ordinal(10, definite=True), u'העשירי') + self.assertEqual(n.to_ordinal(10, gender='f'), u'עשירית') + self.assertEqual(n.to_ordinal(10, gender='f', definite=True), u'העשירית') self.assertEqual(n.to_ordinal(17), u'השבעה עשר') self.assertEqual(n.to_ordinal(17, definite=True), u'השבעה עשר') self.assertEqual(n.to_ordinal(17, gender='f'), u'השבע עשרה') @@ -284,6 +307,36 @@ def test_to_ordinal(self): self.assertEqual(num2words(1, ordinal=True, lang='he', definite=True), u'הראשון') self.assertEqual(num2words(1, ordinal=True, lang='he', gender='f', definite=True), u'הראשונה') + def test_to_ordinal_plural(self): + n = Num2Word_HE() + self.assertEqual(n.to_ordinal(1001, plural=True), u'האלף ואחד') + self.assertEqual(n.to_ordinal(1500, plural=True), u'האלף וחמש מאות') + self.assertEqual(n.to_ordinal(1501, plural=True), u'האלף חמש מאות ואחד') + self.assertEqual(n.to_ordinal(1501, definite=True, plural=True), u'האלף חמש מאות ואחד') + self.assertEqual(n.to_ordinal(1, plural=True), u'ראשונים') + self.assertEqual(n.to_ordinal(1, definite=True, plural=True), u'הראשונים') + self.assertEqual(n.to_ordinal(1, gender='f', plural=True), u'ראשונות') + self.assertEqual(n.to_ordinal(1, gender='f', definite=True, plural=True), u'הראשונות') + self.assertEqual(n.to_ordinal(10, plural=True), u'עשיריים') + self.assertEqual(n.to_ordinal(10, definite=True, plural=True), u'העשיריים') + self.assertEqual(n.to_ordinal(10, gender='f', plural=True), u'עשיריות') + self.assertEqual(n.to_ordinal(10, gender='f', definite=True, plural=True), u'העשיריות') + self.assertEqual(n.to_ordinal(17, plural=True), u'השבעה עשר') + self.assertEqual(n.to_ordinal(17, definite=True, plural=True), u'השבעה עשר') + self.assertEqual(n.to_ordinal(17, gender='f', plural=True), u'השבע עשרה') + self.assertEqual(n.to_ordinal(17, gender='f', definite=True, plural=True), u'השבע עשרה') + self.assertEqual(n.to_ordinal(0, plural=True), u'האפס') + self.assertEqual(n.to_ordinal(0, definite=True, plural=True), u'האפס') + self.assertEqual(n.to_ordinal(0, gender='f', plural=True), u'האפס') + self.assertEqual(n.to_ordinal(0, gender='f', definite=True, plural=True), u'האפס') + self.assertEqual(n.to_ordinal(999999, plural=True), u'התשע מאות תשעים ותשעה אלף תשע מאות תשעים ותשעה') + self.assertEqual(n.to_ordinal(999999, gender='f', plural=True), u'התשע מאות תשעים ותשעה אלף תשע מאות תשעים ותשע') + self.assertEqual(num2words(1, ordinal=True, lang='he', plural=True), u'ראשונים') + self.assertEqual(num2words(1, ordinal=True, lang='he', gender='f', plural=True), u'ראשונות') + self.assertEqual(num2words(1, ordinal=True, lang='he', definite=True, plural=True), u'הראשונים') + self.assertEqual(num2words(1, ordinal=True, lang='he', gender='f', definite=True, plural=True), u'הראשונות') + + def test_cardinal_for_float_number(self): self.assertEqual(num2words(12.5, lang='he'), u'שתים עשרה נקודה חמש') self.assertEqual(num2words(12.51, lang='he'), u'שתים עשרה נקודה חמש אחת') From ba95d984ad801f4646deead726821a9c681e43e8 Mon Sep 17 00:00:00 2001 From: Marlon Rodriguez Garcia Date: Mon, 26 Dec 2022 11:19:09 -0500 Subject: [PATCH 157/200] Change python3.6 to python3.11 because deprecation in ubuntu 22.04 --- .github/workflows/ci.yml | 2 +- setup.py | 2 +- tox.ini | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9bc095e5..159b7ebe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [3.6, 3.7, 3.8, 3.9, '3.10'] + python-version: [3.7, 3.8, 3.9, '3.10', '3.11'] steps: - uses: actions/checkout@v2 diff --git a/setup.py b/setup.py index 3565f62d..af434625 100644 --- a/setup.py +++ b/setup.py @@ -27,11 +27,11 @@ 'Intended Audience :: Developers', 'License :: OSI Approved :: GNU Library or Lesser General Public License ' '(LGPL)', - 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: 3.11', 'Topic :: Software Development :: Internationalization', 'Topic :: Software Development :: Libraries :: Python Modules', 'Topic :: Software Development :: Localization', diff --git a/tox.ini b/tox.ini index 11cf12a3..8e334bcf 100644 --- a/tox.ini +++ b/tox.ini @@ -1,13 +1,13 @@ [tox] -envlist = py36,py37,py38,py39,py310,flake8,isort +envlist = py37,py38,py39,py310,py311,flake8,isort [gh-actions] python = - 3.6: py36 3.7: py37 3.8: py38 3.9: py39 3.10: isort, flake8, py310 + 3.11: py311 [testenv] @@ -23,7 +23,7 @@ commands = [testenv:flake8] changedir = {toxinidir} deps = - flake8 + flake8==5.0.4 flake8-copyright commands = flake8 From 17dc4e0d6a2dbf356dda3c43a694ecf786118ddd Mon Sep 17 00:00:00 2001 From: Elgin Cahangirov Date: Wed, 28 Dec 2022 23:45:40 +0400 Subject: [PATCH 158/200] add support for Azerbaijani language --- README.rst | 1 + num2words/__init__.py | 3 +- num2words/lang_AZ.py | 204 +++++++++++++++++++++++++++++ tests/test_az.py | 289 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 496 insertions(+), 1 deletion(-) create mode 100644 num2words/lang_AZ.py create mode 100644 tests/test_az.py diff --git a/README.rst b/README.rst index 2a8f99f4..743b5439 100644 --- a/README.rst +++ b/README.rst @@ -78,6 +78,7 @@ Besides the numerical argument, there are two main optional arguments. * ``en`` (English, default) * ``am`` (Amharic) * ``ar`` (Arabic) +* ``az`` (Azerbaijani) * ``cz`` (Czech) * ``de`` (German) * ``dk`` (Danish) diff --git a/num2words/__init__.py b/num2words/__init__.py index fb9f7e91..1c438486 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -17,7 +17,7 @@ from __future__ import unicode_literals -from . import (lang_AM, lang_AR, lang_CZ, lang_DE, lang_DK, lang_EN, +from . import (lang_AM, lang_AR, lang_AZ, lang_CZ, lang_DE, lang_DK, lang_EN, lang_EN_IN, lang_EO, lang_ES, lang_ES_CO, 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_IT, lang_JA, @@ -29,6 +29,7 @@ CONVERTER_CLASSES = { 'am': lang_AM.Num2Word_AM(), 'ar': lang_AR.Num2Word_AR(), + 'az': lang_AZ.Num2Word_AZ(), 'cz': lang_CZ.Num2Word_CZ(), 'en': lang_EN.Num2Word_EN(), 'en_IN': lang_EN_IN.Num2Word_EN_IN(), diff --git a/num2words/lang_AZ.py b/num2words/lang_AZ.py new file mode 100644 index 00000000..e225bfb7 --- /dev/null +++ b/num2words/lang_AZ.py @@ -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 diff --git a/tests/test_az.py b/tests/test_az.py new file mode 100644 index 00000000..af52cb27 --- /dev/null +++ b/tests/test_az.py @@ -0,0 +1,289 @@ +# -*- 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 unittest import TestCase + +from num2words import num2words + + +class Num2WordAZTest(TestCase): + lang = 'az' + + CARDINAL_TEST_CASES = ( + (0, 'sıfır',), + (1, 'bir',), + (2, 'iki',), + (3, 'üç',), + (4, 'dörd',), + (5, 'beş',), + (6, 'altı',), + (7, 'yeddi',), + (8, 'səkkiz',), + (9, 'doqquz',), + (10, 'on',), + (11, 'on bir',), + (20, 'iyirmi',), + (22, 'iyirmi iki',), + (30, 'otuz',), + (33, 'otuz üç',), + (40, 'qırx',), + (44, 'qırx dörd',), + (50, 'əlli',), + (55, 'əlli beş',), + (60, 'altmış',), + (66, 'altmış altı',), + (70, 'yetmiş',), + (77, 'yetmiş yeddi',), + (80, 'səksən',), + (88, 'səksən səkkiz',), + (90, 'doxsan',), + (99, 'doxsan doqquz',), + (100, 'yüz',), + (200, 'iki yüz',), + (678, 'altı yüz yetmiş səkkiz',), + (999, 'doqquz yüz doxsan doqquz',), + (1000, 'min',), + (100_000, 'yüz min',), + (328_914, 'üç yüz iyirmi səkkiz min doqquz yüz on dörd',), + (1_000_000, 'bir milyon',), + (1_000_000_000, 'bir milyard',), + (10**12, 'bir trilyon',), + (10**15, 'bir katrilyon',), + (10**18, 'bir kentilyon',), + (10**21, 'bir sekstilyon',), + (10**24, 'bir septilyon',), + (10**27, 'bir oktilyon',), + (10**30, 'bir nonilyon',), + (10**33, 'bir desilyon',), + (10**36, 'bir undesilyon',), + (10**39, 'bir dodesilyon',), + (10**42, 'bir tredesilyon',), + (10**45, 'bir katordesilyon',), + (10**48, 'bir kendesilyon',), + (10**51, 'bir seksdesilyon',), + (10**54, 'bir septendesilyon',), + (10**57, 'bir oktodesilyon',), + (10**60, 'bir novemdesilyon',), + (10**63, 'bir vigintilyon',), + (-0, 'sıfır',), + (-1, 'mənfi bir',), + (-2, 'mənfi iki',), + (-3, 'mənfi üç',), + (-4, 'mənfi dörd',), + (-5, 'mənfi beş',), + (-6, 'mənfi altı',), + (-7, 'mənfi yeddi',), + (-8, 'mənfi səkkiz',), + (-9, 'mənfi doqquz',), + (-10, 'mənfi on',), + (-11, 'mənfi on bir',), + (-20, 'mənfi iyirmi',), + (-22, 'mənfi iyirmi iki',), + (-30, 'mənfi otuz',), + (-33, 'mənfi otuz üç',), + (-40, 'mənfi qırx',), + (-44, 'mənfi qırx dörd',), + (-50, 'mənfi əlli',), + (-55, 'mənfi əlli beş',), + (-60, 'mənfi altmış',), + (-66, 'mənfi altmış altı',), + (-70, 'mənfi yetmiş',), + (-77, 'mənfi yetmiş yeddi',), + (-80, 'mənfi səksən',), + (-88, 'mənfi səksən səkkiz',), + (-90, 'mənfi doxsan',), + (-99, 'mənfi doxsan doqquz',), + (-100, 'mənfi yüz',), + (-200, 'mənfi iki yüz',), + (-678, 'mənfi altı yüz yetmiş səkkiz',), + (-999, 'mənfi doqquz yüz doxsan doqquz',), + (-1000, 'mənfi min',), + (-100_000, 'mənfi yüz min',), + (-328_914, 'mənfi üç yüz iyirmi səkkiz min doqquz yüz on dörd',), + (-1_000_000, 'mənfi bir milyon',), + (-1_000_000_000, 'mənfi bir milyard',), + (-10**12, 'mənfi bir trilyon',), + (-10**15, 'mənfi bir katrilyon',), + (-10**18, 'mənfi bir kentilyon',), + (-10**21, 'mənfi bir sekstilyon',), + (-10**24, 'mənfi bir septilyon',), + (-10**27, 'mənfi bir oktilyon',), + (-10**30, 'mənfi bir nonilyon',), + (-10**33, 'mənfi bir desilyon',), + (-10**36, 'mənfi bir undesilyon',), + (-10**39, 'mənfi bir dodesilyon',), + (-10**42, 'mənfi bir tredesilyon',), + (-10**45, 'mənfi bir katordesilyon',), + (-10**48, 'mənfi bir kendesilyon',), + (-10**51, 'mənfi bir seksdesilyon',), + (-10**54, 'mənfi bir septendesilyon',), + (-10**57, 'mənfi bir oktodesilyon',), + (-10**60, 'mənfi bir novemdesilyon',), + (-10**63, 'mənfi bir vigintilyon'), + ) + + CARDINAL_FRACTION_TEST_CASES = ( + (0.2, 'sıfır nöqtə iki',), + (0.02, 'sıfır nöqtə sıfır iki',), + (0.23, 'sıfır nöqtə iyirmi üç',), + (0.0023, 'sıfır nöqtə sıfır sıfır iyirmi üç',), + (1.43, 'bir nöqtə qırx üç',), + (-0.2, 'mənfi sıfır nöqtə iki',), + (-0.02, 'mənfi sıfır nöqtə sıfır iki',), + (-0.23, 'mənfi sıfır nöqtə iyirmi üç',), + (-0.0023, 'mənfi sıfır nöqtə sıfır sıfır iyirmi üç',), + (-1.43, 'mənfi bir nöqtə qırx üç',), + ) + + ORDINAL_TEST_CASES = ( + (0, 'sıfırıncı',), + (1, 'birinci',), + (2, 'ikinci',), + (3, 'üçüncü',), + (4, 'dördüncü',), + (5, 'beşinci',), + (6, 'altıncı',), + (7, 'yeddinci',), + (8, 'səkkizinci',), + (9, 'doqquzuncu',), + (10, 'onuncu',), + (11, 'on birinci',), + (20, 'iyirminci',), + (22, 'iyirmi ikinci',), + (30, 'otuzuncu',), + (33, 'otuz üçüncü',), + (40, 'qırxıncı',), + (44, 'qırx dördüncü',), + (50, 'əllinci',), + (55, 'əlli beşinci',), + (60, 'altmışıncı',), + (66, 'altmış altıncı',), + (70, 'yetmişinci',), + (77, 'yetmiş yeddinci',), + (80, 'səksəninci',), + (88, 'səksən səkkizinci',), + (90, 'doxsanıncı',), + (99, 'doxsan doqquzuncu',), + (100, 'yüzüncü',), + (1000, 'mininci',), + (328_914, 'üç yüz iyirmi səkkiz min doqquz yüz on dördüncü',), + (1_000_000, 'bir milyonuncu'), + ) + + ORDINAL_NUM_TEST_CASES = ( + (0, '0-cı',), + (1, '1-ci',), + (2, '2-ci',), + (3, '3-cü',), + (4, '4-cü',), + (5, '5-ci',), + (6, '6-cı',), + (7, '7-ci',), + (8, '8-ci',), + (9, '9-cu',), + (10, '10-cu',), + (11, '11-ci',), + (20, '20-ci',), + (22, '22-ci',), + (30, '30-cu',), + (33, '33-cü',), + (40, '40-cı',), + (44, '44-cü',), + (50, '50-ci',), + (55, '55-ci',), + (60, '60-cı',), + (66, '66-cı',), + (70, '70-ci',), + (77, '77-ci',), + (80, '80-ci',), + (88, '88-ci',), + (90, '90-cı',), + (99, '99-cu',), + (100, '100-cü',), + (1000, '1000-ci',), + (328_914, '328914-cü',), + (1_000_000, '1000000-cu'), + ) + + YEAR_TEST_CASES = ( + (167, 'yüz altmış yeddi'), + (1552, 'min beş yüz əlli iki'), + (1881, 'min səkkiz yüz səksən bir'), + (2022, 'iki min iyirmi iki'), + (-1, 'e.ə. bir'), + (-500, 'e.ə. beş yüz'), + (-5000, 'e.ə. beş min'), + ) + + CURRENCY_TEST_CASES = ( + (0.0, 'sıfır manat, sıfır qəpik'), + (0.01, 'sıfır manat, bir qəpik'), + (0.1, 'sıfır manat, on qəpik'), + (1.5, 'bir manat, əlli qəpik'), + (1.94, 'bir manat, doxsan dörd qəpik'), + (17.82, 'on yeddi manat, səksən iki qəpik'), + ) + + def test_cardinal(self): + """Test cardinal conversion for integer numbers.""" + + for number, expected in self.CARDINAL_TEST_CASES: + actual = num2words(number, lang=self.lang, to='cardinal') + + self.assertEqual(actual, expected) + + def test_cardinal_fracion(self): + """Test cardinal conversion for numbers with fraction.""" + + for number, expected in self.CARDINAL_FRACTION_TEST_CASES: + actual = num2words(number, lang=self.lang, to='cardinal') + + self.assertEqual(actual, expected) + + def test_ordinal(self): + """Test ordinal conversion.""" + + for number, expected in self.ORDINAL_TEST_CASES: + actual = num2words(number, lang=self.lang, to='ordinal') + + self.assertEqual(actual, expected) + + def test_ordinal_num(self): + """Test 'ordinal_num' conversion.""" + + for number, expected in self.ORDINAL_NUM_TEST_CASES: + actual = num2words(number, lang=self.lang, to='ordinal_num') + + self.assertEqual(actual, expected) + + def test_year(self): + """Test year conversion.""" + + for number, expected in self.YEAR_TEST_CASES: + actual = num2words(number, lang=self.lang, to='year') + + self.assertEqual(actual, expected) + + def test_currency(self): + """Test currency conversion.""" + + for number, expected in self.CURRENCY_TEST_CASES: + actual = num2words( + number, lang=self.lang, currency='AZN', to='currency') + + self.assertEqual(actual, expected) From be62f3bdfb2c6bf12f4aa0a568f0fe2d4e4d566f Mon Sep 17 00:00:00 2001 From: eyaler Date: Fri, 6 Jan 2023 12:30:04 +0200 Subject: [PATCH 159/200] fix flake8 issues --- num2words/lang_HE.py | 84 ++++++--- tests/test_he.py | 432 ++++++++++++++++++++++++++----------------- 2 files changed, 319 insertions(+), 197 deletions(-) diff --git a/num2words/lang_HE.py b/num2words/lang_HE.py index 947f1c71..fd227889 100644 --- a/num2words/lang_HE.py +++ b/num2words/lang_HE.py @@ -27,19 +27,29 @@ 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'תשיעיים'), + 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'עשיריים'), + 0: (u'עשר', u'עשרה', u'עשר', u'עשרת', + u'עשירית', u'עשירי', u'עשיריות', u'עשיריים'), 1: (u'עשרה', u'עשר'), 2: (u'שתים עשרה', u'שנים עשר'), } @@ -97,7 +107,8 @@ MAXVAL = int('1' + '0'*66) -def chunk2word(n, i, x, gender='f', construct=False, ordinal=False, plural=False): +def chunk2word(n, i, x, gender='f', construct=False, + ordinal=False, plural=False): words = [] n1, n2, n3 = get_digits(x) @@ -125,32 +136,35 @@ def chunk2word(n, i, x, gender='f', construct=False, ordinal=False, plural=False elif n1 > 0: words.append(ONES[n1][male + cop]) - is_last = n % 1000 ** i == 0 + 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 and is_last]) + 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 and is_last]) + words.append(ONES[n1][3] + ' ' + THOUSANDS[3][construct_last]) elif i > 1: if x >= 11: - words[-1] = words[-1] + ' ' + LARGE[i - 1][construct and is_last] + words[-1] = words[-1] + ' ' + LARGE[i - 1][construct_last] elif n1 == 0: - words.append(TENS[0][1 + 2*(construct and is_last)] + ' ' + LARGE[i - 1][construct and is_last]) + 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 and is_last or x == 2)] + ' ' + LARGE[i - 1][construct and is_last]) + 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): +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) @@ -172,9 +186,10 @@ def int2word(n, gender='f', construct=False, ordinal=False, definite=False, plur if x == 0: continue - words += chunk2word(n, i, x, gender=gender, construct=construct, ordinal=ordinal, plural=plural) + words += chunk2word(n, i, x, gender=gender, construct=construct, + ordinal=ordinal, plural=plural) - # source: 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 + # 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] @@ -232,7 +247,8 @@ def to_cardinal(self, value, gender='f', construct=False): try: assert int(value) == value except (ValueError, TypeError, AssertionError): - return self.to_cardinal_float(value, gender=gender) # 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/ + # 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: @@ -250,17 +266,20 @@ def to_ordinal(self, value, gender='m', definite=False, plural=False): if value >= self.MAXVAL: raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL)) - return int2word(int(value), gender=gender, ordinal=True, definite=definite, plural=plural) + 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'): + 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): + 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) try: @@ -277,9 +296,11 @@ def to_currency(self, val, currency='ILS', cents=True, separator=' ' + AND, except KeyError: gender1 = gender2 = '' - money_str = self.to_cardinal(left, gender=gender1, construct=left == 2) + money_str = self.to_cardinal(left, gender=gender1, + construct=left == 2) if cents: - cents_str = self.to_cardinal(right, gender=gender2, construct=right == 2) + cents_str = self.to_cardinal(right, gender=gender2, + construct=right == 2) else: cents_str = self._cents_terse(right, currency) if separator.split()[-1] == AND: @@ -288,16 +309,19 @@ def to_currency(self, val, currency='ILS', cents=True, separator=' ' + AND, strings = [ minus_str, money_str, - self.pluralize(left, cr1, currency=currency, prefer_singular=prefer_singular), + self.pluralize(left, cr1, currency=currency, + prefer_singular=prefer_singular), separator, cents_str, - self.pluralize(right, cr2, currency=currency, prefer_singular=prefer_singular_cents) + 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] - return u'%s%s %s%s%s %s' % tuple(strings) # In Hebrew the separator is along with the following word + # In Hebrew the separator is along with the following word + return u'%s%s %s%s%s %s' % tuple(strings) if __name__ == '__main__': diff --git a/tests/test_he.py b/tests/test_he.py index b1e5dea2..4c0b490c 100644 --- a/tests/test_he.py +++ b/tests/test_he.py @@ -34,25 +34,30 @@ def test_1_to_10(self): self.assertEqual(num2words(2, lang="he"), u'שתיים') self.assertEqual(num2words(7, lang="he"), u'שבע') self.assertEqual(num2words(10, lang="he"), u'עשר') - self.assertEqual(num2words(10, lang="he", gender='m', construct=True), u'עשרת') + self.assertEqual(num2words( + 10, lang="he", gender='m', construct=True), u'עשרת') def test_11_to_19(self): self.assertEqual(num2words(11, lang="he"), u'אחת עשרה') self.assertEqual(num2words(11, lang="he", gender='m'), u'אחד עשר') self.assertEqual(num2words(13, lang="he"), u'שלוש עשרה') - self.assertEqual(num2words(13, lang="he", construct=True), u'שלוש עשרה') + self.assertEqual(num2words( + 13, lang="he", construct=True), u'שלוש עשרה') self.assertEqual(num2words(15, lang="he"), u'חמש עשרה') self.assertEqual(num2words(16, lang="he"), u'שש עשרה') self.assertEqual(num2words(16, lang="he", gender='m'), u'שישה עשר') - self.assertEqual(num2words(16, lang="he", gender='m', construct=True), u'שישה עשר') + self.assertEqual(num2words( + 16, lang="he", gender='m', construct=True), u'שישה עשר') self.assertEqual(num2words(19, lang="he"), u'תשע עשרה') def test_20_to_99(self): self.assertEqual(num2words(20, lang="he"), u'עשרים') self.assertEqual(num2words(23, lang="he"), u'עשרים ושלוש') self.assertEqual(num2words(23, lang="he", gender='m'), u'עשרים ושלושה') - self.assertEqual(num2words(23, lang="he", construct=True), u'עשרים ושלוש') - self.assertEqual(num2words(23, lang="he", gender='m', construct=True), u'עשרים ושלושה') + self.assertEqual(num2words( + 23, lang="he", construct=True), u'עשרים ושלוש') + self.assertEqual(num2words( + 23, lang="he", gender='m', construct=True), u'עשרים ושלושה') self.assertEqual(num2words(28, lang="he"), u'עשרים ושמונה') self.assertEqual(num2words(31, lang="he"), u'שלושים ואחת') self.assertEqual(num2words(40, lang="he"), u'ארבעים') @@ -63,11 +68,14 @@ def test_100_to_999(self): self.assertEqual(num2words(100, lang="he"), u'מאה') self.assertEqual(num2words(100, lang="he", construct=True), u'מאת') self.assertEqual(num2words(111, lang="he"), u'מאה ואחת עשרה') - self.assertEqual(num2words(111, lang="he", construct=True), u'מאה ואחת עשרה') + self.assertEqual(num2words( + 111, lang="he", construct=True), u'מאה ואחת עשרה') self.assertEqual(num2words(150, lang="he"), u'מאה וחמישים') self.assertEqual(num2words(196, lang="he"), u'מאה תשעים ושש') - self.assertEqual(num2words(196, lang="he", gender='m'), u'מאה תשעים ושישה') - self.assertEqual(num2words(196, lang="he", gender='m', construct=True), u'מאה תשעים ושישה') + self.assertEqual(num2words( + 196, lang="he", gender='m'), u'מאה תשעים ושישה') + self.assertEqual(num2words( + 196, lang="he", gender='m', construct=True), u'מאה תשעים ושישה') self.assertEqual(num2words(200, lang="he"), u'מאתיים') self.assertEqual(num2words(200, lang="he", construct=True), u'מאתיים') self.assertEqual(num2words(210, lang="he"), u'מאתיים ועשר') @@ -79,120 +87,185 @@ def test_1000_to_9999(self): self.assertEqual(num2words(1001, lang="he"), u'אלף ואחת') self.assertEqual(num2words(1002, lang="he"), u'אלף ושתיים') self.assertEqual(num2words(1002, lang="he", gender='m'), u'אלף ושניים') - self.assertEqual(num2words(1002, lang="he", gender='m', construct=True), u'אלף ושניים') + self.assertEqual(num2words( + 1002, lang="he", gender='m', construct=True), u'אלף ושניים') self.assertEqual(num2words(1003, lang="he"), u'אלף ושלוש') self.assertEqual(num2words(1003, lang="he", gender='m'), u'אלף ושלושה') - self.assertEqual(num2words(1003, lang="he", gender='m', construct=True), u'אלף ושלושה') + self.assertEqual(num2words( + 1003, lang="he", gender='m', construct=True), u'אלף ושלושה') self.assertEqual(num2words(1010, lang="he"), u'אלף ועשר') self.assertEqual(num2words(1010, lang="he", gender='m'), u'אלף ועשרה') - self.assertEqual(num2words(1010, lang="he", gender='m', construct=True), u'אלף ועשרה') + self.assertEqual(num2words( + 1010, lang="he", gender='m', construct=True), u'אלף ועשרה') self.assertEqual(num2words(1500, lang="he"), u'אלף וחמש מאות') self.assertEqual(num2words(2000, lang="he"), u'אלפיים') self.assertEqual(num2words(2000, lang="he", construct=True), u'אלפיים') self.assertEqual(num2words(2002, lang="he"), u'אלפיים ושתיים') - self.assertEqual(num2words(2002, lang="he", construct=True), u'אלפיים ושתיים') + self.assertEqual(num2words( + 2002, lang="he", construct=True), u'אלפיים ושתיים') self.assertEqual(num2words(3000, lang="he"), u'שלושת אלפים') - self.assertEqual(num2words(3000, lang="he", construct=True), u'שלושת אלפי') + self.assertEqual(num2words( + 3000, lang="he", construct=True), u'שלושת אלפי') self.assertEqual(num2words(3001, lang="he"), u'שלושת אלפים ואחת') - self.assertEqual(num2words(3001, lang="he", construct=True), u'שלושת אלפים ואחת') + self.assertEqual(num2words( + 3001, lang="he", construct=True), u'שלושת אלפים ואחת') self.assertEqual(num2words(3100, lang="he"), u'שלושת אלפים ומאה') - self.assertEqual(num2words(3100, lang="he", construct=True), u'שלושת אלפים ומאה') - self.assertEqual( - num2words(6870, lang="he"), u'ששת אלפים שמונה מאות ושבעים' - ) - self.assertEqual( - num2words(7378, lang="he"), u'שבעת אלפים שלוש מאות שבעים ושמונה' - ) - self.assertEqual( - num2words(9999, lang="he"), u'תשעת אלפים תשע מאות תשעים ותשע' - ) + self.assertEqual(num2words( + 3100, lang="he", construct=True), u'שלושת אלפים ומאה') + self.assertEqual(num2words( + 6870, lang="he"), u'ששת אלפים שמונה מאות ושבעים') + self.assertEqual(num2words( + 7378, lang="he"), u'שבעת אלפים שלוש מאות שבעים ושמונה') + self.assertEqual(num2words( + 9999, lang="he"), u'תשעת אלפים תשע מאות תשעים ותשע') def test_10000_to_99999(self): self.assertEqual(num2words(10000, lang="he"), u'עשרת אלפים') - self.assertEqual(num2words(10000, lang="he", construct=True), u'עשרת אלפי') + self.assertEqual(num2words( + 10000, lang="he", construct=True), u'עשרת אלפי') self.assertEqual(num2words(10001, lang="he"), u'עשרת אלפים ואחת') - self.assertEqual(num2words(10001, lang="he", construct=True), u'עשרת אלפים ואחת') - self.assertEqual(num2words(10999, lang="he"), u'עשרת אלפים תשע מאות תשעים ותשע') + self.assertEqual(num2words( + 10001, lang="he", construct=True), u'עשרת אלפים ואחת') + self.assertEqual(num2words( + 10999, lang="he"), u'עשרת אלפים תשע מאות תשעים ותשע') self.assertEqual(num2words(11000, lang="he"), u'אחד עשר אלף') self.assertEqual(num2words(15000, lang="he"), u'חמישה עשר אלף') - self.assertEqual(num2words(15000, lang="he", gender='m'), u'חמישה עשר אלף') + self.assertEqual(num2words( + 15000, lang="he", gender='m'), u'חמישה עשר אלף') self.assertEqual(num2words(20000, lang="he"), u'עשרים אלף') - self.assertEqual(num2words(20000, lang="he", construct=True), u'עשרים אלף') + self.assertEqual(num2words( + 20000, lang="he", construct=True), u'עשרים אלף') self.assertEqual(num2words(21000, lang="he"), u'עשרים ואחד אלף') self.assertEqual(num2words(25000, lang="he"), u'עשרים וחמישה אלף') - self.assertEqual(num2words(25000, lang="he", construct=True), u'עשרים וחמישה אלף') - self.assertEqual(num2words(68700, lang="he"), u'שישים ושמונה אלף ושבע מאות') - self.assertEqual(num2words(73781, lang="he"), u'שבעים ושלושה אלף שבע מאות שמונים ואחת') - self.assertEqual(num2words(99999, lang="he"), u'תשעים ותשעה אלף תשע מאות תשעים ותשע') + self.assertEqual(num2words( + 25000, lang="he", construct=True), u'עשרים וחמישה אלף') + self.assertEqual(num2words( + 68700, lang="he"), u'שישים ושמונה אלף ושבע מאות') + self.assertEqual(num2words( + 73781, lang="he"), u'שבעים ושלושה אלף שבע מאות שמונים ואחת') + self.assertEqual(num2words( + 99999, lang="he"), u'תשעים ותשעה אלף תשע מאות תשעים ותשע') def test_100000_to_999999(self): self.assertEqual(num2words(100000, lang="he"), u'מאה אלף') - self.assertEqual(num2words(100000, lang="he", construct=True), u'מאה אלף') + self.assertEqual(num2words( + 100000, lang="he", construct=True), u'מאה אלף') self.assertEqual(num2words(100001, lang="he"), u'מאה אלף ואחת') - self.assertEqual(num2words(199999, lang="he"), u'מאה תשעים ותשעה אלף תשע מאות תשעים ותשע') + self.assertEqual(num2words( + 199999, lang="he"), u'מאה תשעים ותשעה אלף תשע מאות תשעים ותשע') self.assertEqual(num2words(110000, lang="he"), u'מאה ועשרה אלף') self.assertEqual(num2words(150000, lang="he"), u'מאה וחמישים אלף') self.assertEqual(num2words(200000, lang="he"), u'מאתיים אלף') self.assertEqual(num2words(210000, lang="he"), u'מאתיים ועשרה אלף') - self.assertEqual(num2words(687000, lang="he"), u'שש מאות שמונים ושבעה אלף') - self.assertEqual(num2words(687000, lang="he", construct=True), u'שש מאות שמונים ושבעה אלף') - self.assertEqual(num2words(737812, lang="he"), u'שבע מאות שלושים ושבעה אלף שמונה מאות ושתים עשרה') - self.assertEqual(num2words(999999, lang="he"), u'תשע מאות תשעים ותשעה אלף תשע מאות תשעים ותשע') + self.assertEqual(num2words( + 687000, lang="he"), u'שש מאות שמונים ושבעה אלף') + self.assertEqual(num2words( + 687000, lang="he", construct=True), u'שש מאות שמונים ושבעה אלף') + self.assertEqual(num2words(737812, lang="he"), + u'שבע מאות שלושים ושבעה אלף שמונה מאות ושתים עשרה') + self.assertEqual(num2words(999999, lang="he"), + u'תשע מאות תשעים ותשעה אלף תשע מאות תשעים ותשע') def test_1000000_to_999999999999999(self): self.assertEqual(num2words(1000000, lang="he"), u'מיליון') - self.assertEqual(num2words(1000000, lang="he", construct=True), u'מיליון') + self.assertEqual(num2words( + 1000000, lang="he", construct=True), u'מיליון') self.assertEqual(num2words(1000002, lang="he"), u'מיליון ושתיים') - self.assertEqual(num2words(1000002, lang="he", construct=True), u'מיליון ושתיים') + self.assertEqual(num2words( + 1000002, lang="he", construct=True), u'מיליון ושתיים') self.assertEqual(num2words(2000000, lang="he"), u'שני מיליון') - self.assertEqual(num2words(2000000, lang="he", construct=True), u'שני מיליוני') + self.assertEqual(num2words( + 2000000, lang="he", construct=True), u'שני מיליוני') self.assertEqual(num2words(3000000, lang="he"), u'שלושה מיליון') - self.assertEqual(num2words(3000000, lang="he", construct=True), u'שלושת מיליוני') + self.assertEqual(num2words( + 3000000, lang="he", construct=True), u'שלושת מיליוני') self.assertEqual(num2words(3000002, lang="he"), u'שלושה מיליון ושתיים') - self.assertEqual(num2words(3000002, lang="he", construct=True), u'שלושה מיליון ושתיים') + self.assertEqual(num2words( + 3000002, lang="he", construct=True), u'שלושה מיליון ושתיים') self.assertEqual(num2words(10000000, lang="he"), u'עשרה מיליון') - self.assertEqual(num2words(10000000, lang="he", construct=True), 'עשרת מיליוני') + self.assertEqual(num2words( + 10000000, lang="he", construct=True), 'עשרת מיליוני') self.assertEqual(num2words(11000000, lang="he"), u'אחד עשר מיליון') - self.assertEqual(num2words(11000000, lang="he", construct=True), 'אחד עשר מיליוני') + self.assertEqual(num2words( + 11000000, lang="he", construct=True), 'אחד עשר מיליוני') self.assertEqual(num2words(1000000000, lang="he"), u'מיליארד') - self.assertEqual(num2words(1000000000, lang="he", construct=True), u'מיליארד') + self.assertEqual(num2words( + 1000000000, lang="he", construct=True), u'מיליארד') self.assertEqual(num2words(1000000002, lang="he"), u'מיליארד ושתיים') - self.assertEqual(num2words(1000000002, lang="he", construct=True), u'מיליארד ושתיים') + self.assertEqual(num2words( + 1000000002, lang="he", construct=True), u'מיליארד ושתיים') self.assertEqual(num2words(2000000000, lang="he"), u'שני מיליארד') - self.assertEqual(num2words(2000000000, lang="he", construct=True), u'שני מיליארדי') + self.assertEqual(num2words( + 2000000000, lang="he", construct=True), u'שני מיליארדי') self.assertEqual(num2words(3000000000, lang="he"), u'שלושה מיליארד') - self.assertEqual(num2words(3000000000, lang="he", construct=True), u'שלושת מיליארדי') - self.assertEqual(num2words(3000000002, lang="he"), u'שלושה מיליארד ושתיים') - self.assertEqual(num2words(3000000002, lang="he", construct=True), u'שלושה מיליארד ושתיים') + self.assertEqual(num2words( + 3000000000, lang="he", construct=True), u'שלושת מיליארדי') + self.assertEqual(num2words( + 3000000002, lang="he"), u'שלושה מיליארד ושתיים') + self.assertEqual(num2words( + 3000000002, lang="he", construct=True), u'שלושה מיליארד ושתיים') self.assertEqual(num2words(10000000000, lang="he"), u'עשרה מיליארד') - self.assertEqual(num2words(10000000000, lang="he", construct=True), 'עשרת מיליארדי') - self.assertEqual(num2words(10000000002, lang="he"), u'עשרה מיליארד ושתיים') - self.assertEqual(num2words(10000000002, lang="he", construct=True), 'עשרה מיליארד ושתיים') + self.assertEqual(num2words( + 10000000000, lang="he", construct=True), 'עשרת מיליארדי') + self.assertEqual(num2words( + 10000000002, lang="he"), u'עשרה מיליארד ושתיים') + self.assertEqual(num2words( + 10000000002, lang="he", construct=True), 'עשרה מיליארד ושתיים') self.assertEqual(num2words(11000000000, lang="he"), u'אחד עשר מיליארד') - self.assertEqual(num2words(11000000000, lang="he", construct=True), 'אחד עשר מיליארדי') + self.assertEqual(num2words( + 11000000000, lang="he", construct=True), 'אחד עשר מיליארדי') self.assertEqual(num2words(1000000000000, lang="he"), u'טריליון') - self.assertEqual(num2words(1000000000000, lang="he", construct=True), u'טריליון') - self.assertEqual(num2words(1000000000002, lang="he"), u'טריליון ושתיים') - self.assertEqual(num2words(1000000000002, lang="he", construct=True), u'טריליון ושתיים') + self.assertEqual(num2words( + 1000000000000, lang="he", construct=True), u'טריליון') + self.assertEqual(num2words( + 1000000000002, lang="he"), u'טריליון ושתיים') + self.assertEqual(num2words( + 1000000000002, lang="he", construct=True), u'טריליון ושתיים') self.assertEqual(num2words(2000000000000, lang="he"), u'שני טריליון') - self.assertEqual(num2words(2000000000000, lang="he", construct=True), u'שני טריליוני') + self.assertEqual(num2words( + 2000000000000, lang="he", construct=True), u'שני טריליוני') self.assertEqual(num2words(3000000000000, lang="he"), u'שלושה טריליון') - self.assertEqual(num2words(3000000000000, lang="he", construct=True), u'שלושת טריליוני') - self.assertEqual(num2words(3000000000002, lang="he"), u'שלושה טריליון ושתיים') - self.assertEqual(num2words(3000000000002, lang="he", construct=True), u'שלושה טריליון ושתיים') + self.assertEqual(num2words( + 3000000000000, lang="he", construct=True), u'שלושת טריליוני') + self.assertEqual(num2words( + 3000000000002, lang="he"), u'שלושה טריליון ושתיים') + self.assertEqual(num2words( + 3000000000002, lang="he", construct=True), u'שלושה טריליון ושתיים') self.assertEqual(num2words(10000000000000, lang="he"), u'עשרה טריליון') - self.assertEqual(num2words(10000000000000, lang="he", construct=True), 'עשרת טריליוני') - self.assertEqual(num2words(10000000000002, lang="he"), u'עשרה טריליון ושתיים') - self.assertEqual(num2words(10000000000002, lang="he", construct=True), 'עשרה טריליון ושתיים') - self.assertEqual(num2words(11000000000000, lang="he"), u'אחד עשר טריליון') - self.assertEqual(num2words(11000000000000, lang="he", construct=True), 'אחד עשר טריליוני') + self.assertEqual(num2words( + 10000000000000, lang="he", construct=True), 'עשרת טריליוני') + self.assertEqual(num2words( + 10000000000002, lang="he"), u'עשרה טריליון ושתיים') + self.assertEqual(num2words( + 10000000000002, lang="he", construct=True), 'עשרה טריליון ושתיים') + self.assertEqual(num2words( + 11000000000000, lang="he"), u'אחד עשר טריליון') + self.assertEqual(num2words( + 11000000000000, lang="he", construct=True), 'אחד עשר טריליוני') - self.assertEqual(num2words(999999999999999, lang="he"), u'תשע מאות תשעים ותשעה טריליון תשע מאות תשעים ותשעה מיליארד תשע מאות תשעים ותשעה מיליון תשע מאות תשעים ותשעה אלף תשע מאות תשעים ותשע') - self.assertEqual(num2words(999999999999999, lang="he", gender='m'), u'תשע מאות תשעים ותשעה טריליון תשע מאות תשעים ותשעה מיליארד תשע מאות תשעים ותשעה מיליון תשע מאות תשעים ותשעה אלף תשע מאות תשעים ותשעה') - self.assertEqual(num2words(999999999999999, lang="he", construct=True), u'תשע מאות תשעים ותשעה טריליון תשע מאות תשעים ותשעה מיליארד תשע מאות תשעים ותשעה מיליון תשע מאות תשעים ותשעה אלף תשע מאות תשעים ותשע') - self.assertEqual(num2words(999999999999999, lang="he", gender='m', construct=True), u'תשע מאות תשעים ותשעה טריליון תשע מאות תשעים ותשעה מיליארד תשע מאות תשעים ותשעה מיליון תשע מאות תשעים ותשעה אלף תשע מאות תשעים ותשעה') + self.assertEqual(num2words(999999999999999, lang="he"), + u'תשע מאות תשעים ותשעה טריליון ' + u'תשע מאות תשעים ותשעה מיליארד ' + u'תשע מאות תשעים ותשעה מיליון ' + u'תשע מאות תשעים ותשעה אלף תשע מאות תשעים ותשע') + self.assertEqual(num2words(999999999999999, lang="he", gender='m'), + u'תשע מאות תשעים ותשעה טריליון ' + u'תשע מאות תשעים ותשעה מיליארד ' + u'תשע מאות תשעים ותשעה מיליון ' + u'תשע מאות תשעים ותשעה אלף תשע מאות תשעים ותשעה') + self.assertEqual(num2words(999999999999999, lang="he", construct=True), + u'תשע מאות תשעים ותשעה טריליון ' + u'תשע מאות תשעים ותשעה מיליארד ' + u'תשע מאות תשעים ותשעה מיליון ' + u'תשע מאות תשעים ותשעה אלף תשע מאות תשעים ותשע') + self.assertEqual(num2words( + 999999999999999, lang="he", gender='m', construct=True), + u'תשע מאות תשעים ותשעה טריליון ' + u'תשע מאות תשעים ותשעה מיליארד ' + u'תשע מאות תשעים ותשעה מיליון ' + u'תשע מאות תשעים ותשעה אלף תשע מאות תשעים ותשעה') def test_pluralize(self): n = Num2Word_HE() @@ -210,66 +283,57 @@ def test_pluralize(self): def test_to_currency(self): n = Num2Word_HE() - self.assertEqual( - n.to_currency(20.0, currency='ILS'), u'עשרים שקלים ואפס אגורות' - ) - self.assertEqual( - n.to_currency(100.0, currency='ILS'), u'מאה שקלים ואפס אגורות' - ) - self.assertEqual( - n.to_currency(100.50, currency='ILS'), u'מאה שקלים וחמישים אגורות' - ) - self.assertEqual( - n.to_currency(101.51, currency='ILS'), u'מאה ואחד שקלים וחמישים ואחת אגורות' - ) - self.assertEqual( - n.to_currency(-101.51, currency='ILS'), u'מינוס מאה ואחד שקלים וחמישים ואחת אגורות' - ) - self.assertEqual( - n.to_currency(-101.51, currency='ILS', prefer_singular=True), u'מינוס מאה ואחד שקל וחמישים ואחת אגורות' - ) - self.assertEqual( - n.to_currency(-101.51, currency='ILS', prefer_singular_cents=True), u'מינוס מאה ואחד שקלים וחמישים ואחת אגורה' - ) - self.assertEqual( - n.to_currency(-101.51, currency='ILS', prefer_singular=True, prefer_singular_cents=True), u'מינוס מאה ואחד שקל וחמישים ואחת אגורה' - ) - self.assertEqual( - n.to_currency(5.05, currency='ILS', prefer_singular=True, prefer_singular_cents=True), u'חמישה שקלים וחמש אגורות' - ) - self.assertEqual( - n.to_currency(-5.05, currency='ILS', prefer_singular=True, prefer_singular_cents=True), u'מינוס חמישה שקלים וחמש אגורות' - ) - self.assertEqual( - n.to_currency(-5.05, currency='ILS', cents=False), u'מינוס חמישה שקלים ו-05 אגורות' - ) - self.assertEqual( - n.to_currency(1.01, currency='ILS'), u'שקל אחד ואגורה אחת' - ) - self.assertEqual( - n.to_currency(-1.01, currency='ILS'), u'מינוס שקל אחד ואגורה אחת' - ) - self.assertEqual( - n.to_currency(2.02, currency='ILS'), u'שני שקלים ושתי אגורות' - ) - self.assertEqual( - n.to_currency(1002.02, currency='ILS'), u'אלף ושניים שקלים ושתי אגורות' - ) - self.assertEqual( - n.to_currency(1000002.02, currency='ILS'), u'מיליון ושניים שקלים ושתי אגורות' - ) - self.assertEqual( - n.to_currency(5.05, currency='USD'), u'חמישה דולרים וחמישה סנטים' - ) - self.assertEqual( - n.to_currency(5.05, currency='USD', prefer_singular=True), u'חמישה דולר וחמישה סנטים' - ) - self.assertEqual( - n.to_currency(5.05, currency='USD', prefer_singular_cents=True), u'חמישה דולרים וחמישה סנט' - ) - self.assertEqual( - n.to_currency(5.05, currency='USD', prefer_singular=True, prefer_singular_cents=True), u'חמישה דולר וחמישה סנט' - ) + self.assertEqual(n.to_currency( + 20.0, currency='ILS'), u'עשרים שקלים ואפס אגורות') + self.assertEqual(n.to_currency( + 100.0, currency='ILS'), u'מאה שקלים ואפס אגורות') + self.assertEqual(n.to_currency( + 100.50, currency='ILS'), u'מאה שקלים וחמישים אגורות') + self.assertEqual(n.to_currency( + 101.51, currency='ILS'), u'מאה ואחד שקלים וחמישים ואחת אגורות') + self.assertEqual(n.to_currency( + -101.51, currency='ILS'), + u'מינוס מאה ואחד שקלים וחמישים ואחת אגורות') + self.assertEqual(n.to_currency( + -101.51, currency='ILS', prefer_singular=True), + u'מינוס מאה ואחד שקל וחמישים ואחת אגורות') + self.assertEqual(n.to_currency( + -101.51, currency='ILS', prefer_singular_cents=True), + u'מינוס מאה ואחד שקלים וחמישים ואחת אגורה') + self.assertEqual(n.to_currency( + -101.51, currency='ILS', prefer_singular=True, + prefer_singular_cents=True), + u'מינוס מאה ואחד שקל וחמישים ואחת אגורה') + self.assertEqual(n.to_currency( + 5.05, currency='ILS', prefer_singular=True, + prefer_singular_cents=True), u'חמישה שקלים וחמש אגורות') + self.assertEqual(n.to_currency( + -5.05, currency='ILS', prefer_singular=True, + prefer_singular_cents=True), u'מינוס חמישה שקלים וחמש אגורות') + self.assertEqual(n.to_currency( + -5.05, currency='ILS', cents=False), + u'מינוס חמישה שקלים ו-05 אגורות') + self.assertEqual(n.to_currency( + 1.01, currency='ILS'), u'שקל אחד ואגורה אחת') + self.assertEqual(n.to_currency( + -1.01, currency='ILS'), u'מינוס שקל אחד ואגורה אחת') + self.assertEqual(n.to_currency( + 2.02, currency='ILS'), u'שני שקלים ושתי אגורות') + self.assertEqual(n.to_currency( + 1002.02, currency='ILS'), u'אלף ושניים שקלים ושתי אגורות') + self.assertEqual(n.to_currency( + 1000002.02, currency='ILS'), u'מיליון ושניים שקלים ושתי אגורות') + self.assertEqual(n.to_currency( + 5.05, currency='USD'), u'חמישה דולרים וחמישה סנטים') + self.assertEqual(n.to_currency( + 5.05, currency='USD', prefer_singular=True), + u'חמישה דולר וחמישה סנטים') + self.assertEqual(n.to_currency( + 5.05, currency='USD', prefer_singular_cents=True), + u'חמישה דולרים וחמישה סנט') + self.assertEqual(n.to_currency( + 5.05, currency='USD', prefer_singular=True, + prefer_singular_cents=True), u'חמישה דולר וחמישה סנט') def test_to_cardinal(self): n = Num2Word_HE() @@ -283,70 +347,104 @@ def test_to_ordinal(self): self.assertEqual(n.to_ordinal(1001), u'האלף ואחד') self.assertEqual(n.to_ordinal(1500), u'האלף וחמש מאות') self.assertEqual(n.to_ordinal(1501), u'האלף חמש מאות ואחד') - self.assertEqual(n.to_ordinal(1501, definite=True), u'האלף חמש מאות ואחד') + self.assertEqual(n.to_ordinal( + 1501, definite=True), u'האלף חמש מאות ואחד') self.assertEqual(n.to_ordinal(1), u'ראשון') self.assertEqual(n.to_ordinal(1, definite=True), u'הראשון') self.assertEqual(n.to_ordinal(1, gender='f'), u'ראשונה') - self.assertEqual(n.to_ordinal(1, gender='f', definite=True), u'הראשונה') + self.assertEqual(n.to_ordinal( + 1, gender='f', definite=True), u'הראשונה') self.assertEqual(n.to_ordinal(10), u'עשירי') self.assertEqual(n.to_ordinal(10, definite=True), u'העשירי') self.assertEqual(n.to_ordinal(10, gender='f'), u'עשירית') - self.assertEqual(n.to_ordinal(10, gender='f', definite=True), u'העשירית') + self.assertEqual(n.to_ordinal( + 10, gender='f', definite=True), u'העשירית') self.assertEqual(n.to_ordinal(17), u'השבעה עשר') self.assertEqual(n.to_ordinal(17, definite=True), u'השבעה עשר') self.assertEqual(n.to_ordinal(17, gender='f'), u'השבע עשרה') - self.assertEqual(n.to_ordinal(17, gender='f', definite=True), u'השבע עשרה') + self.assertEqual(n.to_ordinal( + 17, gender='f', definite=True), u'השבע עשרה') self.assertEqual(n.to_ordinal(0), u'האפס') self.assertEqual(n.to_ordinal(0, definite=True), u'האפס') self.assertEqual(n.to_ordinal(0, gender='f'), u'האפס') self.assertEqual(n.to_ordinal(0, gender='f', definite=True), u'האפס') - self.assertEqual(n.to_ordinal(999999), u'התשע מאות תשעים ותשעה אלף תשע מאות תשעים ותשעה') - self.assertEqual(n.to_ordinal(999999, gender='f'), u'התשע מאות תשעים ותשעה אלף תשע מאות תשעים ותשע') + self.assertEqual(n.to_ordinal( + 999999), u'התשע מאות תשעים ותשעה אלף תשע מאות תשעים ותשעה') + self.assertEqual(n.to_ordinal( + 999999, gender='f'), + u'התשע מאות תשעים ותשעה אלף תשע מאות תשעים ותשע') self.assertEqual(num2words(1, ordinal=True, lang='he'), u'ראשון') - self.assertEqual(num2words(1, ordinal=True, lang='he', gender='f'), u'ראשונה') - self.assertEqual(num2words(1, ordinal=True, lang='he', definite=True), u'הראשון') - self.assertEqual(num2words(1, ordinal=True, lang='he', gender='f', definite=True), u'הראשונה') + self.assertEqual(num2words( + 1, ordinal=True, lang='he', gender='f'), u'ראשונה') + self.assertEqual(num2words( + 1, ordinal=True, lang='he', definite=True), u'הראשון') + self.assertEqual(num2words( + 1, ordinal=True, lang='he', gender='f', definite=True), u'הראשונה') def test_to_ordinal_plural(self): n = Num2Word_HE() self.assertEqual(n.to_ordinal(1001, plural=True), u'האלף ואחד') self.assertEqual(n.to_ordinal(1500, plural=True), u'האלף וחמש מאות') - self.assertEqual(n.to_ordinal(1501, plural=True), u'האלף חמש מאות ואחד') - self.assertEqual(n.to_ordinal(1501, definite=True, plural=True), u'האלף חמש מאות ואחד') + self.assertEqual(n.to_ordinal( + 1501, plural=True), u'האלף חמש מאות ואחד') + self.assertEqual(n.to_ordinal( + 1501, definite=True, plural=True), u'האלף חמש מאות ואחד') self.assertEqual(n.to_ordinal(1, plural=True), u'ראשונים') - self.assertEqual(n.to_ordinal(1, definite=True, plural=True), u'הראשונים') + self.assertEqual(n.to_ordinal( + 1, definite=True, plural=True), u'הראשונים') self.assertEqual(n.to_ordinal(1, gender='f', plural=True), u'ראשונות') - self.assertEqual(n.to_ordinal(1, gender='f', definite=True, plural=True), u'הראשונות') + self.assertEqual(n.to_ordinal( + 1, gender='f', definite=True, plural=True), u'הראשונות') self.assertEqual(n.to_ordinal(10, plural=True), u'עשיריים') - self.assertEqual(n.to_ordinal(10, definite=True, plural=True), u'העשיריים') - self.assertEqual(n.to_ordinal(10, gender='f', plural=True), u'עשיריות') - self.assertEqual(n.to_ordinal(10, gender='f', definite=True, plural=True), u'העשיריות') + self.assertEqual(n.to_ordinal( + 10, definite=True, plural=True), u'העשיריים') + self.assertEqual(n.to_ordinal( + 10, gender='f', plural=True), u'עשיריות') + self.assertEqual(n.to_ordinal( + 10, gender='f', definite=True, plural=True), u'העשיריות') self.assertEqual(n.to_ordinal(17, plural=True), u'השבעה עשר') - self.assertEqual(n.to_ordinal(17, definite=True, plural=True), u'השבעה עשר') - self.assertEqual(n.to_ordinal(17, gender='f', plural=True), u'השבע עשרה') - self.assertEqual(n.to_ordinal(17, gender='f', definite=True, plural=True), u'השבע עשרה') + self.assertEqual(n.to_ordinal( + 17, definite=True, plural=True), u'השבעה עשר') + self.assertEqual(n.to_ordinal( + 17, gender='f', plural=True), u'השבע עשרה') + self.assertEqual(n.to_ordinal( + 17, gender='f', definite=True, plural=True), u'השבע עשרה') self.assertEqual(n.to_ordinal(0, plural=True), u'האפס') self.assertEqual(n.to_ordinal(0, definite=True, plural=True), u'האפס') self.assertEqual(n.to_ordinal(0, gender='f', plural=True), u'האפס') - self.assertEqual(n.to_ordinal(0, gender='f', definite=True, plural=True), u'האפס') - self.assertEqual(n.to_ordinal(999999, plural=True), u'התשע מאות תשעים ותשעה אלף תשע מאות תשעים ותשעה') - self.assertEqual(n.to_ordinal(999999, gender='f', plural=True), u'התשע מאות תשעים ותשעה אלף תשע מאות תשעים ותשע') - self.assertEqual(num2words(1, ordinal=True, lang='he', plural=True), u'ראשונים') - self.assertEqual(num2words(1, ordinal=True, lang='he', gender='f', plural=True), u'ראשונות') - self.assertEqual(num2words(1, ordinal=True, lang='he', definite=True, plural=True), u'הראשונים') - self.assertEqual(num2words(1, ordinal=True, lang='he', gender='f', definite=True, plural=True), u'הראשונות') - + self.assertEqual(n.to_ordinal( + 0, gender='f', definite=True, plural=True), u'האפס') + self.assertEqual(n.to_ordinal(999999, plural=True), + u'התשע מאות תשעים ותשעה אלף תשע מאות תשעים ותשעה') + self.assertEqual(n.to_ordinal(999999, gender='f', plural=True), + u'התשע מאות תשעים ותשעה אלף תשע מאות תשעים ותשע') + self.assertEqual(num2words( + 1, ordinal=True, lang='he', plural=True), u'ראשונים') + self.assertEqual(num2words( + 1, ordinal=True, lang='he', gender='f', plural=True), u'ראשונות') + self.assertEqual(num2words(1, ordinal=True, lang='he', + definite=True, plural=True), u'הראשונים') + self.assertEqual(num2words(1, ordinal=True, lang='he', gender='f', + definite=True, plural=True), u'הראשונות') def test_cardinal_for_float_number(self): self.assertEqual(num2words(12.5, lang='he'), u'שתים עשרה נקודה חמש') - self.assertEqual(num2words(12.51, lang='he'), u'שתים עשרה נקודה חמש אחת') - self.assertEqual(num2words(12.53, lang='he'), u'שתים עשרה נקודה חמש שלוש') - self.assertEqual(num2words(12.59, lang='he'), u'שתים עשרה נקודה חמש תשע') - self.assertEqual(num2words(12.5, lang='he', gender='m'), u'שנים עשר נקודה חמש') - self.assertEqual(num2words(12.51, lang='he', gender='m'), u'שנים עשר נקודה חמש אחת') - self.assertEqual(num2words(12.53, lang='he', gender='m'), u'שנים עשר נקודה חמש שלוש') - self.assertEqual(num2words(12.59, lang='he', gender='m'), u'שנים עשר נקודה חמש תשע') - self.assertEqual(num2words(12.594132, lang='he', gender='m'), u'שנים עשר נקודה חמש תשע ארבע אחת שלוש שתיים') + self.assertEqual(num2words( + 12.51, lang='he'), u'שתים עשרה נקודה חמש אחת') + self.assertEqual(num2words( + 12.53, lang='he'), u'שתים עשרה נקודה חמש שלוש') + self.assertEqual(num2words( + 12.59, lang='he'), u'שתים עשרה נקודה חמש תשע') + self.assertEqual(num2words( + 12.5, lang='he', gender='m'), u'שנים עשר נקודה חמש') + self.assertEqual(num2words( + 12.51, lang='he', gender='m'), u'שנים עשר נקודה חמש אחת') + self.assertEqual(num2words( + 12.53, lang='he', gender='m'), u'שנים עשר נקודה חמש שלוש') + self.assertEqual(num2words( + 12.59, lang='he', gender='m'), u'שנים עשר נקודה חמש תשע') + self.assertEqual(num2words(12.594132, lang='he', gender='m'), + u'שנים עשר נקודה חמש תשע ארבע אחת שלוש שתיים') def test_overflow(self): n = Num2Word_HE() From 30aae7390244fbe349a98a36fa3cabf977141aa0 Mon Sep 17 00:00:00 2001 From: eyaler Date: Fri, 6 Jan 2023 12:55:37 +0200 Subject: [PATCH 160/200] fix typo + try to fix isort issue --- bin/num2words | 95 -------------------------------------------- num2words/lang_HE.py | 1 - tests/test_cli.py | 2 +- 3 files changed, 1 insertion(+), 97 deletions(-) delete mode 100755 bin/num2words diff --git a/bin/num2words b/bin/num2words deleted file mode 100755 index 06ff0443..00000000 --- a/bin/num2words +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/env python -# -*- 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 - -"""num2words: convert numbers into words. - -Usage: - num2words [options] - num2words --list-languages - num2words --list-converters - num2words --help - -Arguments: - Number you want to convert into words - -Options: - -L --list-languages Show all languages. - -C --list-converters Show all converters. - -l --lang= Output language [default: en]. - -t --to= Output converter [default: cardinal]. - -h --help Show this message. - -v --version Show version. - -Examples: - $ num2words 10001 - ten thousand and one - - $ num2words 24,120.10 - twenty-four thousand, one hundred and twenty point one - - $ num2words 24,120.10 -l es - veinticuatro mil ciento veinte punto uno - - $num2words 2.14 -l es --to currency - dos euros con catorce céntimos -""" - -from __future__ import print_function, unicode_literals -import os -import sys -from docopt import docopt -import num2words - -__version__ = "0.5.12" -__license__ = "LGPL" - - -def get_languages(): - return sorted(list(num2words.CONVERTER_CLASSES.keys())) - - -def get_converters(): - return sorted(list(num2words.CONVERTES_TYPES)) - - -def main(): - version = "{}=={}".format(os.path.basename(__file__), __version__) - args = docopt(__doc__, argv=None, help=True, version=version, options_first=False) - if args["--list-languages"]: - for lang in get_languages(): - sys.stdout.write(lang) - sys.stdout.write(os.linesep) - sys.exit(0) - if args["--list-converters"]: - for cvt in get_converters(): - sys.stdout.write(cvt) - sys.stdout.write(os.linesep) - sys.exit(0) - try: - words = num2words.num2words(args[''], lang=args['--lang'], to=args['--to']) - sys.stdout.write(words + os.linesep) - sys.exit(0) - except Exception as err: - sys.stderr.write(str(args[''])) - sys.stderr.write(str(err) + os.linesep) - sys.stderr.write(__doc__) - sys.exit(1) - - -if __name__ == '__main__': - main() diff --git a/num2words/lang_HE.py b/num2words/lang_HE.py index fd227889..b114fb46 100644 --- a/num2words/lang_HE.py +++ b/num2words/lang_HE.py @@ -23,7 +23,6 @@ from .currency import parse_currency_parts from .utils import get_digits, splitbyx - ZERO = (u'אפס',) ONES = { diff --git a/tests/test_cli.py b/tests/test_cli.py index 79610cb7..f4b9b4bb 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -54,7 +54,7 @@ def test_cli_help(self): self.assertTrue(output.err.startswith('Usage:')) def test_cli_list_langs(self): - """You should be able to list all availabe languages + """You should be able to list all available languages """ output = self.cli.run_cmd('--list-languages') self.assertEqual( From 7c2fc26dd33d9dc69ad4e929f9b5ae6362cb62e9 Mon Sep 17 00:00:00 2001 From: eyaler Date: Fri, 6 Jan 2023 13:18:28 +0200 Subject: [PATCH 161/200] resrtored bin deleted accidently. tox passes (py3.10) --- bin/num2words | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100755 bin/num2words diff --git a/bin/num2words b/bin/num2words new file mode 100755 index 00000000..06ff0443 --- /dev/null +++ b/bin/num2words @@ -0,0 +1,95 @@ +#!/usr/bin/env python +# -*- 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 + +"""num2words: convert numbers into words. + +Usage: + num2words [options] + num2words --list-languages + num2words --list-converters + num2words --help + +Arguments: + Number you want to convert into words + +Options: + -L --list-languages Show all languages. + -C --list-converters Show all converters. + -l --lang= Output language [default: en]. + -t --to= Output converter [default: cardinal]. + -h --help Show this message. + -v --version Show version. + +Examples: + $ num2words 10001 + ten thousand and one + + $ num2words 24,120.10 + twenty-four thousand, one hundred and twenty point one + + $ num2words 24,120.10 -l es + veinticuatro mil ciento veinte punto uno + + $num2words 2.14 -l es --to currency + dos euros con catorce céntimos +""" + +from __future__ import print_function, unicode_literals +import os +import sys +from docopt import docopt +import num2words + +__version__ = "0.5.12" +__license__ = "LGPL" + + +def get_languages(): + return sorted(list(num2words.CONVERTER_CLASSES.keys())) + + +def get_converters(): + return sorted(list(num2words.CONVERTES_TYPES)) + + +def main(): + version = "{}=={}".format(os.path.basename(__file__), __version__) + args = docopt(__doc__, argv=None, help=True, version=version, options_first=False) + if args["--list-languages"]: + for lang in get_languages(): + sys.stdout.write(lang) + sys.stdout.write(os.linesep) + sys.exit(0) + if args["--list-converters"]: + for cvt in get_converters(): + sys.stdout.write(cvt) + sys.stdout.write(os.linesep) + sys.exit(0) + try: + words = num2words.num2words(args[''], lang=args['--lang'], to=args['--to']) + sys.stdout.write(words + os.linesep) + sys.exit(0) + except Exception as err: + sys.stderr.write(str(args[''])) + sys.stderr.write(str(err) + os.linesep) + sys.stderr.write(__doc__) + sys.exit(1) + + +if __name__ == '__main__': + main() From 3404faae4ae446bd4a5a15b443b9037d5837a659 Mon Sep 17 00:00:00 2001 From: Marlon Rodriguez Garcia <47992153+mrodriguezg1991@users.noreply.github.com> Date: Fri, 13 Jan 2023 10:20:59 -0500 Subject: [PATCH 162/200] Update __init__.py --- num2words/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/num2words/__init__.py b/num2words/__init__.py index 3a910a9c..0e6b89cf 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -17,7 +17,6 @@ from __future__ import unicode_literals - from . import (lang_AM, lang_AR, lang_AZ, lang_CZ, lang_DE, lang_DK, lang_EN, lang_EN_IN, lang_EO, lang_ES, lang_ES_CO, lang_ES_NI, lang_ES_VE, lang_FA, lang_FI, lang_FR, lang_FR_BE, lang_FR_CH, From a47c485bb7c6d73ac703f269effcef13f6028c47 Mon Sep 17 00:00:00 2001 From: eyaler Date: Fri, 20 Jan 2023 17:34:11 +0200 Subject: [PATCH 163/200] improved coverage, improved custom currency seperator, fixed silent failure in base test --- num2words/lang_HE.py | 15 ++++++------- tests/test_base.py | 5 ++--- tests/test_he.py | 51 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 58 insertions(+), 13 deletions(-) diff --git a/num2words/lang_HE.py b/num2words/lang_HE.py index b114fb46..8898d667 100644 --- a/num2words/lang_HE.py +++ b/num2words/lang_HE.py @@ -277,10 +277,13 @@ def pluralize(self, n, forms, currency=None, prefer_singular=False): return forms[form] def to_currency(self, val, currency='ILS', cents=True, - separator=' ' + AND, adjective=False, + 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] @@ -302,7 +305,8 @@ def to_currency(self, val, currency='ILS', cents=True, construct=right == 2) else: cents_str = self._cents_terse(right, currency) - if separator.split()[-1] == AND: + sep_parts = separator.split() + if sep_parts and sep_parts[-1] == AND: separator += self.makaf strings = [ @@ -321,10 +325,3 @@ def to_currency(self, val, currency='ILS', cents=True, 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) - - -if __name__ == '__main__': - yo = Num2Word_HE() - nums = [1, 11, 21, 24, 99, 100, 101, 200, 211, 345, 1000, 1011] - for num in nums: - print(num, yo.to_cardinal(num)) diff --git a/tests/test_base.py b/tests/test_base.py index 6500db6e..efa1bc81 100644 --- a/tests/test_base.py +++ b/tests/test_base.py @@ -35,10 +35,9 @@ def test_to_currency_not_implemented(self): def test_error_to_cardinal_float(self): from num2words.base import Num2Word_Base + self.base = Num2Word_Base() with self.assertRaises(TypeError): - Num2Word_Base.to_cardinal_float(9) - with self.assertRaises(TypeError): - Num2Word_Base.to_cardinal_float("a") + self.base.to_cardinal_float("a") def test_error_merge(self): from num2words.base import Num2Word_Base diff --git a/tests/test_he.py b/tests/test_he.py index 4c0b490c..b6643e95 100644 --- a/tests/test_he.py +++ b/tests/test_he.py @@ -20,12 +20,15 @@ from unittest import TestCase from num2words import num2words -from num2words.lang_HE import Num2Word_HE +from num2words.lang_HE import Num2Word_HE, int2word class Num2WordsHETest(TestCase): maxDiff = None + def test_negative(self): + self.assertEqual(num2words(-1, lang="he"), u'מינוס אחת') + def test_0(self): self.assertEqual(num2words(0, lang="he"), u'אפס') @@ -313,6 +316,30 @@ def test_to_currency(self): self.assertEqual(n.to_currency( -5.05, currency='ILS', cents=False), u'מינוס חמישה שקלים ו-05 אגורות') + self.assertEqual(n.to_currency( + -5.05, currency='ILS', cents=False, separator='ו'), + u'מינוס חמישה שקלים ו-05 אגורות') + self.assertEqual(n.to_currency( + -5.05, currency='ILS', cents=False, separator='ו-'), + u'מינוס חמישה שקלים ו-05 אגורות') + self.assertEqual(n.to_currency( + -5.05, currency='ILS', cents=False, separator=''), + u'מינוס חמישה שקלים 05 אגורות') + self.assertEqual(n.to_currency( + -5.05, currency='ILS', cents=False, separator='ועוד '), + u'מינוס חמישה שקלים ועוד 05 אגורות') + self.assertEqual(n.to_currency( + -5.05, currency='ILS', cents=False, separator=' ו'), + u'מינוס חמישה שקלים ו-05 אגורות') + self.assertEqual(n.to_currency( + -5.05, currency='ILS', cents=False, separator=' ו-'), + u'מינוס חמישה שקלים ו-05 אגורות') + self.assertEqual(n.to_currency( + -5.05, currency='ILS', cents=False, separator=' '), + u'מינוס חמישה שקלים 05 אגורות') + self.assertEqual(n.to_currency( + -5.05, currency='ILS', cents=False, separator=' ועוד '), + u'מינוס חמישה שקלים ועוד 05 אגורות') self.assertEqual(n.to_currency( 1.01, currency='ILS'), u'שקל אחד ואגורה אחת') self.assertEqual(n.to_currency( @@ -334,6 +361,14 @@ def test_to_currency(self): self.assertEqual(n.to_currency( 5.05, currency='USD', prefer_singular=True, prefer_singular_cents=True), u'חמישה דולר וחמישה סנט') + n.CURRENCY_FORMS['pruta'] = (('פרוטה', 'פרוטות'), ('מאית', 'מאיות')) + self.assertEqual(n.to_currency( + 5.05, currency='pruta'), u'חמש פרוטות וחמש מאיות') + + def test_to_currency_errors(self): + n = Num2Word_HE() + with self.assertRaises(NotImplementedError): + n.to_currency(1, '') def test_to_cardinal(self): n = Num2Word_HE() @@ -446,6 +481,17 @@ def test_cardinal_for_float_number(self): self.assertEqual(num2words(12.594132, lang='he', gender='m'), u'שנים עשר נקודה חמש תשע ארבע אחת שלוש שתיים') + def test_cardinal_float_precision(self): + n = Num2Word_HE() + self.assertEqual(n.to_cardinal_float("1.23"), 'אחת נקודה שתיים שלוש') + n.precision = 1 + self.assertEqual(n.to_cardinal_float("1.2"), 'אחת נקודה שתיים') + + def test_error_to_cardinal_float(self): + n = Num2Word_HE() + with self.assertRaises(TypeError): + n.to_cardinal_float("a") + def test_overflow(self): n = Num2Word_HE() num2words(n.MAXVAL - 1, lang="he") @@ -456,3 +502,6 @@ def test_overflow(self): with self.assertRaises(OverflowError): num2words(n.MAXVAL, lang="he", ordinal=True) + + with self.assertRaises(OverflowError): + int2word(n.MAXVAL) From 0cb3a44dd2362f93c3e45893442e8e67cb7c86d1 Mon Sep 17 00:00:00 2001 From: KhramtsovDR Date: Tue, 7 Mar 2023 14:31:20 +0300 Subject: [PATCH 164/200] Adding genders (m, f, n) --- num2words/lang_RU.py | 219 +++++++++++++++++++++++++------------------ tests/test_ru.py | 40 ++++++++ 2 files changed, 168 insertions(+), 91 deletions(-) diff --git a/num2words/lang_RU.py b/num2words/lang_RU.py index b521cfed..b87f9b9d 100644 --- a/num2words/lang_RU.py +++ b/num2words/lang_RU.py @@ -20,66 +20,78 @@ from .base import Num2Word_Base from .utils import get_digits, splitbyx -ZERO = ('ноль',) - -ONES_FEMININE = { - 1: ('одна',), - 2: ('две',), - 3: ('три',), - 4: ('четыре',), - 5: ('пять',), - 6: ('шесть',), - 7: ('семь',), - 8: ('восемь',), - 9: ('девять',), -} +ZERO = 'ноль' ONES = { - 1: ('один',), - 2: ('два',), - 3: ('три',), - 4: ('четыре',), - 5: ('пять',), - 6: ('шесть',), - 7: ('семь',), - 8: ('восемь',), - 9: ('девять',), + '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: ('девятнадцать',), + 0: 'десять', + 1: 'одиннадцать', + 2: 'двенадцать', + 3: 'тринадцать', + 4: 'четырнадцать', + 5: 'пятнадцать', + 6: 'шестнадцать', + 7: 'семнадцать', + 8: 'восемнадцать', + 9: 'девятнадцать', } TWENTIES = { - 2: ('двадцать',), - 3: ('тридцать',), - 4: ('сорок',), - 5: ('пятьдесят',), - 6: ('шестьдесят',), - 7: ('семьдесят',), - 8: ('восемьдесят',), - 9: ('девяносто',), + 2: 'двадцать', + 3: 'тридцать', + 4: 'сорок', + 5: 'пятьдесят', + 6: 'шестьдесят', + 7: 'семьдесят', + 8: 'восемьдесят', + 9: 'девяносто', } HUNDREDS = { - 1: ('сто',), - 2: ('двести',), - 3: ('триста',), - 4: ('четыреста',), - 5: ('пятьсот',), - 6: ('шестьсот',), - 7: ('семьсот',), - 8: ('восемьсот',), - 9: ('девятьсот',), + 1: 'сто', + 2: 'двести', + 3: 'триста', + 4: 'четыреста', + 5: 'пятьсот', + 6: 'шестьсот', + 7: 'семьсот', + 8: 'восемьсот', + 9: 'девятьсот', } THOUSANDS = { @@ -136,52 +148,49 @@ def setup(self): "восемь": "восьмой", "девять": "девятый", "сто": "сотый"} - self.ords_feminine = {"один": "", - "одна": "", - "две": "двух", - "три": "трёх", - "четыре": "четырёх", - "пять": "пяти", - "шесть": "шести", - "семь": "семи", - "восемь": "восьми", - "девять": "девяти"} - - def to_cardinal(self, number): + self.ords_adjective = {"один": "", + "одна": "", + "две": "двух", + "три": "трёх", + "четыре": "четырёх", + "пять": "пяти", + "шесть": "шести", + "семь": "семи", + "восемь": "восьми", + "девять": "девяти"} + + def to_cardinal(self, number, gender='m'): 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))) + decimal_part = ((ZERO + ' ') * leading_zero_count + + self._int2word(int(right), gender)) return u'%s %s %s' % ( - self._int2word(int(left)), + self._int2word(int(left), gender), self.pointword, decimal_part ) else: - return self._int2word(int(n)) + 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] + if n % 100 in (11, 12, 13, 14): + return forms[2] + if n % 10 == 1: + return forms[0] + if n % 10 in (2, 3, 4): + return forms[1] + return forms[2] - def to_ordinal(self, number): + def to_ordinal(self, number, gender='m'): self.verify_ordinal(number) - outwords = self.to_cardinal(number).split(" ") + outwords = self.to_cardinal(number, 'm').split(" ") lastword = outwords[-1].lower() try: if len(outwords) > 1: - if outwords[-2] in self.ords_feminine: - outwords[-2] = self.ords_feminine.get( + 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] + 'и' @@ -190,8 +199,8 @@ def to_ordinal(self, number): outwords[-3] = '' lastword = self.ords[lastword] except KeyError: - if lastword[:-3] in self.ords_feminine: - lastword = self.ords_feminine.get( + if lastword[:-3] in self.ords_adjective: + lastword = self.ords_adjective.get( lastword[:-3], lastword) + "сотый" elif lastword[-1] == "ь" or lastword[-2] == "т": lastword = lastword[:-1] + "ый" @@ -208,21 +217,43 @@ def to_ordinal(self, number): lastword = lastword[:lastword.rfind('н') + 1] + "ный" elif lastword[-1] == "д" or lastword[-2] == "д": lastword = lastword[:lastword.rfind('д') + 1] + "ный" + + if gender == 'f': + if lastword[-2:] == "ий": + lastword = lastword[:-2] + "ья" + else: + lastword = lastword[:-2] + "ая" + if gender == 'n': + if lastword[-2:] == "ий": + lastword = lastword[:-2] + "ье" + else: + lastword = lastword[:-2] + "ое" + outwords[-1] = self.title(lastword) return " ".join(outwords).strip() def _money_verbose(self, number, currency): - return self._int2word(number, currency == 'UAH') + if currency == 'UAH': + gender = 'f' + else: + gender = 'm' + + return self._int2word(number, gender) def _cents_verbose(self, number, currency): - return self._int2word(number, currency in ('UAH', 'RUB', 'BYN')) + if currency in ('UAH', 'RUB', 'BYN'): + gender = 'f' + else: + gender = 'm' + + return self._int2word(number, gender) - def _int2word(self, n, feminine=False): + def _int2word(self, n, gender): if n < 0: - return ' '.join([self.negword, self._int2word(abs(n))]) + return ' '.join([self.negword, self._int2word(abs(n), gender)]) if n == 0: - return ZERO[0] + return ZERO words = [] chunks = list(splitbyx(str(n), 3)) @@ -236,16 +267,22 @@ def _int2word(self, n, feminine=False): n1, n2, n3 = get_digits(x) if n3 > 0: - words.append(HUNDREDS[n3][0]) + words.append(HUNDREDS[n3]) if n2 > 1: - words.append(TWENTIES[n2][0]) + words.append(TWENTIES[n2]) if n2 == 1: - words.append(TENS[n1][0]) + words.append(TENS[n1]) elif n1 > 0: - ones = ONES_FEMININE if i == 1 or feminine and i == 0 else ONES - words.append(ones[n1][0]) + if i == 0: + ones = ONES[gender] + elif i == 1: + ones = ONES['f'] # Thousands is feminine + else: + ones = ONES['m'] + + words.append(ones[n1]) if i > 0: words.append(self.pluralize(x, THOUSANDS[i])) diff --git a/tests/test_ru.py b/tests/test_ru.py index 85d6dc3e..9b827833 100644 --- a/tests/test_ru.py +++ b/tests/test_ru.py @@ -73,6 +73,32 @@ def test_cardinal(self): self.assertEqual(num2words(-15, lang='ru'), "минус пятнадцать") self.assertEqual(num2words(-100, lang='ru'), "минус сто") + def test_feminine(self): + self.assertEqual(num2words(1, lang='ru', gender='f'), 'одна') + self.assertEqual(num2words(2, lang='ru', gender='f'), 'две') + self.assertEqual(num2words(3, lang='ru', gender='f'), 'три') + self.assertEqual(num2words(100, lang='ru', gender='f'), "сто") + self.assertEqual(num2words(101, lang='ru', gender='f'), "сто одна") + self.assertEqual(num2words(110, lang='ru', gender='f'), "сто десять") + self.assertEqual(num2words(115, lang='ru', gender='f'), "сто пятнадцать") + self.assertEqual(num2words(122, lang='ru', gender='f'), "сто двадцать две") + self.assertEqual(num2words(125.1, lang='ru', gender='f'), 'сто двадцать пять запятая одна') + self.assertEqual(num2words(-1, lang='ru', gender='f'), "минус одна") + self.assertEqual(num2words(-100, lang='ru', gender='f'), "минус сто") + + def test_neuter(self): + self.assertEqual(num2words(1, lang='ru', gender='n'), 'одно') + self.assertEqual(num2words(2, lang='ru', gender='n'), 'два') + self.assertEqual(num2words(3, lang='ru', gender='n'), 'три') + self.assertEqual(num2words(100, lang='ru', gender='n'), "сто") + self.assertEqual(num2words(101, lang='ru', gender='n'), "сто одно") + self.assertEqual(num2words(110, lang='ru', gender='n'), "сто десять") + self.assertEqual(num2words(115, lang='ru', gender='n'), "сто пятнадцать") + self.assertEqual(num2words(122, lang='ru', gender='n'), "сто двадцать два") + self.assertEqual(num2words(125.1, lang='ru', gender='n'), 'сто двадцать пять запятая одно') + self.assertEqual(num2words(-1, lang='ru', gender='n'), "минус одно") + self.assertEqual(num2words(-100, lang='ru', gender='n'), "минус сто") + def test_floating_point(self): self.assertEqual(num2words(5.2, lang='ru'), "пять запятая два") self.assertEqual( @@ -159,6 +185,20 @@ def test_to_ordinal(self): 'миллиардный' ) + def test_to_ordinal_feminine(self): + self.assertEqual(num2words(1, lang='ru', to='ordinal', gender='f'), 'первая') + self.assertEqual(num2words(3, lang='ru', to='ordinal', gender='f'), 'третья') + self.assertEqual(num2words(10, lang='ru', to='ordinal', gender='f'), 'десятая') + self.assertEqual(num2words(23, lang='ru', to='ordinal', gender='f'), 'двадцать третья') + self.assertEqual(num2words(1000, lang='ru', to='ordinal', gender='f'), 'тысячная') + + def test_to_ordinal_neuter(self): + self.assertEqual(num2words(1, lang='ru', to='ordinal', gender='n'), 'первое') + self.assertEqual(num2words(3, lang='ru', to='ordinal', gender='n'), 'третье') + self.assertEqual(num2words(10, lang='ru', to='ordinal', gender='n'), 'десятое') + self.assertEqual(num2words(23, lang='ru', to='ordinal', gender='n'), 'двадцать третье') + self.assertEqual(num2words(1000, lang='ru', to='ordinal', gender='n'), 'тысячное') + def test_to_currency(self): self.assertEqual( num2words(1.0, lang='ru', to='currency', currency='EUR'), From 8d0814d6f1efabd41037eb2a50b193e47f554879 Mon Sep 17 00:00:00 2001 From: KhramtsovDR Date: Wed, 8 Mar 2023 00:18:31 +0300 Subject: [PATCH 165/200] Fix E501 - line too long warning --- tests/test_ru.py | 67 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 51 insertions(+), 16 deletions(-) diff --git a/tests/test_ru.py b/tests/test_ru.py index 9b827833..388cf2a9 100644 --- a/tests/test_ru.py +++ b/tests/test_ru.py @@ -80,9 +80,16 @@ def test_feminine(self): self.assertEqual(num2words(100, lang='ru', gender='f'), "сто") self.assertEqual(num2words(101, lang='ru', gender='f'), "сто одна") self.assertEqual(num2words(110, lang='ru', gender='f'), "сто десять") - self.assertEqual(num2words(115, lang='ru', gender='f'), "сто пятнадцать") - self.assertEqual(num2words(122, lang='ru', gender='f'), "сто двадцать две") - self.assertEqual(num2words(125.1, lang='ru', gender='f'), 'сто двадцать пять запятая одна') + self.assertEqual( + num2words(115, lang='ru', gender='f'), "сто пятнадцать" + ) + self.assertEqual( + num2words(122, lang='ru', gender='f'), "сто двадцать две" + ) + self.assertEqual( + num2words(125.1, lang='ru', gender='f'), + 'сто двадцать пять запятая одна' + ) self.assertEqual(num2words(-1, lang='ru', gender='f'), "минус одна") self.assertEqual(num2words(-100, lang='ru', gender='f'), "минус сто") @@ -93,9 +100,15 @@ def test_neuter(self): self.assertEqual(num2words(100, lang='ru', gender='n'), "сто") self.assertEqual(num2words(101, lang='ru', gender='n'), "сто одно") self.assertEqual(num2words(110, lang='ru', gender='n'), "сто десять") - self.assertEqual(num2words(115, lang='ru', gender='n'), "сто пятнадцать") - self.assertEqual(num2words(122, lang='ru', gender='n'), "сто двадцать два") - self.assertEqual(num2words(125.1, lang='ru', gender='n'), 'сто двадцать пять запятая одно') + self.assertEqual( + num2words(115, lang='ru', gender='n'), "сто пятнадцать" + ) + self.assertEqual( + num2words(122, lang='ru', gender='n'),"сто двадцать два" + ) + self.assertEqual( + num2words(125.1, lang='ru', gender='n'), + 'сто двадцать пять запятая одно') self.assertEqual(num2words(-1, lang='ru', gender='n'), "минус одно") self.assertEqual(num2words(-100, lang='ru', gender='n'), "минус сто") @@ -186,18 +199,40 @@ def test_to_ordinal(self): ) def test_to_ordinal_feminine(self): - self.assertEqual(num2words(1, lang='ru', to='ordinal', gender='f'), 'первая') - self.assertEqual(num2words(3, lang='ru', to='ordinal', gender='f'), 'третья') - self.assertEqual(num2words(10, lang='ru', to='ordinal', gender='f'), 'десятая') - self.assertEqual(num2words(23, lang='ru', to='ordinal', gender='f'), 'двадцать третья') - self.assertEqual(num2words(1000, lang='ru', to='ordinal', gender='f'), 'тысячная') + self.assertEqual( + num2words(1, lang='ru', to='ordinal', gender='f'), 'первая' + ) + self.assertEqual( + num2words(3, lang='ru', to='ordinal', gender='f'), 'третья' + ) + self.assertEqual( + num2words(10, lang='ru', to='ordinal', gender='f'), 'десятая' + ) + self.assertEqual( + num2words(23, lang='ru', to='ordinal', gender='f'), + 'двадцать третья' + ) + self.assertEqual( + num2words(1000, lang='ru', to='ordinal', gender='f'), 'тысячная' + ) def test_to_ordinal_neuter(self): - self.assertEqual(num2words(1, lang='ru', to='ordinal', gender='n'), 'первое') - self.assertEqual(num2words(3, lang='ru', to='ordinal', gender='n'), 'третье') - self.assertEqual(num2words(10, lang='ru', to='ordinal', gender='n'), 'десятое') - self.assertEqual(num2words(23, lang='ru', to='ordinal', gender='n'), 'двадцать третье') - self.assertEqual(num2words(1000, lang='ru', to='ordinal', gender='n'), 'тысячное') + self.assertEqual( + num2words(1, lang='ru', to='ordinal', gender='n'), 'первое' + ) + self.assertEqual( + num2words(3, lang='ru', to='ordinal', gender='n'), 'третье' + ) + self.assertEqual( + num2words(10, lang='ru', to='ordinal', gender='n'), 'десятое' + ) + self.assertEqual( + num2words(23, lang='ru', to='ordinal', gender='n'), + 'двадцать третье' + ) + self.assertEqual( + num2words(1000, lang='ru', to='ordinal', gender='n'), 'тысячное' + ) def test_to_currency(self): self.assertEqual( From 77fbe915b94496e980285935da64ddaa7c101c34 Mon Sep 17 00:00:00 2001 From: "nika.soltani" Date: Wed, 15 Mar 2023 13:05:32 +0330 Subject: [PATCH 166/200] fix 15, 16, 17, 18, 19 issue --- num2words/lang_FA.py | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/num2words/lang_FA.py b/num2words/lang_FA.py index 96e9e526..f652f255 100644 --- a/num2words/lang_FA.py +++ b/num2words/lang_FA.py @@ -3,6 +3,7 @@ # 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 @@ -28,10 +29,10 @@ "دوازده", "سیزده", "چهارده", - "پونزده", - "شونزده", - "هیفده", - "هیجده", + "پانزده", + "شانزده", + "هفده", + "هجده", "نوزده", ] @@ -101,9 +102,9 @@ def float2tuple(self, value): return pre, post, self.precision def cardinal3(self, number): - if (number < 19): + if number <= 19: return farsiOnes[number] - if (number < 100): + if number < 100: x, y = divmod(number, 10) if y == 0: return farsiTens[x] @@ -118,19 +119,19 @@ def cardinalPos(self, number): res = '' for b in farsiBig: x, y = divmod(x, 1000) - if (y == 0): + if y == 0: continue yx = self.cardinal3(y) + b if b == ' هزار' and y == 1: yx = 'هزار' - if (res == ''): + if res == '': res = yx else: res = yx + farsiSeperator + res return res def fractional(self, number, level): - if (number == 5): + if number == 5: return "نیم" x = self.cardinalPos(number) ld3, lm3 = divmod(level, 3) @@ -142,20 +143,21 @@ def to_currency(self, value): def to_ordinal(self, number): r = self.to_cardinal(number) - if (r[-1] == 'ه' and r[-2] == 'س'): + if r[-1] == 'ه' and r[-2] == 'س': return r[:-1] + 'وم' return r + 'م' def to_year(self, value): return self.to_cardinal(value) - def to_ordinal_num(self, 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): + if number == 0: return "صفر" x, y, level = self.float2tuple(number) if y == 0: From 5708ab304a5cf04621ce96019bc6b1b88ed3a68a Mon Sep 17 00:00:00 2001 From: Nse-Abasi Joseph Etim Date: Tue, 21 Mar 2023 11:16:05 +0100 Subject: [PATCH 167/200] Added support for the Nigerian Naira So all thats required is to set the lang attribute to en_NG Hopefully this would be merged into the main branch, when this is done, the language would be represented as en_NG (English - Nigeria) --- num2words/__init__.py | 3 ++- num2words/lang_EN_NG.py | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 num2words/lang_EN_NG.py diff --git a/num2words/__init__.py b/num2words/__init__.py index 6aa20d2d..96b08c62 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -24,7 +24,7 @@ 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_SL, lang_SR, lang_SV, lang_TE, lang_TG, lang_TH, lang_TR, - lang_UK, lang_VI) + lang_UK, lang_VI, lang_EN_NG) CONVERTER_CLASSES = { 'am': lang_AM.Num2Word_AM(), @@ -33,6 +33,7 @@ 'cz': lang_CZ.Num2Word_CZ(), '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(), diff --git a/num2words/lang_EN_NG.py b/num2words/lang_EN_NG.py new file mode 100644 index 00000000..84a2a556 --- /dev/null +++ b/num2words/lang_EN_NG.py @@ -0,0 +1,36 @@ +# -*- 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', + cents=True, separator=',', + adjective=False + ): + result = super(Num2Word_EN_NG, self).to_currency( + val, currency=currency, cents=cents, separator=separator, + adjective=adjective) + return result \ No newline at end of file From fc2ec75ab0f0b77ba59cff014b42b3d734459542 Mon Sep 17 00:00:00 2001 From: Nse-Abasi Joseph Etim Date: Tue, 21 Mar 2023 14:40:52 +0100 Subject: [PATCH 168/200] Added tests and some changes to the keyword argument name from cents to kobo --- README.rst | 3 +- num2words/lang_EN_NG.py | 4 +- tests/test_en_ng.py | 91 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 95 insertions(+), 3 deletions(-) create mode 100644 tests/test_en_ng.py diff --git a/README.rst b/README.rst index c24bb099..39b22255 100644 --- a/README.rst +++ b/README.rst @@ -63,7 +63,7 @@ In code there's only one function to use:: >>> num2words(42, lang='fr') quarante-deux -Besides the numerical argument, there are two main optional arguments. +Besides the numerical argument, there are two main optional arguments, ``to:`` and ``lang:`` **to:** The converter to use. Supported values are: @@ -84,6 +84,7 @@ Besides the numerical argument, there are two main optional arguments. * ``dk`` (Danish) * ``en_GB`` (English - Great Britain) * ``en_IN`` (English - India) +* ``en_NG`` (English - Nigeria) * ``es`` (Spanish) * ``es_CO`` (Spanish - Colombia) * ``es_VE`` (Spanish - Venezuela) diff --git a/num2words/lang_EN_NG.py b/num2words/lang_EN_NG.py index 84a2a556..c69574c0 100644 --- a/num2words/lang_EN_NG.py +++ b/num2words/lang_EN_NG.py @@ -27,10 +27,10 @@ class Num2Word_EN_NG(lang_EN.Num2Word_EN): def to_currency( self, val, currency='NGN', - cents=True, separator=',', + kobo=True, separator=',', adjective=False ): result = super(Num2Word_EN_NG, self).to_currency( - val, currency=currency, cents=cents, separator=separator, + val, currency=currency, cents=kobo, separator=separator, adjective=adjective) return result \ No newline at end of file diff --git a/tests/test_en_ng.py b/tests/test_en_ng.py new file mode 100644 index 00000000..aaef0aab --- /dev/null +++ b/tests/test_en_ng.py @@ -0,0 +1,91 @@ +# -*- 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 unittest import TestCase + +from num2words import num2words + + +class Num2WordsENNGTest(TestCase): + + # only the test for currency is writen as other functions in the Class remains the + # same and have been properly tested in the test test_en which tests the parent class + # upon which this class inherits + + def test_to_currency(self): + + language = 'en_NG' + separator = ' and' + + self.assertEqual( + num2words('38.4', lang=language, to='currency', separator=separator, + kobo=False), + "thirty-eight naira and 40 kobo" + ) + self.assertEqual( + num2words('0', lang=language, to='currency', separator=separator, + kobo=False), + "zero naira and 00 kobo" + ) + + self.assertEqual( + num2words('1.01', lang=language, to='currency', separator=separator, + kobo=True), + "one naira and one cent" + ) + + self.assertEqual( + num2words('4778.00', lang=language, to='currency', separator=separator, + kobo=True, adjective=True), + 'four thousand, seven hundred and seventy-eight Nigerian naira' + ' and zero cents') + + self.assertEqual( + num2words('4778.00', lang=language, to='currency', separator=separator, + kobo=True), + 'four thousand, seven hundred and seventy-eight naira and' + ' zero cents') + + self.assertEqual( + num2words('1.1', lang=language, to='currency', separator=separator, + kobo=True), + "one naira and ten kobo" + ) + + self.assertEqual( + num2words('158.3', lang=language, to='currency', separator=separator, + kobo=True), + "one hundred and fifty-eight naira and thirty kobo" + ) + + self.assertEqual( + num2words('2000.00', lang=language, to='currency', separator=separator, + kobo=True), + "two thousand naira and zero kobo" + ) + + self.assertEqual( + num2words('4.01', lang=language, to='currency', separator=separator, + kobo=True), + "four naira and one kobo" + ) + + self.assertEqual( + num2words('2000.00', lang=language, to='currency', separator=separator, + kobo=True), + "two thousand naira and zero kobo" + ) \ No newline at end of file From 291951e249507a076554b292b1aa3e8e834b795b Mon Sep 17 00:00:00 2001 From: Nse-Abasi Joseph Etim Date: Tue, 21 Mar 2023 19:26:58 +0100 Subject: [PATCH 169/200] updated tests and code formatting --- num2words/__init__.py | 14 +++--- num2words/lang_EN_NG.py | 5 +- tests/test_en_ng.py | 104 ++++++++++++++++++++++++++++++---------- 3 files changed, 88 insertions(+), 35 deletions(-) diff --git a/num2words/__init__.py b/num2words/__init__.py index 96b08c62..0338e951 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -18,13 +18,13 @@ from __future__ import unicode_literals from . import (lang_AM, lang_AR, lang_AZ, lang_CZ, lang_DE, lang_DK, lang_EN, - lang_EN_IN, lang_EO, lang_ES, lang_ES_CO, 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_SL, lang_SR, lang_SV, lang_TE, lang_TG, lang_TH, lang_TR, - lang_UK, lang_VI, lang_EN_NG) + lang_EN_IN, lang_EN_NG, lang_EO, lang_ES, lang_ES_CO, + 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_SL, lang_SR, + lang_SV, lang_TE, lang_TG, lang_TH, lang_TR, lang_UK, lang_VI) CONVERTER_CLASSES = { 'am': lang_AM.Num2Word_AM(), diff --git a/num2words/lang_EN_NG.py b/num2words/lang_EN_NG.py index c69574c0..7de81c84 100644 --- a/num2words/lang_EN_NG.py +++ b/num2words/lang_EN_NG.py @@ -19,6 +19,7 @@ from . import lang_EN + class Num2Word_EN_NG(lang_EN.Num2Word_EN): CURRENCY_FORMS = {'NGN': (('naira', 'naira'), ('kobo', 'kobo'))} @@ -26,11 +27,11 @@ class Num2Word_EN_NG(lang_EN.Num2Word_EN): CURRENCY_ADJECTIVES = {'NGN': 'Nigerian'} def to_currency( - self, val, currency='NGN', + 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 \ No newline at end of file + return result diff --git a/tests/test_en_ng.py b/tests/test_en_ng.py index aaef0aab..6d7e72e5 100644 --- a/tests/test_en_ng.py +++ b/tests/test_en_ng.py @@ -22,8 +22,10 @@ class Num2WordsENNGTest(TestCase): - # only the test for currency is writen as other functions in the Class remains the - # same and have been properly tested in the test test_en which tests the parent class + # only the test for currency is writen as other + # functions in the Class remains the + # same and have been properly tested in the + # test test_en which tests the parent class # upon which this class inherits def test_to_currency(self): @@ -32,60 +34,110 @@ def test_to_currency(self): separator = ' and' self.assertEqual( - num2words('38.4', lang=language, to='currency', separator=separator, - kobo=False), + num2words( + '38.4', + lang=language, + to='currency', + separator=separator, + kobo=False + ), "thirty-eight naira and 40 kobo" ) self.assertEqual( - num2words('0', lang=language, to='currency', separator=separator, - kobo=False), + num2words( + '0', + lang=language, + to='currency', + separator=separator, + kobo=False + ), "zero naira and 00 kobo" ) self.assertEqual( - num2words('1.01', lang=language, to='currency', separator=separator, - kobo=True), - "one naira and one cent" + num2words( + '1.01', + lang=language, + to='currency', + separator=separator, + kobo=True + ), + "one naira and one kobo" ) self.assertEqual( - num2words('4778.00', lang=language, to='currency', separator=separator, - kobo=True, adjective=True), + num2words( + '4778.00', + lang=language, + to='currency', + separator=separator, + kobo=True, adjective=True + ), 'four thousand, seven hundred and seventy-eight Nigerian naira' - ' and zero cents') + ' and zero kobo') self.assertEqual( - num2words('4778.00', lang=language, to='currency', separator=separator, - kobo=True), + num2words( + '4778.00', + lang=language, + to='currency', + separator=separator, + kobo=True + ), 'four thousand, seven hundred and seventy-eight naira and' - ' zero cents') + ' zero kobo') self.assertEqual( - num2words('1.1', lang=language, to='currency', separator=separator, - kobo=True), + num2words( + '1.1', + lang=language, + to='currency', + separator=separator, + kobo=True + ), "one naira and ten kobo" ) self.assertEqual( - num2words('158.3', lang=language, to='currency', separator=separator, - kobo=True), + num2words( + '158.3', + lang=language, + to='currency', + separator=separator, + kobo=True + ), "one hundred and fifty-eight naira and thirty kobo" ) self.assertEqual( - num2words('2000.00', lang=language, to='currency', separator=separator, - kobo=True), + num2words( + '2000.00', + lang=language, + to='currency', + separator=separator, + kobo=True + ), "two thousand naira and zero kobo" ) self.assertEqual( - num2words('4.01', lang=language, to='currency', separator=separator, - kobo=True), + num2words( + '4.01', + lang=language, + to='currency', + separator=separator, + kobo=True + ), "four naira and one kobo" ) self.assertEqual( - num2words('2000.00', lang=language, to='currency', separator=separator, - kobo=True), + num2words( + '2000.00', + lang=language, + to='currency', + separator=separator, + kobo=True + ), "two thousand naira and zero kobo" - ) \ No newline at end of file + ) From 50353485404c292ae71361ce036994d24af6640f Mon Sep 17 00:00:00 2001 From: Nse-Abasi Joseph Etim Date: Fri, 24 Mar 2023 15:38:17 +0100 Subject: [PATCH 170/200] corrected sorting using isort --- num2words/__init__.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/num2words/__init__.py b/num2words/__init__.py index 0338e951..3990bd1f 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -19,12 +19,12 @@ from . import (lang_AM, lang_AR, lang_AZ, lang_CZ, lang_DE, lang_DK, lang_EN, lang_EN_IN, lang_EN_NG, lang_EO, lang_ES, lang_ES_CO, - 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_SL, lang_SR, - lang_SV, lang_TE, lang_TG, lang_TH, lang_TR, lang_UK, lang_VI) + 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_SL, lang_SR, lang_SV, lang_TE, lang_TG, lang_TH, + lang_TR, lang_UK, lang_VI) CONVERTER_CLASSES = { 'am': lang_AM.Num2Word_AM(), From 00836e13e00fa5986526fdd7b841dc1ef44f15f8 Mon Sep 17 00:00:00 2001 From: Mario Monroy Date: Tue, 28 Mar 2023 10:57:57 -0600 Subject: [PATCH 171/200] Guatemala currency --- num2words/__init__.py | 15 ++++++----- num2words/lang_ES.py | 1 + num2words/lang_ES_GT.py | 29 ++++++++++++++++++++ tests/test_es_gt.py | 60 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 98 insertions(+), 7 deletions(-) create mode 100644 num2words/lang_ES_GT.py create mode 100644 tests/test_es_gt.py diff --git a/num2words/__init__.py b/num2words/__init__.py index 6aa20d2d..9193ab5a 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -18,13 +18,13 @@ from __future__ import unicode_literals from . import (lang_AM, lang_AR, lang_AZ, lang_CZ, lang_DE, lang_DK, lang_EN, - lang_EN_IN, lang_EO, lang_ES, lang_ES_CO, 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_SL, lang_SR, lang_SV, lang_TE, lang_TG, lang_TH, lang_TR, - lang_UK, lang_VI) + lang_EN_IN, lang_EO, lang_ES, lang_ES_CO, 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_SL, lang_SR, lang_SV, lang_TE, lang_TG, lang_TH, + lang_TR, lang_UK, lang_VI) CONVERTER_CLASSES = { 'am': lang_AM.Num2Word_AM(), @@ -45,6 +45,7 @@ 'es_CO': lang_ES_CO.Num2Word_ES_CO(), 'es_NI': lang_ES_NI.Num2Word_ES_NI(), 'es_VE': lang_ES_VE.Num2Word_ES_VE(), + 'es_GT': lang_ES_GT.Num2Word_ES_GT(), 'id': lang_ID.Num2Word_ID(), 'ja': lang_JA.Num2Word_JA(), 'kn': lang_KN.Num2Word_KN(), diff --git a/num2words/lang_ES.py b/num2words/lang_ES.py index de2d1e13..3dc70141 100644 --- a/num2words/lang_ES.py +++ b/num2words/lang_ES.py @@ -206,6 +206,7 @@ class Num2Word_ES(Num2Word_EU): 'ZRZ': (('zaire', 'zaires'), ('likuta', 'makuta')), 'ZWL': (GENERIC_DOLLARS, ('céntimo', 'céntimos')), 'ZWL': (GENERIC_DOLLARS, ('céntimo', 'céntimos')), + 'GTQ': (('quetzal', 'quetzales'), GENERIC_CENTS), } # //CHECK: Is this sufficient?? diff --git a/num2words/lang_ES_GT.py b/num2words/lang_ES_GT.py new file mode 100644 index 00000000..70902fc1 --- /dev/null +++ b/num2words/lang_ES_GT.py @@ -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_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") diff --git a/tests/test_es_gt.py b/tests/test_es_gt.py new file mode 100644 index 00000000..1c9429fa --- /dev/null +++ b/tests/test_es_gt.py @@ -0,0 +1,60 @@ +# -*- 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 num2words import num2words + +from . import test_es + +TEST_CASES_TO_CURRENCY = ( + (1, 'un quetzal'), + (2, 'dos quetzales'), + (8, 'ocho quetzales'), + (12, 'doce quetzales'), + (21, 'veintiun quetzales'), + (81.25, 'ochenta y un quetzales y veinticinco centavos'), + (100, 'cien quetzales'), +) + + +class Num2WordsESGTTest(test_es.Num2WordsESTest): + + def test_number(self): + for test in test_es.TEST_CASES_CARDINAL: + self.assertEqual(num2words(test[0], lang='es_GT'), test[1]) + + def test_ordinal(self): + for test in test_es.TEST_CASES_ORDINAL: + self.assertEqual( + num2words(test[0], lang='es_GT', ordinal=True), + test[1] + ) + + def test_ordinal_num(self): + for test in test_es.TEST_CASES_ORDINAL_NUM: + self.assertEqual( + num2words(test[0], lang='es', to='ordinal_num'), + test[1] + ) + + def test_currency(self): + for test in TEST_CASES_TO_CURRENCY: + self.assertEqual( + num2words(test[0], lang='es_GT', to='currency'), + test[1] + ) From 6cfdf779f5f4bcf3da97e6c8c97ade9ed55773aa Mon Sep 17 00:00:00 2001 From: Mario Monroy Date: Tue, 28 Mar 2023 11:21:27 -0600 Subject: [PATCH 172/200] Adding Guatemala in README.rst --- README.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/README.rst b/README.rst index c24bb099..7c348b2a 100644 --- a/README.rst +++ b/README.rst @@ -87,6 +87,7 @@ Besides the numerical argument, there are two main optional arguments. * ``es`` (Spanish) * ``es_CO`` (Spanish - Colombia) * ``es_VE`` (Spanish - Venezuela) +* ``es_GT`` (Spanish - Guatemala) * ``eu`` (EURO) * ``fa`` (Farsi) * ``fi`` (Finnish) From afac78a01c29b0948bf4ba54d0c546be6364fd15 Mon Sep 17 00:00:00 2001 From: Jeronymous Date: Wed, 29 Mar 2023 12:30:05 +0200 Subject: [PATCH 173/200] Fix missing space/and in numbers like 740 --- num2words/lang_AR.py | 2 +- tests/test_ar.py | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/num2words/lang_AR.py b/num2words/lang_AR.py index a0027a83..5f8415c2 100644 --- a/num2words/lang_AR.py +++ b/num2words/lang_AR.py @@ -192,7 +192,7 @@ def process_arabic_group(self, group_number, group_level, ret_val += " و " ret_val += self.digit_feminine_status(ones, group_level) - if ret_val != "" and ones != 0: + if ret_val != "": ret_val += " و " ret_val += self.arabicTens[int(tens)] diff --git a/tests/test_ar.py b/tests/test_ar.py index 5e1ea410..e511329e 100644 --- a/tests/test_ar.py +++ b/tests/test_ar.py @@ -97,6 +97,23 @@ def test_cardinal(self): 'أربعة و تسعون ألفاً و مئتان و واحد و ثلاثون') self.assertEqual(num2words(1431, to='cardinal', lang='ar'), 'واحد ألف و أربعمائة و واحد و ثلاثون') + self.assertEqual(num2words(740, to='cardinal', lang='ar'), + 'سبعمائة و أربعون') + self.assertEqual(num2words(741, to='cardinal', lang='ar'), + #'سبعة مائة و واحد و أربعون' + 'سبعمائة و واحد و أربعون' + ) + self.assertEqual(num2words(710, to='cardinal', lang='ar'), + 'سبعمائة و عشرة') + self.assertEqual(num2words(711, to='cardinal', lang='ar'), + # 'سبعة مائة و إحدى عشر' + 'سبعمائة و أحد عشر' + ) + self.assertEqual(num2words(700, to='cardinal', lang='ar'), + 'سبعمائة') + self.assertEqual(num2words(701, to='cardinal', lang='ar'), + 'سبعمائة و واحد') + def test_prefix_and_suffix(self): self.assertEqual(num2words(645, to='currency', From 302052e805a4f407ddc9ab1e466f29ac3d418c84 Mon Sep 17 00:00:00 2001 From: Jeronymous Date: Wed, 29 Mar 2023 12:33:10 +0200 Subject: [PATCH 174/200] fix extra space. Resolves https://github.com/savoirfairelinux/num2words/issues/393 --- num2words/lang_AR.py | 2 +- tests/test_ar.py | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/num2words/lang_AR.py b/num2words/lang_AR.py index 5f8415c2..61c05a1d 100644 --- a/num2words/lang_AR.py +++ b/num2words/lang_AR.py @@ -229,7 +229,7 @@ def convert_to_arabic(self): if group_description != '': if group > 0: if ret_val != "": - ret_val = "{} و {}".format("", ret_val) + ret_val = "{}و {}".format("", ret_val) if number_to_process != 2: if number_to_process % 100 != 1: if 3 <= number_to_process <= 10: diff --git a/tests/test_ar.py b/tests/test_ar.py index e511329e..d9ff7711 100644 --- a/tests/test_ar.py +++ b/tests/test_ar.py @@ -43,10 +43,10 @@ def test_default_currency(self): 'عشرون ألف ريال و اثنتا عشرة هللة') self.assertEqual(num2words(1000000, to='currency', lang='ar'), 'واحد مليون ريال') - val = 'تسعمائة و ثلاثة و عشرون ألفاً و أربعمائة و أحد عشر ريالاً' + val = 'تسعمائة و ثلاثة و عشرون ألفاً و أربعمائة و أحد عشر ريالاً' self.assertEqual(num2words(923411, to='currency', lang='ar'), val) self.assertEqual(num2words(63411, to='currency', lang='ar'), - 'ثلاثة و ستون ألفاً و أربعمائة و أحد عشر ريالاً') + 'ثلاثة و ستون ألفاً و أربعمائة و أحد عشر ريالاً') self.assertEqual(num2words(1000000.99, to='currency', lang='ar'), 'واحد مليون ريال و تسع و تسعون هللة') @@ -62,7 +62,7 @@ def test_currency_parm(self): 'عشرون ألف جنيه و اثنتا عشرة قرش') self.assertEqual( num2words(923411, to='currency', lang='ar', currency="SR"), - 'تسعمائة و ثلاثة و عشرون ألفاً و أربعمائة و أحد عشر ريالاً') + 'تسعمائة و ثلاثة و عشرون ألفاً و أربعمائة و أحد عشر ريالاً') self.assertEqual( num2words(1000000.99, to='currency', lang='ar', currency="KWD"), 'واحد مليون دينار و تسع و تسعون فلس') @@ -82,21 +82,21 @@ def test_ordinal(self): 'مائة و اثنان') self.assertEqual( num2words(923411, to='ordinal_num', lang='ar'), - 'تسعمائة و ثلاثة و عشرون ألفاً و أربعمائة و أحد عشر') + 'تسعمائة و ثلاثة و عشرون ألفاً و أربعمائة و أحد عشر') def test_cardinal(self): self.assertEqual(num2words(12, to='cardinal', lang='ar'), 'اثنا عشر') self.assertEqual(num2words(-8324, to='cardinal', lang='ar'), - 'سالب ثمانية آلاف و ثلاثمائة و أربعة و عشرون') + 'سالب ثمانية آلاف و ثلاثمائة و أربعة و عشرون') self.assertEqual( num2words(3431.12, to='cardinal', lang='ar'), - 'ثلاثة آلاف و أربعمائة و واحد و ثلاثون , اثنتا عشرة') + 'ثلاثة آلاف و أربعمائة و واحد و ثلاثون , اثنتا عشرة') self.assertEqual(num2words(431, to='cardinal', lang='ar'), 'أربعمائة و واحد و ثلاثون') self.assertEqual(num2words(94231, to='cardinal', lang='ar'), - 'أربعة و تسعون ألفاً و مئتان و واحد و ثلاثون') + 'أربعة و تسعون ألفاً و مئتان و واحد و ثلاثون') self.assertEqual(num2words(1431, to='cardinal', lang='ar'), - 'واحد ألف و أربعمائة و واحد و ثلاثون') + 'واحد ألف و أربعمائة و واحد و ثلاثون') self.assertEqual(num2words(740, to='cardinal', lang='ar'), 'سبعمائة و أربعون') self.assertEqual(num2words(741, to='cardinal', lang='ar'), From 030a76f245d578e74008944626624de3d8df3620 Mon Sep 17 00:00:00 2001 From: Jeronymous Date: Wed, 29 Mar 2023 15:01:38 +0200 Subject: [PATCH 175/200] Resolves https://github.com/savoirfairelinux/num2words/issues/511 : fail with OverflowError on big numbers --- num2words/lang_AR.py | 16 +++++++++++++--- tests/test_ar.py | 9 ++++++--- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/num2words/lang_AR.py b/num2words/lang_AR.py index 61c05a1d..71286354 100644 --- a/num2words/lang_AR.py +++ b/num2words/lang_AR.py @@ -18,6 +18,7 @@ # MA 02110-1301 USA import re +import decimal from decimal import Decimal from math import floor @@ -218,9 +219,14 @@ def convert_to_arabic(self): while temp_number > Decimal(0): - number_to_process = int( - Decimal(str(temp_number)) % Decimal(str(1000))) - temp_number = int(Decimal(temp_number) / Decimal(1000)) + temp_number_dec = Decimal(str(temp_number)) + try: + number_to_process = int(temp_number_dec % Decimal(str(1000))) + except decimal.InvalidOperation: # https://stackoverflow.com/questions/42868278/decimal-invalidoperation-divisionimpossible-for-very-large-numbers + 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, @@ -237,10 +243,14 @@ def convert_to_arabic(self): self.arabicPluralGroups[group], ret_val) else: if ret_val != "": + if group >= len(self.arabicAppendedGroup): + raise OverflowError(self.errmsg_too_big) ret_val = "{} {}".format( self.arabicAppendedGroup[group], ret_val) else: + if group >= len(self.arabicGroup): + raise OverflowError(self.errmsg_too_big) ret_val = "{} {}".format( self.arabicGroup[group], ret_val) diff --git a/tests/test_ar.py b/tests/test_ar.py index d9ff7711..fda08b48 100644 --- a/tests/test_ar.py +++ b/tests/test_ar.py @@ -124,7 +124,10 @@ def test_year(self): self.assertEqual(num2words(2000, to='year', lang='ar'), 'ألفا') def test_max_numbers(self): - with self.assertRaises(Exception) as context: - num2words(10 ** 36, to='year', lang='ar') - self.assertTrue('Too large' in str(context.exception)) + for number in 10 ** 36, 123456789123456789123456789, 123456789123456789123456789123456789: + + with self.assertRaises(OverflowError) as context: + num2words(number, lang='ar') + + self.assertTrue('Too large' in str(context.exception)) From fd0516cc67fd21e907a8c3803d60e6a56877d33c Mon Sep 17 00:00:00 2001 From: Jeronymous Date: Wed, 29 Mar 2023 15:14:29 +0200 Subject: [PATCH 176/200] Resolves https://github.com/savoirfairelinux/num2words/issues/509 : fix error messages when numbers are too big --- num2words/lang_EO.py | 2 +- num2words/lang_FR.py | 2 +- num2words/lang_ID.py | 2 +- num2words/lang_RO.py | 2 +- num2words/lang_SL.py | 2 +- tests/test_fr.py | 9 ++++++++- 6 files changed, 13 insertions(+), 6 deletions(-) diff --git a/num2words/lang_EO.py b/num2words/lang_EO.py index 473e74d1..ff47e69d 100644 --- a/num2words/lang_EO.py +++ b/num2words/lang_EO.py @@ -60,7 +60,7 @@ def setup(self): 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." + 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"), diff --git a/num2words/lang_FR.py b/num2words/lang_FR.py index 0c440b3f..82942a4e 100644 --- a/num2words/lang_FR.py +++ b/num2words/lang_FR.py @@ -37,7 +37,7 @@ def setup(self): self.errmsg_nonnum = ( u"Seulement des nombres peuvent être convertis en mots." ) - self.errmsg_toobig = u"Nombre trop grand pour être converti en mots." + self.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"), diff --git a/num2words/lang_ID.py b/num2words/lang_ID.py index 9a2bbfcb..1973e7e8 100644 --- a/num2words/lang_ID.py +++ b/num2words/lang_ID.py @@ -44,7 +44,7 @@ class Num2Word_ID(): errmsg_floatord = "Cannot treat float number as ordinal" errmsg_negord = "Cannot treat negative number as ordinal" - errmsg_toobig = "Too large" + errmsg_toobig = "Number is too large to convert to words (abs(%s) > %s)." max_num = 10 ** 36 def split_by_koma(self, number): diff --git a/num2words/lang_RO.py b/num2words/lang_RO.py index ec1deda3..b3fcef2a 100644 --- a/num2words/lang_RO.py +++ b/num2words/lang_RO.py @@ -34,7 +34,7 @@ def setup(self): self.pointword = "virgulă" self.exclude_title = ["și", "virgulă", "minus"] self.errmsg_toobig = ( - "Numărul e prea mare pentru a fi convertit în cuvinte." + "Numărul e prea mare pentru a fi convertit în cuvinte (abs(%s) > %s)." ) self.mid_numwords = [(1000, "mie/i"), (100, "sută/e"), (90, "nouăzeci"), (80, "optzeci"), diff --git a/num2words/lang_SL.py b/num2words/lang_SL.py index fb0e2876..cecbbc79 100644 --- a/num2words/lang_SL.py +++ b/num2words/lang_SL.py @@ -31,7 +31,7 @@ def setup(self): self.negword = "minus " self.pointword = "celih" self.errmsg_nonnum = "Only numbers may be converted to words." - self.errmsg_toobig = "Number is too large to convert to words." + self.errmsg_toobig = "Number is too large to convert to words (abs(%s) > %s)." self.exclude_title = [] self.mid_numwords = [(1000, "tisoč"), (900, "devetsto"), diff --git a/tests/test_fr.py b/tests/test_fr.py index 538be341..873473ae 100644 --- a/tests/test_fr.py +++ b/tests/test_fr.py @@ -149,7 +149,7 @@ ) -class Num2WordsENTest(TestCase): +class Num2WordsFRTest(TestCase): def test_ordinal_special_joins(self): # ref https://github.com/savoirfairelinux/num2words/issues/18 self.assertEqual( @@ -203,3 +203,10 @@ def test_currency_usd(self): num2words(test[0], lang='fr', to='currency', currency='USD'), test[1] ) + + def test_max_numbers(self): + + with self.assertRaises(OverflowError) as context: + num2words(10 ** 700, lang='fr') + + self.assertTrue('trop grand' in str(context.exception)) From f55f7c81e020d391984bbaf39cc1df18d35f94d6 Mon Sep 17 00:00:00 2001 From: Jeronymous Date: Wed, 29 Mar 2023 15:54:12 +0200 Subject: [PATCH 177/200] uniform use of errmsg_toobig and MAXVAL --- num2words/lang_AR.py | 23 ++++++++++++++--------- num2words/lang_FA.py | 5 +++-- num2words/lang_ID.py | 6 +++--- tests/test_ar.py | 2 +- 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/num2words/lang_AR.py b/num2words/lang_AR.py index 71286354..11f51f3b 100644 --- a/num2words/lang_AR.py +++ b/num2words/lang_AR.py @@ -38,11 +38,13 @@ ] -class Num2Word_AR(object): - errmsg_too_big = "Too large" - max_num = 10 ** 36 +class Num2Word_AR(object): # Num2Word_Base ? + errmsg_toobig = "abs(%s) must be less than %s." + MAXVAL = 1000000000000000050331649 # 10 **36 def __init__(self): + super().__init__() + self.number = 0 self.arabicPrefixText = "" self.arabicSuffixText = "" @@ -96,6 +98,9 @@ def __init__(self): "", "آلاف", "ملايين", "مليارات", "تريليونات", "كوادريليونات", "كوينتليونات", "سكستيليونات" ] + 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 @@ -163,6 +168,8 @@ def process_arabic_group(self, group_number, group_level, if tens > 0: if tens < 20: + if int(group_level) >= len(self.arabicTwos): + raise OverflowError(self.errmsg_toobig % (self.number, self.MAXVAL)) if tens == 2 and int(hundreds) == 0 and group_level > 0: if self.integer_value in [2000, 2000000, 2000000000, 2000000000000, 2000000000000000, @@ -237,20 +244,18 @@ def convert_to_arabic(self): if ret_val != "": ret_val = "{}و {}".format("", ret_val) if number_to_process != 2: + if group >= len(self.arabicGroup): + raise OverflowError(self.errmsg_toobig % (self.number, self.MAXVAL)) if number_to_process % 100 != 1: if 3 <= number_to_process <= 10: ret_val = "{} {}".format( self.arabicPluralGroups[group], ret_val) else: if ret_val != "": - if group >= len(self.arabicAppendedGroup): - raise OverflowError(self.errmsg_too_big) ret_val = "{} {}".format( self.arabicAppendedGroup[group], ret_val) else: - if group >= len(self.arabicGroup): - raise OverflowError(self.errmsg_too_big) ret_val = "{} {}".format( self.arabicGroup[group], ret_val) @@ -304,8 +309,8 @@ def convert_to_arabic(self): return formatted_number def validate_number(self, number): - if number >= self.max_num: - raise OverflowError(self.errmsg_too_big) + if number >= self.MAXVAL: + raise OverflowError(self.errmsg_toobig % (number, self.MAXVAL)) return number def set_currency_prefer(self, currency): diff --git a/num2words/lang_FA.py b/num2words/lang_FA.py index f652f255..3597b08c 100644 --- a/num2words/lang_FA.py +++ b/num2words/lang_FA.py @@ -78,8 +78,9 @@ class Num2Word_FA(object): - errmsg_too_big = "Too large" - max_num = 10 ** 36 + # Those are unused + errmsg_toobig = "Too large" + MAXNUM = 10 ** 36 def __init__(self): self.number = 0 diff --git a/num2words/lang_ID.py b/num2words/lang_ID.py index 1973e7e8..54e636f9 100644 --- a/num2words/lang_ID.py +++ b/num2words/lang_ID.py @@ -45,7 +45,7 @@ class Num2Word_ID(): 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)." - max_num = 10 ** 36 + MAXVAL = 10 ** 36 def split_by_koma(self, number): return str(number).split('.') @@ -169,8 +169,8 @@ def join(self, word_blocks, float_part): return ' '.join(word_list) + float_part def to_cardinal(self, number): - if number >= self.max_num: - raise OverflowError(self.errmsg_toobig % (number, self.max_num)) + if number >= self.MAXVAL: + raise OverflowError(self.errmsg_toobig % (number, self.MAXVAL)) minus = '' if number < 0: minus = 'min ' diff --git a/tests/test_ar.py b/tests/test_ar.py index fda08b48..f5f56214 100644 --- a/tests/test_ar.py +++ b/tests/test_ar.py @@ -130,4 +130,4 @@ def test_max_numbers(self): with self.assertRaises(OverflowError) as context: num2words(number, lang='ar') - self.assertTrue('Too large' in str(context.exception)) + self.assertTrue('must be less' in str(context.exception)) From 0f233c5b4c950e2610ecb77a1e42eaeb4f6cb79d Mon Sep 17 00:00:00 2001 From: Jeronymous Date: Wed, 29 Mar 2023 16:26:17 +0200 Subject: [PATCH 178/200] Resolves part of https://github.com/savoirfairelinux/num2words/issues/403 : results after calling to ordinal conversion should not change --- num2words/lang_AR.py | 1 + tests/test_ar.py | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/num2words/lang_AR.py b/num2words/lang_AR.py index 11f51f3b..722fe192 100644 --- a/num2words/lang_AR.py +++ b/num2words/lang_AR.py @@ -354,6 +354,7 @@ 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: diff --git a/tests/test_ar.py b/tests/test_ar.py index f5f56214..b98c5906 100644 --- a/tests/test_ar.py +++ b/tests/test_ar.py @@ -68,6 +68,8 @@ def test_currency_parm(self): 'واحد مليون دينار و تسع و تسعون فلس') def test_ordinal(self): + + self.assertEqual(num2words(1, to='ordinal', lang='ar'), 'اول') self.assertEqual(num2words(2, to='ordinal', lang='ar'), 'ثاني') self.assertEqual(num2words(3, to='ordinal', lang='ar'), 'ثالث') @@ -84,6 +86,11 @@ def test_ordinal(self): num2words(923411, to='ordinal_num', lang='ar'), 'تسعمائة و ثلاثة و عشرون ألفاً و أربعمائة و أحد عشر') + # See https://github.com/savoirfairelinux/num2words/issues/403 + self.assertEqual(num2words(23, lang="ar"), 'ثلاثة و عشرون') + self.assertEqual(num2words(23, to='ordinal', lang="ar"), 'ثلاث و عشرون') + self.assertEqual(num2words(23, lang="ar"), 'ثلاثة و عشرون') + def test_cardinal(self): self.assertEqual(num2words(12, to='cardinal', lang='ar'), 'اثنا عشر') self.assertEqual(num2words(-8324, to='cardinal', lang='ar'), From 8002ed41c3fd2f21b117db4e919469eb1826427f Mon Sep 17 00:00:00 2001 From: Jeronymous Date: Thu, 30 Mar 2023 08:48:58 +0200 Subject: [PATCH 179/200] Resolves https://github.com/savoirfairelinux/num2words/issues/394 : make the CLI work with Arabic --- num2words/lang_AR.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/num2words/lang_AR.py b/num2words/lang_AR.py index 722fe192..935b9797 100644 --- a/num2words/lang_AR.py +++ b/num2words/lang_AR.py @@ -37,8 +37,10 @@ "تسعة عشر" ] +from .base import Num2Word_Base -class Num2Word_AR(object): # Num2Word_Base ? + +class Num2Word_AR(Num2Word_Base): errmsg_toobig = "abs(%s) must be less than %s." MAXVAL = 1000000000000000050331649 # 10 **36 From 45a8d503b4f7ebb4dc0f920f45d258650c32c715 Mon Sep 17 00:00:00 2001 From: hedi naouara Date: Thu, 30 Mar 2023 14:04:39 +0100 Subject: [PATCH 180/200] add big numbers until Quintinillion add a test function for a big numbers --- num2words/lang_AR.py | 39 +++++++++++++++++++++++++++++---------- tests/test_ar.py | 15 +++++++++++++-- 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/num2words/lang_AR.py b/num2words/lang_AR.py index 935b9797..438267ea 100644 --- a/num2words/lang_AR.py +++ b/num2words/lang_AR.py @@ -42,7 +42,7 @@ class Num2Word_AR(Num2Word_Base): errmsg_toobig = "abs(%s) must be less than %s." - MAXVAL = 1000000000000000050331649 # 10 **36 + MAXVAL = 9999999999999999999999999999999999999999999999999 # 1000000000000000050331649 # 10 **36 def __init__(self): super().__init__() @@ -79,26 +79,37 @@ def __init__(self): self.arabicHundreds = [ "", "مائة", "مئتان", "ثلاثمائة", "أربعمائة", "خمسمائة", "ستمائة", "سبعمائة", "ثمانمائة", "تسعمائة" - ] + ] # should be : ["تسعة مائة","ثمانية مائة","سبعة مائة","ستة مائة","خمسة مائة","أربعة مائة","ثلاثة مائة","مئتان","مائة"] + self.arabicAppendedTwos = [ "مئتا", "ألفا", "مليونا", "مليارا", "تريليونا", "كوادريليونا", - "كوينتليونا", "سكستيليونا" + "كوينتليونا", "سكستيليونا","سبتيليونا","أوكتيليونا ","نونيليونا", + "ديسيليونا","أندسيليونا","دوديسيليونا","تريديسيليونا","كوادريسيليونا", + "كوينتينيليونا" ] self.arabicTwos = [ "مئتان", "ألفان", "مليونان", "ملياران", "تريليونان", - "كوادريليونان", "كوينتليونان", "سكستيليونان" + "كوادريليونان", "كوينتليونان", "سكستيليونان","سبتيليونان", + "أوكتيليونان ","نونيليونان ","ديسيليونان","أندسيليونان", + "دوديسيليونان","تريديسيليونان","كوادريسيليونان","كوينتينيليونان" ] self.arabicGroup = [ "مائة", "ألف", "مليون", "مليار", "تريليون", "كوادريليون", - "كوينتليون", "سكستيليون" + "كوينتليون", "سكستيليون","سبتيليون","أوكتيليون","نونيليون", + "ديسيليون","أندسيليون","دوديسيليون","تريديسيليون","كوادريسيليون", + "كوينتينيليون" ] self.arabicAppendedGroup = [ "", "ألفاً", "مليوناً", "ملياراً", "تريليوناً", "كوادريليوناً", - "كوينتليوناً", "سكستيليوناً" + "كوينتليوناً", "سكستيليوناً","سبتيليوناً","أوكتيليوناً","نونيليوناً", + "ديسيليوناً","أندسيليوناً","دوديسيليوناً","تريديسيليوناً","كوادريسيليوناً", + "كوينتينيليوناً" ] self.arabicPluralGroups = [ "", "آلاف", "ملايين", "مليارات", "تريليونات", "كوادريليونات", - "كوينتليونات", "سكستيليونات" + "كوينتليونات", "سكستيليونات","سبتيليونات","أوكتيليونات","نونيليونات", + "ديسيليونات","أندسيليونات","دوديسيليونات","تريديسيليونات","كوادريسيليونات", + "كوينتينيليونات" ] assert len(self.arabicAppendedGroup) == len(self.arabicGroup) assert len(self.arabicPluralGroups) == len(self.arabicGroup) @@ -209,8 +220,16 @@ def process_arabic_group(self, group_number, group_level, return ret_val + def abs(self, number): + return number if number >= 0 else -number + + def to_str(self, number): + integer = int(number) + decimal = round((number - integer) * 10**9) + return str(integer) + "." + "{:09d}".format(decimal) + def convert(self, value): - self.number = "{:.9f}".format(value) + self.number = self.to_str(value) self.number_to_arabic(self.arabicPrefixText, self.arabicSuffixText) return self.convert_to_arabic() @@ -346,7 +365,7 @@ def to_ordinal(self, number, prefix=''): self.currency_unit = ('', '', '', '') self.arabicPrefixText = prefix self.arabicSuffixText = "" - return "{}".format(self.convert(abs(number)).strip()) + return "{}".format(self.convert(self.abs(number)).strip()) def to_year(self, value): value = self.validate_number(value) @@ -367,4 +386,4 @@ def to_cardinal(self, number): self.arabicPrefixText = "" self.arabicSuffixText = "" self.arabicOnes = ARABIC_ONES - return minus + self.convert(value=abs(number)).strip() + return minus + self.convert(value=self.abs(number)).strip() diff --git a/tests/test_ar.py b/tests/test_ar.py index b98c5906..f7645478 100644 --- a/tests/test_ar.py +++ b/tests/test_ar.py @@ -132,9 +132,20 @@ def test_year(self): def test_max_numbers(self): - for number in 10 ** 36, 123456789123456789123456789, 123456789123456789123456789123456789: - + for number in 9999999999999999999999999999999999999999999999999, 10000000000000000000000000000000000000000000000000: + with self.assertRaises(OverflowError) as context: num2words(number, lang='ar') self.assertTrue('must be less' in str(context.exception)) + + def test_big_numbers(self): + self.assertEqual(num2words(1000000045000000000000003000000002000000300, to='cardinal', lang='ar'), + 'واحد تريديسيليون و خمسة و أربعون ديسيليوناً و ثلاثة كوينتليونات و ملياران و ثلاثمائة' + ) + self.assertEqual(num2words(-1000000000000000000000003000000002000000302, to='cardinal', lang='ar'), + 'سالب واحد تريديسيليون و ثلاثة كوينتليونات و ملياران و ثلاثمائة و اثنان' + ) + self.assertEqual(num2words(9999999999999999999999999999999999999999999999992, to='cardinal', lang='ar'), + 'تسعة كوينتينيليونات و تسعمائةتسعة و تسعون كوادريسيليوناً و تسعمائةتسعة و تسعون تريديسيليوناً و تسعمائةتسعة و تسعون دوديسيليوناً و تسعمائةتسعة و تسعون أندسيليوناً و تسعمائةتسعة و تسعون ديسيليوناً و تسعمائةتسعة و تسعون نونيليوناً و تسعمائةتسعة و تسعون أوكتيليوناً و تسعمائةتسعة و تسعون سبتيليوناً و تسعمائةتسعة و تسعون سكستيليوناً و تسعمائةتسعة و تسعون كوينتليوناً و تسعمائةتسعة و تسعون كوادريليوناً و تسعمائةتسعة و تسعون تريليوناً و تسعمائةتسعة و تسعون ملياراً و تسعمائةتسعة و تسعون مليوناً و تسعمائةتسعة و تسعون ألفاً و تسعمائةاثنان و تسعون' + ) \ No newline at end of file From 55061d66cff7a489eb6634906c7f12a8f164a2fd Mon Sep 17 00:00:00 2001 From: KhramtsovDR Date: Sun, 2 Apr 2023 23:14:56 +0300 Subject: [PATCH 181/200] RU - adding cases, plural and animate --- num2words/lang_RU.py | 554 +++++++++++++++++++++++++++++-------------- tests/test_ru.py | 158 ++++++++++-- 2 files changed, 513 insertions(+), 199 deletions(-) diff --git a/num2words/lang_RU.py b/num2words/lang_RU.py index b87f9b9d..efaca2db 100644 --- a/num2words/lang_RU.py +++ b/num2words/lang_RU.py @@ -20,92 +20,225 @@ from .base import Num2Word_Base from .utils import get_digits, splitbyx -ZERO = 'ноль' +GENDER_PLURAL_INDEXES = { + 'm': 0, 'masculine': 0, 'м': 0, 'мужской': 0, + 'f': 1, 'feminine': 1, 'ж': 0, 'женский': 0, + 'n': 2, 'neuter': 2, 'с': 0, 'средний': 0, + 'p': 3, 'plural': 3 +} +CASE_INDEXES = { + 'n': 0, 'nominative': 0, 'и': 0, 'именительный': 0, + 'g': 1, 'genitive': 1, 'р': 1, 'родительный': 1, + 'd': 2, 'dative': 2, 'д': 2, 'дательный': 2, + 'a': 3, 'accusative': 3, 'в': 3, 'винительный': 3, + 'i': 4, 'instrumental': 4, 'т': 4, 'творительный': 4, + 'p': 5, 'prepositional': 5, 'п': 5, 'предложный': 5 +} +# Default values +D_CASE = 'n' +D_PLURAL = False +D_GENDER = 'm' +D_ANIMATE = True + + +def get_num_element(cases_dict, num, **kwargs): + return case_classifier_element(cases_dict[num], **kwargs) + + +def case_classifier_element(classifier, case=D_CASE, plural=D_PLURAL, + gender=D_GENDER, animate=D_ANIMATE): + case = classifier[CASE_INDEXES[case]] + if isinstance(case, str): + return case + if plural: + gender = case[GENDER_PLURAL_INDEXES['plural']] + else: + gender = case[GENDER_PLURAL_INDEXES[gender]] + if isinstance(gender, str): + return gender + + if animate: + return gender[0] + return gender[1] + + +# format: +# {n : [case_1 .. case_5]} +# case: text or [gender_1 .. gender_3 plural_4] +# gender: text or [animate, inanimate] 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: 'девять', - } + 0: ['ноль', 'ноля', 'нолю', 'ноль', 'нолём', 'ноле'], + 1: [['один', 'одна', 'одно', 'одни'], + ['одного', 'одной', 'одного', 'одних'], + ['одному', 'одной', 'одному', 'одним'], + [['одного', 'один'], 'одну', 'одно', ['одних', 'одни']], + ['одним', 'одной', 'одним', 'одними'], + ['одном', 'одной', 'одном', 'одних']], + 2: [['два', 'две', 'два', 'двое'], + ['двух'] * 3 + ['двоих'], + ['двум'] * 3 + ['двоим'], + [['двух', 'два'], ['двух', 'две'], 'два', 'двоих'], + ['двумя'] * 3 + ['двоими'], + ['двух'] * 3 + ['двоих']], + 3: [['три'] * 3 + ['трое'], + ['трёх'] * 3 + ['троих'], + ['трём'] * 3 + ['троим'], + [['трёх', 'три'], ['трёх', 'три'], 'три', 'троих'], + ['тремя'] * 3 + ['троими'], + ['трёх'] * 3 + ['троих']], + 4: [['четыре'] * 3 + ['четверо'], + ['четырёх'] * 3 + ['четверых'], + ['четырём'] * 3 + ['четверым'], + [['четырёх', 'четыре'], ['четырёх', 'четыре'], 'четыре', 'четверых'], + ['четырьмя'] * 3 + ['четверыми'], + ['четырёх'] * 3 + ['четверых']], + 5: ['пять', 'пяти', 'пяти', 'пять', 'пятью', 'пяти'], + 6: ['шесть', 'шести', 'шести', 'шесть', 'шестью', 'шести'], + 7: ['семь', 'семи', 'семи', 'семь', 'семью', 'семи'], + 8: ['восемь', 'восьми', 'восьми', 'восемь', 'восемью', 'восьми'], + 9: ['девять', 'девяти', 'девяти', 'девять', 'девятью', 'девяти'] } -TENS = { - 0: 'десять', - 1: 'одиннадцать', - 2: 'двенадцать', - 3: 'тринадцать', - 4: 'четырнадцать', - 5: 'пятнадцать', - 6: 'шестнадцать', - 7: 'семнадцать', - 8: 'восемнадцать', - 9: 'девятнадцать', +ONES_ORD_PREFIXES = {0: 'нулев', 1: 'перв', 2: 'втор', 4: 'четвёрт', 5: 'пят', + 6: 'шест', 7: 'седьм', 8: 'восьм', 9: 'девят'} +ONES_ORD_POSTFIXES_GROUPS = {0: 0, 1: 1, 2: 0, 4: 1, 5: 1, 6: 0, 7: 0, 8: 0, + 9: 1} +CASE_POSTFIXES = [[{0: 'ой', 1: 'ый'}, 'ая', 'ое', 'ые'], + ['ого', 'ой', 'ого', 'ых'], + ['ому', 'ой', 'ому', 'ым'], + [['ого', {0: 'ой', 1: 'ый'}], 'ую', 'ое', ['ых', 'ые']], + ['ым', 'ой', 'ым', 'ыми'], + ['ом', 'ой', 'ом', 'ых']] + + +def get_cases(prefix, post_group): + return [[ + prefix + postfix if isinstance(postfix, str) else + [prefix + animate if isinstance(animate, str) else + prefix + animate[post_group] + for animate in postfix] if isinstance(postfix, list) else + prefix + postfix[post_group] + for postfix in case] + for case in CASE_POSTFIXES] + + +def get_ord_classifier(prefixes, post_groups): + if isinstance(post_groups, int): + post_groups = {n: post_groups for n, i in prefixes.items()} + return { + num: get_cases(prefix, post_groups[num]) + for num, prefix in prefixes.items() + } + +ONES_ORD = { + 3: [['третий', 'третья', 'третье', 'третьи'], + ['третьего', 'третьей', 'третьего', 'третьих'], + ['третьему', 'третьей', 'третьему', 'третьим'], + [['третьего', 'третий'], 'третью', 'третье', ['третьих', 'третьи']], + ['третьим', 'третьей', 'третьим', 'третьими'], + ['третьем', 'третьей', 'третьем', 'третьих']], } +ONES_ORD.update( + get_ord_classifier(ONES_ORD_PREFIXES, ONES_ORD_POSTFIXES_GROUPS) +) + +TENS_PREFIXES = {1: 'один', 2: 'две', 3: 'три', 4: 'четыр', 5: 'пят', 6: 'шест', + 7: 'сем', 8: 'восем', 9: 'девят'} +TENS_POSTFIXES = ['надцать', 'надцати', 'надцати', 'надцать', 'надцатью', + 'надцати'] +TENS = {0: ['десять', 'десяти', 'десяти', 'десять', 'десятью', 'десяти']} +TENS.update({ + num: [prefix + postfix for postfix in TENS_POSTFIXES] + for num, prefix in TENS_PREFIXES.items() +}) + +TENS_ORD_PREFIXES = {0: "десят"} +TENS_ORD_PREFIXES.update({ + num: prefix + 'надцат' for num, prefix in TENS_PREFIXES.items() +}) +TENS_ORD = get_ord_classifier(TENS_ORD_PREFIXES, 1) TWENTIES = { - 2: 'двадцать', - 3: 'тридцать', - 4: 'сорок', - 5: 'пятьдесят', - 6: 'шестьдесят', - 7: 'семьдесят', - 8: 'восемьдесят', - 9: 'девяносто', + 2: ['двадцать', 'двадцати', 'двадцати', 'двадцать', 'двадцатью', + 'двадцати'], + 3: ['тридцать', 'тридцати', 'тридцати', 'тридцать', 'тридцатью', + 'тридцати'], + 4: ['сорок', 'сорока', 'сорока', 'сорок', 'сорока', 'сорока'], + 5: ['пятьдесят', 'пятидесяти', 'пятидесяти', 'пятьдесят', 'пятьюдесятью', + 'пятидесяти'], + 6: ['шестьдесят', 'шестидесяти', 'шестидесяти', 'шестьдесят', + 'шестьюдесятью', 'шестидесяти'], + 7: ['семьдесят', 'семидесяти', 'семидесяти', 'семьдесят', 'семьюдесятью', + 'семидесяти'], + 8: ['восемьдесят', 'восьмидесяти', 'восьмидесяти', 'восемьдесят', + 'восемьюдесятью', 'восьмидесяти'], + 9: ['девяносто', 'девяноста', 'девяноста', 'девяносто', 'девяноста', + 'девяноста'], } +TWENTIES_ORD_PREFIXES = {2: 'двадцат', 3: 'тридцат', 4: 'сороков', + 5: 'пятидесят',6: 'шестидесят', 7: 'семидесят', + 8: 'восьмидесят', 9: 'девяност'} +TWENTIES_ORD_POSTFIXES_GROUPS = {2: 1, 3: 1, 4: 0, 5: 1, 6: 1, 7: 1, 8: 1, 9: 1} +TWENTIES_ORD = get_ord_classifier(TWENTIES_ORD_PREFIXES, + TWENTIES_ORD_POSTFIXES_GROUPS) + HUNDREDS = { - 1: 'сто', - 2: 'двести', - 3: 'триста', - 4: 'четыреста', - 5: 'пятьсот', - 6: 'шестьсот', - 7: 'семьсот', - 8: 'восемьсот', - 9: 'девятьсот', + 1: ['сто', 'ста', 'ста', 'сто', 'ста', 'ста'], + 2: ['двести', 'двухсот', 'двумстам', 'двести', 'двумястами', 'двухстах'], + 3: ['триста', 'трёхсот', 'трёмстам', 'триста', 'тремястами', 'трёхстах'], + 4: ['четыреста', 'четырёхсот', 'четырёмстам', 'четыреста', 'четырьмястами', + 'четырёхстах'], + 5: ['пятьсот', 'пятисот', 'пятистам', 'пятьсот', 'пятьюстами', 'пятистах'], + 6: ['шестьсот', 'шестисот', 'шестистам', 'шестьсот', 'шестьюстами', + 'шестистах'], + 7: ['семьсот', 'семисот', 'семистам', 'семьсот', 'семьюстами', 'семистах'], + 8: ['восемьсот', 'восьмисот', 'восьмистам', 'восемьсот', 'восемьюстами', + 'восьмистах'], + 9: ['девятьсот', 'девятисот', 'девятистам', 'девятьсот', 'девятьюстами', + 'девятистах'], } +HUNDREDS_ORD_PREFIXES = { + num: case[1] if num != 1 else 'сот' for num, case in HUNDREDS.items() +} +HUNDREDS_ORD = get_ord_classifier(HUNDREDS_ORD_PREFIXES, 1) + + +THOUSANDS_PREFIXES = {2: 'миллион', 3: 'миллиард', 4: 'триллион', + 5: 'квадриллион', 6: 'квинтиллион', 7: 'секстиллион', + 8: 'септиллион', 9: 'октиллион', 10: 'нониллион'} +THOUSANDS_POSTFIXES = [('', 'а', 'ов'), + ('а', 'ов', 'ов'), + ('у', 'ам', 'ам'), + ('', 'а', 'ов'), + ('ом', 'ами', 'ами'), + ('е', 'ах', 'ах')] 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 + 1: [['тысяча', 'тысячи', 'тысяч'], + ['тысячи', 'тысяч', 'тысяч'], + ['тысяче', 'тысячам', 'тысячам'], + ['тысячу', 'тысячи', 'тысяч'], + ['тысячей', 'тысячами', 'тысячами'], + ['тысяче', 'тысячах', 'тысячах']] } +THOUSANDS.update({ + num: [ + [prefix + postfix for postfix in case] for case in THOUSANDS_POSTFIXES + ] for num, prefix in THOUSANDS_PREFIXES.items() +}) + + +def get_thousands_elements(num, case): + return THOUSANDS[num][CASE_INDEXES[case]] + + +THOUSANDS_ORD_PREFIXES = {1: 'тысячн'} +THOUSANDS_ORD_PREFIXES.update({ + num: prefix + 'н' for num, prefix in THOUSANDS_PREFIXES.items() +}) +THOUSANDS_ORD = get_ord_classifier(THOUSANDS_ORD_PREFIXES, 1) class Num2Word_RU(Num2Word_Base): @@ -136,43 +269,30 @@ class Num2Word_RU(Num2Word_Base): def setup(self): self.negword = "минус" - self.pointword = "запятая" - self.ords = {"ноль": "нулевой", - "один": "первый", - "два": "второй", - "три": "третий", - "четыре": "четвертый", - "пять": "пятый", - "шесть": "шестой", - "семь": "седьмой", - "восемь": "восьмой", - "девять": "девятый", - "сто": "сотый"} - self.ords_adjective = {"один": "", - "одна": "", - "две": "двух", - "три": "трёх", - "четыре": "четырёх", - "пять": "пяти", - "шесть": "шести", - "семь": "семи", - "восемь": "восьми", - "девять": "девяти"} - - def to_cardinal(self, number, gender='m'): + self.pointword = ('целая', 'целых', 'целых') + self.pointword_ord = get_cases("цел", 1) + + def to_cardinal(self, number, case=D_CASE, plural=D_PLURAL, gender=D_GENDER, + animate=D_ANIMATE): n = str(number).replace(',', '.') if '.' in n: left, right = n.split('.') - leading_zero_count = len(right) - len(right.lstrip('0')) - decimal_part = ((ZERO + ' ') * leading_zero_count + - self._int2word(int(right), gender)) - return u'%s %s %s' % ( - self._int2word(int(left), gender), - self.pointword, - decimal_part + decimal_part = self._int2word(int(right), cardinal=True, gender='f') + return u'%s %s %s %s' % ( + self._int2word(int(left), cardinal=True, gender='f'), + self.pluralize(int(left), self.pointword), + decimal_part, + self.__decimal_bitness(right) ) else: - return self._int2word(int(n), gender) + return self._int2word(int(n), cardinal=True, case=case, + plural=plural, gender=gender, animate=animate) + + def __decimal_bitness(self, n): + l = len(n) + if n[-1] == "1" and n[-2:] != "11": + return self._int2word(10 ** l, cardinal=False, gender='f') + return self._int2word(10 ** l, cardinal=False, case='g', plural='t') def pluralize(self, n, forms): if n % 100 in (11, 12, 13, 14): @@ -183,82 +303,66 @@ def pluralize(self, n, forms): return forms[1] return forms[2] - def to_ordinal(self, number, gender='m'): + def to_ordinal(self, number, case=D_CASE, plural=D_PLURAL, gender=D_GENDER, + animate=D_ANIMATE): self.verify_ordinal(number) - outwords = self.to_cardinal(number, 'm').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[-1] == "ь" or lastword[-2] == "т": - lastword = lastword[:-1] + "ый" - elif lastword[-1] == "к": - lastword = lastword + "овой" - elif lastword[-5:] == "десят": - 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[-1] == "д" or lastword[-2] == "д": - lastword = lastword[:lastword.rfind('д') + 1] + "ный" - - if gender == 'f': - if lastword[-2:] == "ий": - lastword = lastword[:-2] + "ья" - else: - lastword = lastword[:-2] + "ая" - if gender == 'n': - if lastword[-2:] == "ий": - lastword = lastword[:-2] + "ье" - else: - lastword = lastword[:-2] + "ое" - - outwords[-1] = self.title(lastword) - return " ".join(outwords).strip() + n = str(number).replace(',', '.') + return self._int2word(int(n), cardinal=False, case=case, plural=plural, + gender=gender, animate=animate) def _money_verbose(self, number, currency): if currency == 'UAH': - gender = 'f' - else: - gender = 'm' - - return self._int2word(number, gender) + return self._int2word(number, gender='f') + return self._int2word(number, gender='m') def _cents_verbose(self, number, currency): if currency in ('UAH', 'RUB', 'BYN'): + return self._int2word(number, gender='f') + return self._int2word(number, gender='m') + + def _int2word(self, n, feminine=False, cardinal=True, case=D_CASE, + plural=D_PLURAL, gender=D_GENDER, animate=D_ANIMATE): + """ + n: number + feminine: not used - for backward compatibility + gender: 'f' - masculine + 'm' - feminine + 'n' - neuter + case: 'n' - nominative + 'g' - genitive + 'd' - dative + 'a' - accusative + 'i' - instrumental + 'p' - prepositional + animate: True - animate + False - inanimate + ordinal: True - ordinal + False - cardinal + """ + # For backward compatibility + if feminine: gender = 'f' - else: - gender = 'm' - return self._int2word(number, gender) + kwargs = {'case': case, 'plural': plural, 'gender': gender, + 'animate': animate} - def _int2word(self, n, gender): if n < 0: - return ' '.join([self.negword, self._int2word(abs(n), gender)]) + return ' '.join([self.negword, self._int2word(abs(n), + cardinal=cardinal, + **kwargs)]) if n == 0: - return ZERO + return get_num_element(ONES, 0, **kwargs) if cardinal else \ + get_num_element(ONES_ORD, 0, **kwargs) words = [] chunks = list(splitbyx(str(n), 3)) + ord_join = chunks[-1] == 0 # join in one word if ending on 'тысячный' i = len(chunks) + rightest_nonzero_chunk_i = i - 1 - max( + [i for i, e in enumerate(chunks) if e != 0]) for x in chunks: + chunk_words = [] i -= 1 if x == 0: @@ -266,25 +370,117 @@ def _int2word(self, n, gender): n1, n2, n3 = get_digits(x) - if n3 > 0: - words.append(HUNDREDS[n3]) + if cardinal: + chunk_words.extend( + self.__chunk_cardianl(n3, n2, n1, i, **kwargs) + ) + if i > 0: + chunk_words.append( + self.pluralize(x, get_thousands_elements(i, case))) + # ordinal, not joined like 'двухтысячный' + elif not (ord_join and rightest_nonzero_chunk_i == i): + chunk_words.extend( + self.__chunk_ordinal(n3, n2, n1, i, **kwargs) + ) + if i > 0: + t_case = case if rightest_nonzero_chunk_i == i else 'n' + chunk_words.append( + self.pluralize(x, get_thousands_elements(i, t_case))) + # ordinal, joined + else: + chunk_words.extend( + self.__chunk_ordinal_join(n3, n2, n1, i, **kwargs) + ) + if i > 0: + chunk_words.append( + get_num_element(THOUSANDS_ORD, i, **kwargs)) - if n2 > 1: - words.append(TWENTIES[n2]) + chunk_words = [''.join(chunk_words)] - if n2 == 1: - words.append(TENS[n1]) - elif n1 > 0: - if i == 0: - ones = ONES[gender] - elif i == 1: - ones = ONES['f'] # Thousands is feminine - else: - ones = ONES['m'] + words.extend(chunk_words) - words.append(ones[n1]) + return ' '.join(words) + + def __chunk_cardianl(self, hundreds, tens, ones, chunk_num, **kwargs): + words = [] + if hundreds > 0: + words.append(get_num_element(HUNDREDS, hundreds, **kwargs)) + + if tens > 1: + words.append(get_num_element(TWENTIES, tens, **kwargs)) + + if tens == 1: + words.append(get_num_element(TENS, ones, **kwargs)) + elif ones > 0: + if chunk_num == 0: + w_ones = get_num_element(ONES, ones, **kwargs) + elif chunk_num == 1: + # Thousands are feminine + f_kwargs = kwargs.copy() + f_kwargs['gender'] = 'f' + w_ones = get_num_element(ONES, ones, **f_kwargs) + else: + w_ones = get_num_element(ONES, ones, **kwargs) - if i > 0: - words.append(self.pluralize(x, THOUSANDS[i])) + words.append(w_ones) + return words - return ' '.join(words) + def __chunk_ordinal(self, hundreds, tens, ones, chunk_num, **kwargs): + words = [] + if hundreds > 0: + if tens == 0 and ones == 0: + words.append(get_num_element(HUNDREDS_ORD, hundreds, **kwargs)) + else: + words.append(get_num_element(HUNDREDS, hundreds)) + + if tens > 1: + if ones == 0: + words.append(get_num_element(TWENTIES_ORD, tens, **kwargs)) + else: + words.append(get_num_element(TWENTIES, tens)) + + if tens == 1: + words.append(get_num_element(TENS_ORD, ones, **kwargs)) + elif ones > 0: + if chunk_num == 0: + w_ones = get_num_element(ONES_ORD, ones, **kwargs) + # тысячный, миллионнный и т.д. + elif chunk_num > 0 and ones == 1 and hundreds == 0 and tens == 0: + w_ones = None + elif chunk_num == 1: + # Thousands are feminine + w_ones = get_num_element(ONES, ones, gender='f') + else: + w_ones = get_num_element(ONES, ones) + + if w_ones: + words.append(w_ones) + + return words + + def __chunk_ordinal_join(self, hundreds, tens, ones, chunk_num, **kwargs): + words = [] + if hundreds > 0: + words.append(get_num_element(HUNDREDS, hundreds)) + + if tens > 1: + words.append(get_num_element(TWENTIES, tens, case='g')) + + if tens == 1: + words.append(get_num_element(TENS, ones, case='g')) + elif ones > 0: + if chunk_num == 0: + w_ones = get_num_element(ONES_ORD, ones, **kwargs) + # тысячный, миллионнный и т.д., двадцатиоднамиллионный + elif chunk_num > 0 and ones == 1 and tens != 1: + if tens == 0 and hundreds == 0: + w_ones = None + else: + w_ones = get_num_element(ONES, 1, gender='f') + else: + w_ones = get_num_element(ONES, ones, case='g') + + if w_ones: + words.append(w_ones) + + return words diff --git a/tests/test_ru.py b/tests/test_ru.py index 388cf2a9..3bbd784c 100644 --- a/tests/test_ru.py +++ b/tests/test_ru.py @@ -35,7 +35,8 @@ def test_cardinal(self): self.assertEqual(num2words(2012, lang='ru'), "две тысячи двенадцать") self.assertEqual( num2words(12519.85, lang='ru'), - "двенадцать тысяч пятьсот девятнадцать запятая восемьдесят пять") + "двенадцать тысяч пятьсот девятнадцать целых восемьдесят пять сотых" + ) self.assertEqual( num2words(1234567890, lang='ru'), "один миллиард двести тридцать четыре миллиона пятьсот " @@ -73,7 +74,7 @@ def test_cardinal(self): self.assertEqual(num2words(-15, lang='ru'), "минус пятнадцать") self.assertEqual(num2words(-100, lang='ru'), "минус сто") - def test_feminine(self): + def test_cardinal_feminine(self): self.assertEqual(num2words(1, lang='ru', gender='f'), 'одна') self.assertEqual(num2words(2, lang='ru', gender='f'), 'две') self.assertEqual(num2words(3, lang='ru', gender='f'), 'три') @@ -88,12 +89,12 @@ def test_feminine(self): ) self.assertEqual( num2words(125.1, lang='ru', gender='f'), - 'сто двадцать пять запятая одна' + 'сто двадцать пять целых одна десятая' ) self.assertEqual(num2words(-1, lang='ru', gender='f'), "минус одна") self.assertEqual(num2words(-100, lang='ru', gender='f'), "минус сто") - def test_neuter(self): + def test_cardinal_neuter(self): self.assertEqual(num2words(1, lang='ru', gender='n'), 'одно') self.assertEqual(num2words(2, lang='ru', gender='n'), 'два') self.assertEqual(num2words(3, lang='ru', gender='n'), 'три') @@ -108,26 +109,30 @@ def test_neuter(self): ) self.assertEqual( num2words(125.1, lang='ru', gender='n'), - 'сто двадцать пять запятая одно') + 'сто двадцать пять целых одна десятая') self.assertEqual(num2words(-1, lang='ru', gender='n'), "минус одно") self.assertEqual(num2words(-100, lang='ru', gender='n'), "минус сто") def test_floating_point(self): - self.assertEqual(num2words(5.2, lang='ru'), "пять запятая два") - self.assertEqual( - num2words(10.02, lang='ru'), - "десять запятая ноль два" - ) - self.assertEqual( - num2words(15.007, lang='ru'), - "пятнадцать запятая ноль ноль семь" - ) - self.assertEqual( - num2words(561.42, lang='ru'), - "пятьсот шестьдесят один запятая сорок два" - ) + self.assertEqual(num2words(5.2, lang='ru'), "пять целых две десятых") + self.assertEqual(num2words(1.001, lang='ru'), + "одна целая одна тысячная") + self.assertEqual(num2words(1.011, lang='ru'), + "одна целая одиннадцать тысячных") + self.assertEqual(num2words(10.02, lang='ru'), + "десять целых две сотых") + self.assertEqual(num2words(15.007, lang='ru'), + "пятнадцать целых семь тысячных") + self.assertEqual(num2words(561.42, lang='ru'), + "пятьсот шестьдесят одна целая сорок две сотых") + self.assertEqual(num2words(561.00001, lang='ru'), + "пятьсот шестьдесят одна целая одна стотысячная") def test_to_ordinal(self): + self.assertEqual( + num2words(0, lang='ru', to='ordinal'), + 'нулевой' + ) self.assertEqual( num2words(1, lang='ru', to='ordinal'), 'первый' @@ -181,18 +186,54 @@ def test_to_ordinal(self): num2words(1001, lang='ru', to='ordinal'), 'тысяча первый' ) + self.assertEqual( + num2words(1060, lang='ru', to='ordinal'), + 'тысяча шестидесятый' + ) self.assertEqual( num2words(2000, lang='ru', to='ordinal'), - 'двух тысячный' + 'двухтысячный' ) self.assertEqual( num2words(10000, lang='ru', to='ordinal'), - 'десяти тысячный' + 'десятитысячный' + ) + self.assertEqual( + num2words(21000, lang='ru', to='ordinal'), + 'двадцатиоднатысячный' + ) + self.assertEqual( + num2words(130000, lang='ru', to='ordinal'), + 'стотридцатитысячный' + ) + self.assertEqual( + num2words(135000, lang='ru', to='ordinal'), + 'стотридцатипятитысячный' + ) + self.assertEqual( + num2words(135100, lang='ru', to='ordinal'), + 'сто тридцать пять тысяч сотый' + ) + self.assertEqual( + num2words(135120, lang='ru', to='ordinal'), + 'сто тридцать пять тысяч сто двадцатый' + ) + self.assertEqual( + num2words(135121, lang='ru', to='ordinal'), + 'сто тридцать пять тысяч сто двадцать первый' ) self.assertEqual( num2words(1000000, lang='ru', to='ordinal'), 'миллионный' ) + self.assertEqual( + num2words(2000000, lang='ru', to='ordinal'), + 'двухмиллионный' + ) + self.assertEqual( + num2words(5135000, lang='ru', to='ordinal'), + 'пять миллионов стотридцатипятитысячный' + ) self.assertEqual( num2words(1000000000, lang='ru', to='ordinal'), 'миллиардный' @@ -215,6 +256,10 @@ def test_to_ordinal_feminine(self): self.assertEqual( num2words(1000, lang='ru', to='ordinal', gender='f'), 'тысячная' ) + self.assertEqual( + num2words(2000000, lang='ru', to='ordinal', gender='f'), + 'двухмиллионная' + ) def test_to_ordinal_neuter(self): self.assertEqual( @@ -233,6 +278,79 @@ def test_to_ordinal_neuter(self): self.assertEqual( num2words(1000, lang='ru', to='ordinal', gender='n'), 'тысячное' ) + self.assertEqual( + num2words(2000000, lang='ru', to='ordinal', gender='n'), + 'двухмиллионное' + ) + + def test_cardinal_cases(self): + self.assertEqual( + num2words(1, lang='ru', case='nominative'), 'один') + self.assertEqual( + num2words(1, lang='ru', case='genitive'), 'одного') + self.assertEqual( + num2words(1, lang='ru', case='a', plural=True, animate=False), + 'одни') + self.assertEqual( + num2words(2, lang='ru', case='a', gender='f', animate=True), + 'двух') + self.assertEqual( + num2words(2, lang='ru', case='a', gender='f', animate=False), + 'две') + self.assertEqual( + num2words(100, lang='ru', case='g'), + 'ста') + self.assertEqual( + num2words(122, lang='ru', case='d'), + 'ста двадцати двум') + self.assertEqual( + num2words(1000, lang='ru', case='p'), + 'одной тысяче') + self.assertEqual( + num2words(1122, lang='ru', case='p'), + 'одной тысяче ста двадцати двух') + self.assertEqual( + num2words(1211, lang='ru', case='i', gender='f'), + 'одной тысячей двумястами одиннадцатью') + self.assertEqual( + num2words(5121000, lang='ru', case='i'), + 'пятью миллионами ста двадцатью одной тысячей') + + def test_ordinal_cases(self): + self.assertEqual( + num2words(1, lang='ru', to='ordinal', case='nominative'), 'первый') + self.assertEqual( + num2words(1, lang='ru', to='ordinal', case='genitive'), 'первого') + self.assertEqual( + num2words(1, lang='ru', to='ordinal', case='a', plural=True, + animate=False), + 'первые') + self.assertEqual( + num2words(2, lang='ru', to='ordinal', case='a', gender='f', + animate=True), + 'вторую') + self.assertEqual( + num2words(2, lang='ru', to='ordinal', case='a', gender='f', + animate=False), + 'вторую') + self.assertEqual( + num2words(100, lang='ru', to='ordinal', case='g'), + 'сотого') + self.assertEqual( + num2words(122, lang='ru', to='ordinal', case='d'), + 'сто двадцать второму') + self.assertEqual( + num2words(1000, lang='ru', to='ordinal', case='p'), + 'тысячном') + self.assertEqual( + num2words(1122, lang='ru', to='ordinal', case='p'), + 'тысяча сто двадцать втором') + self.assertEqual( + num2words(1211, lang='ru', to='ordinal', case='i', gender='f'), + 'тысяча двести одиннадцатой') + self.assertEqual( + num2words(5121000, lang='ru', to='ordinal', case='i'), + 'пять миллионов стодвадцатиоднатысячным') def test_to_currency(self): self.assertEqual( From 283d3ca8fcdedd21ff18cb40edd5bcd406ffae28 Mon Sep 17 00:00:00 2001 From: hedi naouara Date: Mon, 3 Apr 2023 15:25:04 +0100 Subject: [PATCH 182/200] solve ar: -chahnge the max number to 10 ** 51 -1 -solve the et in 262 and others -add some tests --- num2words/lang_AR.py | 18 ++++++++---------- tests/test_ar.py | 10 ++++++++-- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/num2words/lang_AR.py b/num2words/lang_AR.py index 438267ea..69c40e66 100644 --- a/num2words/lang_AR.py +++ b/num2words/lang_AR.py @@ -42,7 +42,7 @@ class Num2Word_AR(Num2Word_Base): errmsg_toobig = "abs(%s) must be less than %s." - MAXVAL = 9999999999999999999999999999999999999999999999999 # 1000000000000000050331649 # 10 **36 + MAXVAL = 10**51 - 1 # 9999999999999999999999999999999999999999999999999 # 1000000000000000050331649 # 10 **36 def __init__(self): super().__init__() @@ -172,12 +172,14 @@ def process_arabic_group(self, group_number, group_level, 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: @@ -186,16 +188,14 @@ def process_arabic_group(self, group_number, group_level, if tens == 2 and int(hundreds) == 0 and group_level > 0: if self.integer_value in [2000, 2000000, 2000000000, 2000000000000, 2000000000000000, - 2000000000000000000]: + 2000000000000000000,2000000000000000000000,2000000000000000000000000 + ]: ret_val = "{}".format( self.arabicAppendedTwos[int(group_level)]) else: ret_val = "{}".format( self.arabicTwos[int(group_level)]) else: - if ret_val != "": - ret_val += " و " - if tens == 1 and group_level > 0 and hundreds == 0: ret_val += "" elif (tens == 1 or tens == 2) and ( @@ -209,14 +209,12 @@ def process_arabic_group(self, group_number, group_level, ones = tens % 10 tens = (tens / 10) - 2 if ones > 0: - if ret_val != "" and tens < 4: - ret_val += " و " - ret_val += self.digit_feminine_status(ones, group_level) - if ret_val != "": + if ret_val != "" and ones != 0: ret_val += " و " ret_val += self.arabicTens[int(tens)] + return ret_val diff --git a/tests/test_ar.py b/tests/test_ar.py index f7645478..cf0ca23e 100644 --- a/tests/test_ar.py +++ b/tests/test_ar.py @@ -110,6 +110,12 @@ def test_cardinal(self): #'سبعة مائة و واحد و أربعون' 'سبعمائة و واحد و أربعون' ) + self.assertEqual(num2words(262, to='cardinal', lang='ar'), + 'مئتان و اثنان و ستون' + ) + self.assertEqual(num2words(798, to='cardinal', lang='ar'), + 'سبعمائة و ثمانية و تسعون' + ) self.assertEqual(num2words(710, to='cardinal', lang='ar'), 'سبعمائة و عشرة') self.assertEqual(num2words(711, to='cardinal', lang='ar'), @@ -132,7 +138,7 @@ def test_year(self): def test_max_numbers(self): - for number in 9999999999999999999999999999999999999999999999999, 10000000000000000000000000000000000000000000000000: + for number in 10**51 - 1 , 10**51: with self.assertRaises(OverflowError) as context: num2words(number, lang='ar') @@ -147,5 +153,5 @@ def test_big_numbers(self): 'سالب واحد تريديسيليون و ثلاثة كوينتليونات و ملياران و ثلاثمائة و اثنان' ) self.assertEqual(num2words(9999999999999999999999999999999999999999999999992, to='cardinal', lang='ar'), - 'تسعة كوينتينيليونات و تسعمائةتسعة و تسعون كوادريسيليوناً و تسعمائةتسعة و تسعون تريديسيليوناً و تسعمائةتسعة و تسعون دوديسيليوناً و تسعمائةتسعة و تسعون أندسيليوناً و تسعمائةتسعة و تسعون ديسيليوناً و تسعمائةتسعة و تسعون نونيليوناً و تسعمائةتسعة و تسعون أوكتيليوناً و تسعمائةتسعة و تسعون سبتيليوناً و تسعمائةتسعة و تسعون سكستيليوناً و تسعمائةتسعة و تسعون كوينتليوناً و تسعمائةتسعة و تسعون كوادريليوناً و تسعمائةتسعة و تسعون تريليوناً و تسعمائةتسعة و تسعون ملياراً و تسعمائةتسعة و تسعون مليوناً و تسعمائةتسعة و تسعون ألفاً و تسعمائةاثنان و تسعون' + 'تسعة كوينتينيليونات و تسعمائة و تسعة و تسعون كوادريسيليوناً و تسعمائة و تسعة و تسعون تريديسيليوناً و تسعمائة و تسعة و تسعون دوديسيليوناً و تسعمائة و تسعة و تسعون أندسيليوناً و تسعمائة و تسعة و تسعون ديسيليوناً و تسعمائة و تسعة و تسعون نونيليوناً و تسعمائة و تسعة و تسعون أوكتيليوناً و تسعمائة و تسعة و تسعون سبتيليوناً و تسعمائة و تسعة و تسعون سكستيليوناً و تسعمائة و تسعة و تسعون كوينتليوناً و تسعمائة و تسعة و تسعون كوادريليوناً و تسعمائة و تسعة و تسعون تريليوناً و تسعمائة و تسعة و تسعون ملياراً و تسعمائة و تسعة و تسعون مليوناً و تسعمائة و تسعة و تسعون ألفاً و تسعمائة و اثنان و تسعون' ) \ No newline at end of file From c5c4c59988499540c55fbac798372591c3f6a0fd Mon Sep 17 00:00:00 2001 From: KhramtsovDR Date: Mon, 3 Apr 2023 17:26:41 +0300 Subject: [PATCH 183/200] Fix error with ordinal 21000 ( https://russian.stackexchange.com/a/4386 ) --- num2words/lang_RU.py | 2 +- tests/test_ru.py | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/num2words/lang_RU.py b/num2words/lang_RU.py index efaca2db..b34f0e31 100644 --- a/num2words/lang_RU.py +++ b/num2words/lang_RU.py @@ -476,7 +476,7 @@ def __chunk_ordinal_join(self, hundreds, tens, ones, chunk_num, **kwargs): if tens == 0 and hundreds == 0: w_ones = None else: - w_ones = get_num_element(ONES, 1, gender='f') + w_ones = get_num_element(ONES, 1, gender='n') else: w_ones = get_num_element(ONES, ones, case='g') diff --git a/tests/test_ru.py b/tests/test_ru.py index 3bbd784c..ea13bb7f 100644 --- a/tests/test_ru.py +++ b/tests/test_ru.py @@ -115,6 +115,7 @@ def test_cardinal_neuter(self): def test_floating_point(self): self.assertEqual(num2words(5.2, lang='ru'), "пять целых две десятых") + self.assertEqual(num2words(5.0, lang='ru'), "пять целых ноль десятых") self.assertEqual(num2words(1.001, lang='ru'), "одна целая одна тысячная") self.assertEqual(num2words(1.011, lang='ru'), @@ -200,7 +201,7 @@ def test_to_ordinal(self): ) self.assertEqual( num2words(21000, lang='ru', to='ordinal'), - 'двадцатиоднатысячный' + 'двадцатиоднотысячный' ) self.assertEqual( num2words(130000, lang='ru', to='ordinal'), @@ -350,7 +351,7 @@ def test_ordinal_cases(self): 'тысяча двести одиннадцатой') self.assertEqual( num2words(5121000, lang='ru', to='ordinal', case='i'), - 'пять миллионов стодвадцатиоднатысячным') + 'пять миллионов стодвадцатиоднотысячным') def test_to_currency(self): self.assertEqual( From 7883b2936bbe2574d704c515fb2f63246b8f58da Mon Sep 17 00:00:00 2001 From: Mario Monroy Date: Mon, 3 Apr 2023 12:22:28 -0600 Subject: [PATCH 184/200] FIx --- num2words/lang_ES.py | 1 - tests/test_es_gt.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/num2words/lang_ES.py b/num2words/lang_ES.py index 3dc70141..de2d1e13 100644 --- a/num2words/lang_ES.py +++ b/num2words/lang_ES.py @@ -206,7 +206,6 @@ class Num2Word_ES(Num2Word_EU): 'ZRZ': (('zaire', 'zaires'), ('likuta', 'makuta')), 'ZWL': (GENERIC_DOLLARS, ('céntimo', 'céntimos')), 'ZWL': (GENERIC_DOLLARS, ('céntimo', 'céntimos')), - 'GTQ': (('quetzal', 'quetzales'), GENERIC_CENTS), } # //CHECK: Is this sufficient?? diff --git a/tests/test_es_gt.py b/tests/test_es_gt.py index 1c9429fa..b65f8d33 100644 --- a/tests/test_es_gt.py +++ b/tests/test_es_gt.py @@ -48,7 +48,7 @@ def test_ordinal(self): def test_ordinal_num(self): for test in test_es.TEST_CASES_ORDINAL_NUM: self.assertEqual( - num2words(test[0], lang='es', to='ordinal_num'), + num2words(test[0], lang='es_GT', to='ordinal_num'), test[1] ) From 4863fb16b0bcc234b2f66dd1dad17d0a0cbcfe14 Mon Sep 17 00:00:00 2001 From: hedi naouara Date: Tue, 4 Apr 2023 09:54:18 +0100 Subject: [PATCH 185/200] solving ar issues: - change maxval to 10 ** 51. - add comments to abs & to_str functions. - change a list of integer_value by a pow condition --- num2words/lang_AR.py | 13 +++++++------ tests/test_ar.py | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/num2words/lang_AR.py b/num2words/lang_AR.py index 69c40e66..da3a1321 100644 --- a/num2words/lang_AR.py +++ b/num2words/lang_AR.py @@ -17,6 +17,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA +import math import re import decimal from decimal import Decimal @@ -42,7 +43,7 @@ class Num2Word_AR(Num2Word_Base): errmsg_toobig = "abs(%s) must be less than %s." - MAXVAL = 10**51 - 1 # 9999999999999999999999999999999999999999999999999 # 1000000000000000050331649 # 10 **36 + MAXVAL = 10**51 # 9999999999999999999999999999999999999999999999999 # 1000000000000000050331649 # 10 **36 def __init__(self): super().__init__() @@ -186,10 +187,8 @@ def process_arabic_group(self, group_number, group_level, if int(group_level) >= len(self.arabicTwos): raise OverflowError(self.errmsg_toobig % (self.number, self.MAXVAL)) if tens == 2 and int(hundreds) == 0 and group_level > 0: - if self.integer_value in [2000, 2000000, 2000000000, - 2000000000000, 2000000000000000, - 2000000000000000000,2000000000000000000000,2000000000000000000000000 - ]: + 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: @@ -217,10 +216,12 @@ def process_arabic_group(self, group_number, group_level, 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) decimal = round((number - integer) * 10**9) diff --git a/tests/test_ar.py b/tests/test_ar.py index cf0ca23e..d9c695fd 100644 --- a/tests/test_ar.py +++ b/tests/test_ar.py @@ -138,7 +138,7 @@ def test_year(self): def test_max_numbers(self): - for number in 10**51 - 1 , 10**51: + for number in 10**51,10**51 + 2: with self.assertRaises(OverflowError) as context: num2words(number, lang='ar') From 667723aca42e5f9023c70e55d6593dbc0424b73e Mon Sep 17 00:00:00 2001 From: hedi naouara Date: Wed, 5 Apr 2023 08:56:30 +0100 Subject: [PATCH 186/200] solve the one problem --- num2words/lang_AR.py | 12 +++++++----- tests/test_ar.py | 26 ++++++++++++++++++-------- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/num2words/lang_AR.py b/num2words/lang_AR.py index da3a1321..7e23d2c6 100644 --- a/num2words/lang_AR.py +++ b/num2words/lang_AR.py @@ -164,10 +164,9 @@ def digit_feminine_status(self, digit, group_level): 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) @@ -195,12 +194,15 @@ def process_arabic_group(self, group_number, group_level, ret_val = "{}".format( self.arabicTwos[int(group_level)]) else: + if tens == 1 and group_level > 0 and hundreds == 0: ret_val += "" elif (tens == 1 or tens == 2) and ( group_level == 0 or group_level == -1) and \ hundreds == 0 and remaining_number == 0: 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) @@ -263,11 +265,11 @@ def convert_to_arabic(self): if group > 0: if ret_val != "": ret_val = "{}و {}".format("", ret_val) - if number_to_process != 2: + if number_to_process != 2 and number_to_process != 1: if group >= len(self.arabicGroup): raise OverflowError(self.errmsg_toobig % (self.number, self.MAXVAL)) if number_to_process % 100 != 1: - if 3 <= number_to_process <= 10: + if 3 <= number_to_process <= 9: ret_val = "{} {}".format( self.arabicPluralGroups[group], ret_val) else: @@ -278,7 +280,7 @@ def convert_to_arabic(self): else: ret_val = "{} {}".format( self.arabicGroup[group], ret_val) - + else: ret_val = "{} {}".format(self.arabicGroup[group], ret_val) diff --git a/tests/test_ar.py b/tests/test_ar.py index d9c695fd..3a292209 100644 --- a/tests/test_ar.py +++ b/tests/test_ar.py @@ -38,17 +38,17 @@ def test_default_currency(self): self.assertEqual(num2words(541, to='currency', lang='ar'), 'خمسمائة و واحد و أربعون ريالاً') self.assertEqual(num2words(10000, to='currency', lang='ar'), - 'عشرة آلاف ريال') + 'عشرة ألف ريال') self.assertEqual(num2words(20000.12, to='currency', lang='ar'), 'عشرون ألف ريال و اثنتا عشرة هللة') self.assertEqual(num2words(1000000, to='currency', lang='ar'), - 'واحد مليون ريال') + 'مليون ريال') val = 'تسعمائة و ثلاثة و عشرون ألفاً و أربعمائة و أحد عشر ريالاً' self.assertEqual(num2words(923411, to='currency', lang='ar'), val) self.assertEqual(num2words(63411, to='currency', lang='ar'), 'ثلاثة و ستون ألفاً و أربعمائة و أحد عشر ريالاً') self.assertEqual(num2words(1000000.99, to='currency', lang='ar'), - 'واحد مليون ريال و تسع و تسعون هللة') + 'مليون ريال و تسع و تسعون هللة') def test_currency_parm(self): self.assertEqual( @@ -65,7 +65,7 @@ def test_currency_parm(self): 'تسعمائة و ثلاثة و عشرون ألفاً و أربعمائة و أحد عشر ريالاً') self.assertEqual( num2words(1000000.99, to='currency', lang='ar', currency="KWD"), - 'واحد مليون دينار و تسع و تسعون فلس') + 'مليون دينار و تسع و تسعون فلس') def test_ordinal(self): @@ -103,7 +103,7 @@ def test_cardinal(self): self.assertEqual(num2words(94231, to='cardinal', lang='ar'), 'أربعة و تسعون ألفاً و مئتان و واحد و ثلاثون') self.assertEqual(num2words(1431, to='cardinal', lang='ar'), - 'واحد ألف و أربعمائة و واحد و ثلاثون') + 'ألف و أربعمائة و واحد و ثلاثون') self.assertEqual(num2words(740, to='cardinal', lang='ar'), 'سبعمائة و أربعون') self.assertEqual(num2words(741, to='cardinal', lang='ar'), @@ -127,6 +127,14 @@ def test_cardinal(self): self.assertEqual(num2words(701, to='cardinal', lang='ar'), 'سبعمائة و واحد') + self.assertEqual(num2words(1258888, to='cardinal', lang='ar'), + 'مليون و مئتان و ثمانية و خمسون ألفاً و ثمانمائة و ثمانية و ثمانون') + + self.assertEqual(num2words(1100, to='cardinal', lang='ar'), + 'ألف و مائة') + + self.assertEqual(num2words(1000000521, to='cardinal', lang='ar'), + 'مليار و خمسمائة و واحد و عشرون') def test_prefix_and_suffix(self): self.assertEqual(num2words(645, to='currency', @@ -147,11 +155,13 @@ def test_max_numbers(self): def test_big_numbers(self): self.assertEqual(num2words(1000000045000000000000003000000002000000300, to='cardinal', lang='ar'), - 'واحد تريديسيليون و خمسة و أربعون ديسيليوناً و ثلاثة كوينتليونات و ملياران و ثلاثمائة' + 'تريديسيليون و خمسة و أربعون ديسيليوناً و ثلاثة كوينتليونات و ملياران و ثلاثمائة' ) self.assertEqual(num2words(-1000000000000000000000003000000002000000302, to='cardinal', lang='ar'), - 'سالب واحد تريديسيليون و ثلاثة كوينتليونات و ملياران و ثلاثمائة و اثنان' + 'سالب تريديسيليون و ثلاثة كوينتليونات و ملياران و ثلاثمائة و اثنان' ) self.assertEqual(num2words(9999999999999999999999999999999999999999999999992, to='cardinal', lang='ar'), 'تسعة كوينتينيليونات و تسعمائة و تسعة و تسعون كوادريسيليوناً و تسعمائة و تسعة و تسعون تريديسيليوناً و تسعمائة و تسعة و تسعون دوديسيليوناً و تسعمائة و تسعة و تسعون أندسيليوناً و تسعمائة و تسعة و تسعون ديسيليوناً و تسعمائة و تسعة و تسعون نونيليوناً و تسعمائة و تسعة و تسعون أوكتيليوناً و تسعمائة و تسعة و تسعون سبتيليوناً و تسعمائة و تسعة و تسعون سكستيليوناً و تسعمائة و تسعة و تسعون كوينتليوناً و تسعمائة و تسعة و تسعون كوادريليوناً و تسعمائة و تسعة و تسعون تريليوناً و تسعمائة و تسعة و تسعون ملياراً و تسعمائة و تسعة و تسعون مليوناً و تسعمائة و تسعة و تسعون ألفاً و تسعمائة و اثنان و تسعون' - ) \ No newline at end of file + ) + + \ No newline at end of file From ff9385fb95a4a4a6d644140782a1005559137e43 Mon Sep 17 00:00:00 2001 From: hedi naouara Date: Wed, 5 Apr 2023 08:58:03 +0100 Subject: [PATCH 187/200] solve the 10000 currency problem --- num2words/lang_AR.py | 2 +- tests/test_ar.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/num2words/lang_AR.py b/num2words/lang_AR.py index 7e23d2c6..e40b107c 100644 --- a/num2words/lang_AR.py +++ b/num2words/lang_AR.py @@ -269,7 +269,7 @@ def convert_to_arabic(self): if group >= len(self.arabicGroup): raise OverflowError(self.errmsg_toobig % (self.number, self.MAXVAL)) if number_to_process % 100 != 1: - if 3 <= number_to_process <= 9: + if 3 <= number_to_process <= 10: ret_val = "{} {}".format( self.arabicPluralGroups[group], ret_val) else: diff --git a/tests/test_ar.py b/tests/test_ar.py index 3a292209..20058f05 100644 --- a/tests/test_ar.py +++ b/tests/test_ar.py @@ -38,7 +38,7 @@ def test_default_currency(self): self.assertEqual(num2words(541, to='currency', lang='ar'), 'خمسمائة و واحد و أربعون ريالاً') self.assertEqual(num2words(10000, to='currency', lang='ar'), - 'عشرة ألف ريال') + 'عشرة آلاف ريال') self.assertEqual(num2words(20000.12, to='currency', lang='ar'), 'عشرون ألف ريال و اثنتا عشرة هللة') self.assertEqual(num2words(1000000, to='currency', lang='ar'), From 02a04c91ac206d1087b334b572043e8b262c1d14 Mon Sep 17 00:00:00 2001 From: Mario Monroy Date: Wed, 5 Apr 2023 18:54:58 -0600 Subject: [PATCH 188/200] fixes flake8 --- num2words/__init__.py | 2 +- num2words/lang_ES_GT.py | 9 ++++++--- tests/test_es.py | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/num2words/__init__.py b/num2words/__init__.py index 9193ab5a..5b975107 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -43,9 +43,9 @@ 'eo': lang_EO.Num2Word_EO(), 'es': lang_ES.Num2Word_ES(), 'es_CO': lang_ES_CO.Num2Word_ES_CO(), + 'es_GT': lang_ES_GT.Num2Word_ES_GT(), 'es_NI': lang_ES_NI.Num2Word_ES_NI(), 'es_VE': lang_ES_VE.Num2Word_ES_VE(), - 'es_GT': lang_ES_GT.Num2Word_ES_GT(), 'id': lang_ID.Num2Word_ID(), 'ja': lang_JA.Num2Word_JA(), 'kn': lang_KN.Num2Word_KN(), diff --git a/num2words/lang_ES_GT.py b/num2words/lang_ES_GT.py index 70902fc1..9bc4c750 100644 --- a/num2words/lang_ES_GT.py +++ b/num2words/lang_ES_GT.py @@ -23,7 +23,10 @@ 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" + 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") diff --git a/tests/test_es.py b/tests/test_es.py index 68a14e0f..a2c1242b 100644 --- a/tests/test_es.py +++ b/tests/test_es.py @@ -2742,7 +2742,7 @@ def test_currency_qar(self): def test_currency_qtq(self): for test in TEST_CASES_TO_CURRENCY_GTQ: self.assertEqual( - num2words(test[0], lang='es', to='currency', currency='QTQ'), + num2words(test[0], lang='es', to='currency', currency='GTQ'), test[1] ) From 373f6420f697bbc2acf92b6746d77f4066b04d18 Mon Sep 17 00:00:00 2001 From: KhramtsovDR Date: Thu, 6 Apr 2023 11:29:53 +0300 Subject: [PATCH 189/200] Fix 100000 and 90000 ordinal exceptions --- num2words/lang_RU.py | 13 +++++++++---- tests/test_ru.py | 16 ++++++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/num2words/lang_RU.py b/num2words/lang_RU.py index b34f0e31..4a3bbf90 100644 --- a/num2words/lang_RU.py +++ b/num2words/lang_RU.py @@ -460,10 +460,15 @@ def __chunk_ordinal(self, hundreds, tens, ones, chunk_num, **kwargs): def __chunk_ordinal_join(self, hundreds, tens, ones, chunk_num, **kwargs): words = [] - if hundreds > 0: - words.append(get_num_element(HUNDREDS, hundreds)) - if tens > 1: + if hundreds > 1: + words.append(get_num_element(HUNDREDS, hundreds, case='g')) + elif hundreds == 1: + words.append(get_num_element(HUNDREDS, hundreds)) # стО, not стА + + if tens == 9: + words.append(get_num_element(TWENTIES, tens)) # девяностО, not А + elif tens > 1: words.append(get_num_element(TWENTIES, tens, case='g')) if tens == 1: @@ -471,7 +476,7 @@ def __chunk_ordinal_join(self, hundreds, tens, ones, chunk_num, **kwargs): elif ones > 0: if chunk_num == 0: w_ones = get_num_element(ONES_ORD, ones, **kwargs) - # тысячный, миллионнный и т.д., двадцатиоднамиллионный + # тысячный, миллионнный и т.д., двадцатиодномиллионный elif chunk_num > 0 and ones == 1 and tens != 1: if tens == 0 and hundreds == 0: w_ones = None diff --git a/tests/test_ru.py b/tests/test_ru.py index ea13bb7f..6cf85b3e 100644 --- a/tests/test_ru.py +++ b/tests/test_ru.py @@ -199,6 +199,10 @@ def test_to_ordinal(self): num2words(10000, lang='ru', to='ordinal'), 'десятитысячный' ) + self.assertEqual( + num2words(90000, lang='ru', to='ordinal'), + 'девяностотысячный' + ) self.assertEqual( num2words(21000, lang='ru', to='ordinal'), 'двадцатиоднотысячный' @@ -223,6 +227,10 @@ def test_to_ordinal(self): num2words(135121, lang='ru', to='ordinal'), 'сто тридцать пять тысяч сто двадцать первый' ) + self.assertEqual( + num2words(190000, lang='ru', to='ordinal'), + 'стодевяностотысячный' + ) self.assertEqual( num2words(1000000, lang='ru', to='ordinal'), 'миллионный' @@ -235,10 +243,18 @@ def test_to_ordinal(self): num2words(5135000, lang='ru', to='ordinal'), 'пять миллионов стотридцатипятитысячный' ) + self.assertEqual( + num2words(21000000, lang='ru', to='ordinal'), + 'двадцатиодномиллионный' + ) self.assertEqual( num2words(1000000000, lang='ru', to='ordinal'), 'миллиардный' ) + self.assertEqual( + num2words(123456000000, lang='ru', to='ordinal'), + 'сто двадцать три миллиарда четырёхсотпятидесятишестимиллионный' + ) def test_to_ordinal_feminine(self): self.assertEqual( From b9c6c632d4e69982bbd98b6c4801a2a5199841e9 Mon Sep 17 00:00:00 2001 From: Jeronymous Date: Fri, 7 Apr 2023 11:11:22 +0200 Subject: [PATCH 190/200] format code --- num2words/lang_AR.py | 52 +++++++++++++++++++-------------------- tests/test_ar.py | 58 +++++++++++++++++++++----------------------- 2 files changed, 54 insertions(+), 56 deletions(-) diff --git a/num2words/lang_AR.py b/num2words/lang_AR.py index e40b107c..036b7d0d 100644 --- a/num2words/lang_AR.py +++ b/num2words/lang_AR.py @@ -17,6 +17,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA +from .base import Num2Word_Base import math import re import decimal @@ -38,12 +39,10 @@ "تسعة عشر" ] -from .base import Num2Word_Base - class Num2Word_AR(Num2Word_Base): errmsg_toobig = "abs(%s) must be less than %s." - MAXVAL = 10**51 # 9999999999999999999999999999999999999999999999999 # 1000000000000000050331649 # 10 **36 + MAXVAL = 10**51 def __init__(self): super().__init__() @@ -80,36 +79,36 @@ def __init__(self): self.arabicHundreds = [ "", "مائة", "مئتان", "ثلاثمائة", "أربعمائة", "خمسمائة", "ستمائة", "سبعمائة", "ثمانمائة", "تسعمائة" - ] # should be : ["تسعة مائة","ثمانية مائة","سبعة مائة","ستة مائة","خمسة مائة","أربعة مائة","ثلاثة مائة","مئتان","مائة"] + ] # should be : ["تسعة مائة","ثمانية مائة","سبعة مائة","ستة مائة","خمسة مائة","أربعة مائة","ثلاثة مائة","مئتان","مائة"] self.arabicAppendedTwos = [ "مئتا", "ألفا", "مليونا", "مليارا", "تريليونا", "كوادريليونا", - "كوينتليونا", "سكستيليونا","سبتيليونا","أوكتيليونا ","نونيليونا", - "ديسيليونا","أندسيليونا","دوديسيليونا","تريديسيليونا","كوادريسيليونا", + "كوينتليونا", "سكستيليونا", "سبتيليونا", "أوكتيليونا ", "نونيليونا", + "ديسيليونا", "أندسيليونا", "دوديسيليونا", "تريديسيليونا", "كوادريسيليونا", "كوينتينيليونا" ] self.arabicTwos = [ "مئتان", "ألفان", "مليونان", "ملياران", "تريليونان", - "كوادريليونان", "كوينتليونان", "سكستيليونان","سبتيليونان", - "أوكتيليونان ","نونيليونان ","ديسيليونان","أندسيليونان", - "دوديسيليونان","تريديسيليونان","كوادريسيليونان","كوينتينيليونان" + "كوادريليونان", "كوينتليونان", "سكستيليونان", "سبتيليونان", + "أوكتيليونان ", "نونيليونان ", "ديسيليونان", "أندسيليونان", + "دوديسيليونان", "تريديسيليونان", "كوادريسيليونان", "كوينتينيليونان" ] self.arabicGroup = [ "مائة", "ألف", "مليون", "مليار", "تريليون", "كوادريليون", - "كوينتليون", "سكستيليون","سبتيليون","أوكتيليون","نونيليون", - "ديسيليون","أندسيليون","دوديسيليون","تريديسيليون","كوادريسيليون", + "كوينتليون", "سكستيليون", "سبتيليون", "أوكتيليون", "نونيليون", + "ديسيليون", "أندسيليون", "دوديسيليون", "تريديسيليون", "كوادريسيليون", "كوينتينيليون" ] self.arabicAppendedGroup = [ "", "ألفاً", "مليوناً", "ملياراً", "تريليوناً", "كوادريليوناً", - "كوينتليوناً", "سكستيليوناً","سبتيليوناً","أوكتيليوناً","نونيليوناً", - "ديسيليوناً","أندسيليوناً","دوديسيليوناً","تريديسيليوناً","كوادريسيليوناً", + "كوينتليوناً", "سكستيليوناً", "سبتيليوناً", "أوكتيليوناً", "نونيليوناً", + "ديسيليوناً", "أندسيليوناً", "دوديسيليوناً", "تريديسيليوناً", "كوادريسيليوناً", "كوينتينيليوناً" ] self.arabicPluralGroups = [ "", "آلاف", "ملايين", "مليارات", "تريليونات", "كوادريليونات", - "كوينتليونات", "سكستيليونات","سبتيليونات","أوكتيليونات","نونيليونات", - "ديسيليونات","أندسيليونات","دوديسيليونات","تريديسيليونات","كوادريسيليونات", + "كوينتليونات", "سكستيليونات", "سبتيليونات", "أوكتيليونات", "نونيليونات", + "ديسيليونات", "أندسيليونات", "دوديسيليونات", "تريديسيليونات", "كوادريسيليونات", "كوينتينيليونات" ] assert len(self.arabicAppendedGroup) == len(self.arabicGroup) @@ -166,25 +165,26 @@ def digit_feminine_status(self, digit, group_level): 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: + 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)) + raise OverflowError(self.errmsg_toobig % + (self.number, self.MAXVAL)) 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): @@ -194,7 +194,7 @@ def process_arabic_group(self, group_number, group_level, ret_val = "{}".format( self.arabicTwos[int(group_level)]) else: - + if tens == 1 and group_level > 0 and hundreds == 0: ret_val += "" elif (tens == 1 or tens == 2) and ( @@ -215,14 +215,13 @@ def process_arabic_group(self, group_number, group_level, 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) @@ -251,7 +250,7 @@ def convert_to_arabic(self): temp_number_dec = Decimal(str(temp_number)) try: number_to_process = int(temp_number_dec % Decimal(str(1000))) - except decimal.InvalidOperation: # https://stackoverflow.com/questions/42868278/decimal-invalidoperation-divisionimpossible-for-very-large-numbers + except decimal.InvalidOperation: # https://stackoverflow.com/questions/42868278/decimal-invalidoperation-divisionimpossible-for-very-large-numbers decimal.getcontext().prec = len(temp_number_dec.as_tuple().digits) number_to_process = int(temp_number_dec % Decimal(str(1000))) @@ -267,7 +266,8 @@ def convert_to_arabic(self): 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)) + raise OverflowError( + self.errmsg_toobig % (self.number, self.MAXVAL)) if number_to_process % 100 != 1: if 3 <= number_to_process <= 10: ret_val = "{} {}".format( @@ -280,7 +280,7 @@ def convert_to_arabic(self): else: ret_val = "{} {}".format( self.arabicGroup[group], ret_val) - + else: ret_val = "{} {}".format(self.arabicGroup[group], ret_val) diff --git a/tests/test_ar.py b/tests/test_ar.py index 20058f05..1c0c9754 100644 --- a/tests/test_ar.py +++ b/tests/test_ar.py @@ -69,7 +69,6 @@ def test_currency_parm(self): def test_ordinal(self): - self.assertEqual(num2words(1, to='ordinal', lang='ar'), 'اول') self.assertEqual(num2words(2, to='ordinal', lang='ar'), 'ثاني') self.assertEqual(num2words(3, to='ordinal', lang='ar'), 'ثالث') @@ -87,8 +86,9 @@ def test_ordinal(self): 'تسعمائة و ثلاثة و عشرون ألفاً و أربعمائة و أحد عشر') # See https://github.com/savoirfairelinux/num2words/issues/403 - self.assertEqual(num2words(23, lang="ar"), 'ثلاثة و عشرون') - self.assertEqual(num2words(23, to='ordinal', lang="ar"), 'ثلاث و عشرون') + self.assertEqual(num2words(23, lang="ar"), 'ثلاثة و عشرون') + self.assertEqual(num2words(23, to='ordinal', + lang="ar"), 'ثلاث و عشرون') self.assertEqual(num2words(23, lang="ar"), 'ثلاثة و عشرون') def test_cardinal(self): @@ -107,34 +107,34 @@ def test_cardinal(self): self.assertEqual(num2words(740, to='cardinal', lang='ar'), 'سبعمائة و أربعون') self.assertEqual(num2words(741, to='cardinal', lang='ar'), - #'سبعة مائة و واحد و أربعون' - 'سبعمائة و واحد و أربعون' - ) + # 'سبعة مائة و واحد و أربعون' + 'سبعمائة و واحد و أربعون' + ) self.assertEqual(num2words(262, to='cardinal', lang='ar'), - 'مئتان و اثنان و ستون' - ) + 'مئتان و اثنان و ستون' + ) self.assertEqual(num2words(798, to='cardinal', lang='ar'), - 'سبعمائة و ثمانية و تسعون' - ) + 'سبعمائة و ثمانية و تسعون' + ) self.assertEqual(num2words(710, to='cardinal', lang='ar'), - 'سبعمائة و عشرة') + 'سبعمائة و عشرة') self.assertEqual(num2words(711, to='cardinal', lang='ar'), - # 'سبعة مائة و إحدى عشر' - 'سبعمائة و أحد عشر' - ) + # 'سبعة مائة و إحدى عشر' + 'سبعمائة و أحد عشر' + ) self.assertEqual(num2words(700, to='cardinal', lang='ar'), - 'سبعمائة') + 'سبعمائة') self.assertEqual(num2words(701, to='cardinal', lang='ar'), - 'سبعمائة و واحد') - + 'سبعمائة و واحد') + self.assertEqual(num2words(1258888, to='cardinal', lang='ar'), - 'مليون و مئتان و ثمانية و خمسون ألفاً و ثمانمائة و ثمانية و ثمانون') - + 'مليون و مئتان و ثمانية و خمسون ألفاً و ثمانمائة و ثمانية و ثمانون') + self.assertEqual(num2words(1100, to='cardinal', lang='ar'), - 'ألف و مائة') - + 'ألف و مائة') + self.assertEqual(num2words(1000000521, to='cardinal', lang='ar'), - 'مليار و خمسمائة و واحد و عشرون') + 'مليار و خمسمائة و واحد و عشرون') def test_prefix_and_suffix(self): self.assertEqual(num2words(645, to='currency', @@ -146,22 +146,20 @@ def test_year(self): def test_max_numbers(self): - for number in 10**51,10**51 + 2: - + for number in 10**51, 10**51 + 2: + with self.assertRaises(OverflowError) as context: num2words(number, lang='ar') self.assertTrue('must be less' in str(context.exception)) def test_big_numbers(self): - self.assertEqual(num2words(1000000045000000000000003000000002000000300, to='cardinal', lang='ar'), + self.assertEqual(num2words(1000000045000000000000003000000002000000300, to='cardinal', lang='ar'), 'تريديسيليون و خمسة و أربعون ديسيليوناً و ثلاثة كوينتليونات و ملياران و ثلاثمائة' ) - self.assertEqual(num2words(-1000000000000000000000003000000002000000302, to='cardinal', lang='ar'), + self.assertEqual(num2words(-1000000000000000000000003000000002000000302, to='cardinal', lang='ar'), 'سالب تريديسيليون و ثلاثة كوينتليونات و ملياران و ثلاثمائة و اثنان' ) - self.assertEqual(num2words(9999999999999999999999999999999999999999999999992, to='cardinal', lang='ar'), - 'تسعة كوينتينيليونات و تسعمائة و تسعة و تسعون كوادريسيليوناً و تسعمائة و تسعة و تسعون تريديسيليوناً و تسعمائة و تسعة و تسعون دوديسيليوناً و تسعمائة و تسعة و تسعون أندسيليوناً و تسعمائة و تسعة و تسعون ديسيليوناً و تسعمائة و تسعة و تسعون نونيليوناً و تسعمائة و تسعة و تسعون أوكتيليوناً و تسعمائة و تسعة و تسعون سبتيليوناً و تسعمائة و تسعة و تسعون سكستيليوناً و تسعمائة و تسعة و تسعون كوينتليوناً و تسعمائة و تسعة و تسعون كوادريليوناً و تسعمائة و تسعة و تسعون تريليوناً و تسعمائة و تسعة و تسعون ملياراً و تسعمائة و تسعة و تسعون مليوناً و تسعمائة و تسعة و تسعون ألفاً و تسعمائة و اثنان و تسعون' + self.assertEqual(num2words(9999999999999999999999999999999999999999999999992, to='cardinal', lang='ar'), + 'تسعة كوينتينيليونات و تسعمائة و تسعة و تسعون كوادريسيليوناً و تسعمائة و تسعة و تسعون تريديسيليوناً و تسعمائة و تسعة و تسعون دوديسيليوناً و تسعمائة و تسعة و تسعون أندسيليوناً و تسعمائة و تسعة و تسعون ديسيليوناً و تسعمائة و تسعة و تسعون نونيليوناً و تسعمائة و تسعة و تسعون أوكتيليوناً و تسعمائة و تسعة و تسعون سبتيليوناً و تسعمائة و تسعة و تسعون سكستيليوناً و تسعمائة و تسعة و تسعون كوينتليوناً و تسعمائة و تسعة و تسعون كوادريليوناً و تسعمائة و تسعة و تسعون تريليوناً و تسعمائة و تسعة و تسعون ملياراً و تسعمائة و تسعة و تسعون مليوناً و تسعمائة و تسعة و تسعون ألفاً و تسعمائة و اثنان و تسعون' ) - - \ No newline at end of file From 488eeea4e47293cd658c9166dcf5b4cd0d2da56b Mon Sep 17 00:00:00 2001 From: Jeronymous Date: Fri, 7 Apr 2023 17:52:58 +0200 Subject: [PATCH 191/200] code formatting to pass flake8 --- num2words/lang_AR.py | 48 ++++++++++++++++++++++++++------------------ num2words/lang_FR.py | 4 +++- num2words/lang_RO.py | 3 ++- num2words/lang_SL.py | 4 +++- tests/test_ar.py | 40 ++++++++++++++++++++++++++---------- 5 files changed, 65 insertions(+), 34 deletions(-) diff --git a/num2words/lang_AR.py b/num2words/lang_AR.py index 036b7d0d..229606a3 100644 --- a/num2words/lang_AR.py +++ b/num2words/lang_AR.py @@ -17,13 +17,14 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # MA 02110-1301 USA -from .base import Num2Word_Base +import decimal import math import re -import decimal from decimal import Decimal from math import floor +from .base import Num2Word_Base + CURRENCY_SR = [("ريال", "ريالان", "ريالات", "ريالاً"), ("هللة", "هللتان", "هللات", "هللة")] CURRENCY_EGP = [("جنيه", "جنيهان", "جنيهات", "جنيهاً"), @@ -79,13 +80,13 @@ def __init__(self): self.arabicHundreds = [ "", "مائة", "مئتان", "ثلاثمائة", "أربعمائة", "خمسمائة", "ستمائة", "سبعمائة", "ثمانمائة", "تسعمائة" - ] # should be : ["تسعة مائة","ثمانية مائة","سبعة مائة","ستة مائة","خمسة مائة","أربعة مائة","ثلاثة مائة","مئتان","مائة"] + ] self.arabicAppendedTwos = [ "مئتا", "ألفا", "مليونا", "مليارا", "تريليونا", "كوادريليونا", - "كوينتليونا", "سكستيليونا", "سبتيليونا", "أوكتيليونا ", "نونيليونا", - "ديسيليونا", "أندسيليونا", "دوديسيليونا", "تريديسيليونا", "كوادريسيليونا", - "كوينتينيليونا" + "كوينتليونا", "سكستيليونا", "سبتيليونا", "أوكتيليونا ", + "نونيليونا", "ديسيليونا", "أندسيليونا", "دوديسيليونا", + "تريديسيليونا", "كوادريسيليونا", "كوينتينيليونا" ] self.arabicTwos = [ "مئتان", "ألفان", "مليونان", "ملياران", "تريليونان", @@ -96,20 +97,20 @@ def __init__(self): self.arabicGroup = [ "مائة", "ألف", "مليون", "مليار", "تريليون", "كوادريليون", "كوينتليون", "سكستيليون", "سبتيليون", "أوكتيليون", "نونيليون", - "ديسيليون", "أندسيليون", "دوديسيليون", "تريديسيليون", "كوادريسيليون", - "كوينتينيليون" + "ديسيليون", "أندسيليون", "دوديسيليون", "تريديسيليون", + "كوادريسيليون", "كوينتينيليون" ] self.arabicAppendedGroup = [ "", "ألفاً", "مليوناً", "ملياراً", "تريليوناً", "كوادريليوناً", - "كوينتليوناً", "سكستيليوناً", "سبتيليوناً", "أوكتيليوناً", "نونيليوناً", - "ديسيليوناً", "أندسيليوناً", "دوديسيليوناً", "تريديسيليوناً", "كوادريسيليوناً", - "كوينتينيليوناً" + "كوينتليوناً", "سكستيليوناً", "سبتيليوناً", "أوكتيليوناً", + "نونيليوناً", "ديسيليوناً", "أندسيليوناً", "دوديسيليوناً", + "تريديسيليوناً", "كوادريسيليوناً", "كوينتينيليوناً" ] self.arabicPluralGroups = [ "", "آلاف", "ملايين", "مليارات", "تريليونات", "كوادريليونات", - "كوينتليونات", "سكستيليونات", "سبتيليونات", "أوكتيليونات", "نونيليونات", - "ديسيليونات", "أندسيليونات", "دوديسيليونات", "تريديسيليونات", "كوادريسيليونات", - "كوينتينيليونات" + "كوينتليونات", "سكستيليونات", "سبتيليونات", "أوكتيليونات", + "نونيليونات", "ديسيليونات", "أندسيليونات", "دوديسيليونات", + "تريديسيليونات", "كوادريسيليونات", "كوينتينيليونات" ] assert len(self.arabicAppendedGroup) == len(self.arabicGroup) assert len(self.arabicPluralGroups) == len(self.arabicGroup) @@ -187,7 +188,8 @@ def process_arabic_group(self, group_number, group_level, (self.number, self.MAXVAL)) 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): + 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: @@ -218,11 +220,14 @@ def process_arabic_group(self, group_number, group_level, return ret_val - # We use this instead of built-in `abs` function, because `abs` suffers from loss of precision for big numbers + # 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 + # 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) decimal = round((number - integer) * 10**9) @@ -250,8 +255,10 @@ def convert_to_arabic(self): temp_number_dec = Decimal(str(temp_number)) try: number_to_process = int(temp_number_dec % Decimal(str(1000))) - except decimal.InvalidOperation: # https://stackoverflow.com/questions/42868278/decimal-invalidoperation-divisionimpossible-for-very-large-numbers - decimal.getcontext().prec = len(temp_number_dec.as_tuple().digits) + 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)) @@ -267,7 +274,8 @@ def convert_to_arabic(self): if number_to_process != 2 and number_to_process != 1: if group >= len(self.arabicGroup): raise OverflowError( - self.errmsg_toobig % (self.number, self.MAXVAL)) + self.errmsg_toobig % (self.number, self.MAXVAL) + ) if number_to_process % 100 != 1: if 3 <= number_to_process <= 10: ret_val = "{} {}".format( diff --git a/num2words/lang_FR.py b/num2words/lang_FR.py index 82942a4e..f843205c 100644 --- a/num2words/lang_FR.py +++ b/num2words/lang_FR.py @@ -37,7 +37,9 @@ def setup(self): 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.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"), diff --git a/num2words/lang_RO.py b/num2words/lang_RO.py index b3fcef2a..feb96105 100644 --- a/num2words/lang_RO.py +++ b/num2words/lang_RO.py @@ -34,7 +34,8 @@ def setup(self): self.pointword = "virgulă" self.exclude_title = ["și", "virgulă", "minus"] self.errmsg_toobig = ( - "Numărul e prea mare pentru a fi convertit în cuvinte (abs(%s) > %s)." + "Numărul e prea mare pentru a \ +fi convertit în cuvinte (abs(%s) > %s)." ) self.mid_numwords = [(1000, "mie/i"), (100, "sută/e"), (90, "nouăzeci"), (80, "optzeci"), diff --git a/num2words/lang_SL.py b/num2words/lang_SL.py index cecbbc79..617b0335 100644 --- a/num2words/lang_SL.py +++ b/num2words/lang_SL.py @@ -31,7 +31,9 @@ def setup(self): self.negword = "minus " self.pointword = "celih" self.errmsg_nonnum = "Only numbers may be converted to words." - self.errmsg_toobig = "Number is too large to convert to words (abs(%s) > %s)." + self.errmsg_toobig = ( + "Number is too large to convert to words (abs(%s) > %s)." + ) self.exclude_title = [] self.mid_numwords = [(1000, "tisoč"), (900, "devetsto"), diff --git a/tests/test_ar.py b/tests/test_ar.py index 1c0c9754..50f9dd74 100644 --- a/tests/test_ar.py +++ b/tests/test_ar.py @@ -127,8 +127,10 @@ def test_cardinal(self): self.assertEqual(num2words(701, to='cardinal', lang='ar'), 'سبعمائة و واحد') - self.assertEqual(num2words(1258888, to='cardinal', lang='ar'), - 'مليون و مئتان و ثمانية و خمسون ألفاً و ثمانمائة و ثمانية و ثمانون') + self.assertEqual( + num2words(1258888, to='cardinal', lang='ar'), + 'مليون و مئتان و ثمانية و خمسون ألفاً و ثمانمائة و ثمانية و ثمانون' + ) self.assertEqual(num2words(1100, to='cardinal', lang='ar'), 'ألف و مائة') @@ -154,12 +156,28 @@ def test_max_numbers(self): self.assertTrue('must be less' in str(context.exception)) def test_big_numbers(self): - self.assertEqual(num2words(1000000045000000000000003000000002000000300, to='cardinal', lang='ar'), - 'تريديسيليون و خمسة و أربعون ديسيليوناً و ثلاثة كوينتليونات و ملياران و ثلاثمائة' - ) - self.assertEqual(num2words(-1000000000000000000000003000000002000000302, to='cardinal', lang='ar'), - 'سالب تريديسيليون و ثلاثة كوينتليونات و ملياران و ثلاثمائة و اثنان' - ) - self.assertEqual(num2words(9999999999999999999999999999999999999999999999992, to='cardinal', lang='ar'), - 'تسعة كوينتينيليونات و تسعمائة و تسعة و تسعون كوادريسيليوناً و تسعمائة و تسعة و تسعون تريديسيليوناً و تسعمائة و تسعة و تسعون دوديسيليوناً و تسعمائة و تسعة و تسعون أندسيليوناً و تسعمائة و تسعة و تسعون ديسيليوناً و تسعمائة و تسعة و تسعون نونيليوناً و تسعمائة و تسعة و تسعون أوكتيليوناً و تسعمائة و تسعة و تسعون سبتيليوناً و تسعمائة و تسعة و تسعون سكستيليوناً و تسعمائة و تسعة و تسعون كوينتليوناً و تسعمائة و تسعة و تسعون كوادريليوناً و تسعمائة و تسعة و تسعون تريليوناً و تسعمائة و تسعة و تسعون ملياراً و تسعمائة و تسعة و تسعون مليوناً و تسعمائة و تسعة و تسعون ألفاً و تسعمائة و اثنان و تسعون' - ) + self.assertEqual( + num2words(1000000045000000000000003000000002000000300, + to='cardinal', lang='ar'), + 'تريديسيليون و خمسة و أربعون ديسيليوناً\ + و ثلاثة كوينتليونات و ملياران و ثلاثمائة' + ) + self.assertEqual( + num2words(-1000000000000000000000003000000002000000302, + to='cardinal', lang='ar'), + 'سالب تريديسيليون و ثلاثة كوينتليونات \ +و ملياران و ثلاثمائة و اثنان' + ) + self.assertEqual( + num2words(9999999999999999999999999999999999999999999999992, + to='cardinal', lang='ar'), + 'تسعة كوينتينيليونات و تسعمائة و تسعة و تسعون كوادريسيليوناً و تسعمائة و تسعة\ + و تسعون تريديسيليوناً و تسعمائة و تسعة و تسعون دوديسيليوناً و تسعمائة\ + و تسعة و تسعون أندسيليوناً و تسعمائة و تسعة و تسعون ديسيليوناً\ + و تسعمائة و تسعة و تسعون نونيليوناً و تسعمائة و تسعة و تسعون\ + أوكتيليوناً و تسعمائة و تسعة و تسعون سبتيليوناً و تسعمائة و تسعة\ + و تسعون سكستيليوناً و تسعمائة و تسعة و تسعون كوينتليوناً و تسعمائة و\ + تسعة و تسعون كوادريليوناً و تسعمائة و تسعة و تسعون تريليوناً\ + و تسعمائة و تسعة و تسعون ملياراً و تسعمائة و تسعة و تسعون مليوناً\ + و تسعمائة و تسعة و تسعون ألفاً و تسعمائة و اثنان و تسعون' + ) From cc4b2cccbb1662f79a249cbe970dd4041500befc Mon Sep 17 00:00:00 2001 From: Mario Monroy Date: Fri, 7 Apr 2023 11:59:43 -0600 Subject: [PATCH 192/200] fix isort --- num2words/__init__.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/num2words/__init__.py b/num2words/__init__.py index 2f7cab56..0942928f 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -18,13 +18,13 @@ from __future__ import unicode_literals from . import (lang_AM, lang_AR, lang_AZ, lang_CZ, lang_DE, lang_DK, lang_EN, - lang_EN_IN, lang_EN_NG, lang_EO, lang_ES, lang_ES_CO, 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_SL, lang_SR, lang_SV, lang_TE, lang_TG, lang_TH, - lang_TR, lang_UK, lang_VI) + lang_EN_IN, lang_EN_NG, lang_EO, lang_ES, lang_ES_CO, + 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_SL, lang_SR, lang_SV, lang_TE, lang_TG, + lang_TH, lang_TR, lang_UK, lang_VI) CONVERTER_CLASSES = { 'am': lang_AM.Num2Word_AM(), From 66ff4958ce69ce1e1b718c7be7f9d0318f79b9aa Mon Sep 17 00:00:00 2001 From: Jeronymous Date: Tue, 11 Apr 2023 09:14:56 +0200 Subject: [PATCH 193/200] split too long line --- tests/test_ar.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_ar.py b/tests/test_ar.py index 50f9dd74..0d281700 100644 --- a/tests/test_ar.py +++ b/tests/test_ar.py @@ -171,7 +171,8 @@ def test_big_numbers(self): self.assertEqual( num2words(9999999999999999999999999999999999999999999999992, to='cardinal', lang='ar'), - 'تسعة كوينتينيليونات و تسعمائة و تسعة و تسعون كوادريسيليوناً و تسعمائة و تسعة\ + 'تسعة كوينتينيليونات و تسعمائة و\ + تسعة و تسعون كوادريسيليوناً و تسعمائة و تسعة\ و تسعون تريديسيليوناً و تسعمائة و تسعة و تسعون دوديسيليوناً و تسعمائة\ و تسعة و تسعون أندسيليوناً و تسعمائة و تسعة و تسعون ديسيليوناً\ و تسعمائة و تسعة و تسعون نونيليوناً و تسعمائة و تسعة و تسعون\ From 37dc16eb96580cad2687f837382c173f10cd856e Mon Sep 17 00:00:00 2001 From: Jeronymous Date: Tue, 11 Apr 2023 19:25:23 +0200 Subject: [PATCH 194/200] improve code test coverage --- num2words/lang_AR.py | 30 +++++++++++++++++++----------- tests/test_ar.py | 22 ++++++++++++++++++++++ 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/num2words/lang_AR.py b/num2words/lang_AR.py index 229606a3..7195dd47 100644 --- a/num2words/lang_AR.py +++ b/num2words/lang_AR.py @@ -122,7 +122,6 @@ def number_to_arabic(self, arabic_prefix_text, arabic_suffix_text): self.extract_integer_and_decimal_parts() def extract_integer_and_decimal_parts(self): - re.split('\\.', str(self.number)) splits = re.split('\\.', str(self.number)) self.integer_value = int(splits[0]) @@ -149,8 +148,9 @@ def decimal_value(self, decimal_part): else: result = decimal_part - for i in range(len(result), self.partPrecision): - result += '0' + # 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): @@ -158,6 +158,7 @@ def digit_feminine_status(self, digit, group_level): 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: @@ -183,9 +184,10 @@ def process_arabic_group(self, group_number, group_level, if tens > 0: if tens < 20: - if int(group_level) >= len(self.arabicTwos): - raise OverflowError(self.errmsg_toobig % - (self.number, self.MAXVAL)) + # 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 \ @@ -198,10 +200,13 @@ def process_arabic_group(self, group_number, 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)] @@ -230,8 +235,10 @@ def abs(self, number): # 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) + return str(integer) + "." + "{:09d}".format(decimal).rstrip("0") def convert(self, value): self.number = self.to_str(value) @@ -272,10 +279,11 @@ def convert_to_arabic(self): 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) - ) + # 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( diff --git a/tests/test_ar.py b/tests/test_ar.py index 0d281700..91e648a6 100644 --- a/tests/test_ar.py +++ b/tests/test_ar.py @@ -92,9 +92,31 @@ def test_ordinal(self): self.assertEqual(num2words(23, lang="ar"), 'ثلاثة و عشرون') def test_cardinal(self): + self.assertEqual(num2words(0, to='cardinal', lang='ar'), 'صفر') self.assertEqual(num2words(12, to='cardinal', lang='ar'), 'اثنا عشر') + self.assertEqual(num2words(12.3, to='cardinal', lang='ar'), + 'اثنا عشر , ثلاثون') + self.assertEqual(num2words(12.01, to='cardinal', lang='ar'), + 'اثنا عشر , إحدى') + self.assertEqual(num2words(12.02, to='cardinal', lang='ar'), + 'اثنا عشر , اثنتان') + self.assertEqual(num2words(12.03, to='cardinal', lang='ar'), + 'اثنا عشر , ثلاث') + self.assertEqual(num2words(12.34, to='cardinal', lang='ar'), + 'اثنا عشر , أربع و ثلاثون') + # Not implemented + self.assertEqual(num2words(12.345, to='cardinal', lang='ar'), + num2words(12.34, to='cardinal', lang='ar')) self.assertEqual(num2words(-8324, to='cardinal', lang='ar'), 'سالب ثمانية آلاف و ثلاثمائة و أربعة و عشرون') + + self.assertEqual(num2words(200, to='cardinal', lang='ar'), + 'مئتا') + self.assertEqual(num2words(700, to='cardinal', lang='ar'), + 'سبعمائة') + self.assertEqual(num2words(101010, to='cardinal', lang='ar'), + 'مائة و ألف ألف و عشرة') + self.assertEqual( num2words(3431.12, to='cardinal', lang='ar'), 'ثلاثة آلاف و أربعمائة و واحد و ثلاثون , اثنتا عشرة') From 30a8810050c6ed85082c07850ec7b08eb93a04d6 Mon Sep 17 00:00:00 2001 From: KhramtsovDR Date: Tue, 18 Apr 2023 13:01:26 +0300 Subject: [PATCH 195/200] Fixes for PEP8 compatibility --- num2words/lang_RU.py | 38 ++++++++++++++++++++++---------------- tests/test_ru.py | 16 ++++++++++------ 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/num2words/lang_RU.py b/num2words/lang_RU.py index 4a3bbf90..aa052aed 100644 --- a/num2words/lang_RU.py +++ b/num2words/lang_RU.py @@ -131,6 +131,7 @@ def get_ord_classifier(prefixes, post_groups): for num, prefix in prefixes.items() } + ONES_ORD = { 3: [['третий', 'третья', 'третье', 'третьи'], ['третьего', 'третьей', 'третьего', 'третьих'], @@ -143,8 +144,8 @@ def get_ord_classifier(prefixes, post_groups): get_ord_classifier(ONES_ORD_PREFIXES, ONES_ORD_POSTFIXES_GROUPS) ) -TENS_PREFIXES = {1: 'один', 2: 'две', 3: 'три', 4: 'четыр', 5: 'пят', 6: 'шест', - 7: 'сем', 8: 'восем', 9: 'девят'} +TENS_PREFIXES = {1: 'один', 2: 'две', 3: 'три', 4: 'четыр', 5: 'пят', + 6: 'шест', 7: 'сем', 8: 'восем', 9: 'девят'} TENS_POSTFIXES = ['надцать', 'надцати', 'надцати', 'надцать', 'надцатью', 'надцати'] TENS = {0: ['десять', 'десяти', 'десяти', 'десять', 'десятью', 'десяти']} @@ -178,9 +179,10 @@ def get_ord_classifier(prefixes, post_groups): } TWENTIES_ORD_PREFIXES = {2: 'двадцат', 3: 'тридцат', 4: 'сороков', - 5: 'пятидесят',6: 'шестидесят', 7: 'семидесят', + 5: 'пятидесят', 6: 'шестидесят', 7: 'семидесят', 8: 'восьмидесят', 9: 'девяност'} -TWENTIES_ORD_POSTFIXES_GROUPS = {2: 1, 3: 1, 4: 0, 5: 1, 6: 1, 7: 1, 8: 1, 9: 1} +TWENTIES_ORD_POSTFIXES_GROUPS = {2: 1, 3: 1, 4: 0, 5: 1, 6: 1, 7: 1, 8: 1, + 9: 1} TWENTIES_ORD = get_ord_classifier(TWENTIES_ORD_PREFIXES, TWENTIES_ORD_POSTFIXES_GROUPS) @@ -272,12 +274,13 @@ def setup(self): self.pointword = ('целая', 'целых', 'целых') self.pointword_ord = get_cases("цел", 1) - def to_cardinal(self, number, case=D_CASE, plural=D_PLURAL, gender=D_GENDER, - animate=D_ANIMATE): + def to_cardinal(self, number, case=D_CASE, plural=D_PLURAL, + gender=D_GENDER, animate=D_ANIMATE): n = str(number).replace(',', '.') if '.' in n: left, right = n.split('.') - decimal_part = self._int2word(int(right), cardinal=True, gender='f') + decimal_part = self._int2word(int(right), cardinal=True, + gender='f') return u'%s %s %s %s' % ( self._int2word(int(left), cardinal=True, gender='f'), self.pluralize(int(left), self.pointword), @@ -286,13 +289,14 @@ def to_cardinal(self, number, case=D_CASE, plural=D_PLURAL, gender=D_GENDER, ) else: return self._int2word(int(n), cardinal=True, case=case, - plural=plural, gender=gender, animate=animate) + plural=plural, gender=gender, + animate=animate) def __decimal_bitness(self, n): - l = len(n) if n[-1] == "1" and n[-2:] != "11": - return self._int2word(10 ** l, cardinal=False, gender='f') - return self._int2word(10 ** l, cardinal=False, case='g', plural='t') + return self._int2word(10 ** len(n), cardinal=False, gender='f') + return self._int2word(10 ** len(n), cardinal=False, case='g', + plural=True) def pluralize(self, n, forms): if n % 100 in (11, 12, 13, 14): @@ -325,19 +329,21 @@ def _int2word(self, n, feminine=False, cardinal=True, case=D_CASE, """ n: number feminine: not used - for backward compatibility - gender: 'f' - masculine - 'm' - feminine - 'n' - neuter + cardinal:True - cardinal + False - ordinal case: 'n' - nominative 'g' - genitive 'd' - dative 'a' - accusative 'i' - instrumental 'p' - prepositional + plural: True - plural + False - singular + gender: 'f' - masculine + 'm' - feminine + 'n' - neuter animate: True - animate False - inanimate - ordinal: True - ordinal - False - cardinal """ # For backward compatibility if feminine: diff --git a/tests/test_ru.py b/tests/test_ru.py index 6cf85b3e..206873c4 100644 --- a/tests/test_ru.py +++ b/tests/test_ru.py @@ -35,7 +35,8 @@ def test_cardinal(self): self.assertEqual(num2words(2012, lang='ru'), "две тысячи двенадцать") self.assertEqual( num2words(12519.85, lang='ru'), - "двенадцать тысяч пятьсот девятнадцать целых восемьдесят пять сотых" + "двенадцать тысяч пятьсот девятнадцать целых восемьдесят пять " + "сотых" ) self.assertEqual( num2words(1234567890, lang='ru'), @@ -105,7 +106,7 @@ def test_cardinal_neuter(self): num2words(115, lang='ru', gender='n'), "сто пятнадцать" ) self.assertEqual( - num2words(122, lang='ru', gender='n'),"сто двадцать два" + num2words(122, lang='ru', gender='n'), "сто двадцать два" ) self.assertEqual( num2words(125.1, lang='ru', gender='n'), @@ -116,18 +117,21 @@ def test_cardinal_neuter(self): def test_floating_point(self): self.assertEqual(num2words(5.2, lang='ru'), "пять целых две десятых") self.assertEqual(num2words(5.0, lang='ru'), "пять целых ноль десятых") + self.assertEqual(num2words(5.10, lang='ru'), "пять целых одна десятая") + self.assertEqual(num2words("5.10", lang='ru'), + "пять целых десять сотых") self.assertEqual(num2words(1.001, lang='ru'), "одна целая одна тысячная") self.assertEqual(num2words(1.011, lang='ru'), "одна целая одиннадцать тысячных") self.assertEqual(num2words(10.02, lang='ru'), - "десять целых две сотых") + "десять целых две сотых") self.assertEqual(num2words(15.007, lang='ru'), - "пятнадцать целых семь тысячных") + "пятнадцать целых семь тысячных") self.assertEqual(num2words(561.42, lang='ru'), - "пятьсот шестьдесят одна целая сорок две сотых") + "пятьсот шестьдесят одна целая сорок две сотых") self.assertEqual(num2words(561.00001, lang='ru'), - "пятьсот шестьдесят одна целая одна стотысячная") + "пятьсот шестьдесят одна целая одна стотысячная") def test_to_ordinal(self): self.assertEqual( From 87def57c4a747ee50009f79ad9fd6ca4a40fa138 Mon Sep 17 00:00:00 2001 From: Arthur O'Dwyer Date: Mon, 1 May 2023 16:36:42 -0400 Subject: [PATCH 196/200] [it] Handle string inputs in `to_ordinal` Fixes #508. --- num2words/lang_IT.py | 12 ++++++------ tests/test_it.py | 25 ++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/num2words/lang_IT.py b/num2words/lang_IT.py index d532f7f4..427e6d36 100644 --- a/num2words/lang_IT.py +++ b/num2words/lang_IT.py @@ -146,13 +146,13 @@ def to_cardinal(self, number): elif isinstance(number, float): string = self.float_to_words(number) elif number < 20: - string = CARDINAL_WORDS[number] + string = CARDINAL_WORDS[int(number)] elif number < 100: - string = self.tens_to_cardinal(number) + string = self.tens_to_cardinal(int(number)) elif number < 1000: - string = self.hundreds_to_cardinal(number) + string = self.hundreds_to_cardinal(int(number)) elif number < 1000000: - string = self.thousands_to_cardinal(number) + string = self.thousands_to_cardinal(int(number)) else: string = self.big_number_to_cardinal(number) return accentuate(string) @@ -167,9 +167,9 @@ def to_ordinal(self, number): elif number % 1 != 0: return self.float_to_words(number, ordinal=True) elif number < 20: - return ORDINAL_WORDS[number] + return ORDINAL_WORDS[int(number)] elif is_outside_teens and tens % 10 == 3: - # Gets ride of the accent ~~~~~~~~~~ + # 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" diff --git a/tests/test_it.py b/tests/test_it.py index 9023355f..23c081d1 100644 --- a/tests/test_it.py +++ b/tests/test_it.py @@ -263,7 +263,7 @@ def test_nth_big(self): "cinquecentosessantasettemilaottocentonovantesimo" ) - def test_with_decimals(self): + def test_with_floats(self): self.assertAlmostEqual( num2words(1.0, lang="it"), "uno virgola zero" ) @@ -271,6 +271,29 @@ def test_with_decimals(self): num2words(1.1, lang="it"), "uno virgola uno" ) + def test_with_strings(self): + for i in range(2002): + # Just make sure it doesn't raise an exception + num2words(str(i), lang='it', to='cardinal') + num2words(str(i), lang='it', to='ordinal') + self.assertEqual(num2words('1', lang="it", to='ordinal'), "primo") + self.assertEqual( + num2words('100', lang="it", to='ordinal'), + "centesimo" + ) + self.assertEqual( + num2words('1000', lang="it", to='ordinal'), + "millesimo" + ) + self.assertEqual( + num2words('1234567890123456789012345678', lang="it", to='ordinal'), + "un quadriliardo, duecentotrentaquattro quadrilioni, " + "cinquecentosessantasette triliardi, ottocentonovanta trilioni, " + "centoventitré biliardi, quattrocentocinquantasei bilioni, " + "settecentottantanove miliardi, dodici milioni e " + "trecentoquarantacinquemilaseicentosettantottesimo" + ) + def test_currency_eur(self): for test in TEST_CASES_TO_CURRENCY_EUR: self.assertEqual( From 5635a41c7111393a3a867076b4225cb436c80e2c Mon Sep 17 00:00:00 2001 From: Andrii Kurdiumov Date: Fri, 28 Jul 2023 10:59:40 +0600 Subject: [PATCH 197/200] Add gender and morphological cases support for Ukrainian Added two parameters: gender and case gender can accept either 'masculine' (default) or 'feminine' case can accept either 'nominative' (default) or 'genitive','dative','accusative','instrumetnal','locative' and 'vocative'. This parameters now working only for to='cardinal' --- num2words/lang_UK.py | 155 ++++++----- tests/test_uk.py | 609 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 698 insertions(+), 66 deletions(-) diff --git a/num2words/lang_UK.py b/num2words/lang_UK.py index a6c0a3bb..0b62d858 100644 --- a/num2words/lang_UK.py +++ b/num2words/lang_UK.py @@ -23,27 +23,27 @@ ZERO = ('нуль',) ONES_FEMININE = { - 1: ('одна',), - 2: ('дві',), - 3: ('три',), - 4: ('чотири',), - 5: ('п\'ять',), - 6: ('шість',), - 7: ('сім',), - 8: ('вісім',), - 9: ('дев\'ять',), + 1: ('одна', "однієї", "одній", "одну", "однією", "одній"), + 2: ('дві', "двох", "двом", "дві", "двома", "двох"), + 3: ('три', "трьох", "трьом", "три", "трьома", "трьох"), + 4: ('чотири', "чотирьох", "чотирьом", "чотири", "чотирма", "чотирьох"), + 5: ('п\'ять', "п'яти", "п'яти", "п'ять", "п'ятьма", "п'яти"), + 6: ('шість', "шести", "шести", "шість", "шістьма", "шести"), + 7: ('сім', "семи", "семи", "сім", "сьома", "семи"), + 8: ('вісім', "восьми", "восьми", "вісім", "вісьма", "восьми"), + 9: ("дев'ять", "дев'яти", "дев'яти", "дев'ять", "дев'ятьма","дев'яти"), } ONES = { - 1: ('один',), - 2: ('два',), - 3: ('три',), - 4: ('чотири',), - 5: ('п\'ять',), - 6: ('шість',), - 7: ('сім',), - 8: ('вісім',), - 9: ('дев\'ять',), + 1: ('один', 'одного', "одному", "один", "одним", "одному"), + 2: ('два', 'двох', "двом", "два", "двома", "двох"), + 3: ('три', 'трьох', "трьом", "три", "трьома", "трьох"), + 4: ('чотири', 'чотирьох', "чотирьом", "чотири", "чотирма", "чотирьох"), + 5: ('п\'ять', "п'яти", "п'яти", "п'ять", "п'ятьма", "п'яти"), + 6: ('шість', 'шести', "шести", "шість", "шістьма", "шести"), + 7: ('сім', 'семи', "семи", "сім", "сьома", "семи"), + 8: ('вісім', 'восьми', "восьми", "вісім", "вісьма", "восьми"), + 9: ('дев\'ять', "дев'яти", "дев'яти", "дев'ять", "дев'ятьма","дев'яти"), } ONES_ORDINALS = { @@ -69,27 +69,27 @@ } TENS = { - 0: ('десять',), - 1: ('одинадцять',), - 2: ('дванадцять',), - 3: ('тринадцять',), - 4: ('чотирнадцять',), - 5: ('п\'ятнадцять',), - 6: ('шістнадцять',), - 7: ('сімнадцять',), - 8: ('вісімнадцять',), - 9: ('дев\'ятнадцять',), + 0: ('десять', 'десяти', "десяти", "десять", "десятьма", "десяти"), + 1: ('одинадцять', 'одинадцяти', "одинадцяти", "одинадцять", "одинадцятьма", "одинадцяти"), + 2: ('дванадцять', 'дванадцяти', "дванадцяти", "дванадцять", "дванадцятьма", "дванадцяти"), + 3: ('тринадцять', 'тринадцяти', "тринадцяти", "тринадцять", "тринадцятьма", "тринадцяти"), + 4: ('чотирнадцять', 'чотирнадцяти', "чотирнадцяти", "чотирнадцять", "чотирнадцятьма", "чотирнадцяти"), + 5: ("п'ятнадцять", "п'ятнадцяти", "п'ятнадцяти", "п'ятнадцять", "п'ятнадцятьма", "п'ятнадцяти"), + 6: ('шістнадцять', 'шістнадцяти', "шістнадцяти", "шістнадцять", "шістнадцятьма", "шістнадцяти"), + 7: ('сімнадцять', 'сімнадцяти', "сімнадцяти", "сімнадцять", "сімнадцятьма", "сімнадцяти"), + 8: ('вісімнадцять', 'вісімнадцяти', "вісімнадцяти", "вісімнадцять", "вісімнадцятьма", "вісімнадцяти"), + 9: ("дев'ятнадцять","дев'ятнадцяти","дев'ятнадцяти","дев'ятнадцять","дев'ятнадцятьма", "дев'ятнадцяти"), } TWENTIES = { - 2: ('двадцять',), - 3: ('тридцять',), - 4: ('сорок',), - 5: ('п\'ятдесят',), - 6: ('шістдесят',), - 7: ('сімдесят',), - 8: ('вісімдесят',), - 9: ('дев\'яносто',), + 2: ('двадцять', "двадцяти", "двадцяти", "двадцять", "двадцятьма", "двадцяти"), + 3: ('тридцять', "тридцяти", "тридцяти", "тридцять", "тридцятьма", "тридцяти"), + 4: ('сорок', "сорока", "сорока", "сорок", "сорока", "сорока"), + 5: ('п\'ятдесят', "п'ятдесяти", "п'ятдесяти", "п'ятдесят", "п'ятдесятьма", "п'ятдесяти"), + 6: ('шістдесят', "шістдесяти", "шістдесяти", "шістдесят", "шістдесятьма", "шістдесяти"), + 7: ('сімдесят', "сімдесяти", "сімдесяти", "сімдесят", "сімдесятьма", "сімдесяти"), + 8: ('вісімдесят', "вісімдесяти", "вісімдесяти", "вісімдесят", "вісімдесятьма","вісімдесяти"), + 9: ('дев\'яносто', "дев'яноста", "дев'яноста", "дев'яносто", "дев'яностами", "дев'яноста"), } TWENTIES_ORDINALS = { @@ -104,15 +104,15 @@ } HUNDREDS = { - 1: ('сто',), - 2: ('двісті',), - 3: ('триста',), - 4: ('чотириста',), - 5: ('п\'ятсот',), - 6: ('шістсот',), - 7: ('сімсот',), - 8: ('вісімсот',), - 9: ('дев\'ятсот',), + 1: ('сто', "ста", "ста", "сто", "стами", "стах"), + 2: ('двісті', "двохста", "двомстам", "двісті", "двомастами", "двохстах"), + 3: ('триста', "трьохста", "трьомстам", "триста", "трьомастами", "трьохстах"), + 4: ('чотириста',"чотирьохста", "чотирьомстам", "чотириста","чотирмастами", "чотирьохстах"), + 5: ('п\'ятсот', "п'ятиста", "п'ятистам", "п'ятсот", "п'ятьмастами", "п'ятистах"), + 6: ('шістсот', "шестиста", "шестистам", "шістсот", "шістьмастами", "шестистах"), + 7: ('сімсот', "семиста", "семистам", "сімсот", "сьомастами", "семистах"), + 8: ('вісімсот', "восьмиста", "восьмистам", "вісімсот", "восьмастами", "восьмистах"), + 9: ("дев'ятсот","дев'ятиста", "дев'ятистам", "дев'ятсот","дев'ятьмастами","дев'ятистах"), } HUNDREDS_ORDINALS = { @@ -128,16 +128,28 @@ } 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 + # Nominative Genitive Dative Accusative Instrumental Locative + # ----------------------------------------------------- --------------------------------------------------- --------------------------------------------------- --------------------------------------------------- ------------------------------------------------------- -------------------------------------------------------- + # 10^3 + 1: (('тисяча', 'тисячі', 'тисяч'), ('тисячи', 'тисяч', 'тисяч'), ('тисячі', 'тисячам', 'тисячам'), ('тисячу', 'тисячі', 'тисяч'), ('тисячею', 'тисячами', 'тисячами'), ('тисячі', 'тисячах', 'тисячах'),), + # 10^6 + 2: (('мільйон', 'мільйони', 'мільйонів'), ('мільйона', 'мільйонів', 'мільйонів'), ('мільйону', 'мільйонам', 'мільйонам'), ('мільйон', 'мільйони', 'мільйонів'), ('мільйоном', 'мільйонами', 'мільйонів'), ('мільйоні', 'мільйонах', 'мільйонах'),), + # 10^9 + 3: (('мільярд', 'мільярди', 'мільярдів'), ('мільярда', 'мільярдів', 'мільярдів'), ('мільярду', 'мільярдам', 'мільярдам'), ('мільярд', 'мільярди', 'мільярдів'), ('мільярдом', 'мільярдами', 'мільярдів'), ('мільярді', 'мільярдах', 'мільярдах'),), + # 10^12 + 4: (('трильйон', 'трильйони', 'трильйонів'), ('трильйона', 'трильйонів', 'трильйонів'), ('трильйону', 'трильйонам', 'трильйонам'), ('трильйон', 'трильйони', 'трильйонів'), ('трильйоном', 'трильйонами', 'трильйонів'), ('трильйоні', 'трильйонах', 'трильйонах'),), + # 10^15 + 5: (('квадрильйон', 'квадрильйони', 'квадрильйонів'), ('квадрильйона', 'квадрильйонів', 'квадрильйонів'), ('квадрильйону', 'квадрильйонам', 'квадрильйонам'), ('квадрильйон', 'квадрильйони', 'квадрильйонів'), ('квадрильйоном', 'квадрильйонами', 'квадрильйонів'), ('квадрильйоні', 'квадрильйонах', 'квадрильйонах'),), + # 10^18 + 6: (('квінтильйон', 'квінтильйони', 'квінтильйонів'), ('квінтильйона', 'квінтильйонів', 'квінтильйонів'), ('квінтильйону', 'квінтильйонам', 'квінтильйонам'), ('квінтильйон', 'квінтильйони', 'квінтильйонів'), ('квінтильйоном', 'квінтильйонами', 'квінтильйонів'), ('квінтильйоні', 'квінтильйонах', 'квінтильйонах'),), + # 10^21 + 7: (('секстильйон', 'секстильйони', 'секстильйонів'), ('секстильйона', 'секстильйонів', 'секстильйонів'), ('секстильйону', 'секстильйонам', 'секстильйонам'), ('секстильйон', 'секстильйони', 'секстильйонів'), ('секстильйоном', 'секстильйонами', 'секстильйонів'), ('секстильйоні', 'секстильйонах', 'секстильйонах'),), + # 10^24 + 8: (('септильйон', 'септильйони', 'септильйонів'), ('септильйона', 'септильйонів', 'септильйонів'), ('септильйону', 'септильйонам', 'септильйонам'), ('септильйон', 'септильйони', 'септильйонів'), ('септильйоном', 'септильйонами', 'септильйонів'), ('септильйоні', 'септильйонах', 'септильйонах'),), + # 10^27 + 9: (('октильйон', 'октильйони', 'октильйонів'), ('октильйона', 'октильйонів', 'октильйонів'), ('октильйону', 'октильйонам', 'октильйонам'), ('октильйон', 'октильйони', 'октильйонів'), ('октильйоном', 'октильйонами', 'октильйонів'), ('октильйоні', 'октильйонах', 'октильйонах'),), + # 10^30 + 10: (('нонільйон', 'нонільйони', 'нонільйонів'), ('нонільйона', 'нонільйонів', 'нонільйонів'), ('нонільйону', 'нонільйонам', 'нонільйонам'), ('нонільйон', 'нонільйони', 'нонільйонів'), ('нонільйоном', 'нонільйонами', 'нонільйонів'), ('нонільйоні', 'нонільйонах', 'нонільйонах'),), } prefixes_ordinal = { @@ -711,20 +723,31 @@ def setup(self): self.negword = "мінус" self.pointword = "кома" - def to_cardinal(self, number): + def to_cardinal(self, number, **kwargs): + if 'case' in kwargs: + case = kwargs['case'] + morphological_case = ["nominative", "genitive", "dative", "accusative", "instrumental", "locative"].index(case) + else: + morphological_case = 0 + + if 'gender' in kwargs: + gender = kwargs['gender'] == 'feminine' + else: + gender = False + 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))) + self._int2word(int(right), gender, morphological_case)) return u'%s %s %s' % ( - self._int2word(int(left)), + self._int2word(int(left), gender, morphological_case), self.pointword, decimal_part ) else: - return self._int2word(int(n)) + return self._int2word(int(n), gender, morphological_case) def pluralize(self, n, forms): if n % 100 < 10 or n % 100 > 20: @@ -739,9 +762,9 @@ def pluralize(self, n, forms): return forms[form] - def _int2word(self, n, feminine=False): + def _int2word(self, n, feminine=False, morphological_case = 0): if n < 0: - return ' '.join([self.negword, self._int2word(abs(n))]) + return ' '.join([self.negword, self._int2word(abs(n), feminine, morphological_case)]) if n == 0: return ZERO[0] @@ -758,20 +781,20 @@ def _int2word(self, n, feminine=False): n1, n2, n3 = get_digits(x) if n3 > 0: - words.append(HUNDREDS[n3][0]) + words.append(HUNDREDS[n3][morphological_case]) if n2 > 1: - words.append(TWENTIES[n2][0]) + words.append(TWENTIES[n2][morphological_case]) if n2 == 1: - words.append(TENS[n1][0]) + words.append(TENS[n1][morphological_case]) # elif n1 > 0 and not (i > 0 and x == 1): elif n1 > 0: ones = ONES_FEMININE if i == 1 or feminine and i == 0 else ONES - words.append(ones[n1][0]) + words.append(ones[n1][morphological_case]) if i > 0: - words.append(self.pluralize(x, THOUSANDS[i])) + words.append(self.pluralize(x, THOUSANDS[i][morphological_case])) return ' '.join(words) diff --git a/tests/test_uk.py b/tests/test_uk.py index 84fb770a..3f57eb2d 100644 --- a/tests/test_uk.py +++ b/tests/test_uk.py @@ -117,6 +117,582 @@ "двісті двадцять тисяч двісті дев'яносто один") ) +TEST_CASES_CARDINAL_FEMININE = ( + (1, "одна"), + (2, "дві"), + (3, "три"), + (4, "чотири"), + (5, "п'ять"), + (6, "шість"), + (7, "сім"), + (8, "вісім"), + (9, "дев'ять"), + (10, "десять"), + (10.02, "десять кома нуль дві"), + (11, "одинадцять"), + (12, "дванадцять"), + (12.40, "дванадцять кома чотири"), + (13, "тринадцять"), + (14, "чотирнадцять"), + (14.13, "чотирнадцять кома тринадцять"), + (15, "п'ятнадцять"), + (16, "шістнадцять"), + (17, "сімнадцять"), + (17.31, "сімнадцять кома тридцять одна"), + (18, "вісімнадцять"), + (19, "дев'ятнадцять"), + (20, "двадцять"), + (21, "двадцять одна"), + (21.20, "двадцять одна кома дві"), + (30, "тридцять"), + (32, "тридцять дві"), + (40, "сорок"), + (43, "сорок три"), + (43.007, "сорок три кома нуль нуль сім"), + (50, "п'ятдесят"), + (54, "п'ятдесят чотири"), + (60, "шістдесят"), + (60.059, "шістдесят кома нуль п'ятдесят дев'ять"), + (65, "шістдесят п'ять"), + (70, "сімдесят"), + (76, "сімдесят шість"), + (80, "вісімдесят"), + (87, "вісімдесят сім"), + (90, "дев'яносто"), + (98, "дев'яносто вісім"), + (99, "дев'яносто дев'ять"), + (100, "сто"), + (101, "сто одна"), + (199, "сто дев'яносто дев'ять"), + (200, "двісті"), + (203, "двісті три"), + (300, "триста"), + (356, "триста п'ятдесят шість"), + (400, "чотириста"), + (434, "чотириста тридцять чотири"), + (500, "п'ятсот"), + (578, "п'ятсот сімдесят вісім"), + (600, "шістсот"), + (689, "шістсот вісімдесят дев'ять"), + (700, "сімсот"), + (729, "сімсот двадцять дев'ять"), + (800, "вісімсот"), + (894, "вісімсот дев'яносто чотири"), + (900, "дев'ятсот"), + (999, "дев'ятсот дев'яносто дев'ять"), + (1000, "одна тисяча"), + (1001, "одна тисяча одна"), + (2012, "дві тисячі дванадцять"), + (12519, "дванадцять тисяч п'ятсот дев'ятнадцять"), + (12519.85, "дванадцять тисяч п'ятсот дев'ятнадцять кома вісімдесят п'ять"), + (-260000, "мінус двісті шістдесят тисяч"), + (1000000, "один мільйон"), + (1000000000, "один мільярд"), + (1234567890, "один мільярд двісті тридцять чотири мільйони " + "п'ятсот шістдесят сім тисяч вісімсот дев'яносто"), + (1000000000000, "один трильйон"), + (1000000000000000, "один квадрильйон"), + (1000000000000000000, "один квінтильйон"), + (1000000000000000000000, "один секстильйон"), + (1000000000000000000000000, "один септильйон"), + (1000000000000000000000000000, "один октильйон"), + (1000000000000000000000000000000, "один нонільйон"), + (215461407892039002157189883901676, + "двісті п'ятнадцять нонільйонів чотириста шістдесят один " + "октильйон чотириста сім септильйонів вісімсот дев'яносто " + "два секстильйони тридцять дев'ять квінтильйонів два " + "квадрильйони сто п'ятдесят сім трильйонів сто вісімдесят " + "дев'ять мільярдів вісімсот вісімдесят три мільйони " + "дев'ятсот одна тисяча шістсот сімдесят шість"), + (719094234693663034822824384220291, + "сімсот дев'ятнадцять нонільйонів дев'яносто чотири октильйони " + "двісті тридцять чотири септильйони шістсот дев'яносто три " + "секстильйони шістсот шістдесят три квінтильйони тридцять " + "чотири квадрильйони вісімсот двадцять два трильйони вісімсот " + "двадцять чотири мільярди триста вісімдесят чотири мільйони " + "двісті двадцять тисяч двісті дев'яносто одна") +) + +TEST_CASES_CARDINAL_GENITIVE = ( + (1, "одного"), + (2, "двох"), + (3, "трьох"), + (4, "чотирьох"), + (5, "п'яти"), + (6, "шести"), + (7, "семи"), + (8, "восьми"), + (9, "дев'яти"), + (10, "десяти"), + (10.02, "десяти кома нуль двох"), + (11, "одинадцяти"), + (12, "дванадцяти"), + (12.40, "дванадцяти кома чотирьох"), + (13, "тринадцяти"), + (14, "чотирнадцяти"), + (14.13, "чотирнадцяти кома тринадцяти"), + (15, "п'ятнадцяти"), + (16, "шістнадцяти"), + (17, "сімнадцяти"), + (17.31, "сімнадцяти кома тридцяти одного"), + (18, "вісімнадцяти"), + (19, "дев'ятнадцяти"), + (20, "двадцяти"), + (21, "двадцяти одного"), + (21.20, "двадцяти одного кома двох"), + (30, "тридцяти"), + (32, "тридцяти двох"), + (40, "сорока"), + (43, "сорока трьох"), + (43.007, "сорока трьох кома нуль нуль семи"), + (50, "п'ятдесяти"), + (54, "п'ятдесяти чотирьох"), + (60, "шістдесяти"), + (60.059, "шістдесяти кома нуль п'ятдесяти дев'яти"), + (65, "шістдесяти п'яти"), + (70, "сімдесяти"), + (76, "сімдесяти шести"), + (80, "вісімдесяти"), + (87, "вісімдесяти семи"), + (90, "дев'яноста"), + (98, "дев'яноста восьми"), + (99, "дев'яноста дев'яти"), + (100, "ста"), + (101, "ста одного"), + (199, "ста дев'яноста дев'яти"), + (200, "двохста"), + (203, "двохста трьох"), + (300, "трьохста"), + (356, "трьохста п'ятдесяти шести"), + (400, "чотирьохста"), + (434, "чотирьохста тридцяти чотирьох"), + (500, "п'ятиста"), + (578, "п'ятиста сімдесяти восьми"), + (600, "шестиста"), + (689, "шестиста вісімдесяти дев'яти"), + (700, "семиста"), + (729, "семиста двадцяти дев'яти"), + (800, "восьмиста"), + (894, "восьмиста дев'яноста чотирьох"), + (900, "дев'ятиста"), + (999, "дев'ятиста дев'яноста дев'яти"), + (1000, "однієї тисячи"), + (1001, "однієї тисячи одного"), + (2012, "двох тисяч дванадцяти"), + (12519, "дванадцяти тисяч п'ятиста дев'ятнадцяти"), + (12519.85, "дванадцяти тисяч п'ятиста дев'ятнадцяти кома вісімдесяти п'яти"), + (-260000, "мінус двохста шістдесяти тисяч"), + (1000000, "одного мільйона"), + (1000000000, "одного мільярда"), + (1234567890, "одного мільярда двохста тридцяти чотирьох мільйонів " + "п'ятиста шістдесяти семи тисяч восьмиста дев'яноста"), + (1000000000000, "одного трильйона"), + (1000000000000000, "одного квадрильйона"), + (1000000000000000000, "одного квінтильйона"), + (1000000000000000000000, "одного секстильйона"), + (1000000000000000000000000, "одного септильйона"), + (1000000000000000000000000000, "одного октильйона"), + (1000000000000000000000000000000, "одного нонільйона"), + (215461407892039002157189883901676, + "двохста п'ятнадцяти нонільйонів чотирьохста шістдесяти одного " + "октильйона чотирьохста семи септильйонів восьмиста дев'яноста " + "двох секстильйонів тридцяти дев'яти квінтильйонів двох " + "квадрильйонів ста п'ятдесяти семи трильйонів ста вісімдесяти " + "дев'яти мільярдів восьмиста вісімдесяти трьох мільйонів " + "дев'ятиста однієї тисячи шестиста сімдесяти шести"), + (719094234693663034822824384220291, + "семиста дев'ятнадцяти нонільйонів дев'яноста чотирьох октильйонів " + "двохста тридцяти чотирьох септильйонів шестиста дев'яноста трьох " + "секстильйонів шестиста шістдесяти трьох квінтильйонів тридцяти " + "чотирьох квадрильйонів восьмиста двадцяти двох трильйонів восьмиста " + "двадцяти чотирьох мільярдів трьохста вісімдесяти чотирьох мільйонів " + "двохста двадцяти тисяч двохста дев'яноста одного") +) + +TEST_CASES_CARDINAL_DATIVE = ( + (1, "одному"), + (2, "двом"), + (3, "трьом"), + (4, "чотирьом"), + (5, "п'яти"), + (6, "шести"), + (7, "семи"), + (8, "восьми"), + (9, "дев'яти"), + (10, "десяти"), + (10.02, "десяти кома нуль двом"), + (11, "одинадцяти"), + (12, "дванадцяти"), + (12.40, "дванадцяти кома чотирьом"), + (13, "тринадцяти"), + (14, "чотирнадцяти"), + (14.13, "чотирнадцяти кома тринадцяти"), + (15, "п'ятнадцяти"), + (16, "шістнадцяти"), + (17, "сімнадцяти"), + (17.31, "сімнадцяти кома тридцяти одному"), + (18, "вісімнадцяти"), + (19, "дев'ятнадцяти"), + (20, "двадцяти"), + (21, "двадцяти одному"), + (21.20, "двадцяти одному кома двом"), + (30, "тридцяти"), + (32, "тридцяти двом"), + (40, "сорока"), + (43, "сорока трьом"), + (43.007, "сорока трьом кома нуль нуль семи"), + (50, "п'ятдесяти"), + (54, "п'ятдесяти чотирьом"), + (60, "шістдесяти"), + (60.059, "шістдесяти кома нуль п'ятдесяти дев'яти"), + (65, "шістдесяти п'яти"), + (70, "сімдесяти"), + (76, "сімдесяти шести"), + (80, "вісімдесяти"), + (87, "вісімдесяти семи"), + (90, "дев'яноста"), + (98, "дев'яноста восьми"), + (99, "дев'яноста дев'яти"), + (100, "ста"), + (101, "ста одному"), + (199, "ста дев'яноста дев'яти"), + (200, "двомстам"), + (203, "двомстам трьом"), + (300, "трьомстам"), + (356, "трьомстам п'ятдесяти шести"), + (400, "чотирьомстам"), + (434, "чотирьомстам тридцяти чотирьом"), + (500, "п'ятистам"), + (578, "п'ятистам сімдесяти восьми"), + (600, "шестистам"), + (689, "шестистам вісімдесяти дев'яти"), + (700, "семистам"), + (729, "семистам двадцяти дев'яти"), + (800, "восьмистам"), + (894, "восьмистам дев'яноста чотирьом"), + (900, "дев'ятистам"), + (999, "дев'ятистам дев'яноста дев'яти"), + (1000, "одній тисячі"), + (1001, "одній тисячі одному"), + (2012, "двом тисячам дванадцяти"), + (12519, "дванадцяти тисячам п'ятистам дев'ятнадцяти"), + (12519.85, "дванадцяти тисячам п'ятистам дев'ятнадцяти кома вісімдесяти п'яти"), + (-260000, "мінус двомстам шістдесяти тисячам"), + (1000000, "одному мільйону"), + (1000000000, "одному мільярду"), + (1234567890, "одному мільярду двомстам тридцяти чотирьом мільйонам " + "п'ятистам шістдесяти семи тисячам восьмистам дев'яноста"), + (1000000000000, "одному трильйону"), + (1000000000000000, "одному квадрильйону"), + (1000000000000000000, "одному квінтильйону"), + (1000000000000000000000, "одному секстильйону"), + (1000000000000000000000000, "одному септильйону"), + (1000000000000000000000000000, "одному октильйону"), + (1000000000000000000000000000000, "одному нонільйону"), + (215461407892039002157189883901676, + "двомстам п'ятнадцяти нонільйонам чотирьомстам шістдесяти одному " + "октильйону чотирьомстам семи септильйонам восьмистам дев'яноста " + "двом секстильйонам тридцяти дев'яти квінтильйонам двом " + "квадрильйонам ста п'ятдесяти семи трильйонам ста вісімдесяти " + "дев'яти мільярдам восьмистам вісімдесяти трьом мільйонам " + "дев'ятистам одній тисячі шестистам сімдесяти шести"), + (719094234693663034822824384220291, + "семистам дев'ятнадцяти нонільйонам дев'яноста чотирьом октильйонам " + "двомстам тридцяти чотирьом септильйонам шестистам дев'яноста трьом " + "секстильйонам шестистам шістдесяти трьом квінтильйонам тридцяти " + "чотирьом квадрильйонам восьмистам двадцяти двом трильйонам восьмистам " + "двадцяти чотирьом мільярдам трьомстам вісімдесяти чотирьом мільйонам " + "двомстам двадцяти тисячам двомстам дев'яноста одному") +) + +TEST_CASES_CARDINAL_ACCUSATIVE = ( + (1, "один"), + (2, "два"), + (3, "три"), + (4, "чотири"), + (5, "п'ять"), + (6, "шість"), + (7, "сім"), + (8, "вісім"), + (9, "дев'ять"), + (10, "десять"), + (10.02, "десять кома нуль два"), + (11, "одинадцять"), + (12, "дванадцять"), + (12.40, "дванадцять кома чотири"), + (13, "тринадцять"), + (14, "чотирнадцять"), + (14.13, "чотирнадцять кома тринадцять"), + (15, "п'ятнадцять"), + (16, "шістнадцять"), + (17, "сімнадцять"), + (17.31, "сімнадцять кома тридцять один"), + (18, "вісімнадцять"), + (19, "дев'ятнадцять"), + (20, "двадцять"), + (21, "двадцять один"), + (21.20, "двадцять один кома два"), + (30, "тридцять"), + (32, "тридцять два"), + (40, "сорок"), + (43, "сорок три"), + (43.007, "сорок три кома нуль нуль сім"), + (50, "п'ятдесят"), + (54, "п'ятдесят чотири"), + (60, "шістдесят"), + (60.059, "шістдесят кома нуль п'ятдесят дев'ять"), + (65, "шістдесят п'ять"), + (70, "сімдесят"), + (76, "сімдесят шість"), + (80, "вісімдесят"), + (87, "вісімдесят сім"), + (90, "дев'яносто"), + (98, "дев'яносто вісім"), + (99, "дев'яносто дев'ять"), + (100, "сто"), + (101, "сто один"), + (199, "сто дев'яносто дев'ять"), + (200, "двісті"), + (203, "двісті три"), + (300, "триста"), + (356, "триста п'ятдесят шість"), + (400, "чотириста"), + (434, "чотириста тридцять чотири"), + (500, "п'ятсот"), + (578, "п'ятсот сімдесят вісім"), + (600, "шістсот"), + (689, "шістсот вісімдесят дев'ять"), + (700, "сімсот"), + (729, "сімсот двадцять дев'ять"), + (800, "вісімсот"), + (894, "вісімсот дев'яносто чотири"), + (900, "дев'ятсот"), + (999, "дев'ятсот дев'яносто дев'ять"), + (1000, "одну тисячу"), + (1001, "одну тисячу один"), + (2012, "дві тисячі дванадцять"), + (12519, "дванадцять тисяч п'ятсот дев'ятнадцять"), + (12519.85, "дванадцять тисяч п'ятсот дев'ятнадцять кома вісімдесят п'ять"), + (-260000, "мінус двісті шістдесят тисяч"), + (1000000, "один мільйон"), + (1000000000, "один мільярд"), + (1234567890, "один мільярд двісті тридцять чотири мільйони " + "п'ятсот шістдесят сім тисяч вісімсот дев'яносто"), + (1000000000000, "один трильйон"), + (1000000000000000, "один квадрильйон"), + (1000000000000000000, "один квінтильйон"), + (1000000000000000000000, "один секстильйон"), + (1000000000000000000000000, "один септильйон"), + (1000000000000000000000000000, "один октильйон"), + (1000000000000000000000000000000, "один нонільйон"), + (215461407892039002157189883901676, + "двісті п'ятнадцять нонільйонів чотириста шістдесят один " + "октильйон чотириста сім септильйонів вісімсот дев'яносто " + "два секстильйони тридцять дев'ять квінтильйонів два " + "квадрильйони сто п'ятдесят сім трильйонів сто вісімдесят " + "дев'ять мільярдів вісімсот вісімдесят три мільйони " + "дев'ятсот одну тисячу шістсот сімдесят шість"), + (719094234693663034822824384220291, + "сімсот дев'ятнадцять нонільйонів дев'яносто чотири октильйони " + "двісті тридцять чотири септильйони шістсот дев'яносто три " + "секстильйони шістсот шістдесят три квінтильйони тридцять " + "чотири квадрильйони вісімсот двадцять два трильйони вісімсот " + "двадцять чотири мільярди триста вісімдесят чотири мільйони " + "двісті двадцять тисяч двісті дев'яносто один") +) + +TEST_CASES_CARDINAL_INSTRUMENTAL = ( + (1, "одним"), + (2, "двома"), + (3, "трьома"), + (4, "чотирма"), + (5, "п'ятьма"), + (6, "шістьма"), + (7, "сьома"), + (8, "вісьма"), + (9, "дев'ятьма"), + (10, "десятьма"), + (10.02, "десятьма кома нуль двома"), + (11, "одинадцятьма"), + (12, "дванадцятьма"), + (12.40, "дванадцятьма кома чотирма"), + (13, "тринадцятьма"), + (14, "чотирнадцятьма"), + (14.13, "чотирнадцятьма кома тринадцятьма"), + (15, "п'ятнадцятьма"), + (16, "шістнадцятьма"), + (17, "сімнадцятьма"), + (17.31, "сімнадцятьма кома тридцятьма одним"), + (18, "вісімнадцятьма"), + (19, "дев'ятнадцятьма"), + (20, "двадцятьма"), + (21, "двадцятьма одним"), + (21.20, "двадцятьма одним кома двома"), + (30, "тридцятьма"), + (32, "тридцятьма двома"), + (40, "сорока"), + (43, "сорока трьома"), + (43.007, "сорока трьома кома нуль нуль сьома"), + (50, "п'ятдесятьма"), + (54, "п'ятдесятьма чотирма"), + (60, "шістдесятьма"), + (60.059, "шістдесятьма кома нуль п'ятдесятьма дев'ятьма"), + (65, "шістдесятьма п'ятьма"), + (70, "сімдесятьма"), + (76, "сімдесятьма шістьма"), + (80, "вісімдесятьма"), + (87, "вісімдесятьма сьома"), + (90, "дев'яностами"), + (98, "дев'яностами вісьма"), + (99, "дев'яностами дев'ятьма"), + (100, "стами"), + (101, "стами одним"), + (199, "стами дев'яностами дев'ятьма"), + (200, "двомастами"), + (203, "двомастами трьома"), + (300, "трьомастами"), + (356, "трьомастами п'ятдесятьма шістьма"), + (400, "чотирмастами"), + (434, "чотирмастами тридцятьма чотирма"), + (500, "п'ятьмастами"), + (578, "п'ятьмастами сімдесятьма вісьма"), + (600, "шістьмастами"), + (689, "шістьмастами вісімдесятьма дев'ятьма"), + (700, "сьомастами"), + (729, "сьомастами двадцятьма дев'ятьма"), + (800, "восьмастами"), + (894, "восьмастами дев'яностами чотирма"), + (900, "дев'ятьмастами"), + (999, "дев'ятьмастами дев'яностами дев'ятьма"), + (1000, "однією тисячею"), + (1001, "однією тисячею одним"), + (2012, "двома тисячами дванадцятьма"), + (12519, "дванадцятьма тисячами п'ятьмастами дев'ятнадцятьма"), + (12519.85, "дванадцятьма тисячами п'ятьмастами дев'ятнадцятьма кома вісімдесятьма п'ятьма"), + (-260000, "мінус двомастами шістдесятьма тисячами"), + (1000000, "одним мільйоном"), + (1000000000, "одним мільярдом"), + (1234567890, "одним мільярдом двомастами тридцятьма чотирма мільйонами " + "п'ятьмастами шістдесятьма сьома тисячами восьмастами дев'яностами"), + (1000000000000, "одним трильйоном"), + (1000000000000000, "одним квадрильйоном"), + (1000000000000000000, "одним квінтильйоном"), + (1000000000000000000000, "одним секстильйоном"), + (1000000000000000000000000, "одним септильйоном"), + (1000000000000000000000000000, "одним октильйоном"), + (1000000000000000000000000000000, "одним нонільйоном"), + (215461407892039002157189883901676, + "двомастами п'ятнадцятьма нонільйонів чотирмастами шістдесятьма одним " + "октильйоном чотирмастами сьома септильйонів восьмастами дев'яностами " + "двома секстильйонами тридцятьма дев'ятьма квінтильйонів двома " + "квадрильйонами стами п'ятдесятьма сьома трильйонів стами вісімдесятьма " + "дев'ятьма мільярдів восьмастами вісімдесятьма трьома мільйонами " + "дев'ятьмастами однією тисячею шістьмастами сімдесятьма шістьма"), + (719094234693663034822824384220291, + "сьомастами дев'ятнадцятьма нонільйонів дев'яностами чотирма октильйонами " + "двомастами тридцятьма чотирма септильйонами шістьмастами дев'яностами трьома " + "секстильйонами шістьмастами шістдесятьма трьома квінтильйонами тридцятьма " + "чотирма квадрильйонами восьмастами двадцятьма двома трильйонами восьмастами " + "двадцятьма чотирма мільярдами трьомастами вісімдесятьма чотирма мільйонами " + "двомастами двадцятьма тисячами двомастами дев'яностами одним") +) + +TEST_CASES_CARDINAL_LOCATIVE = ( + (1, "одному"), + (2, "двох"), + (3, "трьох"), + (4, "чотирьох"), + (5, "п'яти"), + (6, "шести"), + (7, "семи"), + (8, "восьми"), + (9, "дев'яти"), + (10, "десяти"), + (10.02, "десяти кома нуль двох"), + (11, "одинадцяти"), + (12, "дванадцяти"), + (12.40, "дванадцяти кома чотирьох"), + (13, "тринадцяти"), + (14, "чотирнадцяти"), + (14.13, "чотирнадцяти кома тринадцяти"), + (15, "п'ятнадцяти"), + (16, "шістнадцяти"), + (17, "сімнадцяти"), + (17.31, "сімнадцяти кома тридцяти одному"), + (18, "вісімнадцяти"), + (19, "дев'ятнадцяти"), + (20, "двадцяти"), + (21, "двадцяти одному"), + (21.20, "двадцяти одному кома двох"), + (30, "тридцяти"), + (32, "тридцяти двох"), + (40, "сорока"), + (43, "сорока трьох"), + (43.007, "сорока трьох кома нуль нуль семи"), + (50, "п'ятдесяти"), + (54, "п'ятдесяти чотирьох"), + (60, "шістдесяти"), + (60.059, "шістдесяти кома нуль п'ятдесяти дев'яти"), + (65, "шістдесяти п'яти"), + (70, "сімдесяти"), + (76, "сімдесяти шести"), + (80, "вісімдесяти"), + (87, "вісімдесяти семи"), + (90, "дев'яноста"), + (98, "дев'яноста восьми"), + (99, "дев'яноста дев'яти"), + (100, "стах"), + (101, "стах одному"), + (199, "стах дев'яноста дев'яти"), + (200, "двохстах"), + (203, "двохстах трьох"), + (300, "трьохстах"), + (356, "трьохстах п'ятдесяти шести"), + (400, "чотирьохстах"), + (434, "чотирьохстах тридцяти чотирьох"), + (500, "п'ятистах"), + (578, "п'ятистах сімдесяти восьми"), + (600, "шестистах"), + (689, "шестистах вісімдесяти дев'яти"), + (700, "семистах"), + (729, "семистах двадцяти дев'яти"), + (800, "восьмистах"), + (894, "восьмистах дев'яноста чотирьох"), + (900, "дев'ятистах"), + (999, "дев'ятистах дев'яноста дев'яти"), + (1000, "одній тисячі"), + (1001, "одній тисячі одному"), + (2012, "двох тисячах дванадцяти"), + (12519, "дванадцяти тисячах п'ятистах дев'ятнадцяти"), + (12519.85, "дванадцяти тисячах п'ятистах дев'ятнадцяти кома вісімдесяти п'яти"), + (-260000, "мінус двохстах шістдесяти тисячах"), + (1000000, "одному мільйоні"), + (1000000000, "одному мільярді"), + (1234567890, "одному мільярді двохстах тридцяти чотирьох мільйонах " + "п'ятистах шістдесяти семи тисячах восьмистах дев'яноста"), + (1000000000000, "одному трильйоні"), + (1000000000000000, "одному квадрильйоні"), + (1000000000000000000, "одному квінтильйоні"), + (1000000000000000000000, "одному секстильйоні"), + (1000000000000000000000000, "одному септильйоні"), + (1000000000000000000000000000, "одному октильйоні"), + (1000000000000000000000000000000, "одному нонільйоні"), + (215461407892039002157189883901676, + "двохстах п'ятнадцяти нонільйонах чотирьохстах шістдесяти одному " + "октильйоні чотирьохстах семи септильйонах восьмистах дев'яноста " + "двох секстильйонах тридцяти дев'яти квінтильйонах двох " + "квадрильйонах стах п'ятдесяти семи трильйонах стах вісімдесяти " + "дев'яти мільярдах восьмистах вісімдесяти трьох мільйонах " + "дев'ятистах одній тисячі шестистах сімдесяти шести"), + (719094234693663034822824384220291, + "семистах дев'ятнадцяти нонільйонах дев'яноста чотирьох октильйонах " + "двохстах тридцяти чотирьох септильйонах шестистах дев'яноста трьох " + "секстильйонах шестистах шістдесяти трьох квінтильйонах тридцяти " + "чотирьох квадрильйонах восьмистах двадцяти двох трильйонах восьмистах " + "двадцяти чотирьох мільярдах трьохстах вісімдесяти чотирьох мільйонах " + "двохстах двадцяти тисячах двохстах дев'яноста одному") +) + TEST_CASES_ORDINAL = ( (1, "перший"), (2, "другий"), @@ -2449,10 +3025,43 @@ class Num2WordsUKTest(TestCase): + def test_to_cardinal(self): for test in TEST_CASES_CARDINAL: self.assertEqual(num2words(test[0], lang='uk'), test[1]) + def test_to_cardinal_feminine(self): + for test in TEST_CASES_CARDINAL_FEMININE: + self.assertEqual(num2words(test[0], lang='uk', gender='feminine'), test[1]) + + def test_to_cardinal_nominative(self): + for test in TEST_CASES_CARDINAL: + self.assertEqual(num2words(test[0], lang='uk', case='nominative'), test[1]) + + def test_to_cardinal_genitive(self): + for test in TEST_CASES_CARDINAL_GENITIVE: + self.assertEqual(num2words(test[0], lang='uk', case='genitive'), test[1]) + + def test_to_cardinal_dative(self): + self.maxDiff = None + for test in TEST_CASES_CARDINAL_DATIVE: + self.assertEqual(num2words(test[0], lang='uk', case='dative'), test[1]) + + def test_to_cardinal_accusative(self): + self.maxDiff = None + for test in TEST_CASES_CARDINAL_ACCUSATIVE: + self.assertEqual(num2words(test[0], lang='uk', case='accusative'), test[1]) + + def test_to_cardinal_instrumental(self): + self.maxDiff = None + for test in TEST_CASES_CARDINAL_INSTRUMENTAL: + self.assertEqual(num2words(test[0], lang='uk', case='instrumental'), test[1]) + + def test_to_cardinal_locative(self): + self.maxDiff = None + for test in TEST_CASES_CARDINAL_LOCATIVE: + self.assertEqual(num2words(test[0], lang='uk', case='locative'), test[1]) + def test_to_ordinal(self): for test in TEST_CASES_ORDINAL: self.assertEqual( From ad42ffdea573b448de8215e2a2316dcaace13d42 Mon Sep 17 00:00:00 2001 From: Andrii Kurdiumov Date: Sat, 12 Aug 2023 15:43:19 +0600 Subject: [PATCH 198/200] Reformat source code --- num2words/lang_UK.py | 318 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 255 insertions(+), 63 deletions(-) diff --git a/num2words/lang_UK.py b/num2words/lang_UK.py index 0b62d858..188d7ced 100644 --- a/num2words/lang_UK.py +++ b/num2words/lang_UK.py @@ -23,27 +23,27 @@ ZERO = ('нуль',) ONES_FEMININE = { - 1: ('одна', "однієї", "одній", "одну", "однією", "одній"), - 2: ('дві', "двох", "двом", "дві", "двома", "двох"), - 3: ('три', "трьох", "трьом", "три", "трьома", "трьох"), - 4: ('чотири', "чотирьох", "чотирьом", "чотири", "чотирма", "чотирьох"), - 5: ('п\'ять', "п'яти", "п'яти", "п'ять", "п'ятьма", "п'яти"), - 6: ('шість', "шести", "шести", "шість", "шістьма", "шести"), - 7: ('сім', "семи", "семи", "сім", "сьома", "семи"), - 8: ('вісім', "восьми", "восьми", "вісім", "вісьма", "восьми"), - 9: ("дев'ять", "дев'яти", "дев'яти", "дев'ять", "дев'ятьма","дев'яти"), + 1: ('одна', "однієї", "одній", "одну", "однією", "одній"), + 2: ('дві', "двох", "двом", "дві", "двома", "двох"), + 3: ('три', "трьох", "трьом", "три", "трьома", "трьох"), + 4: ('чотири', "чотирьох", "чотирьом", "чотири", "чотирма", "чотирьох"), + 5: ('п\'ять', "п'яти", "п'яти", "п'ять", "п'ятьма", "п'яти"), + 6: ('шість', "шести", "шести", "шість", "шістьма", "шести"), + 7: ('сім', "семи", "семи", "сім", "сьома", "семи"), + 8: ('вісім', "восьми", "восьми", "вісім", "вісьма", "восьми"), + 9: ("дев'ять", "дев'яти", "дев'яти", "дев'ять", "дев'ятьма", "дев'яти"), } ONES = { - 1: ('один', 'одного', "одному", "один", "одним", "одному"), - 2: ('два', 'двох', "двом", "два", "двома", "двох"), - 3: ('три', 'трьох', "трьом", "три", "трьома", "трьох"), - 4: ('чотири', 'чотирьох', "чотирьом", "чотири", "чотирма", "чотирьох"), - 5: ('п\'ять', "п'яти", "п'яти", "п'ять", "п'ятьма", "п'яти"), - 6: ('шість', 'шести', "шести", "шість", "шістьма", "шести"), - 7: ('сім', 'семи', "семи", "сім", "сьома", "семи"), - 8: ('вісім', 'восьми', "восьми", "вісім", "вісьма", "восьми"), - 9: ('дев\'ять', "дев'яти", "дев'яти", "дев'ять", "дев'ятьма","дев'яти"), + 1: ('один', 'одного', "одному", "один", "одним", "одному"), + 2: ('два', 'двох', "двом", "два", "двома", "двох"), + 3: ('три', 'трьох', "трьом", "три", "трьома", "трьох"), + 4: ('чотири', 'чотирьох', "чотирьом", "чотири", "чотирма", "чотирьох"), + 5: ('п\'ять', "п'яти", "п'яти", "п'ять", "п'ятьма", "п'яти"), + 6: ('шість', 'шести', "шести", "шість", "шістьма", "шести"), + 7: ('сім', 'семи', "семи", "сім", "сьома", "семи"), + 8: ('вісім', 'восьми', "восьми", "вісім", "вісьма", "восьми"), + 9: ("дев'ять", "дев'яти", "дев'яти", "дев'ять", "дев'ятьма", "дев'яти"), } ONES_ORDINALS = { @@ -67,29 +67,118 @@ 18: ("вісімнадцятий", "вісімнадцяти"), 19: ("дев'ятнадцятий", "дев'ятнадцяти"), } - TENS = { - 0: ('десять', 'десяти', "десяти", "десять", "десятьма", "десяти"), - 1: ('одинадцять', 'одинадцяти', "одинадцяти", "одинадцять", "одинадцятьма", "одинадцяти"), - 2: ('дванадцять', 'дванадцяти', "дванадцяти", "дванадцять", "дванадцятьма", "дванадцяти"), - 3: ('тринадцять', 'тринадцяти', "тринадцяти", "тринадцять", "тринадцятьма", "тринадцяти"), - 4: ('чотирнадцять', 'чотирнадцяти', "чотирнадцяти", "чотирнадцять", "чотирнадцятьма", "чотирнадцяти"), - 5: ("п'ятнадцять", "п'ятнадцяти", "п'ятнадцяти", "п'ятнадцять", "п'ятнадцятьма", "п'ятнадцяти"), - 6: ('шістнадцять', 'шістнадцяти', "шістнадцяти", "шістнадцять", "шістнадцятьма", "шістнадцяти"), - 7: ('сімнадцять', 'сімнадцяти', "сімнадцяти", "сімнадцять", "сімнадцятьма", "сімнадцяти"), - 8: ('вісімнадцять', 'вісімнадцяти', "вісімнадцяти", "вісімнадцять", "вісімнадцятьма", "вісімнадцяти"), - 9: ("дев'ятнадцять","дев'ятнадцяти","дев'ятнадцяти","дев'ятнадцять","дев'ятнадцятьма", "дев'ятнадцяти"), + 0: ('десять', + 'десяти', + "десяти", + "десять", + "десятьма", + "десяти"), + 1: ('одинадцять', + 'одинадцяти', + "одинадцяти", + "одинадцять", + "одинадцятьма", + "одинадцяти"), + 2: ('дванадцять', + 'дванадцяти', + "дванадцяти", + "дванадцять", + "дванадцятьма", + "дванадцяти"), + 3: ('тринадцять', + 'тринадцяти', + "тринадцяти", + "тринадцять", + "тринадцятьма", + "тринадцяти"), + 4: ('чотирнадцять', + 'чотирнадцяти', + "чотирнадцяти", + "чотирнадцять", + "чотирнадцятьма", + "чотирнадцяти"), + 5: ("п'ятнадцять", + "п'ятнадцяти", + "п'ятнадцяти", + "п'ятнадцять", + "п'ятнадцятьма", + "п'ятнадцяти"), + 6: ('шістнадцять', + 'шістнадцяти', + "шістнадцяти", + "шістнадцять", + "шістнадцятьма", + "шістнадцяти"), + 7: ('сімнадцять', + 'сімнадцяти', + "сімнадцяти", + "сімнадцять", + "сімнадцятьма", + "сімнадцяти"), + 8: ('вісімнадцять', + 'вісімнадцяти', + "вісімнадцяти", + "вісімнадцять", + "вісімнадцятьма", + "вісімнадцяти"), + 9: ("дев'ятнадцять", + "дев'ятнадцяти", + "дев'ятнадцяти", + "дев'ятнадцять", + "дев'ятнадцятьма", + "дев'ятнадцяти"), } TWENTIES = { - 2: ('двадцять', "двадцяти", "двадцяти", "двадцять", "двадцятьма", "двадцяти"), - 3: ('тридцять', "тридцяти", "тридцяти", "тридцять", "тридцятьма", "тридцяти"), - 4: ('сорок', "сорока", "сорока", "сорок", "сорока", "сорока"), - 5: ('п\'ятдесят', "п'ятдесяти", "п'ятдесяти", "п'ятдесят", "п'ятдесятьма", "п'ятдесяти"), - 6: ('шістдесят', "шістдесяти", "шістдесяти", "шістдесят", "шістдесятьма", "шістдесяти"), - 7: ('сімдесят', "сімдесяти", "сімдесяти", "сімдесят", "сімдесятьма", "сімдесяти"), - 8: ('вісімдесят', "вісімдесяти", "вісімдесяти", "вісімдесят", "вісімдесятьма","вісімдесяти"), - 9: ('дев\'яносто', "дев'яноста", "дев'яноста", "дев'яносто", "дев'яностами", "дев'яноста"), + 2: ('двадцять', + "двадцяти", + "двадцяти", + "двадцять", + "двадцятьма", + "двадцяти"), + 3: ('тридцять', + "тридцяти", + "тридцяти", + "тридцять", + "тридцятьма", + "тридцяти"), + 4: ('сорок', + "сорока", + "сорока", + "сорок", + "сорока", + "сорока"), + 5: ('п\'ятдесят', + "п'ятдесяти", + "п'ятдесяти", + "п'ятдесят", + "п'ятдесятьма", + "п'ятдесяти"), + 6: ('шістдесят', + "шістдесяти", + "шістдесяти", + "шістдесят", + "шістдесятьма", + "шістдесяти"), + 7: ('сімдесят', + "сімдесяти", + "сімдесяти", + "сімдесят", + "сімдесятьма", + "сімдесяти"), + 8: ('вісімдесят', + "вісімдесяти", + "вісімдесяти", + "вісімдесят", + "вісімдесятьма", + "вісімдесяти"), + 9: ('дев\'яносто', + "дев'яноста", + "дев'яноста", + "дев'яносто", + "дев'яностами", + "дев'яноста"), } TWENTIES_ORDINALS = { @@ -104,15 +193,60 @@ } HUNDREDS = { - 1: ('сто', "ста", "ста", "сто", "стами", "стах"), - 2: ('двісті', "двохста", "двомстам", "двісті", "двомастами", "двохстах"), - 3: ('триста', "трьохста", "трьомстам", "триста", "трьомастами", "трьохстах"), - 4: ('чотириста',"чотирьохста", "чотирьомстам", "чотириста","чотирмастами", "чотирьохстах"), - 5: ('п\'ятсот', "п'ятиста", "п'ятистам", "п'ятсот", "п'ятьмастами", "п'ятистах"), - 6: ('шістсот', "шестиста", "шестистам", "шістсот", "шістьмастами", "шестистах"), - 7: ('сімсот', "семиста", "семистам", "сімсот", "сьомастами", "семистах"), - 8: ('вісімсот', "восьмиста", "восьмистам", "вісімсот", "восьмастами", "восьмистах"), - 9: ("дев'ятсот","дев'ятиста", "дев'ятистам", "дев'ятсот","дев'ятьмастами","дев'ятистах"), + 1: ('сто', + "ста", + "ста", + "сто", + "стами", + "стах"), + 2: ('двісті', + "двохста", + "двомстам", + "двісті", + "двомастами", + "двохстах"), + 3: ('триста', + "трьохста", + "трьомстам", + "триста", + "трьомастами", + "трьохстах"), + 4: ('чотириста', + "чотирьохста", + "чотирьомстам", + "чотириста", + "чотирмастами", + "чотирьохстах"), + 5: ('п\'ятсот', + "п'ятиста", + "п'ятистам", + "п'ятсот", + "п'ятьмастами", + "п'ятистах"), + 6: ('шістсот', + "шестиста", + "шестистам", + "шістсот", + "шістьмастами", + "шестистах"), + 7: ('сімсот', + "семиста", + "семистам", + "сімсот", + "сьомастами", + "семистах"), + 8: ('вісімсот', + "восьмиста", + "восьмистам", + "вісімсот", + "восьмастами", + "восьмистах"), + 9: ("дев'ятсот", + "дев'ятиста", + "дев'ятистам", + "дев'ятсот", + "дев'ятьмастами", + "дев'ятистах"), } HUNDREDS_ORDINALS = { @@ -128,28 +262,76 @@ } THOUSANDS = { - # Nominative Genitive Dative Accusative Instrumental Locative - # ----------------------------------------------------- --------------------------------------------------- --------------------------------------------------- --------------------------------------------------- ------------------------------------------------------- -------------------------------------------------------- # 10^3 - 1: (('тисяча', 'тисячі', 'тисяч'), ('тисячи', 'тисяч', 'тисяч'), ('тисячі', 'тисячам', 'тисячам'), ('тисячу', 'тисячі', 'тисяч'), ('тисячею', 'тисячами', 'тисячами'), ('тисячі', 'тисячах', 'тисячах'),), + 1: (('тисяча', 'тисячі', 'тисяч'), + ('тисячи', 'тисяч', 'тисяч'), + ('тисячі', 'тисячам', 'тисячам'), + ('тисячу', 'тисячі', 'тисяч'), + ('тисячею', 'тисячами', 'тисячами'), + ('тисячі', 'тисячах', 'тисячах'),), # 10^6 - 2: (('мільйон', 'мільйони', 'мільйонів'), ('мільйона', 'мільйонів', 'мільйонів'), ('мільйону', 'мільйонам', 'мільйонам'), ('мільйон', 'мільйони', 'мільйонів'), ('мільйоном', 'мільйонами', 'мільйонів'), ('мільйоні', 'мільйонах', 'мільйонах'),), + 2: (('мільйон', 'мільйони', 'мільйонів'), + ('мільйона', 'мільйонів', 'мільйонів'), + ('мільйону', 'мільйонам', 'мільйонам'), + ('мільйон', 'мільйони', 'мільйонів'), + ('мільйоном', 'мільйонами', 'мільйонів'), + ('мільйоні', 'мільйонах', 'мільйонах'),), # 10^9 - 3: (('мільярд', 'мільярди', 'мільярдів'), ('мільярда', 'мільярдів', 'мільярдів'), ('мільярду', 'мільярдам', 'мільярдам'), ('мільярд', 'мільярди', 'мільярдів'), ('мільярдом', 'мільярдами', 'мільярдів'), ('мільярді', 'мільярдах', 'мільярдах'),), + 3: (('мільярд', 'мільярди', 'мільярдів'), + ('мільярда', 'мільярдів', 'мільярдів'), + ('мільярду', 'мільярдам', 'мільярдам'), + ('мільярд', 'мільярди', 'мільярдів'), + ('мільярдом', 'мільярдами', 'мільярдів'), + ('мільярді', 'мільярдах', 'мільярдах'),), # 10^12 - 4: (('трильйон', 'трильйони', 'трильйонів'), ('трильйона', 'трильйонів', 'трильйонів'), ('трильйону', 'трильйонам', 'трильйонам'), ('трильйон', 'трильйони', 'трильйонів'), ('трильйоном', 'трильйонами', 'трильйонів'), ('трильйоні', 'трильйонах', 'трильйонах'),), + 4: (('трильйон', 'трильйони', 'трильйонів'), + ('трильйона', 'трильйонів', 'трильйонів'), + ('трильйону', 'трильйонам', 'трильйонам'), + ('трильйон', 'трильйони', 'трильйонів'), + ('трильйоном', 'трильйонами', 'трильйонів'), + ('трильйоні', 'трильйонах', 'трильйонах'),), # 10^15 - 5: (('квадрильйон', 'квадрильйони', 'квадрильйонів'), ('квадрильйона', 'квадрильйонів', 'квадрильйонів'), ('квадрильйону', 'квадрильйонам', 'квадрильйонам'), ('квадрильйон', 'квадрильйони', 'квадрильйонів'), ('квадрильйоном', 'квадрильйонами', 'квадрильйонів'), ('квадрильйоні', 'квадрильйонах', 'квадрильйонах'),), + 5: (('квадрильйон', 'квадрильйони', 'квадрильйонів'), + ('квадрильйона', 'квадрильйонів', 'квадрильйонів'), + ('квадрильйону', 'квадрильйонам', 'квадрильйонам'), + ('квадрильйон', 'квадрильйони', 'квадрильйонів'), + ('квадрильйоном', 'квадрильйонами', 'квадрильйонів'), + ('квадрильйоні', 'квадрильйонах', 'квадрильйонах'),), # 10^18 - 6: (('квінтильйон', 'квінтильйони', 'квінтильйонів'), ('квінтильйона', 'квінтильйонів', 'квінтильйонів'), ('квінтильйону', 'квінтильйонам', 'квінтильйонам'), ('квінтильйон', 'квінтильйони', 'квінтильйонів'), ('квінтильйоном', 'квінтильйонами', 'квінтильйонів'), ('квінтильйоні', 'квінтильйонах', 'квінтильйонах'),), + 6: (('квінтильйон', 'квінтильйони', 'квінтильйонів'), + ('квінтильйона', 'квінтильйонів', 'квінтильйонів'), + ('квінтильйону', 'квінтильйонам', 'квінтильйонам'), + ('квінтильйон', 'квінтильйони', 'квінтильйонів'), + ('квінтильйоном', 'квінтильйонами', 'квінтильйонів'), + ('квінтильйоні', 'квінтильйонах', 'квінтильйонах'),), # 10^21 - 7: (('секстильйон', 'секстильйони', 'секстильйонів'), ('секстильйона', 'секстильйонів', 'секстильйонів'), ('секстильйону', 'секстильйонам', 'секстильйонам'), ('секстильйон', 'секстильйони', 'секстильйонів'), ('секстильйоном', 'секстильйонами', 'секстильйонів'), ('секстильйоні', 'секстильйонах', 'секстильйонах'),), + 7: (('секстильйон', 'секстильйони', 'секстильйонів'), + ('секстильйона', 'секстильйонів', 'секстильйонів'), + ('секстильйону', 'секстильйонам', 'секстильйонам'), + ('секстильйон', 'секстильйони', 'секстильйонів'), + ('секстильйоном', 'секстильйонами', 'секстильйонів'), + ('секстильйоні', 'секстильйонах', 'секстильйонах'),), # 10^24 - 8: (('септильйон', 'септильйони', 'септильйонів'), ('септильйона', 'септильйонів', 'септильйонів'), ('септильйону', 'септильйонам', 'септильйонам'), ('септильйон', 'септильйони', 'септильйонів'), ('септильйоном', 'септильйонами', 'септильйонів'), ('септильйоні', 'септильйонах', 'септильйонах'),), + 8: (('септильйон', 'септильйони', 'септильйонів'), + ('септильйона', 'септильйонів', 'септильйонів'), + ('септильйону', 'септильйонам', 'септильйонам'), + ('септильйон', 'септильйони', 'септильйонів'), + ('септильйоном', 'септильйонами', 'септильйонів'), + ('септильйоні', 'септильйонах', 'септильйонах'),), # 10^27 - 9: (('октильйон', 'октильйони', 'октильйонів'), ('октильйона', 'октильйонів', 'октильйонів'), ('октильйону', 'октильйонам', 'октильйонам'), ('октильйон', 'октильйони', 'октильйонів'), ('октильйоном', 'октильйонами', 'октильйонів'), ('октильйоні', 'октильйонах', 'октильйонах'),), + 9: (('октильйон', 'октильйони', 'октильйонів'), + ('октильйона', 'октильйонів', 'октильйонів'), + ('октильйону', 'октильйонам', 'октильйонам'), + ('октильйон', 'октильйони', 'октильйонів'), + ('октильйоном', 'октильйонами', 'октильйонів'), + ('октильйоні', 'октильйонах', 'октильйонах'),), # 10^30 - 10: (('нонільйон', 'нонільйони', 'нонільйонів'), ('нонільйона', 'нонільйонів', 'нонільйонів'), ('нонільйону', 'нонільйонам', 'нонільйонам'), ('нонільйон', 'нонільйони', 'нонільйонів'), ('нонільйоном', 'нонільйонами', 'нонільйонів'), ('нонільйоні', 'нонільйонах', 'нонільйонах'),), + 10: (('нонільйон', 'нонільйони', 'нонільйонів'), + ('нонільйона', 'нонільйонів', 'нонільйонів'), + ('нонільйону', 'нонільйонам', 'нонільйонам'), + ('нонільйон', 'нонільйони', 'нонільйонів'), + ('нонільйоном', 'нонільйонами', 'нонільйонів'), + ('нонільйоні', 'нонільйонах', 'нонільйонах'),), } prefixes_ordinal = { @@ -726,7 +908,13 @@ def setup(self): def to_cardinal(self, number, **kwargs): if 'case' in kwargs: case = kwargs['case'] - morphological_case = ["nominative", "genitive", "dative", "accusative", "instrumental", "locative"].index(case) + morphological_case = [ + "nominative", + "genitive", + "dative", + "accusative", + "instrumental", + "locative"].index(case) else: morphological_case = 0 @@ -739,8 +927,9 @@ def to_cardinal(self, number, **kwargs): if '.' in n: left, right = n.split('.') leading_zero_count = len(right) - len(right.lstrip('0')) + right_side = self._int2word(int(right), gender, morphological_case) decimal_part = ((ZERO[0] + ' ') * leading_zero_count + - self._int2word(int(right), gender, morphological_case)) + right_side) return u'%s %s %s' % ( self._int2word(int(left), gender, morphological_case), self.pointword, @@ -762,9 +951,11 @@ def pluralize(self, n, forms): return forms[form] - def _int2word(self, n, feminine=False, morphological_case = 0): + def _int2word(self, n, feminine=False, morphological_case=0): if n < 0: - return ' '.join([self.negword, self._int2word(abs(n), feminine, morphological_case)]) + n_value = self._int2word(abs(n), feminine, morphological_case) + return ' '.join([self.negword, + n_value]) if n == 0: return ZERO[0] @@ -794,7 +985,8 @@ def _int2word(self, n, feminine=False, morphological_case = 0): words.append(ones[n1][morphological_case]) if i > 0: - words.append(self.pluralize(x, THOUSANDS[i][morphological_case])) + thousands_val = THOUSANDS[i][morphological_case] + words.append(self.pluralize(x, thousands_val)) return ' '.join(words) From 6c8e66bd37f38eac3ef339963b88ebf8140b26d7 Mon Sep 17 00:00:00 2001 From: Andrii Kurdiumov Date: Sat, 19 Aug 2023 00:31:33 +0600 Subject: [PATCH 199/200] Fix style in tests --- tests/test_uk.py | 51 ++++++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/tests/test_uk.py b/tests/test_uk.py index 3f57eb2d..4dcd7cb1 100644 --- a/tests/test_uk.py +++ b/tests/test_uk.py @@ -280,7 +280,8 @@ (1001, "однієї тисячи одного"), (2012, "двох тисяч дванадцяти"), (12519, "дванадцяти тисяч п'ятиста дев'ятнадцяти"), - (12519.85, "дванадцяти тисяч п'ятиста дев'ятнадцяти кома вісімдесяти п'яти"), + (12519.85, "дванадцяти тисяч п'ятиста дев'ятнадцяти " + "кома вісімдесяти п'яти"), (-260000, "мінус двохста шістдесяти тисяч"), (1000000, "одного мільйона"), (1000000000, "одного мільярда"), @@ -376,7 +377,8 @@ (1001, "одній тисячі одному"), (2012, "двом тисячам дванадцяти"), (12519, "дванадцяти тисячам п'ятистам дев'ятнадцяти"), - (12519.85, "дванадцяти тисячам п'ятистам дев'ятнадцяти кома вісімдесяти п'яти"), + (12519.85, "дванадцяти тисячам п'ятистам дев'ятнадцяти " + "кома вісімдесяти п'яти"), (-260000, "мінус двомстам шістдесяти тисячам"), (1000000, "одному мільйону"), (1000000000, "одному мільярду"), @@ -568,12 +570,14 @@ (1001, "однією тисячею одним"), (2012, "двома тисячами дванадцятьма"), (12519, "дванадцятьма тисячами п'ятьмастами дев'ятнадцятьма"), - (12519.85, "дванадцятьма тисячами п'ятьмастами дев'ятнадцятьма кома вісімдесятьма п'ятьма"), + (12519.85, "дванадцятьма тисячами п'ятьмастами дев'ятнадцятьма " + "кома вісімдесятьма п'ятьма"), (-260000, "мінус двомастами шістдесятьма тисячами"), (1000000, "одним мільйоном"), (1000000000, "одним мільярдом"), (1234567890, "одним мільярдом двомастами тридцятьма чотирма мільйонами " - "п'ятьмастами шістдесятьма сьома тисячами восьмастами дев'яностами"), + "п'ятьмастами шістдесятьма сьома тисячами восьмастами " + "дев'яностами"), (1000000000000, "одним трильйоном"), (1000000000000000, "одним квадрильйоном"), (1000000000000000000, "одним квінтильйоном"), @@ -589,12 +593,13 @@ "дев'ятьма мільярдів восьмастами вісімдесятьма трьома мільйонами " "дев'ятьмастами однією тисячею шістьмастами сімдесятьма шістьма"), (719094234693663034822824384220291, - "сьомастами дев'ятнадцятьма нонільйонів дев'яностами чотирма октильйонами " - "двомастами тридцятьма чотирма септильйонами шістьмастами дев'яностами трьома " - "секстильйонами шістьмастами шістдесятьма трьома квінтильйонами тридцятьма " - "чотирма квадрильйонами восьмастами двадцятьма двома трильйонами восьмастами " - "двадцятьма чотирма мільярдами трьомастами вісімдесятьма чотирма мільйонами " - "двомастами двадцятьма тисячами двомастами дев'яностами одним") + "сьомастами дев'ятнадцятьма нонільйонів дев'яностами чотирма " + "октильйонами двомастами тридцятьма чотирма септильйонами шістьмастами " + "дев'яностами трьома секстильйонами шістьмастами шістдесятьма трьома " + "квінтильйонами тридцятьма чотирма квадрильйонами восьмастами двадцятьма " + "двома трильйонами восьмастами двадцятьма чотирма мільярдами трьомастами " + "вісімдесятьма чотирма мільйонами двомастами двадцятьма тисячами " + "двомастами дев'яностами одним") ) TEST_CASES_CARDINAL_LOCATIVE = ( @@ -664,7 +669,8 @@ (1001, "одній тисячі одному"), (2012, "двох тисячах дванадцяти"), (12519, "дванадцяти тисячах п'ятистах дев'ятнадцяти"), - (12519.85, "дванадцяти тисячах п'ятистах дев'ятнадцяти кома вісімдесяти п'яти"), + (12519.85, "дванадцяти тисячах п'ятистах дев'ятнадцяти " + "кома вісімдесяти п'яти"), (-260000, "мінус двохстах шістдесяти тисячах"), (1000000, "одному мільйоні"), (1000000000, "одному мільярді"), @@ -3025,42 +3031,49 @@ class Num2WordsUKTest(TestCase): - + def test_to_cardinal(self): for test in TEST_CASES_CARDINAL: self.assertEqual(num2words(test[0], lang='uk'), test[1]) def test_to_cardinal_feminine(self): for test in TEST_CASES_CARDINAL_FEMININE: - self.assertEqual(num2words(test[0], lang='uk', gender='feminine'), test[1]) + word = num2words(test[0], lang='uk', gender='feminine') + self.assertEqual(word, test[1]) def test_to_cardinal_nominative(self): for test in TEST_CASES_CARDINAL: - self.assertEqual(num2words(test[0], lang='uk', case='nominative'), test[1]) + word = num2words(test[0], lang='uk', case='nominative') + self.assertEqual(word, test[1]) def test_to_cardinal_genitive(self): for test in TEST_CASES_CARDINAL_GENITIVE: - self.assertEqual(num2words(test[0], lang='uk', case='genitive'), test[1]) + word = num2words(test[0], lang='uk', case='genitive') + self.assertEqual(word, test[1]) def test_to_cardinal_dative(self): self.maxDiff = None for test in TEST_CASES_CARDINAL_DATIVE: - self.assertEqual(num2words(test[0], lang='uk', case='dative'), test[1]) + word = num2words(test[0], lang='uk', case='dative') + self.assertEqual(word, test[1]) def test_to_cardinal_accusative(self): self.maxDiff = None for test in TEST_CASES_CARDINAL_ACCUSATIVE: - self.assertEqual(num2words(test[0], lang='uk', case='accusative'), test[1]) + word = num2words(test[0], lang='uk', case='accusative') + self.assertEqual(word, test[1]) def test_to_cardinal_instrumental(self): self.maxDiff = None for test in TEST_CASES_CARDINAL_INSTRUMENTAL: - self.assertEqual(num2words(test[0], lang='uk', case='instrumental'), test[1]) + word = num2words(test[0], lang='uk', case='instrumental') + self.assertEqual(word, test[1]) def test_to_cardinal_locative(self): self.maxDiff = None for test in TEST_CASES_CARDINAL_LOCATIVE: - self.assertEqual(num2words(test[0], lang='uk', case='locative'), test[1]) + word = num2words(test[0], lang='uk', case='locative') + self.assertEqual(word, test[1]) def test_to_ordinal(self): for test in TEST_CASES_ORDINAL: From 2da1f924dfd49c57a9fa841bd39a6583564badbd Mon Sep 17 00:00:00 2001 From: Michal Juranyi Date: Sun, 3 Sep 2023 20:39:47 +0200 Subject: [PATCH 200/200] Add Slovak language support Signed-off-by: Michal Juranyi --- num2words/__init__.py | 5 +- num2words/lang_SK.py | 160 ++++++++++++++++++++++++++++++++++++++++++ tests/test_sk.py | 98 ++++++++++++++++++++++++++ 3 files changed, 261 insertions(+), 2 deletions(-) create mode 100644 num2words/lang_SK.py create mode 100644 tests/test_sk.py diff --git a/num2words/__init__.py b/num2words/__init__.py index 0942928f..53a28591 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -23,8 +23,8 @@ 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_SL, lang_SR, lang_SV, lang_TE, lang_TG, - lang_TH, lang_TR, lang_UK, lang_VI) + lang_RO, lang_RU, lang_SK, lang_SL, lang_SR, lang_SV, lang_TE, + lang_TG, lang_TH, lang_TR, lang_UK, lang_VI) CONVERTER_CLASSES = { 'am': lang_AM.Num2Word_AM(), @@ -57,6 +57,7 @@ '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(), diff --git a/num2words/lang_SK.py b/num2words/lang_SK.py new file mode 100644 index 00000000..35ece024 --- /dev/null +++ b/num2words/lang_SK.py @@ -0,0 +1,160 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + +from __future__ import unicode_literals + +from .base import Num2Word_Base +from .utils import get_digits, splitbyx + +ZERO = ('nula',) + +ONES = { + 1: ('jeden', 'jeden', set()), + 2: ('dva', 'dve', {1, 3, 5, 7, 9}), + 3: ('tri', 'tri', set()), + 4: ('štyri', 'štyri', set()), + 5: ('päť', 'päť', set()), + 6: ('šesť', 'šesť', set()), + 7: ('sedem', 'sedem', set()), + 8: ('osem', 'osem', set()), + 9: ('deväť', 'deväť', set()), +} + +TENS = { + 0: ('desať',), + 1: ('jedenásť',), + 2: ('dvanásť',), + 3: ('trinásť',), + 4: ('štrnásť',), + 5: ('pätnásť',), + 6: ('šestnásť',), + 7: ('sedemnásť',), + 8: ('osemnásť',), + 9: ('devätnásť',), +} + +TWENTIES = { + 2: ('dvadsať',), + 3: ('tridsať',), + 4: ('štyridsať',), + 5: ('päťdesiat',), + 6: ('šesťdesiat',), + 7: ('sedemdesiat',), + 8: ('osemdesiat',), + 9: ('deväťdesiat',), +} + +HUNDREDS = { + 1: ('sto',), + 2: ('dvesto',), + 3: ('tristo',), + 4: ('štyristo',), + 5: ('päťsto',), + 6: ('šesťsto',), + 7: ('sedemsto',), + 8: ('osemsto',), + 9: ('deväťsto',), +} + +THOUSANDS = { + 1: ('tisíc', 'tisíc', 'tisíc'), # 10^3 + 2: ('milión', 'milióny', 'miliónov'), # 10^6 + 3: ('miliarda', 'miliardy', 'miliárd'), # 10^9 + 4: ('bilión', 'bilióny', 'biliónov'), # 10^12 + 5: ('biliarda', 'biliardy', 'biliárd'), # 10^15 + 6: ('trilión', 'trilióny', 'triliónov'), # 10^18 + 7: ('triliarda', 'triliardy', 'triliárd'), # 10^21 + 8: ('kvadrilión', 'kvadrilióny', 'kvadriliónov'), # 10^24 + 9: ('kvadriliarda', 'kvadriliardy', 'kvadriliárd'), # 10^27 + 10: ('kvintilión', 'kvintillióny', 'kvintiliónov'), # 10^30 +} + + +class Num2Word_SK(Num2Word_Base): + CURRENCY_FORMS = { + 'EUR': ( + ('euro', 'eurá', 'eur'), ('cent', 'centy', 'centov') + ), + } + + def setup(self): + self.negword = "mínus" + self.pointword = "celých" + + 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 0 < n < 5: + form = 1 + else: + form = 2 + return forms[form] + + def to_ordinal(self, value): + 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) + + word_chunk = [] + + if n3 > 0: + word_chunk.append(HUNDREDS[n3][0]) + + if n2 > 1: + word_chunk.append(TWENTIES[n2][0]) + + if n2 == 1: + word_chunk.append(TENS[n1][0]) + elif n1 > 0 and not (i > 0 and x == 1): + if n2 == 0 and n3 == 0 and i in ONES[n1][2]: + word_chunk.append(ONES[n1][1]) + else: + word_chunk.append(ONES[n1][0]) + if i > 1 and word_chunk: + word_chunk.append(' ') + if i > 0: + word_chunk.append(self.pluralize(x, THOUSANDS[i])) + words.append(''.join(word_chunk)) + + return ' '.join(words[:-1]) + ''.join(words[-1:]) diff --git a/tests/test_sk.py b/tests/test_sk.py new file mode 100644 index 00000000..314a7c2b --- /dev/null +++ b/tests/test_sk.py @@ -0,0 +1,98 @@ + +# -*- 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 unittest import TestCase + +from num2words import num2words + + +class Num2WordsSKTest(TestCase): + def test_cardinal(self): + self.assertEqual(num2words(100, lang='sk'), "sto") + self.assertEqual(num2words(101, lang='sk'), "stojeden") + self.assertEqual(num2words(110, lang='sk'), "stodesať") + self.assertEqual(num2words(115, lang='sk'), "stopätnásť") + self.assertEqual(num2words(123, lang='sk'), "stodvadsaťtri") + self.assertEqual(num2words(1000, lang='sk'), "tisíc") + self.assertEqual(num2words(1001, lang='sk'), "tisícjeden") + self.assertEqual(num2words(2012, lang='sk'), "dvetisícdvanásť") + self.assertEqual( + num2words(10.02, lang='sk'), + "desať celých nula dva" + ) + self.assertEqual( + num2words(15.007, lang='sk'), + "pätnásť celých nula nula sedem" + ) + self.assertEqual( + num2words(12519.85, lang='sk'), + "dvanásťtisícpäťstodevätnásť celých osemdesiatpäť" + ) + self.assertEqual( + num2words(123.50, lang='sk'), + "stodvadsaťtri celých päť" + ) + self.assertEqual( + num2words(1234567890, lang='sk'), + "miliarda dvestotridsaťštyri miliónov päťstošesťdesiat" + "sedemtisícosemstodeväťdesiat" + ) + self.assertEqual( + num2words(215461407892039002157189883901676, lang='sk'), + "dvestopätnásť kvintiliónov štyristošesťdesiatjeden kvadriliárd " + "štyristosedem kvadriliónov osemstodeväťdesiatdva triliárd " + "tridsaťdeväť triliónov dve biliardy stopäťdesiatsedem biliónov " + "stoosemdesiatdeväť miliárd osemstoosemdesiattri miliónov " + "deväťstojedentisícšesťstosedemdesiatšesť" + ) + self.assertEqual( + num2words(719094234693663034822824384220291, lang='sk'), + "sedemstodevätnásť kvintiliónov deväťdesiatštyri kvadriliárd " + "dvestotridsaťštyri kvadriliónov šesťstodeväťdesiattri triliárd " + "šesťstošesťdesiattri triliónov tridsaťštyri biliárd " + "osemstodvadsaťdva biliónov osemstodvadsaťštyri miliárd " + "tristoosemdesiatštyri miliónov " + "dvestodvadsaťtisícdvestodeväťdesiatjeden" + ) + + def test_to_ordinal(self): + # @TODO: implement to_ordinal + with self.assertRaises(NotImplementedError): + num2words(1, lang='sk', to='ordinal') + + def test_currency(self): + self.assertEqual( + num2words(10.0, lang='sk', to='currency', currency='EUR'), + "desať eur, nula centov") + self.assertEqual( + num2words(1234.56, lang='sk', to='currency', currency='EUR'), + "tisícdvestotridsaťštyri eur, päťdesiatšesť centov") + self.assertEqual( + num2words(101.11, lang='sk', to='currency', currency='EUR', + separator=' a'), + "stojeden eur a jedenásť centov") + self.assertEqual( + num2words(-12519.85, lang='sk', to='currency', cents=False), + "mínus dvanásťtisícpäťstodevätnásť eur, 85 centov" + ) + self.assertEqual( + num2words(19.50, lang='sk', to='currency', cents=False), + "devätnásť eur, 50 centov" + )