Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
ajiragroup authored Dec 15, 2024
2 parents 555c22a + 0df2a0e commit b86dbe6
Show file tree
Hide file tree
Showing 24 changed files with 4,464 additions and 139 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ dist
/.tox
.eggs/
/venv/
.venv/
9 changes: 7 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,11 @@ Besides the numerical argument, there are two main optional arguments, ``to:`` a
* ``am`` (Amharic)
* ``ar`` (Arabic)
* ``az`` (Azerbaijani)
* ``by`` (Belarusian)
* ``cz`` (Czech)
* ``be`` (Belarusian)
* ``bn`` (Bangladeshi)
* ``ce`` (Chechen)
* ``cs`` (Czech)
* ``cy`` (Welsh)
* ``de`` (German)
* ``dk`` (Danish)
* ``en_GB`` (English - Great Britain)
Expand All @@ -89,6 +92,7 @@ Besides the numerical argument, there are two main optional arguments, ``to:`` a
* ``en_NP`` (English - Nepal)
* ``es`` (Spanish)
* ``es_CO`` (Spanish - Colombia)
* ``es_CR`` (Spanish - Costa Rica)
* ``es_VE`` (Spanish - Venezuela)
* ``es_GT`` (Spanish - Guatemala)
* ``eu`` (EURO)
Expand Down Expand Up @@ -119,6 +123,7 @@ Besides the numerical argument, there are two main optional arguments, ``to:`` a
* ``ro`` (Romanian)
* ``ru`` (Russian)
* ``te`` (Telugu)
* ``tet`` (Tetum)
* ``tg`` (Tajik)
* ``tr`` (Turkish)
* ``th`` (Thai)
Expand Down
70 changes: 70 additions & 0 deletions num2words/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Add new language

for each new language you must create a file `lang_NN.py` where `NN` is the
ISO 639-1 or ISO 639-3 [language code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes).

This class must be a subclass of `Num2Word_EU` and implement at least the following methods

```
to_cardinal(self, number)
to_ordinal(self, number)
``
To integrate your language into the `num2words` module, add the name of your file
to the import list in [num2words/__init__.py](num2words/__init__.py) (top of the file),
and `'nn': lang_NN.Num2Word_NN()` to the `CONVERTER_CLASSES` list in the same file.
Do not forget to remplace `NN` by the appropriate ISO 639 language code.
The following is a template for a new language class
```
from .lang_EU import Num2Word_EU

class Num2Word_CY(Num2Word_EU):
def setup(self):
Num2Word_EU.setup(self)

def __init__(self):
pass

def to_ordinal(self, number):
# implement here your code. number is the integer to be transformed into an ordinal
# as a word (str)
# which is returned
return "NOT IMPLEMENTED"

