From 551a980e544407c618a18c8e29eeb7f40fc013f0 Mon Sep 17 00:00:00 2001 From: dede64 Date: Mon, 19 Feb 2018 22:30:20 +0100 Subject: [PATCH] Created translation to Czech language (#154) * Create lang_CZ.py * Added czech language to init . * Update __init__.py * Update lang_CZ.py * Added translation to czech language * Fixed thousands translation * Added czech language to readme * Changed pointword in czech translation. * Create test_cz.py * Fixed names for very big numbers. * Fixed currency spelling. * Created tests for czech language. * Fixed: Shortened length of some long lines. * Shortened one more line of code. * Fixed tests * Fixed flake-8. * Changed name of the test class --- README.rst | 1 + num2words/__init__.py | 2 + num2words/lang_CZ.py | 153 ++++++++++++++++++++++++++++++++++++++++++ tests/test_cz.py | 105 +++++++++++++++++++++++++++++ 4 files changed, 261 insertions(+) create mode 100644 num2words/lang_CZ.py create mode 100644 tests/test_cz.py diff --git a/README.rst b/README.rst index d2a781c..27fcf6c 100644 --- a/README.rst +++ b/README.rst @@ -62,6 +62,7 @@ Besides the numerical argument, there's two optional arguments. * ``en`` (English, default) * ``ar`` (Arabic) +* ``cz`` (Czech) * ``de`` (German) * ``dk`` (Danish) * ``en_GB`` (English - Great Britain) diff --git a/num2words/__init__.py b/num2words/__init__.py index 9f7c337..81d7a5d 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -17,6 +17,7 @@ from __future__ import unicode_literals from . import lang_AR +from . import lang_CZ from . import lang_EN from . import lang_EN_IN from . import lang_FR @@ -46,6 +47,7 @@ from . import lang_TH CONVERTER_CLASSES = { 'ar': lang_AR.Num2Word_AR(), + 'cz': lang_CZ.Num2Word_CZ(), 'en': lang_EN.Num2Word_EN(), 'en_IN': lang_EN_IN.Num2Word_EN_IN(), 'fr': lang_FR.Num2Word_FR(), diff --git a/num2words/lang_CZ.py b/num2words/lang_CZ.py new file mode 100644 index 0000000..c94e2c5 --- /dev/null +++ b/num2words/lang_CZ.py @@ -0,0 +1,153 @@ +# -*- encoding: utf-8 -*- +# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. +# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA +from __future__ import unicode_literals + +from .base import Num2Word_Base +from .utils import get_digits, splitbyx + +ZERO = ('nula',) + +ONES = { + 1: ('jedna',), + 2: ('dva',), + 3: ('tři',), + 4: ('čtyři',), + 5: ('pět',), + 6: ('šest',), + 7: ('sedm',), + 8: ('osm',), + 9: ('devět',), +} + +TENS = { + 0: ('deset',), + 1: ('jedenáct',), + 2: ('dvanáct',), + 3: ('třináct',), + 4: ('čtrnáct',), + 5: ('patnáct',), + 6: ('šestnáct',), + 7: ('sedmnáct',), + 8: ('osmnáct',), + 9: ('devatenáct',), +} + +TWENTIES = { + 2: ('dvacet',), + 3: ('třicet',), + 4: ('čtyřicet',), + 5: ('padesát',), + 6: ('šedesát',), + 7: ('sedmdesát',), + 8: ('osmdesát',), + 9: ('devadesát',), +} + +HUNDREDS = { + 1: ('sto',), + 2: ('dvěstě',), + 3: ('třista',), + 4: ('čtyřista',), + 5: ('pětset',), + 6: ('šestset',), + 7: ('sedmset',), + 8: ('osmset',), + 9: ('devětset',), +} + +THOUSANDS = { + 1: ('tisíc', 'tisíce', 'tisíc'), # 10^3 + 2: ('milion', 'miliony', 'milionů'), # 10^6 + 3: ('miliarda', 'miliardy', 'miliard'), # 10^9 + 4: ('bilion', 'biliony', 'bilionů'), # 10^12 + 5: ('biliarda', 'biliardy', 'biliard'), # 10^15 + 6: ('trilion', 'triliony', 'trilionů'), # 10^18 + 7: ('triliarda', 'triliardy', 'triliard'), # 10^21 + 8: ('kvadrilion', 'kvadriliony', 'kvadrilionů'), # 10^24 + 9: ('kvadriliarda', 'kvadriliardy', 'kvadriliard'), # 10^27 + 10: ('quintillion', 'quintilliony', 'quintillionů'), # 10^30 +} + + +class Num2Word_CZ(Num2Word_Base): + CURRENCY_FORMS = { + 'CZK': ( + ('koruna', 'koruny', 'korun'), ('halíř', 'halíře', 'haléřů') + ), + 'EUR': ( + ('euro', 'euro', 'euro'), ('cent', 'centy', 'centů') + ), + } + + def setup(self): + self.negword = "mínus" + self.pointword = "celá" + + def set_numwords(self): + # @FIXME + self.cards[0] = [] + + def to_cardinal(self, number): + n = str(number).replace(',', '.') + if '.' in n: + left, right = n.split('.') + return u'%s %s %s' % ( + self._int2word(int(left)), + self.pointword, + self._int2word(int(right)) + ) + else: + return self._int2word(int(n)) + + def pluralize(self, n, forms): + if n == 1: + form = 0 + elif 5 > n % 10 > 1 and (n % 100 < 10 or n % 100 > 20): + form = 1 + else: + form = 2 + return forms[form] + + def to_ordinal(self, number): + raise NotImplementedError() + + def _int2word(self, n): + if n == 0: + return ZERO[0] + + words = [] + chunks = list(splitbyx(str(n), 3)) + i = len(chunks) + for x in chunks: + i -= 1 + n1, n2, n3 = get_digits(x) + + if n3 > 0: + words.append(HUNDREDS[n3][0]) + + if n2 > 1: + words.append(TWENTIES[n2][0]) + + if n2 == 1: + words.append(TENS[n1][0]) + elif n1 > 0 and not (i > 0 and x == 1): + words.append(ONES[n1][0]) + + if i > 0: + words.append(self.pluralize(x, THOUSANDS[i])) + + return ' '.join(words) diff --git a/tests/test_cz.py b/tests/test_cz.py new file mode 100644 index 0000000..c092edb --- /dev/null +++ b/tests/test_cz.py @@ -0,0 +1,105 @@ +# -*- encoding: utf-8 -*- +# Copyright (c) 2015, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + +from __future__ import unicode_literals + +from unittest import TestCase + +from num2words import num2words + + +class Num2WordsCZTest(TestCase): + def test_cardinal(self): + self.assertEqual(num2words(100, lang='cz'), "sto") + self.assertEqual(num2words(101, lang='cz'), "sto jedna") + self.assertEqual(num2words(110, lang='cz'), "sto deset") + self.assertEqual(num2words(115, lang='cz'), "sto patnáct") + self.assertEqual(num2words(123, lang='cz'), "sto dvacet tři") + 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(12519.85, lang='cz'), + "dvanáct tisíc pětset devatenáct celá osmdesát pět" + ) + self.assertEqual( + num2words(123.50, lang='cz'), + "sto dvacet tři celá pět" + ) + self.assertEqual( + num2words(1234567890, lang='cz'), + "miliarda dvěstě třicet čtyři miliony pětset šedesát " + "sedm tisíc osmset devadesát" + ) + self.assertEqual( + num2words(215461407892039002157189883901676, lang='cz'), + "dvěstě patnáct quintillionů čtyřista šedesát jedna kvadriliard " + "čtyřista sedm kvadrilionů osmset devadesát dva triliardy třicet " + "devět trilionů dva biliardy sto padesát sedm bilionů sto " + "osmdesát devět miliard osmset osmdesát tři miliony " + "devětset jedna tisíc šestset sedmdesát šest" + ) + self.assertEqual( + num2words(719094234693663034822824384220291, lang='cz'), + "sedmset devatenáct quintillionů devadesát " + "čtyři kvadriliardy dvěstě třicet čtyři " + "kvadriliony šestset devadesát tři triliardy " + "šestset šedesát tři triliony třicet čtyři biliardy osmset " + "dvacet dva biliony osmset dvacet čtyři " + "miliardy třista osmdesát čtyři miliony dvěstě dvacet " + "tisíc dvěstě devadesát jedna" + ) + + def test_to_ordinal(self): + # @TODO: implement to_ordinal + with self.assertRaises(NotImplementedError): + num2words(1, lang='cz', to='ordinal') + + def test_currency(self): + self.assertEqual( + num2words(10.0, lang='cz', to='currency', currency='EUR'), + "deset euro, nula centů") + self.assertEqual( + num2words(1.0, lang='cz', to='currency', currency='CZK'), + "jedna koruna, nula haléřů") + self.assertEqual( + num2words(1234.56, lang='cz', to='currency', currency='EUR'), + "tisíc dvěstě třicet čtyři euro, padesát šest centů") + self.assertEqual( + num2words(1234.56, lang='cz', to='currency', currency='CZK'), + "tisíc dvěstě třicet čtyři koruny, padesát šest haléřů") + self.assertEqual( + num2words(101.11, lang='cz', to='currency', currency='EUR', + seperator=' a'), + "sto jedna euro a jedenáct centů") + self.assertEqual( + num2words(101.21, lang='cz', to='currency', currency='CZK', + seperator=' a'), + "sto jedna korun a dvacet jedna haléřů" + ) + self.assertEqual( + num2words(-12519.85, lang='cz', to='currency', cents=False), + "mínus dvanáct tisíc pětset devatenáct euro, 85 centů" + ) + self.assertEqual( + num2words(123.50, lang='cz', to='currency', currency='CZK', + seperator=' a'), + "sto dvacet tři koruny a padesát haléřů" + ) + self.assertEqual( + num2words(19.50, lang='cz', to='currency', cents=False), + "devatenáct euro, 50 centů" + )