diff --git a/README.rst b/README.rst index 9cf9cc5..a65d706 100644 --- a/README.rst +++ b/README.rst @@ -4,7 +4,7 @@ num2words - Convert numbers to words in multiple languages .. image:: https://travis-ci.org/savoirfairelinux/num2words.svg?branch=master :target: https://travis-ci.org/savoirfairelinux/num2words -``num2words`` is a library that converts numbers like ``42`` to words like ``forty-two``. +``num2words`` is a library that converts numbers like ``42`` to words like ``forty-two``. It supports multiple languages (see the list below for full list of languages) and can even generate ordinal numbers like ``forty-second`` (although this last feature is a bit buggy for some languages at the moment). @@ -67,6 +67,7 @@ cardinal one. * ``no`` (Norwegian) * ``pl`` (Polish) * ``pt_BR`` (Brazilian Portuguese) +* ``sl`` (Slovene) * ``ru`` (Russian) * ``tr`` (Turkish) * ``vn`` (Vietnamese) diff --git a/num2words/lang_SL.py b/num2words/lang_SL.py index 7e6982e..4de0a90 100644 --- a/num2words/lang_SL.py +++ b/num2words/lang_SL.py @@ -37,14 +37,8 @@ class Num2Word_SL(Num2Word_EU): self.errmsg_toobig = "Number is too large to convert to words." self.exclude_title = [] - lows = ["non", "okt", "sept", "sext", "quint", "quadr", "tr", "b", "m"] - units = ["", "un", "duo", "tre", "quattuor", "quin", "sex", "sept", - "okto", "novem"] - tens = ["dez", "vigint", "trigint", "quadragint", "quinquagint", - "sexagint", "septuagint", "oktogint", "nonagint"] - self.high_numwords = ["zent"]+self.gen_high_numwords(units, tens, lows) - self.mid_numwords = [(1000, "tisoč "), (900, "devetsto"), (800, "osemsto"), - (700, "sedemsto"), (600, "šesto"), (500, "petsto"), (400, "štiristo"), (300, "tristo"), + self.mid_numwords = [(1000, "tisoč"), (900, "devetsto"), (800, "osemsto"), + (700, "sedemsto"), (600, "šesto"), (500, "petsto"), (400, "štiristo"), (300, "tristo"), (200, "dvesto"), (100, "sto"), (90, "devetdeset"), (80, "osemdeset"), (70, "sedemdeset"), (60, "šestdeset"), (50, "petdeset"), (40, "štirideset"), @@ -52,19 +46,27 @@ class Num2Word_SL(Num2Word_EU): self.low_numwords = ["dvajset", "devetnajst", "osemnajst", "sedemnajst", "šestnajst", "petnajst", "štirinajst", "trinajst", "dvanajst", "enajst", "deset", "devet", "osem", "sedem", - "šest", "pet", "štiri", "tri", "dva", "ena", + "šest", "pet", "štiri", "tri", "dve", "ena", "nič"] - self.ords = { "ena" : "prvi", - "dve" : "drugi", - "acht" : "ach", - "sieben" : "sieb", - "ig" : "igs" } + self.ords = { "ena" : "prv", + "dve" : "drug", + "tri" : "tretj", + "štiri" : "četrt", + "sedem" : "sedm", + "osem" : "osm", + "sto" : "stot", + "tisoč" : "tisoč", + "miljon" : "miljont" + } self.ordflag = False def merge(self, curr, next): ctext, cnum, ntext, nnum = curr + next + if ctext == "dve" and not self.ordflag: + ctext = "dva" + if cnum == 1: if nnum < 10**6 or self.ordflag: return next @@ -72,25 +74,43 @@ class Num2Word_SL(Num2Word_EU): if nnum > cnum: if nnum >= 10**6: - if cnum > 1: - if ntext.endswith("d") or self.ordflag: + if self.ordflag: + ntext += "t" + + elif cnum == 2: + if ntext.endswith("d"): + ntext += "i" + else: + ntext += "a" + + elif 2 < cnum < 5: + if ntext.endswith("d"): + ntext += "e" + elif not ntext.endswith("d"): + ntext += "i" + + else: + if ntext.endswith("d"): ntext += "" + elif ntext.endswith("d"): + ntext += "e" else: ntext += "ov" + + if nnum >= 10**2 and self.ordflag == False: ctext += " " + val = cnum * nnum else: if nnum < 10 < cnum < 100: - if nnum == 1: - ntext = "ena" ntext, ctext = ctext, ntext + "in" - elif cnum >= 10**6: + elif cnum >= 10**2 and self.ordflag == False: ctext += " " val = cnum + nnum word = ctext + ntext return (word, val) - + def to_ordinal(self, value): self.verify_ordinal(value) @@ -101,13 +121,13 @@ class Num2Word_SL(Num2Word_EU): if outword.endswith(key): outword = outword[:len(outword) - len(key)] + self.ords[key] break - return outword + "te" + return outword + "i" # Is this correct?? def to_ordinal_num(self, value): self.verify_ordinal(value) - return str(value) + "te" + return str(value) + "." def to_currency(self, val, longval=True, old=False): @@ -123,7 +143,7 @@ class Num2Word_SL(Num2Word_EU): return self.to_splitnum(val, hightxt="hundert", longval=longval) - + n2w = Num2Word_SL() to_card = n2w.to_cardinal to_ord = n2w.to_ordinal @@ -138,9 +158,8 @@ def main(): n2w.test(val) n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730) - print n2w.to_currency(112121) - print n2w.to_year(2000) + print(n2w.to_currency(112121)) + print(n2w.to_year(2000)) if __name__ == "__main__": main() - diff --git a/tests/test_sl.py b/tests/test_sl.py new file mode 100644 index 0000000..b41332f --- /dev/null +++ b/tests/test_sl.py @@ -0,0 +1,55 @@ +# -*- encoding: utf-8 -*- +# Copyright (c) 2015, Savoir-faire Linux inc. All Rights Reserved. + +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + +from __future__ import unicode_literals + +from unittest import TestCase + +from num2words import num2words + +class Num2WordsDETest(TestCase): + def test_ordinal_less_than_twenty(self): + self.assertEqual(num2words(2, ordinal=True, lang='sl'), "drugi") + self.assertEqual(num2words(4, ordinal=True, lang='sl'), "četrti") + self.assertEqual(num2words(7, ordinal=True, lang='sl'), "sedmi") + self.assertEqual(num2words(8, ordinal=True, lang='sl'), "osmi") + self.assertEqual(num2words(12, ordinal=True, lang='sl'), "dvanajsti") + self.assertEqual(num2words(17, ordinal=True, lang='sl'), "sedemnajsti") + + def test_ordinal_more_than_twenty(self): + self.assertEqual(num2words(81, ordinal=True, lang='sl'), "enainosemdeseti") + + def test_ordinal_at_crucial_number(self): + self.assertEqual(num2words(100, ordinal=True, lang='sl'), "stoti") + self.assertEqual(num2words(1000, ordinal=True, lang='sl'), "tisoči") + self.assertEqual(num2words(4000, ordinal=True, lang='sl'), "štiritisoči") + self.assertEqual(num2words(2000000, ordinal=True, lang='sl'), "dvemiljonti") + self.assertEqual(num2words(5000000000, ordinal=True, lang='sl'), "petmiljardti") + + def test_cardinal_at_some_numbers(self): + self.assertEqual(num2words(2, lang='sl'), "dve") + self.assertEqual(num2words(4000, lang='sl'), "štiri tisoč") + self.assertEqual(num2words(2000000, lang='sl'), "dva miljona") + self.assertEqual(num2words(4000000000, lang='sl'), "štiri miljarde") + + def test_cardinal_for_decimal_number(self): + self.assertEqual(num2words(3.486, lang='sl'), "tri celih štiri osem") + + def test_ordinal_for_negative_numbers(self): + self.assertRaises(TypeError, num2words, -12, ordinal=True, lang='sl') + + def test_ordinal_for_floating_numbers(self): + self.assertRaises(TypeError, num2words, 2.453, ordinal=True, lang='sl')