diff --git a/README.rst b/README.rst index 7b9b487..2a8f99f 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 86f1b63..236f2c7 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -17,16 +17,15 @@ 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_TH, lang_TR, lang_UK, lang_VI) +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) CONVERTER_CLASSES = { - 'am': lang_AM.Num2Word_AM(), 'ar': lang_AR.Num2Word_AR(), 'cz': lang_CZ.Num2Word_CZ(), 'en': lang_EN.Num2Word_EN(), @@ -62,6 +61,7 @@ CONVERTER_CLASSES = { '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 0000000..48291a2 --- /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 + + else: + 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 0000000..53a49e4 --- /dev/null +++ b/tests/test_tg.py @@ -0,0 +1,118 @@ +# -*- 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): + 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"), "яксаду понздаҳ") + 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(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"), "минус понздаҳ") + 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"), + "як ҳазору дусаду си доллар, панҷову шаш сент", + ) + + def test_to_ordinal_num(self): + self.assertEqual( + num2words("100", lang="tg", to="ordinal_num"), + "100ум", + )