From 62cc1f61438ad793f2c7f831c61352a38c4a769b Mon Sep 17 00:00:00 2001 From: PP6464 Date: Wed, 28 Jan 2026 11:49:24 +0000 Subject: [PATCH] Added gujarati to num2words --- README.rst | 1 + num2words/__init__.py | 3 +- num2words/lang_GU.py | 195 ++++++++++++++++++++++++++++++ tests/test_gu.py | 273 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 471 insertions(+), 1 deletion(-) create mode 100644 num2words/lang_GU.py create mode 100644 tests/test_gu.py diff --git a/README.rst b/README.rst index 2d8ea4e3..8ae42d63 100644 --- a/README.rst +++ b/README.rst @@ -102,6 +102,7 @@ Besides the numerical argument, there are two main optional arguments, ``to:`` a * ``fr_BE`` (French - Belgium) * ``fr_CH`` (French - Switzerland) * ``fr_DZ`` (French - Algeria) +* ``gu`` (Gujarati) * ``he`` (Hebrew) * ``hi`` (Hindi) * ``hu`` (Hungarian) diff --git a/num2words/__init__.py b/num2words/__init__.py index b6969060..ba7fb5d5 100644 --- a/num2words/__init__.py +++ b/num2words/__init__.py @@ -26,7 +26,7 @@ lang_KZ, lang_LT, lang_LV, lang_MN, lang_NL, lang_NO, lang_PL, lang_PT, lang_PT_BR, lang_RO, lang_RU, lang_SK, lang_SL, lang_SR, lang_SV, lang_TE, lang_TET, lang_TG, lang_TH, lang_TR, - lang_UK, lang_VI, lang_ZH, lang_ZH_CN, lang_ZH_HK, lang_ZH_TW) + lang_UK, lang_VI, lang_ZH, lang_ZH_CN, lang_ZH_HK, lang_ZH_TW, lang_GU) CONVERTER_CLASSES = { 'am': lang_AM.Num2Word_AM(), @@ -56,6 +56,7 @@ 'fr_BE': lang_FR_BE.Num2Word_FR_BE(), 'fr_CH': lang_FR_CH.Num2Word_FR_CH(), 'fr_DZ': lang_FR_DZ.Num2Word_FR_DZ(), + 'gu': lang_GU.Num2Word_GU(), 'he': lang_HE.Num2Word_HE(), 'hi': lang_HI.Num2Word_HI(), 'hu': lang_HU.Num2Word_HU(), diff --git a/num2words/lang_GU.py b/num2words/lang_GU.py new file mode 100644 index 00000000..f7fb8a61 --- /dev/null +++ b/num2words/lang_GU.py @@ -0,0 +1,195 @@ +# -*- 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 + +import string + +from num2words.base import Num2Word_Base + + +class Num2Word_GU(Num2Word_Base): + """ + Gujarati (GU) Num2Word class + """ + + _irregular_ordinals = { + 1: "પ્રથમ", + 2: "બિજુ", + 3: "ત્રિજુ", + 4: "ચોથું", + 6: "છઠ્ઠું", + } + _irregular_ordinals_nums = { + 1: "૧લી", + 2: "૨જુ", + 3: "૩જુ", + 4: "૪થુ", + 6: "૬ઠુ", + } + _gujarati_digits = "૦૧૨૩૪૫૬૭૮૯" # 0-9 + _digits_to_gujarati_digits = dict(zip(string.digits, _gujarati_digits)) + _regular_ordinal_suffix = "મું" + + def setup(self): + # Note: alternative forms are informal + self.low_numwords = [ + "નવ્વાણું", + "અઠ્ઠાણું", + "સત્તાણું", + "છન્નું", + "પંચાણું", + "ચોરાણું", + "ત્રાણું", + "બાણું", + "એકાણું", + "નેવું", + "નેવ્યાસી", + "ઈઠ્યાસી", + "સિત્યાસી", + "છ્યાસી", + "પંચાસી", + "ચોર્યાસી", + "ત્યાસી", + "બ્યાસી", + "એક્યાસી", + "એંસી", + "ઓગણાએંસી", + "ઇઠ્યોતેર", + "સિત્યોતેર", + "છોતેર", + "પંચોતેર", + "ચુમોતેર", + "તોતેર", + "બોતેર", + "એકોતેર", + "સિત્તેર", + "અગણોસિત્તેર", + "અડસઠ", + "સડસઠ", + "છાસઠ", + "પાંસઠ", + "ચોસઠ", + "ત્રેસઠ", + "બાસઠ", + "એકસઠ", + "સાઈઠ", + "ઓગણસાઠ", + "અઠ્ઠાવન", + "સત્તાવન", + "છપ્પન", + "પંચાવન", + "ચોપન", + "ત્રેપન", + "બાવન", + "એકાવન", + "પચાસ", + "ઓગણપચાસ", + "અડતાલીસ", + "સુડતાલીસ", + "છેતાલીસ", + "પિસ્તાલીસ", + "ચુંમાલીસ", + "ત્રેતાલીસ", + "બેતાલીસ", + "એકતાલીસ", + "ચાલીસ", + "ઓગણચાલીસ", + "અડત્રીસ", + "સડત્રીસ", + "છત્રીસ", + "પાંત્રીસ", + "ચોત્રીસ", + "તેત્રીસ", + "બત્રીસ", + "એકત્રીસ", + "ત્રીસ", + "ઓગણત્રીસ", + "અઠ્ઠાવીસ", + "સત્તાવીસ", + "છવીસ", + "પચ્ચીસ", + "ચોવીસ", + "તેવીસ", + "બાવીસ", + "એકવીસ", + "વીસ", + "ઓગણિસ", + "અઢાર", + "સત્તર", + "સોળ", + "પંદર", + "ચૌદ", + "તેર", + "બાર", + "અગિયાર", + "દસ", + "નવ", + "આઠ", + "સાત", + "છ", + "પાંચ", + "ચાર", + "ત્રણ", + "બે", + "એક", + "શૂન્ય", + ] + + self.mid_numwords = [(100, "સૌ")] + self.high_numwords = [ + (7, "કરોડ઼"), # alternative "करोड़" + (5, "લખ"), + (3, "હઝર"), # alternative "हज़ार" + ] + self.pointword = "દશાંશ" + self.negword = "માઈન્સ " + + def set_high_numwords(self, high): + for n, word in self.high_numwords: + self.cards[10**n] = word + + def merge(self, lpair, rpair): + ltext, lnum = lpair + rtext, rnum = rpair + if lnum == 1 and rnum < 100: + return rtext, 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): + if value in self._irregular_ordinals: + return self._irregular_ordinals[value] + + # regular Gujarati ordinals are derived from cardinals + # by modifying the last member of the expression. + cardinal = self.to_cardinal(value) + return cardinal + self._regular_ordinal_suffix + + def _convert_to_gujarati_numerals(self, value): + return "".join(map(self._digits_to_gujarati_digits.__getitem__, + str(value))) + + def to_ordinal_num(self, value): + if value in self._irregular_ordinals_nums: + return self._irregular_ordinals_nums[value] + + return self._convert_to_gujarati_numerals(value) \ + + self._regular_ordinal_suffix diff --git a/tests/test_gu.py b/tests/test_gu.py new file mode 100644 index 00000000..e869115f --- /dev/null +++ b/tests/test_gu.py @@ -0,0 +1,273 @@ +from unittest import TestCase +from num2words import num2words + +# number, gujarati number, pronounced form +TEST_CASES_CARDINAL = ( + (0, 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"નવ"), + (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"વીસ"), + (21, u"૨૧", u"એકવીસ"), + (22, u"૨૨", u"બાવીસ"), + (23, u"૨૩", u"તેવીસ"), + (24, u"૨૪", u"ચોવીસ"), + (25, u"૨૫", u"પચ્ચીસ"), + (26, u"૨૬", u"છવીસ"), + (27, u"૨૭", u"સત્તાવીસ"), + (28, u"૨૮", u"અઠ્ઠાવીસ"), + (29, u"૨૯", u"ઓગણત્રીસ"), + (30, u"૩૦", u"ત્રીસ"), + (31, u"૩૧", u"એકત્રીસ"), + (32, u"૩૨", u"બત્રીસ"), + (33, u"૩૩", u"તેત્રીસ"), + (34, u"૩૪", u"ચોત્રીસ"), + (35, u"૩૫", u"પાંત્રીસ"), + (36, u"૩૬", u"છત્રીસ"), + (37, u"૩૭", u"સડત્રીસ"), + (38, u"૩૮", u"અડત્રીસ"), + (39, u"૩૯", u"ઓગણચાલીસ"), + (40, u"૪૦", u"ચાલીસ"), + (41, u"૪૧", u"એકતાલીસ"), + (42, u"૪૨", u"બેતાલીસ"), + (43, u"૪૩", u"ત્રેતાલીસ"), + (44, u"૪૪", u"ચુંમાલીસ"), + (45, u"૪૫", u"પિસ્તાલીસ"), + (46, u"૪૬", u"છેતાલીસ"), + (47, u"૪૭", u"સુડતાલીસ"), + (48, u"૪૮", u"અડતાલીસ"), + (49, u"૪૯", u"ઓગણપચાસ"), + (50, u"૫૦", u"પચાસ"), + (51, u"૫૧", u"એકાવન"), + (52, u"૫૨", u"બાવન"), + (53, u"૫૩", u"ત્રેપન"), + (54, u"૫૪", u"ચોપન"), + (55, u"૫૫", u"પંચાવન"), + (56, u"૫૬", u"છપ્પન"), + (57, u"૫૭", u"સત્તાવન"), + (58, u"૫૮", u"અઠ્ઠાવન"), + (59, u"૫૯", u"ઓગણસાઠ"), + (60, u"૬૦", u"સાઈઠ"), + (61, u"૬૧", u"એકસઠ"), + (62, u"૬૨", u"બાસઠ"), + (63, u"૬૩", u"ત્રેસઠ"), + (64, u"૬૪", u"ચોસઠ"), + (65, u"૬૫", u"પાંસઠ"), + (66, u"૬૬", u"છાસઠ"), + (67, u"૬૭", u"સડસઠ"), + (68, u"૬૮", u"અડસઠ"), + (69, u"૬૯", u"અગણોસિત્તેર"), + (70, u"૭૦", u"સિત્તેર"), + (71, u"૭૧", u"એકોતેર"), + (72, u"૭૨", u"બોતેર"), + (73, u"૭૩", u"તોતેર"), + (74, u"૭૪", u"ચુમોતેર"), + (75, u"૭૫", u"પંચોતેર"), + (76, u"૭૬", u"છોતેર"), + (77, u"૭૭", u"સિત્યોતેર"), + (78, u"૭૮", u"ઇઠ્યોતેર"), + (79, u"૭૯", u"ઓગણાએંસી"), + (80, u"૮૦", u"એંસી"), + (81, u"૮૧", u"એક્યાસી"), + (82, u"૮૨", u"બ્યાસી"), + (83, u"૮૩", u"ત્યાસી"), + (84, u"૮૪", u"ચોર્યાસી"), + (85, u"૮૫", u"પંચાસી"), + (86, u"૮૬", u"છ્યાસી"), + (87, u"૮૭", u"સિત્યાસી"), + (88, u"૮૮", u"ઈઠ્યાસી"), + (89, u"૮૯", u"નેવ્યાસી"), + (90, u"૯૦", u"નેવું"), + (91, u"૯૧", u"એકાણું"), + (92, u"૯૨", u"બાણું"), + (93, u"૯૩", u"ત્રાણું"), + (94, u"૯૪", u"ચોરાણું"), + (95, u"૯૫", u"પંચાણું"), + (96, u"૯૬", u"છન્નું"), + (97, u"૯૭", u"સત્તાણું"), + (98, u"૯૮", u"અઠ્ઠાણું"), + (99, u"૯૯", u"નવ્વાણું"), + (100, u"૧૦૦", u"એક સૌ"), + (1000, u"૧૦૦૦", u"એક હઝર"), + (100000, u"૧૦૦૦૦૦", u"એક લખ"), + (1000000, u"૧૦૦૦૦૦૦", u"દસ લખ"), + (10000000, u"૧૦૦૦૦૦૦૦", u"એક કરોડ઼"), + (100000000, u"૧૦૦૦૦૦૦૦૦", u"દસ કરોડ઼"), + (1000000000, u"૧૦૦૦૦૦૦૦૦૦", u"એક સૌ કરોડ઼"), + (1234, u"૧૨૩૪", u"એક હઝર બે સૌ ચોત્રીસ"), + (8901234, u"૮૯૦૧૨૩૪", u"નેવ્યાસી લખ એક હઝર બે સૌ ચોત્રીસ"), + (567890123, u"૫૬૭૮૯૦૧૨૩", u"છપ્પન કરોડ઼ ઇઠ્યોતેર લખ નેવું હઝર એક સૌ તેવીસ"), + (113345, u"૧૧૩૩૪૫", u"એક લખ તેર હઝર ત્રણ સૌ પિસ્તાલીસ"), +) + +# number, gujarati numeric notation, pronounced form +TEST_CASES_ORDINAL = ( + (0, 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"નવમું"), + (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"વીસમું"), + (21, u"૨૧મું", u"એકવીસમું"), + (22, u"૨૨મું", u"બાવીસમું"), + (23, u"૨૩મું", u"તેવીસમું"), + (24, u"૨૪મું", u"ચોવીસમું"), + (25, u"૨૫મું", u"પચ્ચીસમું"), + (26, u"૨૬મું", u"છવીસમું"), + (27, u"૨૭મું", u"સત્તાવીસમું"), + (28, u"૨૮મું", u"અઠ્ઠાવીસમું"), + (29, u"૨૯મું", u"ઓગણત્રીસમું"), + (30, u"૩૦મું", u"ત્રીસમું"), + (31, u"૩૧મું", u"એકત્રીસમું"), + (32, u"૩૨મું", u"બત્રીસમું"), + (33, u"૩૩મું", u"તેત્રીસમું"), + (34, u"૩૪મું", u"ચોત્રીસમું"), + (35, u"૩૫મું", u"પાંત્રીસમું"), + (36, u"૩૬મું", u"છત્રીસમું"), + (37, u"૩૭મું", u"સડત્રીસમું"), + (38, u"૩૮મું", u"અડત્રીસમું"), + (39, u"૩૯મું", u"ઓગણચાલીસમું"), + (40, u"૪૦મું", u"ચાલીસમું"), + (41, u"૪૧મું", u"એકતાલીસમું"), + (42, u"૪૨મું", u"બેતાલીસમું"), + (43, u"૪૩મું", u"ત્રેતાલીસમું"), + (44, u"૪૪મું", u"ચુંમાલીસમું"), + (45, u"૪૫મું", u"પિસ્તાલીસમું"), + (46, u"૪૬મું", u"છેતાલીસમું"), + (47, u"૪૭મું", u"સુડતાલીસમું"), + (48, u"૪૮મું", u"અડતાલીસમું"), + (49, u"૪૯મું", u"ઓગણપચાસમું"), + (50, u"૫૦મું", u"પચાસમું"), + (51, u"૫૧મું", u"એકાવનમું"), + (52, u"૫૨મું", u"બાવનમું"), + (53, u"૫૩મું", u"ત્રેપનમું"), + (54, u"૫૪મું", u"ચોપનમું"), + (55, u"૫૫મું", u"પંચાવનમું"), + (56, u"૫૬મું", u"છપ્પનમું"), + (57, u"૫૭મું", u"સત્તાવનમું"), + (58, u"૫૮મું", u"અઠ્ઠાવનમું"), + (59, u"૫૯મું", u"ઓગણસાઠમું"), + (60, u"૬૦મું", u"સાઈઠમું"), + (61, u"૬૧મું", u"એકસઠમું"), + (62, u"૬૨મું", u"બાસઠમું"), + (63, u"૬૩મું", u"ત્રેસઠમું"), + (64, u"૬૪મું", u"ચોસઠમું"), + (65, u"૬૫મું", u"પાંસઠમું"), + (66, u"૬૬મું", u"છાસઠમું"), + (67, u"૬૭મું", u"સડસઠમું"), + (68, u"૬૮મું", u"અડસઠમું"), + (69, u"૬૯મું", u"અગણોસિત્તેરમું"), + (70, u"૭૦મું", u"સિત્તેરમું"), + (71, u"૭૧મું", u"એકોતેરમું"), + (72, u"૭૨મું", u"બોતેરમું"), + (73, u"૭૩મું", u"તોતેરમું"), + (74, u"૭૪મું", u"ચુમોતેરમું"), + (75, u"૭૫મું", u"પંચોતેરમું"), + (76, u"૭૬મું", u"છોતેરમું"), + (77, u"૭૭મું", u"સિત્યોતેરમું"), + (78, u"૭૮મું", u"ઇઠ્યોતેરમું"), + (79, u"૭૯મું", u"ઓગણાએંસીમું"), + (80, u"૮૦મું", u"એંસીમું"), + (81, u"૮૧મું", u"એક્યાસીમું"), + (82, u"૮૨મું", u"બ્યાસીમું"), + (83, u"૮૩મું", u"ત્યાસીમું"), + (84, u"૮૪મું", u"ચોર્યાસીમું"), + (85, u"૮૫મું", u"પંચાસીમું"), + (86, u"૮૬મું", u"છ્યાસીમું"), + (87, u"૮૭મું", u"સિત્યાસીમું"), + (88, u"૮૮મું", u"ઈઠ્યાસીમું"), + (89, u"૮૯મું", u"નેવ્યાસીમું"), + (90, u"૯૦મું", u"નેવુંમું"), + (91, u"૯૧મું", u"એકાણુંમું"), + (92, u"૯૨મું", u"બાણુંમું"), + (93, u"૯૩મું", u"ત્રાણુંમું"), + (94, u"૯૪મું", u"ચોરાણુંમું"), + (95, u"૯૫મું", u"પંચાણુંમું"), + (96, u"૯૬મું", u"છન્નુંમું"), + (97, u"૯૭મું", u"સત્તાણુંમું"), + (98, u"૯૮મું", u"અઠ્ઠાણુંમું"), + (99, u"૯૯મું", u"નવ્વાણુંમું"), + (100, u"૧૦૦મું", u"એક સૌમું"), + (1000, u"૧૦૦૦મું", u"એક હઝરમું"), + (100000, u"૧૦૦૦૦૦મું", u"એક લખમું"), + (1000000, u"૧૦૦૦૦૦૦મું", u"દસ લખમું"), + (10000000, u"૧૦૦૦૦૦૦૦મું", u"એક કરોડ઼મું"), + (100000000, u"૧૦૦૦૦૦૦૦૦મું", u"દસ કરોડ઼મું"), + (1000000000, u"૧૦૦૦૦૦૦૦૦૦મું", u"એક સૌ કરોડ઼મું"), +) + +class Num2WordsGUTest(TestCase): + def test_examples(self): + self.assertEqual("એક સૌ કરોડ઼ પાંચ હઝર સડસઠ", num2words(1000005067, lang="gu")) + self.assertEqual("છઠ્ઠું", num2words(6, lang="gu", ordinal=True)) + self.assertEqual("૫૧મું", num2words(51, to="ordinal_num", lang="gu")) + + def test_cardinal(self): + for number, _, words in TEST_CASES_CARDINAL: + self.assertEqual( + num2words(number, lang="gu"), + words, + msg="failing number %s" % number, + ) + + def test_negative_cardinal(self): + self.assertEqual(num2words(-42, lang="gu"), u"માઈન્સ બેતાલીસ") + + def test_float_cardinal(self): + self.assertEqual(num2words(12.5, lang="gu"), u"બાર દશાંશ પાંચ") + self.assertEqual(num2words(12.51, lang="gu"), u"બાર દશાંશ પાંચ એક") + + def test_ordinal(self): + for number, _, words in TEST_CASES_ORDINAL: + self.assertEqual( + num2words(number, lang="gu", ordinal=True), + words, + msg="failing number %s" % number, + ) + + def test_ordinal_num(self): + for number, numeric_notation, _ in TEST_CASES_ORDINAL: + self.assertEqual( + num2words(number, lang="gu", to="ordinal_num"), + numeric_notation, + msg="failing number %s" % number, + ) + + def test_gujarati_numeric_input(self): + for number, gujarati_number, words in TEST_CASES_CARDINAL: + self.assertEqual( + num2words(gujarati_number, lang="gu"), + words, + msg="failing number %s" % number, + )