def to_cardinal(self, number):
# implement here your code. number is the integer to be transformed into an cardinal
# as a word (str)
# which is returned
return "NOT IMPLEMENTED"
```
You can use as manu auxiliary methods as you need to make your code efficient and readable.
If you need further options like Gender, Formal/Informal, add those parameters to the methods,
e.g.
```
def to_ordinal(self, number, gender="fem", informal=True)
# your code
pass
```
More inspiration can be found in existing `num2words/lang_NN.py` files
## Code validation
In order to get your contribution merged into the main project, your code must test the validation tests.
For this install the packages needed to test
```
pip install -r requirements-test.txt
```
run `tox` and `coverage` to check that the code is well formated and all parts of the code are tested
```
tox
python3 -m coverage report -m
```
20 changes: 14 additions & 6 deletions num2words/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,27 @@

from __future__ import unicode_literals

from . import (lang_AM, lang_AR, lang_AZ, lang_BY, lang_CZ, lang_DE, lang_DK,
lang_EN, lang_EN_IN, lang_EN_NG, lang_EN_NP, lang_EO, lang_ES, lang_ES_CO,

from . import (lang_AM, lang_AR, lang_AZ, lang_BE, lang_BN, lang_CA, lang_CE,
lang_CS, lang_CY, lang_DE, lang_DK, lang_EN, lang_EN_IN,lang_EN_NP,
lang_EN_NG, lang_EO, lang_ES, lang_ES_CO, lang_ES_CR,
lang_ES_GT, 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_IS, 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_SK, lang_SL, lang_SR, lang_SV, lang_TE,
lang_TG, lang_TH, lang_TR, lang_UK, lang_VI)
lang_TET, lang_TG, lang_TH, lang_TR, lang_UK, lang_VI)

CONVERTER_CLASSES = {
'am': lang_AM.Num2Word_AM(),
'ar': lang_AR.Num2Word_AR(),
'az': lang_AZ.Num2Word_AZ(),
'by': lang_BY.Num2Word_BY(),
'cz': lang_CZ.Num2Word_CZ(),
'be': lang_BE.Num2Word_BE(),
'bn': lang_BN.Num2Word_BN(),
'ca': lang_CA.Num2Word_CA(),
'ce': lang_CE.Num2Word_CE(),
'cs': lang_CS.Num2Word_CS(),
'cy': lang_CY.Num2Word_CY(),
'en': lang_EN.Num2Word_EN(),
'en_IN': lang_EN_IN.Num2Word_EN_IN(),
'en_NG': lang_EN_NG.Num2Word_EN_NG(),
Expand All @@ -46,6 +52,7 @@
'eo': lang_EO.Num2Word_EO(),
'es': lang_ES.Num2Word_ES(),
'es_CO': lang_ES_CO.Num2Word_ES_CO(),
'es_CR': lang_ES_CR.Num2Word_ES_CR(),
'es_GT': lang_ES_GT.Num2Word_ES_GT(),
'es_NI': lang_ES_NI.Num2Word_ES_NI(),
'es_VE': lang_ES_VE.Num2Word_ES_VE(),
Expand Down Expand Up @@ -76,8 +83,9 @@
'nl': lang_NL.Num2Word_NL(),
'uk': lang_UK.Num2Word_UK(),
'te': lang_TE.Num2Word_TE(),
'tet': lang_TET.Num2Word_TET(),
'hu': lang_HU.Num2Word_HU(),
'is': lang_IS.Num2Word_IS()
'is': lang_IS.Num2Word_IS(),
}

CONVERTES_TYPES = ['cardinal', 'ordinal', 'ordinal_num', 'year', 'currency']
Expand Down
48 changes: 31 additions & 17 deletions num2words/lang_BY.py → num2words/lang_BE.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,17 @@
9: "дзевяноста",
}

TWENTIES_ORD = (
("дваццаць", "дваццаці"),
("трыццаць", "трыццаці"),
("сорак", "сарака"),
("пяцьдзясят", "пяцідзясяці"),
("шэсцьдзясят", "шaсцідзясяці"),
("семдзесят", "сямідзесяці"),
("восемдзесят", "васьмідзесяці"),
("дзевяноста", "дзевяноста"),
)

HUNDREDS = {
1: "сто",
2: "дзвесце",
Expand All @@ -120,7 +131,7 @@
}


class Num2Word_BY(Num2Word_Base):
class Num2Word_BE(Num2Word_Base):
CURRENCY_FORMS = {
"RUB": (
("расійскі рубель", "расійскія рублі", "расійскіх рублёў"),
Expand All @@ -138,6 +149,7 @@ class Num2Word_BY(Num2Word_Base):
("капейка", "капейкі", "капеек"),
),
"UZS": (("сум", "сумы", "сумаў"), ("тыйін", "тыйіны", "тыйінаў")),
"PLN": (("злоты", "злотых", "злотых"), ("грош", "грошы", "грошаў")),
}

def setup(self):
Expand Down Expand Up @@ -204,6 +216,8 @@ def pluralize(self, n, forms):

def to_ordinal(self, number, gender="m"):
self.verify_ordinal(number)
if isinstance(gender, bool) and gender:
gender = "f"
outwords = self.to_cardinal(number, gender).split(" ")
lastword = outwords[-1].lower()
try:
Expand All @@ -223,8 +237,6 @@ def to_ordinal(self, number, gender="m"):
lastword = (
self.ords_adjective.get(lastword[:-3], lastword) + "соты"
)
elif lastword[-5:] == "шэсць":
lastword = "шосты"
elif lastword[-7:] == "дзесяць":
lastword = "дзясяты"
elif lastword[-9:] == "семдзесят":
Expand All @@ -242,6 +254,8 @@ def to_ordinal(self, number, gender="m"):

elif lastword[-1] == "н" or lastword[-2] == "н":
lastword = lastword[: lastword.rfind("н") + 1] + "ны"
elif lastword[-3:] == "наў":
lastword = lastword[: lastword.rfind("н") + 1] + "ны"
elif lastword[-1] == "д" or lastword[-2] == "д":
lastword = lastword[: lastword.rfind("д") + 1] + "ны"

Expand All @@ -254,9 +268,7 @@ def to_ordinal(self, number, gender="m"):
lastword = lastword[:-1] + "ая"

if gender == "n":
if lastword[-2:] in [
"ці", "ца"
]:
if lastword[-2:] in ["ці", "ца"]:
lastword = lastword[:-2] + "цяе"
else:
lastword = lastword[:-1] + "ае"
Expand All @@ -266,16 +278,20 @@ def to_ordinal(self, number, gender="m"):
outwords[-2] = outwords[-1]
del outwords[-1]

if len(outwords) > 2 and "тысяч" in outwords[-1]:
if 'сорак' in outwords[-3]:
outwords[-3] = outwords[-3].replace('сорак', 'сарака')
outwords[-3] = outwords[-3] + outwords[-2] + outwords[-1]
del outwords[-1]
del outwords[-1]
if len(outwords) > 1 and (
(any(x[0] in outwords[-1] for x in THOUSANDS.values()))
or "тысяч" in outwords[-1]
):
new_outwords = []
for _w in outwords:
replacement = next(
(x for x in TWENTIES_ORD if x[0] in _w), None
)
if replacement:
_w = _w.replace(replacement[0], replacement[1])
new_outwords.append(_w)
outwords = ["".join(new_outwords)]

elif len(outwords) > 1 and "тысяч" in outwords[-1]:
outwords[-2] = outwords[-2] + outwords[-1]
del outwords[-1]
return " ".join(outwords).strip()

def _money_verbose(self, number, currency):
Expand All @@ -294,8 +310,6 @@ def _cents_verbose(self, number, currency):
return self._int2word(number, gender)

def _int2word(self, n, gender="m"):
if isinstance(gender, bool) and gender:
gender = "f"
if n < 0:
return " ".join([self.negword, self._int2word(abs(n), gender)])

Expand Down
Loading

0 comments on commit b86dbe6

Please sign in to comment.