From e8bcc0ef2d78fec6a9f72ecb84ba8d6accd9e400 Mon Sep 17 00:00:00 2001 From: Brett Anthoine Date: Fri, 18 Mar 2016 15:52:30 +0100 Subject: [PATCH] Add Swiss-French variants of numbers between 60 and 100. --- num2words/__init__.py | 2 + num2words/lang_FR_CH.py | 113 ++++++++++++++++++++++++++++++++++++++++ tests/test_fr_ch.py | 36 +++++++++++++ 3 files changed, 151 insertions(+) create mode 100644 num2words/lang_FR_CH.py create mode 100644 tests/test_fr_ch.py diff --git a/num2words/__init__.py b/num2words/__init__.py index 1a753ce..220f0c3 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -20,6 +20,7 @@ from . import lang_EN from . import lang_EN_GB from . import lang_EN_IN from . import lang_FR +from . import lang_FR_CH from . import lang_DE from . import lang_ES from . import lang_LT @@ -31,6 +32,7 @@ CONVERTER_CLASSES = { 'en_GB': lang_EN_GB.Num2Word_EN_GB(), 'en_IN': lang_EN_IN.Num2Word_EN_IN(), 'fr': lang_FR.Num2Word_FR(), + 'fr_CH': lang_FR_CH.Num2Word_FR_CH(), 'de': lang_DE.Num2Word_DE(), 'es': lang_ES.Num2Word_ES(), 'lt': lang_LT.Num2Word_LT(), diff --git a/num2words/lang_FR_CH.py b/num2words/lang_FR_CH.py new file mode 100644 index 0000000..127037d --- /dev/null +++ b/num2words/lang_FR_CH.py @@ -0,0 +1,113 @@ +# -*- 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 .lang_EU import Num2Word_EU + +class Num2Word_FR_CH(Num2Word_EU): + def setup(self): + self.negword = "moins " + self.pointword = "virgule" + self.errmsg_nonnum = u"Seulement des nombres peuvent être convertis en mots." + self.errmsg_toobig = u"Nombre trop grand pour être converti en mots." + self.exclude_title = ["et", "virgule", "moins"] + self.mid_numwords = [(1000, "mille"), (100, "cent"), (90, "nonante"), + (80, "huitante"), (70, "septante"), (60, "soixante"), + (50, "cinquante"), (40, "quarante"), + (30, "trente")] + self.low_numwords = ["vingt", "dix-neuf", "dix-huit", "dix-sept", + "seize", "quinze", "quatorze", "treize", "douze", + "onze", "dix", "neuf", "huit", "sept", "six", + "cinq", "quatre", "trois", "deux", "un", "zéro"] + self.ords = { + "cinq": "cinquième", + "neuf": "neuvième", + } + + + def merge(self, curr, next): + ctext, cnum, ntext, nnum = curr + next + + if cnum == 1: + if nnum < 1000000: + return next + else: + # if (not (cnum - 80)%100 or not cnum%100) and ctext[-1] == "s": + # ctext = ctext[:-1] + if (cnum<1000 and nnum != 1000 and ntext[-1] != "s" + and not nnum%100): + ntext += "s" + + if nnum < cnum < 100: + if nnum % 10 == 1:# and cnum != 80: + return ("%s et %s"%(ctext, ntext), cnum + nnum) + return ("%s-%s"%(ctext, ntext), cnum + nnum) + elif nnum > cnum: + return ("%s %s"%(ctext, ntext), cnum * nnum) + return ("%s %s"%(ctext, ntext), cnum + nnum) + + + # Is this right for such things as 1001 - "mille unième" instead of + # "mille premier"?? "millième"?? + + def to_ordinal(self,value): + self.verify_ordinal(value) + if value == 1: + return "premier" + word = self.to_cardinal(value) + for src, repl in self.ords.items(): + if word.endswith(src): + word = word[:-len(src)] + repl + break + else: + if word[-1] == "e": + word = word[:-1] + word = word + "ième" + return word + + def to_ordinal_num(self, value): + self.verify_ordinal(value) + out = str(value) + out += {"1" : "er" }.get(out[-1], "me") + return out + + def to_currency(self, val, longval=True, old=False): + hightxt = "Euro/s" + if old: + hightxt="franc/s" + return self.to_splitnum(val, hightxt=hightxt, lowtxt="centime/s", + jointxt="et",longval=longval) + +n2w = Num2Word_FR_CH() +to_card = n2w.to_cardinal +to_ord = n2w.to_ordinal +to_ordnum = n2w.to_ordinal_num + +def main(): + for val in [ 1, 11, 12, 21, 31, 33, 71, 80, 81, 91, 99, 100, 101, 102, 155, + 180, 300, 308, 832, 1000, 1001, 1061, 1100, 1500, 1701, 3000, + 8280, 8291, 150000, 500000, 1000000, 2000000, 2000001, + -21212121211221211111, -2.121212, -1.0000100]: + n2w.test(val) + + n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730) + print n2w.to_currency(112121) + print n2w.to_year(1996) + + +if __name__ == "__main__": + main() diff --git a/tests/test_fr_ch.py b/tests/test_fr_ch.py new file mode 100644 index 0000000..97ba4e5 --- /dev/null +++ b/tests/test_fr_ch.py @@ -0,0 +1,36 @@ +# -*- 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 Num2WordsENTest(TestCase): + def test_ordinal_special_joins(self): + self.assertEqual(num2words(5, ordinal=True, lang='fr_CH'), "cinquième") + self.assertEqual(num2words(6, ordinal=True, lang='fr_CH'), "sixième") + self.assertEqual(num2words(35, ordinal=True, lang='fr_CH'), "trente-cinquième") + self.assertEqual(num2words(9, ordinal=True, lang='fr_CH'), "neuvième") + self.assertEqual(num2words(49, ordinal=True, lang='fr_CH'), "quarante-neuvième") + self.assertEqual(num2words(71, lang='fr_CH'), "septante et un") + self.assertEqual(num2words(81, lang='fr_CH'), "huitante et un") + self.assertEqual(num2words(80, lang='fr_CH'), "huitante") + self.assertEqual(num2words(880, lang='fr_CH'), "huit cents huitante") + self.assertEqual(num2words(91, ordinal=True, lang='fr_CH'), "nonante et unième") + self.assertEqual(num2words(53, lang='fr_CH'), "cinquante-trois") +