581 Commits

Author SHA1 Message Date
Marlon Rodriguez Garcia
67146ed02c Merge pull request #366 from JonasTriki/master
Fixes lang_DK issues
2022-08-19 17:31:22 -04:00
Marlon Rodriguez Garcia
46588097f0 Merge branch 'master' into master 2022-08-19 17:28:38 -04:00
Marlon Rodriguez Garcia
931d71b4dd Merge pull request #477 from emregeldegul/#454
#454: [tr] fix negative number problem
2022-08-19 17:03:15 -04:00
Yunus Emre Geldegul
a7d095c97d #454: [tr] fix flake8 E128 2022-08-19 23:56:14 +03:00
Yunus Emre Geldegul
ddf6a88af6 #454: [tr] fix flake8 E501 problem 2022-08-19 23:51:30 +03:00
Yunus Emre Geldegul
3ffdbec8e0 #454: [tr] fix negative number problem 2022-08-19 23:37:53 +03:00
Marlon Rodriguez Garcia
a218b332d2 Merge pull request #436 from Daniel-EST/master
Fixes #435 [pt_BR] Issue with the hundreds of millions, billions, ... when the hundreds of those are exact.
2022-08-19 15:34:16 -04:00
Marlon Rodriguez Garcia
01219318ab Merge branch 'master' into master 2022-08-19 15:26:55 -04:00
Marlon Rodriguez Garcia
b28fb086cc Merge pull request #421 from Cris140/patch-1
To fix a problem in Brazilian Portuguese code referred to thousands when the hundreds are exact.
2022-08-19 11:16:43 -04:00
Marlon Rodriguez Garcia
5142fe851b Merge branch 'master' into patch-1 2022-08-19 11:12:35 -04:00
Marlon Rodriguez Garcia
1fd633c4df Merge pull request #475 from savoirfairelinux/release_0.5.12
new release
2022-08-19 10:48:34 -04:00
Marlon Rodriguez
0865ac247e new release 2022-08-19 10:28:08 -04:00
Marlon Rodriguez Garcia
7c86a85d25 Merge pull request #326 from hapytex/bugfix/dutch_zero_ordinal
Fix zeroth in Dutch to nulde fixing #325
2022-08-18 13:35:57 -04:00
Willem Van Onsem
bb1c718906 Merge remote-tracking branch 'org/master' into bugfix/dutch_zero_ordinal 2022-08-18 19:00:34 +02:00
Willem Van Onsem
2ee06aa086 reformatting 2022-08-18 18:59:35 +02:00
ismail eski
b6a80e0e2a [FIX] E231 missing whitespace after ',' 2022-08-18 18:58:35 +02:00
ismail eski
7109e16e73 [TEST] ordinal_num test 2022-08-18 18:58:35 +02:00
Antoine Planchot
75eec68f3e Added support for Esperanto numbers. 2022-08-18 18:58:31 +02:00
ismail eski
44a2b7cc2d [TEST] ordinal_num test 2022-08-18 18:58:18 +02:00
Sergio Zanchetta
593435f21a Add tests for italian language currencies 2022-08-18 18:58:18 +02:00
Sergio Zanchetta
3dda6ee22e Add to_currency and CURRENCY_FORMS for italian 2022-08-18 18:58:18 +02:00
cyriaka90
e4b75bb00d increase Polish test coverage 2022-08-18 18:58:18 +02:00
cyriaka90
5878cd07fe adapt polish tests 2022-08-18 18:58:18 +02:00
cyriaka90
d1fe26961c fix Polish twenties 2022-08-18 18:58:17 +02:00
potapov.s
084ace67cb - add uzs for ru and en 2022-08-18 18:58:17 +02:00
Eyosiyas Bereketab
2ca98971e1 Add additional test case 2022-08-18 18:58:17 +02:00
Eyosiyas Bereketab
a7442708fa Update __init__.py 2022-08-18 18:58:14 +02:00
Drew Echerd
7bf80d5dd7 Fixed flake8 errors 2022-08-18 18:57:45 +02:00
Drew Echerd
beb3326bbc Added MEGA_SUFFIX and GIGA_SUFFIX tests 2022-08-18 18:57:45 +02:00
Drew Echerd
af97683fdc Added test for OverflowError and ordinal_num 2022-08-18 18:57:44 +02:00
Drew Echerd
5bfcebd9fb Added Tajik language support 2022-08-18 18:57:42 +02:00
Eyosiyas Bereketab
8ed54f332d Update Amharic language support 2022-08-18 18:57:22 +02:00
Eyosiyas Bereketab
83203ed98e Fix line too long __init__.py 2022-08-18 18:57:21 +02:00
Eyosiyas Bereketab
5948065b36 Fix flake 8 requirements in python3.1 and increase test coverage. 2022-08-18 18:57:21 +02:00
Eyosiyas Bereketab
a5a812d421 Add test cases 2022-08-18 18:57:21 +02:00
Eyosiyas Bereketab
770cd6d1d5 Add Amharic currency form 2022-08-18 18:57:21 +02:00
Eyosiyas Bereketab
736db5149e Update Amharic language 2022-08-18 18:57:21 +02:00
Eyosiyas Bereketab
4355e11637 Update init for Amharic language 2022-08-18 18:57:17 +02:00
Eyosiyas Bereketab
16229a31a4 Add Amharic language 2022-08-18 18:56:44 +02:00
Marlon Rodriguez Garcia
5d1e3c7d1a Update __init__.py
remove space
2022-08-18 18:56:36 +02:00
Katsuya Iida
4e6a573248 Support Japanese Reiwa (令和/れいわ) era. 2022-08-18 18:55:44 +02:00
hamidreza kalbasi
464f9ed7af fix flake8 problems 2022-08-18 18:55:43 +02:00
hamidreza kalbasi
3d2fa184cf try fix test failure 2022-08-18 18:52:05 +02:00
hamidreza kalbasi
a1f0392beb remove unneccery if 2022-08-18 18:52:04 +02:00
hamidreza kalbasi
bbd9de8299 fix test coverage 2022-08-18 18:52:04 +02:00
hamidreza kalbasi
9f59c5c894 add basic farsi support 2022-08-18 18:52:04 +02:00
Gabriel Shekler
b01c44e33c typo 2022-08-18 18:52:04 +02:00
Gabriel Shekler
c11927b353 fix flake issues 2022-08-18 18:52:04 +02:00
gshekler
7993ca5023 typo 2022-08-18 18:52:04 +02:00
gshekler
f820ee5ec1 add unit tests 2022-08-18 18:52:03 +02:00
gshekler
07ea1baca2 implement currency for HE 2022-08-18 18:52:03 +02:00
gshekler
112e91c35a fix pluralize 2022-08-18 18:52:03 +02:00
Marlon Rodriguez Garcia
f2acbc2873 Add new check to base 2022-08-18 18:52:03 +02:00
Marlon Rodriguez Garcia
2cb98d3af1 Added new release 2022-08-18 18:52:03 +02:00
gonzy
b8a215a991 Added tests for every currency gender combination (dollars, cents) 2022-08-18 18:52:03 +02:00
gonzy
12e8402da4 Improved currency gender handling, now splitting 'dollars' and 'cents' parts on 2022-08-18 18:52:02 +02:00
gonzy
62eba31778 lang_ES: improved currency gender handling, improved error messages; test_es: updated accordingly 2022-08-18 18:52:02 +02:00
Gonçal Garcés Díaz-Munío
db5e1d175f Fixed accent in Spanish command line examples
Fixed accent in Spanish command line examples ("centimos"->"céntimos"), thus making the example consistent with actual current behaviour.
2022-08-18 18:52:02 +02:00
Gonçal
d4c979ea52 Fixed accent in examples ("centimos"->"céntimos")
Fixed accent in Spanish examples ("centimos"->"céntimos"), thus making the example consistent with actual current behaviour.
2022-08-18 18:52:02 +02:00
gonzy
0ee149a4c8 Added test covering new fix penny->penique 2022-08-18 18:52:02 +02:00
gonzy
fc0c15c4b2 Fixed pound cents: penny->penique, pence->peniques; fixed tests accordingly 2022-08-18 18:52:02 +02:00
Gonçal
4afc68f233 flake8 fix: fixed comment style
Fixed:
./num2words/lang_ES.py:366:56: E261 at least two spaces before inline comment
./num2words/lang_ES.py:366:80: E501 line too long (100 > 79 characters)
2022-08-18 18:52:02 +02:00
gonzy
1cea15170d Orthography fixes: added missing accent (nuevos dolares->nuevos dólares); fixed accents in test_es.py (dieciséis, dólar, dólares, veintiún) 2022-08-18 18:52:01 +02:00
Gonçal
a61760bd28 Orthography fix: added accent veintiun->veintiún 2022-08-18 18:52:01 +02:00
Gonçal
0b896c5c7d Orthography fixes: added 2 missing accents (dieciseis->dieciséis ; dolar->dólar) 2022-08-18 18:52:01 +02:00
Marlon Rodriguez
5a8a17d144 feat: ci: replace travis by github workflows 2022-08-18 18:52:01 +02:00
ismail eski
3b27a09a30 [FIX] /num2words/lang_TR.py:812:1: W293 blank line contains whitespace 2022-08-18 18:52:01 +02:00
İsmail Eski
b5875b81f7 [ADD] to ordinal number for Turkish 2022-08-18 18:52:01 +02:00
Rostyslav Ivanyk
6bf14bee7b Improve Ukrainian support and minor fixes in CZ, KZ, LT, LV, PL, RU, SR languages (#400)
* Fix English char 'i' in Ukrainian words

* Fix the feminine currency processing for UAH in lang_UK.py

* Fix test_ua.py

* Fix the feminine currency processing for UAH in lang_RU.py

* Add tests for UAH in test_ru.py

* Add world currencies to lang_UK.py; Add test cases to test_uk.py for world currencies

* Fix incorrect handling of zeros after decimal point for CZ, KZ, LT, LV, PL, RU, SR and UK languages

* Add ukrainian ordinal numbers

* Fix too long lines of code

* Add test for negative cardinal number
2022-08-18 18:52:01 +02:00
cyriaka90
79a9abfaba [tr] return Turkish 0 ordinal and cardinal (#347)
* [tr] return Turkish 0 ordinal and cardinal

* add str_to_number to Turkish

* try rather use Num2Word_Base
2022-08-18 18:52:00 +02:00
Paulina Komorek
ea82fe11ca [ADD] polish ordinal numbers (#367) 2022-08-18 18:52:00 +02:00
Erwin de Haan
5cb46055d7 Fix ordinal_num output for Dutch (NL) 2022-08-18 18:52:00 +02:00
Peter Nordstrom
f1cfc8e41e updated readme (added swedish) 2022-08-18 18:52:00 +02:00
Peter Nordstrom
2039df64cf split some lines that were too long for flake8 2022-08-18 18:52:00 +02:00
Fernanda Hernandez
402b1e88e7 Add translations to spanish of several currencies 2022-08-18 18:52:00 +02:00
Peter Nordstrom
3e494d71a0 updated failing flake8 test 2022-08-18 18:51:59 +02:00
Peter Nordstrom
469aaff8e6 updated test case to increase coverage. raised NotImplementedError for options not implemented. 2022-08-18 18:51:59 +02:00
Peter Nordstrom
a35effbd1b added correct ordinal handling and more test cases 2022-08-18 18:51:59 +02:00
Peter Nordstrom
1b35e7fe58 added swedish language including test cases 2022-08-18 18:51:59 +02:00
Israel Teixeira
cb24e20785 This error is already raised in line 223 2022-08-18 18:51:59 +02:00
Maroua Romdhane
9c64d48612 [UPD] Readme file 2022-08-18 18:51:59 +02:00
Israel Teixeira
8db643a918 Remove dupplicated line in lang_PT_BR
Remove an unnecessary condition, since the very same action follows it.
2022-08-18 18:51:58 +02:00
Marlon Rodriguez Garcia
48dd5bd0f7 Merge pull request #468 from ieski/master
[ADD] to ordinal number for Turkish
2022-08-18 12:25:12 -04:00
ismail eski
a05f6e5c1d [FIX] E231 missing whitespace after ',' 2022-08-18 18:48:10 +03:00
Marlon Rodriguez Garcia
605d82ec34 Merge branch 'master' into master 2022-08-18 10:07:36 -04:00
ismail eski
c19ea13145 [TEST] ordinal_num test 2022-08-17 19:56:11 +03:00
ismail eski
e000cd2dab Merge branch 'master' of github.com-ieski:ieski/num2words 2022-08-17 19:12:50 +03:00
ismail eski
3187fa2e05 [TEST] ordinal_num test 2022-08-17 19:12:11 +03:00
Marlon Rodriguez Garcia
e08193a367 Merge branch 'master' into master 2022-08-17 11:41:19 -04:00
Marlon Rodriguez Garcia
18b00075fc Merge pull request #387 from OpesMentis/master
Added support for Esperanto numbers.
2022-08-17 11:37:05 -04:00
Marlon Rodriguez Garcia
ebada15c04 Merge branch 'master' into master 2022-08-17 11:24:27 -04:00
ismail eski
0b435c427b Merge branch 'savoirfairelinux:master' into master 2022-08-17 18:10:02 +03:00
ismail eski
2ced5f9458 Merge branch 'master' of github.com-ieski:ieski/num2words 2022-08-17 18:09:30 +03:00
ismail eski
8633c0baf2 [FIX] /num2words/lang_TR.py:812:1: W293 blank line contains whitespace 2022-08-17 18:09:07 +03:00
Marlon Rodriguez Garcia
8816154db5 Merge pull request #422 from DogRuz/master
- add uzs for ru and en
2022-08-16 09:57:20 -04:00
Marlon Rodriguez Garcia
2dee99ab1e Merge branch 'master' into master 2022-08-16 09:51:53 -04:00
Marlon Rodriguez Garcia
540c5bdfd2 Merge pull request #345 from cyriaka90/fix_polish_twenty
fix Polish twenties
2022-08-16 09:25:08 -04:00
Marlon Rodriguez Garcia
6284e71297 Merge branch 'master' into fix_polish_twenty 2022-08-16 09:18:42 -04:00
Marlon Rodriguez Garcia
d8c199b00c Merge pull request #434 from PNLUG/add-to_currency_support
[ADD] num2words: add support to translate some currencies in italian language
2022-08-16 09:18:11 -04:00
cyriaka90
91e6d76710 Merge branch 'master' into fix_polish_twenty 2022-08-16 15:05:19 +02:00
cyriaka90
3715260bc5 increase Polish test coverage 2022-08-16 14:58:50 +02:00
cyriaka90
e239f1a474 adapt polish tests 2022-08-16 14:00:15 +02:00
cyriaka90
e3d53c3ff9 fix Polish twenties 2022-08-16 14:00:15 +02:00
Sergio Zanchetta
389bfd555d Add tests for italian language currencies 2022-08-15 20:52:09 +02:00
Sergio Zanchetta
e8425024a6 Add to_currency and CURRENCY_FORMS for italian 2022-08-15 20:51:50 +02:00
ismail eski
febe8d5175 Merge branch 'master' into master 2022-08-13 23:41:00 +03:00
Daniel dos Santos
882c08b639 Merge branch 'master' into master 2022-08-12 16:28:40 -03:00
Antoine Planchot
66fc44d5db Merge branch 'master' into master 2022-08-12 10:56:35 +02:00
Marlon Rodriguez Garcia
cb22eecdc3 Merge branch 'master' into master 2022-08-11 14:59:47 -04:00
Marlon Rodriguez Garcia
13c5b1c8d1 Merge pull request #330 from gs202/master
Fix Hebrew pluralize and implement to_currency
2022-08-11 10:08:31 -04:00
Marlon Rodriguez Garcia
17cde9b6b8 Merge branch 'master' into master 2022-08-11 10:03:52 -04:00
Marlon Rodriguez Garcia
47a4b80215 Merge pull request #465 from devEyosiyas/master
Fix Amharic language support
2022-08-10 10:57:25 -04:00
Eyosiyas Bereketab
4c873a6a88 Add additional test case 2022-08-10 09:34:03 +03:00
Eyosiyas Bereketab
b7277ffb93 Update __init__.py 2022-08-09 21:19:56 +03:00
Eyosiyas Bereketab
992fdf1cc3 Merge branch 'master' of https://github.com/devEyosiyas/num2words 2022-08-09 21:15:27 +03:00
Eyosiyas Bereketab
75fdd6289f Update Amharic language support 2022-08-09 21:13:53 +03:00
Marlon Rodriguez Garcia
fbf7dd40ca Merge pull request #406 from decherd/add-tajik-lang
Added Tajik language support
2022-08-09 12:14:08 -04:00
Eyosiyas Bereketab
6ea21b8200 Fix line too long __init__.py 2022-08-09 17:00:56 +03:00
Drew Echerd
c966c98337 Fixed flake8 errors 2022-08-09 09:57:58 -04:00
Eyosiyas Bereketab
c586bef2d6 Fix flake 8 requirements in python3.1 and increase test coverage. 2022-08-09 11:14:40 +03:00
Marlon Rodriguez Garcia
60ffee907a Merge branch 'master' into add-tajik-lang 2022-08-08 12:07:08 -04:00
Marlon Rodriguez Garcia
ddc496aa69 Merge branch 'master' into master 2022-08-08 11:55:46 -04:00
Eyosiyas Bereketab
308965bb99 Add test cases 2022-08-07 23:06:48 +03:00
Eyosiyas Bereketab
d1a85b315a Add Amharic currency form 2022-08-07 23:02:25 +03:00
Eyosiyas Bereketab
47d63acabf Update Amharic language 2022-08-07 22:34:49 +03:00
Eyosiyas Bereketab
c06ff54f64 Update init for Amharic language 2022-08-07 22:30:30 +03:00
Eyosiyas Bereketab
ed97e11bfb Add Amharic language 2022-08-07 22:19:49 +03:00
Daniel dos Santos
531afc86bb Merge branch 'master' into master 2022-08-07 14:41:24 -03:00
Gabriel Shekler
e9c2562509 Merge branch 'master' into master 2022-08-06 13:54:07 +03:00
Gabriel Shekler
55deaa9cbe typo 2022-08-06 13:53:14 +03:00
Gabriel Shekler
4b13dfddb7 fix flake issues 2022-08-06 13:51:57 +03:00
Marlon Rodriguez Garcia
5e9f28c6c9 Merge branch 'master' into master 2022-08-05 13:18:59 -04:00
Marlon Rodriguez Garcia
d7199522b9 Merge pull request #354 from HKalbasi/master
add basic farsi support
2022-08-04 16:26:57 -04:00
Marlon Rodriguez Garcia
d741a9d790 Update __init__.py
remove space
2022-08-04 16:17:58 -04:00
Marlon Rodriguez Garcia
c40b9cf6e6 Merge branch 'master' into master 2022-08-04 16:14:55 -04:00
Marlon Rodriguez Garcia
204f6e3d13 Merge branch 'master' into master 2022-08-04 16:07:00 -04:00
Marlon Rodriguez Garcia
e9aa9d5606 Merge branch 'master' into master 2022-08-04 16:05:47 -04:00
Katsuya Iida
b8a1d3168e Support Japanese Reiwa (令和/れいわ) era. 2022-08-04 14:01:03 -04:00
Marlon Rodriguez Garcia
d4d00e9277 Merge branch 'master' into master 2022-08-04 13:54:36 -04:00
Marlon Rodriguez Garcia
99a647cbcc Merge branch 'master' into patch-1 2022-08-04 13:50:31 -04:00
Marlon Rodriguez Garcia
4136338554 Merge branch 'master' into master 2022-08-04 13:41:16 -04:00
Marlon Rodriguez Garcia
2a0148ba4d Add new check to base 2022-08-04 12:17:20 -04:00
Marlon Rodriguez Garcia
f89306e32c Added new release 2022-08-03 15:09:49 -04:00
gonzy
4d4ca043f7 Added tests for every currency gender combination (dollars, cents) 2022-08-03 10:19:24 -04:00
gonzy
ef69a13084 Improved currency gender handling, now splitting 'dollars' and 'cents' parts on 2022-08-03 10:19:24 -04:00
gonzy
72f1f88c2c lang_ES: improved currency gender handling, improved error messages; test_es: updated accordingly 2022-08-03 10:19:24 -04:00
Gonçal Garcés Díaz-Munío
bd699be047 Fixed accent in Spanish command line examples
Fixed accent in Spanish command line examples ("centimos"->"céntimos"), thus making the example consistent with actual current behaviour.
2022-08-03 10:19:24 -04:00
Gonçal
996f5ddbd4 Fixed accent in examples ("centimos"->"céntimos")
Fixed accent in Spanish examples ("centimos"->"céntimos"), thus making the example consistent with actual current behaviour.
2022-08-03 10:19:24 -04:00
gonzy
4f82655c74 Added test covering new fix penny->penique 2022-08-03 10:19:24 -04:00
gonzy
5602246319 Fixed pound cents: penny->penique, pence->peniques; fixed tests accordingly 2022-08-03 10:19:24 -04:00
Gonçal
b60a58bc85 flake8 fix: fixed comment style
Fixed:
./num2words/lang_ES.py:366:56: E261 at least two spaces before inline comment
./num2words/lang_ES.py:366:80: E501 line too long (100 > 79 characters)
2022-08-03 10:19:24 -04:00
gonzy
30f23ccd13 Orthography fixes: added missing accent (nuevos dolares->nuevos dólares); fixed accents in test_es.py (dieciséis, dólar, dólares, veintiún) 2022-08-03 10:19:24 -04:00
Gonçal
7d613beb9d Orthography fix: added accent veintiun->veintiún 2022-08-03 10:19:24 -04:00
Gonçal
bba96cf1fa Orthography fixes: added 2 missing accents (dieciseis->dieciséis ; dolar->dólar) 2022-08-03 10:19:24 -04:00
Marlon Rodriguez Garcia
4b6b0c7b7f Merge branch 'master' into master 2022-07-28 13:59:52 -04:00
support-savoirfairelinux
edb289c3d0 Merge pull request #448 from savoirfairelinux/replace-travis
feat: ci: replace travis by github workflows
2022-07-19 10:15:53 -04:00
Marlon Rodriguez
b70a28dab7 feat: ci: replace travis by github workflows 2022-03-20 21:10:15 -04:00
Daniel dos Santos
5f2c988d1d Merge pull request #1 from Cris140/master
To fix a problem in Brazilian Portuguese code referred to thousands when the hundreds are exact.
2022-01-28 16:08:20 -03:00
Daniel-EST
31a250eb90 Tests fix for issue #435 2022-01-28 15:31:41 -03:00
Daniel-EST
74ba6ee3b3 Fixes savoirfairelinux/num2words#435 2022-01-28 15:30:48 -03:00
potapov.s
86b9a00a67 - add uzs for ru and en 2021-11-02 12:59:24 +03:00
Cris140
fe0d185059 Update lang_PT_BR.py
To fix a problem with the thousands when the hundreds are exacts.
2021-10-29 22:42:10 -04:00
Cris140
84e6322006 Update lang_PT_BR.py 2021-10-28 14:53:27 -04:00
İsmail Eski
9b62e333d7 [ADD] to ordinal number for Turkish 2021-10-12 10:09:49 +03:00
Drew Echerd
cdb2acb052 Added MEGA_SUFFIX and GIGA_SUFFIX tests 2021-07-02 22:29:28 +05:00
Drew Echerd
1d98e0261e Added test for OverflowError and ordinal_num 2021-07-02 18:51:22 +05:00
Drew Echerd
5374a0ee44 Added Tajik language support 2021-07-02 17:00:13 +05:00
Rostyslav Ivanyk
40ab739f6c Improve Ukrainian support and minor fixes in CZ, KZ, LT, LV, PL, RU, SR languages (#400)
* Fix English char 'i' in Ukrainian words

* Fix the feminine currency processing for UAH in lang_UK.py

* Fix test_ua.py

* Fix the feminine currency processing for UAH in lang_RU.py

* Add tests for UAH in test_ru.py

* Add world currencies to lang_UK.py; Add test cases to test_uk.py for world currencies

* Fix incorrect handling of zeros after decimal point for CZ, KZ, LT, LV, PL, RU, SR and UK languages

* Add ukrainian ordinal numbers

* Fix too long lines of code

* Add test for negative cardinal number
2021-06-30 13:23:46 -04:00
Antoine Planchot
1e4470bc24 Added support for Esperanto numbers. 2021-05-14 22:31:46 +02:00
cyriaka90
8061cf3b20 [tr] return Turkish 0 ordinal and cardinal (#347)
* [tr] return Turkish 0 ordinal and cardinal

* add str_to_number to Turkish

* try rather use Num2Word_Base
2021-05-07 11:05:01 -04:00
Jonas Triki
3e0b89679b Merge branch 'master' into master 2021-04-24 14:01:00 +02:00
Paulina Komorek
3f5f6163cd [ADD] polish ordinal numbers (#367) 2021-04-23 15:27:47 -04:00
Jonas Triki
52dcb45ded Merge branch 'master' into master 2021-03-06 15:50:24 +01:00
Maroua Romdhane
8cc0e24596 Merge pull request #369 from EraYaN/EraYaN-dutch-ordinal_num-fix
[Fix] ordinal_num output for Dutch (NL)
2021-03-05 17:22:01 -05:00
Erwin de Haan
9082085d59 Fix ordinal_num output for Dutch (NL) 2021-02-14 19:56:24 +01:00
Jonas Triki
21d02eaec9 Fixes #339 2021-02-06 14:42:28 +01:00
Maroua Romdhane
a2abf77232 Merge pull request #355 from israelst/patch-1
Remove dupplicated line in lang_PT_BR
2021-01-29 11:50:06 -05:00
Ernesto Rodriguez Ortiz
bc80d18203 Merge branch 'master' into patch-1 2021-01-28 11:40:30 -05:00
Maroua Romdhane
75c1489874 Merge pull request #352 from peternordstrom/Swedish
added swedish language including test cases
2021-01-28 11:37:22 -05:00
Peter Nordstrom
94db9521b0 updated readme (added swedish) 2021-01-28 08:09:56 +01:00
Peter Nordstrom
219c2a5eb4 split some lines that were too long for flake8 2021-01-27 08:09:27 +01:00
Peter Nordstrom
0f325f8a82 Merge branch 'Swedish' of https://github.com/peternordstrom/num2words into Swedish 2021-01-26 08:43:22 +01:00
peternordstrom
5cb823af02 Merge branch 'master' into Swedish 2021-01-26 08:42:37 +01:00
Peter Nordstrom
e6fb2b128b updated failing flake8 test 2021-01-26 08:40:17 +01:00
Fernanda Hernandez
400917aa89 Add translations to spanish of several currencies 2021-01-25 21:48:53 -05:00
Israel Teixeira
5611325b9d This error is already raised in line 223 2021-01-25 22:31:17 -03:00
peternordstrom
92158f031f Merge branch 'master' into Swedish 2021-01-25 14:41:07 +01:00
Peter Nordstrom
3b52c5f924 updated test case to increase coverage. raised NotImplementedError for options not implemented. 2021-01-25 14:30:43 +01:00
hamidreza kalbasi
6cbd81cfbb fix flake8 problems 2021-01-25 10:34:01 +03:30
hamidreza kalbasi
5bb2be74a2 fix format problem 2021-01-25 01:16:45 +03:30
hamidreza kalbasi
a51b3e4d2b try fix test failure 2021-01-25 00:14:05 +03:30
HKalbasi
9a45cff4e9 Merge branch 'master' into master 2021-01-24 23:10:50 +03:30
hamidreza kalbasi
ca2651ad0f remove unneccery if 2021-01-24 10:30:06 +03:30
hamidreza kalbasi
b191c1fe1e fix test coverage 2021-01-24 10:10:24 +03:30
Ernesto Rodriguez Ortiz
003800422e Merge branch 'master' into patch-1 2021-01-23 22:25:30 -05:00
Maroua Romdhane
d90f99d4a4 [UPD] Readme file 2021-01-23 21:34:36 -05:00
Israel Teixeira
1f6ac0a7e3 Remove dupplicated line in lang_PT_BR
Remove an unnecessary condition, since the very same action follows it.
2020-12-22 07:43:10 -03:00
hamidreza kalbasi
f65df3fc61 add basic farsi support 2020-12-16 21:11:52 +03:30
Peter Nordstrom
e88f3d75e3 added correct ordinal handling and more test cases 2020-12-07 16:24:58 +01:00
Peter Nordstrom
895af7dccf added swedish language including test cases 2020-12-07 14:24:51 +01:00
gshekler
c95fe6260b typo 2020-10-03 15:14:21 +03:00
gshekler
6ea1a3da71 add unit tests 2020-10-03 15:03:57 +03:00
gshekler
92a0915508 implement currency for HE 2020-10-03 15:03:43 +03:00
gshekler
a6cae07703 fix pluralize 2020-10-03 15:03:19 +03:00
Willem Van Onsem
47a3cac323 Fix zeroth in Dutch to nulde fixing #325 2020-09-21 18:54:03 +02:00
Daniel Marai
e5bed36054 Removed unnecessary whitespaces 2020-05-03 23:27:34 -04:00
Daniel Marai
fb7ac21089 Fixed comma error 2020-05-03 23:27:34 -04:00
Daniel Marai
4dab316025 Added support for Hungarian language 2020-05-03 23:27:34 -04:00
Sarah Beranek
ebdb52e55f Update README.rst 2020-01-16 08:55:23 -05:00
Olzhas
7c924fe8ef Added kazakh lang to README 2020-01-15 09:39:52 -05:00
Olzhas
c2abbbec59 Linted KZ modules 2020-01-15 09:39:52 -05:00
Olzhas
3bb4ab120a Added kz tests for negative numbers and zero in chunks 2020-01-15 09:39:52 -05:00
Olzhas
d7742442c6 Updated kz tests 2020-01-15 09:39:52 -05:00
Olzhas
d576817c7f Initial kazakh implementation 2020-01-15 09:39:52 -05:00
Pierre Duchemin
e06493ceda Merge pull request #263 from venu1807/master
Adding Language Support for Telugu / Bug Fix in Kannada
2019-12-31 15:31:02 -05:00
Pierre Duchemin
82418b2612 Merge branch 'master' into master 2019-12-31 15:28:12 -05:00
Ernesto Rodriguez Ortiz
ca33d8ba98 Merge pull request #260 from mariaS210/romanian-issues-259
Romanian issues 259
2019-12-31 12:20:36 -05:00
Ernesto Rodriguez Ortiz
ff9bd868ba Merge branch 'master' into romanian-issues-259 2019-12-31 12:13:16 -05:00
Ernesto Rodriguez Ortiz
d1c2f94132 Merge pull request #270 from yliharma/master
Fixed misspelling of 21 (cardinal and ordinal number) in IT language
2019-12-31 12:05:01 -05:00
Ernesto Rodriguez Ortiz
0a88055c4a Merge branch 'master' into master 2019-12-31 11:03:46 -05:00
Ernesto Rodriguez Ortiz
5fe8815fad Merge pull request #283 from williamjmorenor/base
Add more tests to base.py
2019-12-31 10:30:39 -05:00
Ernesto Rodriguez Ortiz
af7882a7bd Merge branch 'master' into base 2019-12-31 09:59:08 -05:00
Ernesto Rodriguez Ortiz
ff6ff0e6a6 Merge pull request #288 from btharper/en_coverage
Add testcase for lang_EN.py
2019-12-31 09:48:23 -05:00
Ernesto Rodriguez Ortiz
ede0c42806 Merge branch 'master' into en_coverage 2019-12-31 09:42:04 -05:00
Ernesto Rodriguez Ortiz
e674ce70f3 Merge pull request #286 from btharper/test_dk
Add simple tests for lang_DK.py
2019-12-31 09:40:12 -05:00
Ernesto Rodriguez Ortiz
a2fe2aa4c9 Merge branch 'master' into test_dk 2019-12-31 09:35:45 -05:00
Ernesto Rodriguez Ortiz
432b763e1d Merge pull request #287 from btharper/es_coverage
Add ordinal 12,345 to ES test suite to increase coverage
2019-12-31 09:32:23 -05:00
Ernesto Rodriguez Ortiz
cb9fff1189 Merge branch 'master' into es_coverage 2019-12-30 17:15:38 -05:00
Ernesto Rodriguez Ortiz
3d14f7a5bb Merge branch 'master' into en_coverage 2019-12-27 16:35:33 -05:00
Ernesto Rodriguez Ortiz
b594ac0513 Merge pull request #298 from toofun666/master
Update test_tr.py to increase coverage
2019-12-27 16:11:50 -05:00
Tufan Kaynak
234e02dd54 updated tests 2019-12-13 20:18:59 +03:00
Tufan Kaynak
0236257876 updated tests 2019-12-13 19:49:39 +03:00
Tufan Kaynak
39ef298626 updated tests 2019-12-13 19:13:41 +03:00
Tufan Kaynak
3da9fd8705 updated tests 2019-12-13 19:08:49 +03:00
Tufan Kaynak
fe0bc1adbd updated tests 2019-12-13 19:06:36 +03:00
Tufan Kaynak
6a4e955049 updated tests 2019-12-13 19:02:02 +03:00
Tufan Kaynak
739f02d830 updated tests 2019-12-13 18:55:38 +03:00
Tufan Kaynak
a7971f1156 updated tests 2019-12-13 18:46:34 +03:00
Tufan Kaynak
f5c07d714d updated tests 2019-12-13 17:35:32 +03:00
Tufan Kaynak
2fae9512ce updated tests 2019-12-13 17:26:26 +03:00
Tufan Kaynak
2c629f8349 updated tests 2019-12-13 17:16:02 +03:00
Tufan Kaynak
7c6a716165 updated tests 2019-12-13 17:12:13 +03:00
Tufan Kaynak
0b22ac1950 updated tests 2019-12-13 17:11:07 +03:00
Tufan Kaynak
1514514ed9 updated tests 2019-12-13 17:06:07 +03:00
Tufan Kaynak
8e19dd584b updated tests 2019-12-13 16:59:02 +03:00
Tufan Kaynak
12ef620b29 updated tests 2019-12-13 16:49:40 +03:00
Tufan Kaynak
9b8a541224 updated tests 2019-12-13 16:45:01 +03:00
Tufan Kaynak
ede1db8690 updated tests 2019-12-13 16:38:39 +03:00
yliharma
ed47b30e99 Merge branch 'master' into master 2019-11-22 16:03:41 +01:00
mariaS210
dc7f7907e5 romanian-issues-259: revert a test 2019-11-07 23:29:43 +02:00
mariaS210
09d5da3555 romanian-issues-259: fix linter error 2019-11-07 23:08:16 +02:00
mariaS210
b362b7b347 romanian-issues-259: implement and use pluralize 2019-11-07 23:02:41 +02:00
Ben Harper
f665cb32f4 Merge branch 'master' into es_coverage 2019-10-29 21:57:27 -04:00
mariaS210
9943be7d71 Merge branch 'master' into romanian-issues-259 2019-10-28 15:49:51 +02:00
Ariel Allon
c1e3e854bb Use non-url-encoded source URL to avoid CI rejection for too-long line 2019-10-28 09:34:14 -04:00
Ariel Allon
28c304c2f4 Fix Hebrew support
- Correct gender of 1 and 2 (and 11 and 12) to match remainder of numbers
- Fix spelling of 8 (and 18 and 80)
- Add cases for thousands 3-9 and support in the logic
- Fix placement of "and" conjunction to match Academy of Hebrew Language position
- Add tests
2019-10-28 09:34:14 -04:00
btharper
b82bf457d4 Fill out coverage for lang_EN.py 2019-10-26 23:39:24 -04:00
btharper
d161b4348d Remove excess try/except KeyError block 2019-10-26 23:22:23 -04:00
btharper
6819f5a6ed Fix py2/3 difference on division and update test case 2019-10-26 22:38:50 -04:00
btharper
d82f739bc9 Add ordinal 12,345 to ES test suite to increase coverage 2019-10-26 17:37:47 -04:00
btharper
7cd31a93f1 Add simple tests for lang_DK.py 2019-10-26 16:37:22 -04:00
William José Moreno Reyes
a1d29fc2bc Update to title test
Signed-off-by: William José Moreno Reyes <williamjmorenor@gmail.com>
2019-10-25 21:40:26 -06:00
William José Moreno Reyes
e90061af65 Add more tests to cover num2words/base.py
Fix:
 - https://github.com/savoirfairelinux/num2words/issues/125

Signed-off-by: William José Moreno Reyes <williamjmorenor@gmail.com>
2019-10-25 21:40:26 -06:00
William José Moreno Reyes
601e8cee84 Add AttributeError to to_cardinal_float
Signed-off-by: William José Moreno Reyes <williamjmorenor@gmail.com>
2019-10-25 21:40:26 -06:00
Ernesto Rodriguez Ortiz
9290282ca2 Merge branch 'master' into romanian-issues-259 2019-10-25 23:22:02 -04:00
William José Moreno Reyes
4f116228b5 Update .gitignore to add .eggs/ directory
Signed-off-by: William José Moreno Reyes <williamjmorenor@gmail.com>
2019-10-25 23:20:51 -04:00
Ernesto Rodriguez Ortiz
af199a472c Merge branch 'master' into master 2019-10-25 18:37:47 -04:00
Ernesto Rodriguez Ortiz
7e893f1ef6 Merge branch 'master' into romanian-issues-259 2019-10-25 18:36:11 -04:00
William José Moreno Reyes
3cb0b40fd5 Signed-off-by: William José Moreno Reyes <williamjmorenor@gmail.com>
Add a test to check correct error raises

This is a simple test to check that NotImplementedError raises
fine. This also should improve test code coverage.
2019-10-25 18:33:40 -04:00
William José Moreno Reyes
3202476d55 Add es_NI test
Signed-off-by: William José Moreno Reyes <williamjmorenor@gmail.com>
2019-10-25 18:33:40 -04:00
William José Moreno Reyes
5e15702912 Add es_NI currency
Examples:

  python bin/num2words 1 -l es_NI --to currency
  un córdoba con cero centavos

  python bin/num2words 1.02 -l es_NI --to currency
  un córdoba con dos centavos

  python bin/num2words 2.02 -l es_NI --to currency
  dos córdobas con dos centavos

  python bin/num2words 1.01 -l es_NI --to currency
  un córdoba con un centavo

Signed-off-by: William José Moreno Reyes <williamjmorenor@gmail.com>
2019-10-25 18:33:40 -04:00
Ivan Petukhov
ca5989a3ec Add KZT and UAH currencies to lang RU 2019-09-10 16:46:05 -04:00
Paola Coccia
d14f3388ff Fixed misspelling of 21st (ordinal number) in IT language 2019-08-26 18:07:30 +02:00
A.V.GOPAL
4bd2f0259f Merge pull request #1 from sarahberanek/master
Add Ordinal Numbers Test for Kannada.
2019-08-19 14:11:44 +02:00
Sarah Beranek
b89acf6709 Add Ordinal Numbers Test for Kannada. 2019-08-19 13:07:47 +02:00
VENUGOPAL ACHHE
3c51be6c1f correction for ordinal case telugu test case and lang_TE 2019-07-22 09:36:57 +02:00
VENUGOPAL ACHHE
0283012532 2nd correction for telugu test case and lang_TE 2019-07-17 11:50:25 +02:00
VENUGOPAL ACHHE
607e270cad correction for telugu test case 2019-07-17 10:59:07 +02:00
VENUGOPAL ACHHE
a2900faccf Final telugu num2words. 2019-07-04 17:43:00 +02:00
VENUGOPAL ACHHE
6b3d303332 Add Telugu Num2Words. 2019-06-13 17:26:17 +02:00
Maria S
a192afec85 romanian-issues-259: test new branch 2019-06-09 12:43:01 +03:00
Maria S
bdf651d1fa romanian-issues-259: rough implementation 2019-06-09 12:24:01 +03:00
VENUGOPAL ACHHE
e887530462 Telugu Language num2words file 2019-05-21 18:15:38 +02:00
Ernesto Rodriguez Ortiz
2d1a318359 Release v0.5.10 2019-05-12 11:48:38 -04:00
Akhilesh
cbfc8fd5d0 add kannada language support (#243)
* add kannada support

* add Kannada Language support

* add tests for kannada

* reformatted

* change lang param

* fix tests

* add condition

* add modifier

* add few more test cases

* fix test

* fix test

* modify test

* fix flake8

* fix isort

* add more tests

* add unicode prefix

* edit tests for float numbers

* add more tests

* add unicode prefix in tests

* add Kannada language
2019-05-12 11:03:31 -04:00
Filippo Costa
f6dc5a3893 Revert some copyright changes made in commit 53b4518 (#254)
Commit 53b4518 made added explicit utf-8 encoding for all sources, among
other things. A copyright notice in `tests/test_tr.py` was removed and
two were added in `num2words/lang_it.py`. I know this was a simple
mistake, I just thought it would be best to explicitly give credit where
credit is due.
2019-05-07 11:04:19 -04:00
Chintalagiri Shashank
f4b2bac098 Add support for the Indian rupee. (#248) 2019-04-11 20:14:59 -04:00
Sarah Beranek
a869745813 Fixing currency functions for german and french. Adding Currency_Forms for DE, FR and NL. (#247)
* Fix currency function for French. Adding Currency_Forms.

* Fix currency function for German. Adding Currency_Forms.

* Move FR_DZ to new currency functions, too.

* Fix tests

* Add more currency options for dutch.

* Add more tests for German, Dutch and French currencies.
2019-04-11 19:07:44 -04:00
Blaž Bregar
18194b52ef Multitude of corrections of Slovene language (#246)
* Multitude of corrections of Slovene language

* Indentation correction for flake8

* Added tests from https://github.com/gregopet/num2words by @gregopet and merged them with existing.

* Flake8ing tests.

* Sorted imports

* Some more sorting...

* Last time for sorting?
2019-03-29 13:47:18 -04:00
Alvaro
eef5b03593 Updates accents on céntimos in Spanish (#240)
* Updates accents on céntimos in Spanish

* Update test_es.py

* Update test_es.py

* fix tests

* fix encoding

* Update tox.ini

* Update test_cli.py

* Update test_cli.py

* Update test_cli.py

* Update lang_AR.py

flake-8 compliant

* Update test_cli.py

flake8 compliant

* Update test_cli.py

* Update test_cli.py
2019-02-12 13:59:46 -05:00
Pierre Duchemin
aa9b882fe6 Merge pull request #238 from savoirfairelinux/fix_typo_seperator
Fix typo 'seperator' on source code
2019-01-23 14:23:07 -05:00
Ernesto Rodriguez Ortiz
2eee037648 Fix typo 'seperator' on source code 2019-01-19 17:00:26 -05:00
kkonieczny
c1292c1499 Merge pull request #223 from btharper/strings
Convert strings to Decimal values
2019-01-18 16:01:39 -05:00
kkonieczny
e459021792 Merge branch 'master' into strings 2019-01-18 15:16:24 -05:00
kkonieczny
83cfcdc999 Merge pull request #237 from zenogantner/master
German improvements
2019-01-18 15:05:24 -05:00
kkonieczny
a3a0961b7d Merge branch 'master' into master 2019-01-18 14:55:41 -05:00
kkonieczny
cebcaa6e64 Merge pull request #233 from TrangOul/master
PL: regular names for powers of thousand
2019-01-18 14:38:04 -05:00
Marek Madejski
38d2752728 Merge branch 'master' into master 2019-01-14 15:19:17 +01:00
Zeno Gantner
67d58e7081 German: add 3 more test cases for thousands 2019-01-13 23:57:57 +01:00
Zeno Gantner
b71facf3ea German: ordinals involving 'Million' etc. are written without space, and lower case 2019-01-13 23:55:34 +01:00
Zeno Gantner
e321caf392 Million etc. are upper case in German 2019-01-13 23:25:54 +01:00
Zeno Gantner
df65296a80 German: similar rule for million as for 100 and 1000; 2 more ordinal tests 2019-01-13 23:18:51 +01:00
Zeno Gantner
0398d16460 German: 2 more ordinal tests 2019-01-13 23:04:10 +01:00
Zeno Gantner
778786b65b fix ordinal_num for French numbers ending with 1 (#236) 2019-01-12 13:10:31 -05:00
Pierre Duchemin
218d184583 Merge pull request #235 from savoirfairelinux/release-0.5.9
Release 0.5.9
2019-01-11 15:13:32 -05:00
Ernesto Rodriguez Ortiz
f2fb5bc67f Release 0.5.9 2019-01-10 20:09:08 -05:00
Marek Madejski
52fb935d8c PL: regular names for powers of thousand
Names for powers of thousand are now built instead of being hardcoded - less error-prone and more concise.
2018-12-28 11:57:12 +01:00
Marek Madejski
cb55d7b91d Merge remote-tracking branch 'upstream/master' 2018-12-28 11:14:26 +01:00
Pierre Duchemin
c12131d557 Merge pull request #231 from savoirfairelinux/issue_229
Issue 229: Add explicit encoding, license and unix line separators.
2018-12-26 09:54:48 -05:00
Ernesto Rodriguez Ortiz
53b4518afb Issue 229: Add explicit encoding, license and unix line separators.
Some maintainers for different linux distribution are having some
problems with the encoding on different python versions. This change
intents to make all python files define explicitly the encoding, license
and unix line separators. Remove one example of the README.rst file
where a possible non UTF-8 character is used.
2018-12-23 12:10:24 -05:00
kkonieczny
7f125590f7 Merge pull request #228 from TrangOul/patch-1
Extend Polish names + typos; power of thousand names not inserted when value is 0
2018-12-21 14:20:07 -05:00
Marek Madejski
9bd1bebb0e Shortened one test number for PEP8 compliance - smaller number parts are already tested. 2018-12-05 10:54:02 +01:00
Marek Madejski
4a0b323fa9 early continue
skip processing given power of thousand if it is 0
2018-12-03 16:07:15 +01:00
Marek Madejski
d78add4c3a Update test_pl.py
unit test fix
2018-12-03 12:40:04 +01:00
Marek Madejski
b8cd4ba181 no word for zero value of thousand's power; PL unit test fix
Before: 1_000_000_000 = "miliard milionów tysięcy" (with words for zero millions and thousands)
After: "miliard" (no words if value for given power of 1000 is 0)
2018-12-03 12:03:16 +01:00
Marek Madejski
518ce0b606 Update lang_PL.py
typo in "dziewięćset" (900) fix
2018-12-03 11:30:45 +01:00
Marek Madejski
efde954697 Update test_pl.py
added test for a really big number in Polish
2018-12-03 11:14:55 +01:00
Marek Madejski
f26c3a139a Update test_pl.py
test for really big number's Polish name
2018-12-03 11:05:36 +01:00
Marek Madejski
a147dc3d34 Update lang_PL.py
PEP8 compliance
2018-12-03 09:59:53 +01:00
Marek Madejski
8fde057760 Update lang_PL.py
- typo in "kwadryliard"
- expanded long scale up to decilliard (10^63)
- PEP8 compliance
2018-12-03 09:57:37 +01:00
Marek Madejski
562e446716 Update lang_PL.py
- typo in "kwadryliard"
- expanded long scale up to decilliard (10^63)
2018-11-30 09:42:15 +01:00
Maxime St-Pierre
58613e0a18 Merge pull request #225 from savoirfairelinux/v0.5.8
Release 0.5.8
2018-11-17 20:03:20 -05:00
Ernesto Rodriguez Ortiz
fffb5c2dcf Release 0.5.8 2018-11-17 14:38:49 -05:00
Hugo Lefeuvre
66a47e2423 Improve german support (#222)
* german: fix case in currency names

Also, add more tests for german language.

* german: default to amount of euros, not cents

If a non-float number is provided, interpret it as a quantity in euros,
not cents.

* german: handle "ein Euro" vs "eins Euro" exception

* german: prefer "einhundert" over "hundert"

"hundert" is usually colloquial (even if widely used).

Exception: "eintausendste" and "hundertste" are special cases, here
"hundertste" and "tausendste" are usually preferred (see Duden).
2018-11-16 16:19:36 -05:00
Sangbum Kim
4d8c93847c Add: Korean support (#219)
* Add: lang_KO support

Added Korean language support and tests

* Remove commented code
2018-11-10 18:44:02 -05:00
fatkaratekid
1ed09f511d Add support for Serbian (Latin) (#207)
* Add support for Serbian language

* Fix the billion strings for short scale

Used the long scale name instead of the short one. Simplified the scale and the ones geneder definition.

* Adds Serbian to README
2018-11-10 18:36:51 -05:00
btharper
446e918e14 Convert strings to Decimal values
Punt string handling to python Decimal object, this correctly represents both
integers and floats (except with regards to trailing zeros)
Change command line tests to reflect handling of ints
2018-10-31 22:01:26 -04:00
btharper
5c9bce19e4 Refactor testing setup (#220)
* Refactor tox and travis config files

Separates flake8 and isort into separate tox tasks
Tie flake8 and isort to specific python version so they only run once on Travis
Add python3.7 to tested python versions
* Requires newer Xenial base
* Running Xenial on Travis requires sudo
Move coveralls submission to travis config to avoid triggering during local runs.

* Require all tests to be run

Clean up test generation code form test_fi.py
Perform coverage measurement of tests
Fail tox if coverage of tests directory isn't at 100%

* Further Tox refactoring

Measure project coverage explicitly instead of omitting non-project files from reporting
Add branch measurement to coverage
Only report to coveralls if a .coverage result file exists
Make dependencies for each testenv explict and only include requried deps

* Small readme update to trigger travis

Add overly brief message about installing and running tox

* Fix unescaped flake8 violations

Unescaped \w -> \\w and \e to \\e in regex patterns found with updated flake8
2018-10-26 09:31:41 -04:00
Aaron M
c606fd54e8 Added missing numbers in "self.ords". (#218) 2018-10-20 16:56:19 -04:00
Olos
0f63859572 Add support for Portuguese (Portugal) (PT) (#198)
* add support for Portuguese (Portugal) (PT)

* FIX ADD SUPPORT TO PORTUGUESE (PORTUGAL) [PT]

removed venv/ from .gitignore.
correction from "milião" to "milhão" done on merge function.
removed hack for negword, creating a backup of the original one.

* add support PT (Portugal) (PT)

* add support PT (Portugal) (PT)

* add support PT (Portugal) (PT)

* add support PT (Portugal) (PT)

new tests
2018-10-20 15:53:14 -04:00
Sergej Herbert
6d30cb9e83 Increase German test coverage to 100% (#214)
* increase test coverage - german ordinal_num

* push coverage of german to 100%

* fix line width

* travis ci fix

* remove underscore between numbers due to backwords comp

* removed coverage file
2018-10-19 18:17:50 -04:00
mariaS210
ca61c77f3b Add Romanian support (#215)
* romanian-support: start implementation

* romanian-support: implement basic merge and to_ordinal

* romanian-support: fix linting error

* romaniansupport: fix spacing for linter

* romanian-support: correct indent of error message

* romanian-support: add encoding to test file

* romanian-support: python2 fix: make strings in test unicode

* romanian-support: complete rough implementation

* romanian-support: pylint fixes

* romanian-support: fix tests for python2

* romanian-support: small fixes

* romanian-support: add romanian to readme

* ensure alphabetical order in readme
2018-10-17 09:56:40 -04:00
Maxime St-Pierre
3544e49376 Merge pull request #216 from savoirfairelinux/issue165_iso_code_vi
Use language iso code for Vietnamese
2018-10-16 11:29:36 -04:00
Ernesto Rodriguez Ortiz
f9107c4938 Use language iso code for Vietnamese
Also update the readme and fix error, on the README.rst file we say tha
code language to use is vn, but to make it work you have to use vi_VN.
Let's refactor this to use the proper iso code `vi` in all places.
2018-10-15 12:32:42 -04:00
Sergej Herbert
dd25a8b4bf Correction of german ordinals. (#213) 2018-10-15 09:45:00 -04:00
MontakOleg
9a31d900e3 Add USD currency support to RU language (#211)
* Add USD currency support to RU language
2018-10-14 17:23:53 -04:00
Jose Carlos
dc733cfa1b lang_es: Add currency PEN (#200) 2018-10-13 19:29:58 -04:00
Temoctzin
424cf9fda8 feat(Num2Word_EU): add MX to CURRENCY_FORMS (#187)
* lang_EU: add MX to CURRENCY_FORMS and CURRENCY_ADJETIVES
2018-10-13 19:25:58 -04:00
btharper
26a2204f3b Add Delegator.py to test dependencies (#205)
Delegator.py is used for cli tests but isn't included in dependencies.
2018-10-13 19:20:54 -04:00
Vadim Smirnov
af49bb360f Implemented to_ordinal for RU (#212)
* Implemented to_ordinal for RU
2018-10-13 18:57:48 -04:00
romangraef
411a92a4fe fixed issues found in this PR 2018-10-05 20:14:28 -04:00
romangraef
0377347cb9 fixed pep8 line too long errors in tests/test_de.py 2018-10-05 20:14:28 -04:00
romangraef
5650d2818d added more tests to lang_DE.py 2018-10-05 20:14:28 -04:00
CrazyMerlyn
f09ad9afdf Add tests for lang_EN ordinal coversion 2018-09-25 11:03:53 -04:00
Mārtiņš Šulcs
5f91c1420f Reduce indent level 2018-09-25 17:44:08 +03:00
Mārtiņš Šulcs
61dd1c9a4f Test currency not implemented, remove dead method. 2018-09-25 17:44:08 +03:00
Mārtiņš Šulcs
26fef2e116 More tests 2018-09-25 17:44:08 +03:00
Mārtiņš Šulcs
03d44f4bc3 Very naive to_currency implementation for NL 2018-09-25 17:44:08 +03:00
CrazyMerlyn
23902ab7c5 [FIX] lang_FR: Fixed decimal handling in french currency
Fixes #179
2018-09-25 10:29:56 -04:00
CrazyMerlyn
b541ee8d8e Add tests for lang_EN_IN 2018-09-21 16:12:06 +05:30
Lise Rebout
c71d99cddf Small corrections concerning the plural of millions, milliards, cents and vingts 2018-09-17 13:04:32 -04:00
Mārtiņš Šulcs
2a99ff1061 Cleanup (#194)
* Remove some dead code.

* Overloadable _cents_terse

* One setup should be enough

* Move gen_high_numwords up

* Cards are optional.

* Line length

* DRY set_hight_numwords for EU base.

* Remove unused error message. It has to be an exception anyway.
2018-09-17 09:30:36 -04:00
Jacob Cook
44354bf9ce Merge pull request #193 from savoirfairelinux/cmd
Add a command line tool to use num2words, credits to @hernamesbarbara
2018-09-16 17:10:33 -04:00
Ernesto Rodriguez Ortiz
62f3cad2d6 Add a command line tool to use num2words, credits to @hernamesbarbara 2018-09-16 16:43:44 -04:00
Abdullah Alhazmy
f72c9997c6 Improve Arabic implementation (#176)
* Change Arabic Lang implementation
* Improve Arabic class, * update Arabic test cases
* Support EGP and KWD currency
* Add test cases
* Remove .cache and .pytest_cache folder
* Increase coverage from 84 to 90 #122
* Increase coverage from 90 to 92 #122
* Fix ordinal issue #166
2018-09-11 13:45:26 -04:00
SButko
7639f5a820 [ADD] lang_LT: new currencies, feminine numerals
- Adding feminine numeric forms.
- Implementing new currency forms: USD, GBP, PLN, RUB (with feminine
	numeric forms).
2018-08-30 11:38:17 -04:00
Andrius Laukavičius
39f522f34a [FIX] lang_LT, lang_LV: negative amounts (#185)
Negative amounts were not working (when no currency is used), because
`get_digits` method does not expect `-` sign, which crashes conversion.
To avoid that, we split minus sign from number string and prepare its
word to be used with amount words.

closes: #184
2018-08-23 10:39:03 -04:00
Andrew Hlynskyi
1ca8225ea6 Fix orthography for EUR currency in UK lang (#183) 2018-08-16 10:17:37 -04:00
Ege Güneş
e394ca6e9e Fix typo 2018-07-20 11:51:10 -04:00
Istvan SZALAÏ
f275d0fde9 Release 0.5.7 (#175)
* New maintainer 🚀

Since @erozqba no longer work for Savoir-faire Linux, the maintainer has changed.

* Bump version from 0.5.6 -> 0.5.7

* Update CHANGE.rst to publish a new release.
2018-06-27 17:55:14 -04:00
Istvan SZALAÏ
8975222487 [FIX] move language specific info to the wiki (#174)
* [FIX] move language specific info to the wiki

The informations about Finnish and Japanese can be found in the [wiki](https://github.com/savoirfairelinux/num2words.wiki.git)
The goal of this commit is to keep the readme short.

* [FIX] add wiki mention in the readme.rst
2018-06-27 17:51:28 -04:00
siikamiika
8820681169 add support for Finnish (FI) (#170)
FI: Add support for Finnish

This is a squash of the following commits :

* The recommendation by Kotus was optional. The code didn't work anyway
because million is 10**6, not 10**9, and the recommendation only applies
to round millions, billions and so on where the multiplier is 10 or
greater.
* FI: currency: use inheritance, add FIM and USD
* FI: add some common currencies
* FI: add inflections
* FI: inflections: small fixes
* FI: fix ordinal 200
* FI: fix comitative
* FI: actually fix ordinal 200
* FI: refactoring
* FI: fix tens
* FI: fix plural for tens and higher
* FI: toinen --> kahdes for numbers > 200
* FI: use collection for options
* FI: add tests
* FI: add minced tests
* FI: trim tests
* FI: finishing touches
* FI: improve cardinal_float, ordinal, add tests
* FI: add documentation to README.rst
2018-06-22 10:00:49 -04:00
siikamiika
89554ff9e2 add support for Japanese (JA) (#171)
* add support for Japanese (JA)
2018-06-15 11:14:56 -04:00
Abraham Anes
b492530cfa Change implementation of to_currency() in es_ES (#167)
* Change implementation of to_currency()
* Change OLD to ESP and add USD
2018-04-18 09:05:13 -04:00
dede64
551a980e54 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
2018-02-19 16:30:20 -05:00
James ADJINWA
569b29af39 Typo correction in documentation (#155) 2018-01-31 09:24:28 -05:00
François Honoré (Acsone)
ce21cb9f18 [ADD] Add lang fr_BE + tests (#151) 2018-01-16 14:38:43 -05:00
Antonio Gurgel
e28394d29f Improve README.rst. (#145)
* Improve README.rst.

* Fix "Usage": "cardinal" => "ordinal".

>>> num2words(42,to='cardinal')
u'forty-two'
>>> num2words(42,to='ordinal')
u'forty-second'

* Add PyPI shield. Closes #36.

* Fix link to GitHub.

* Maintain "country - language" consistency

* Fix typos, clarify country-language fallback
2017-12-19 07:51:58 -05:00
Antonio Gurgel
1a2b783d31 lang_EN.to_year(): render correct pronunciations (#144)
* Add tests

Starting work on #141, which points out that 2017 should come out
"twenty seventeen"; it currently comes out "two thousand seventeen".

* Handle English years properly.

Resolves #141.

* Whoops -- didn't PEP-8 my tests

* Handle years MORE properly...with suffixes!

- Rendering years between 10-99 was bugged (e.g. "zero fifty").
Fixed that by thinking outside the high/low text box I had made.
- Added suffixes: default none if positive, 'BC' if negative.
User-overrideable.
2017-12-18 10:56:38 -05:00
pipech
ab54bed93a add Thai Language from Thailand (#139)
* add Thai

* change splitby3 to splitbyx

* change lang_th to use function from currency

* make Num2Word_TH inherit from Num2Word_Base

* comment out test failed in 2.7 env

* fix python2.7 error

* add USD EUR for Thai

* pep8 fix

* added Thai
2017-12-14 11:48:12 -05:00
Carli Samuele
efce631944 Fix lang_IT handling of floats (#143)
`n % 1 != 0` is not a valid test for float:

In []: 1.1 % 1 == 0
Out[]: False

but:

In []: 1.0 % 1 == 0
Out[]: True

hence it's really necessary to explicitly test for type in this case.
2017-12-04 17:16:06 -05:00
Ernesto Rodriguez Ortiz
8ffdc5e49d Update CHANGE.rst to publish a new release.
Ref: issue #140
2017-11-22 14:35:46 -05:00
Ernesto Rodriguez Ortiz
9819498a14 Increase test coverage for lang fr* (#136)
Ref: issues #116 #121 #127
2017-11-09 10:15:29 -05:00
Mārtiņš Šulcs
1e954c909b Attempt at refactoring to_currency into base (#135)
* Attempt at refactoring lv to base

* Remove dead files.

* Use static props.

* Convert doctests, move utils out.

* Refactor lt

* Update and move ru doctests.

* Refactor ru.

* Refactor pl.

* Move uk doctests.

* Refactor uk.

* DRY

* Cleanup.
2017-11-09 10:13:01 -05:00
Ernesto Rodriguez Ortiz
1c699d1bb4 Fix bugs in the float precision and the currency, increase test coverage (#134)
* Fix some bugs in the float precision and the currency, increase test coverage.

Ref: issue #112 #113

* Update README.rst
2017-11-06 20:19:26 -05:00
Mārtiņš Šulcs
5a131fedc6 Long form for currency name is optional. Currency name rendering in e… (#133)
* Long form for currency name is optional. Currency name rendering in english.

* Missing encoding header.
2017-11-05 17:59:25 -05:00
Ernesto Rodriguez Ortiz
ee9f767b06 Create PULL_REQUEST_TEMPLATE.md 2017-11-05 15:19:46 -05:00
Ernesto Rodriguez Ortiz
c511f499b9 Create ISSUE_TEMPLATE.md 2017-11-05 15:16:23 -05:00
Ernesto Rodriguez Ortiz
a98c75e394 Create CONTRIBUTING.md 2017-11-05 15:15:15 -05:00
Ernesto Rodriguez Ortiz
dde43cb4e5 Create CODE_OF_CONDUCT.md 2017-11-05 15:07:12 -05:00
Mārtiņš Šulcs
a1a3c53b39 Improve lv (#132)
* Add legal form.

* Fix fractions (comma)

* Fix edge case, improve test coverage.

* Add most popular currencies

* PEP8 line length

* Fix some forms.
2017-11-01 13:04:09 -04:00
Ernesto Rodriguez Ortiz
c326d59b2d Replace a custom implementation of an ordered dict in the file orderedmapping.py by collections.OrderedDict (#131) 2017-11-01 09:55:24 -04:00
Mārtiņš Šulcs
f9d8868794 Refactor and fix some issues with to_currency. Reduce code duplication. (#129)
* Refactor and fix some issues with to_currency. Reduce code duplication.

* Use unicode literals in uk testcase.
2017-10-31 20:17:13 -04:00
Ernesto Rodriguez Ortiz
abae0b56a2 Update fichier README.rst to fix the coverage badge 2017-10-30 14:08:44 -04:00
Ernesto Rodriguez Ortiz
3da0c54f3b Activate flake8, isort and coveralls in the configuration of tox (#105)
* Activate flake8, isort and coveralls in the configuration of tox

* Update code to respect PEP8

* Fix bug in the lang_IT for python 3

* Update the README to include the new converters.
2017-10-30 14:06:46 -04:00
Ernesto Rodriguez Ortiz
c6015db8b4 Update tox.ini to check more stuffs (#103) 2017-10-26 20:10:44 -04:00
Ernesto Rodriguez Ortiz
34d5a4cd5a Merge pull request #102 from savoirfairelinux/remove_lang_EN_GB_old_file
Remove old and not used file num2words/lang_EN_GB_old.py
2017-10-26 16:11:06 -04:00
Ernesto Rodriguez Ortiz
14bcd99cab Remove old and not used file num2words/lang_EN_GB_old.py 2017-10-26 16:08:33 -04:00
Ernesto Rodriguez Ortiz
3788cb213a Merge pull request #101 from shulcsm/expose_to_currency
Expose to to_currency.
2017-10-26 15:06:34 -04:00
Ernesto Rodriguez Ortiz
02a52aab5b Merge pull request #100 from shulcsm/pass_kwargs_to_converters
Pass kwargs to converters.
2017-10-26 15:05:12 -04:00
Ernesto Rodriguez Ortiz
168707744d Merge pull request #98 from williamjmorenor/master
Fix some pep8 issues
2017-10-26 15:03:27 -04:00
Mārtiņš Šulcs
7461ef6d78 Expose to to_currency. 2017-10-26 13:26:17 +03:00
Mārtiņš Šulcs
f01dfa2de0 Pass kwargs to converters. 2017-10-26 13:14:09 +03:00
William Moreno Reyes
0600fbb183 Fix many to long lines issues
Signed-off-by: William Moreno Reyes <williamjmorenor@gmail.com>
2017-10-24 17:48:51 -06:00
William Moreno Reyes
6462321257 Remove unnecessary line break
Signed-off-by: William Moreno Reyes <williamjmorenor@gmail.com>
2017-10-24 07:10:58 -06:00
William Moreno Reyes
9e6015494c Fix tests
Signed-off-by: William Moreno Reyes <williamjmorenor@gmail.com>
2017-10-23 18:38:21 -06:00
William Moreno
d65f5b10db Merge branch 'master' into master 2017-10-23 18:15:55 -06:00
William Moreno Reyes
94c73d277e Fix as many pep8 issues as posible
Signed-off-by: William Moreno Reyes <williamjmorenor@gmail.com>
2017-10-23 18:12:36 -06:00
William Moreno Reyes
e2ce7c2562 Many PEP8 fixes
Signed-off-by: William Moreno Reyes <williamjmorenor@gmail.com>
2017-10-23 15:58:00 -06:00
William Moreno Reyes
27058f5ddc Include tests in release
Please include tests in the release, I am the mantainer of this library
for Fedora/EPEL and have the tests available in the releases file is
reale usefull

Signed-off-by: William Moreno Reyes <williamjmorenor@gmail.com>
2017-10-23 15:05:58 -06:00
William Moreno Reyes
55cb0ea3e9 Fix a py3 issue with print like a funtion
Signed-off-by: William Moreno Reyes <williamjmorenor@gmail.com>
2017-10-23 14:33:25 -06:00
William Moreno Reyes
d73acaa985 Fix missing print funtion for py3
Signed-off-by: William Moreno Reyes <williamjmorenor@gmail.com>
2017-10-23 14:25:37 -06:00
Ernesto Rodriguez Ortiz
096cb45ad9 Merge pull request #97 from bblaz/master
Added Slovene (sl) languange
2017-10-23 16:19:30 -04:00
Ernesto Rodriguez Ortiz
931d7063db Merge pull request #95 from savoirfairelinux/allow_call_to_other_converters
Allow call to other convertes as to_currency, to_year
2017-10-23 16:18:14 -04:00
William Moreno Reyes
d9aee6934f Fix some pep8 issues
W291:
 pycodestyle-3.6 num2words | grep W291
 num2words/lang_NL.py:64:40: W291 trailing whitespace
 num2words/lang_NL.py:97:38: W291 trailing whitespace

Signed-off-by: William Moreno Reyes <williamjmorenor@gmail.com>
2017-10-23 14:16:46 -06:00
Ernesto Rodriguez Ortiz
38db45cc4a Merge pull request #96 from marcu/master
lang_DK do not depends on num2words
2017-10-23 16:16:37 -04:00
William Moreno Reyes
34de8f7f87 Fix some pep8 issues
W293:
 pycodestyle-3.6 num2words | grep W293
 num2words/lang_EN_EUR.py:19:1: W293 blank line contains whitespace
 num2words/lang_EN_EUR.py:43:1: W293 blank line contains whitespace
 num2words/lang_EN_IN.py:19:1: W293 blank line contains whitespace
 num2words/lang_EU.py:28:1: W293 blank line contains whitespace
 num2words/lang_RU.py:236:1: W293 blank line contains whitespace
 num2words/lang_UK.py:218:1: W293 blank line contains whitespace
 num2words/lang_UK.py:238:1: W293 blank line contains whitespace
 num2words/lang_UK.py:248:1: W293 blank line contains whitespace
 num2words/orderedmapping.py:22:1: W293 blank line contains whitespace

Signed-off-by: William Moreno Reyes <williamjmorenor@gmail.com>
2017-10-23 14:10:29 -06:00
William Moreno
e15e7486c4 Merge pull request #1 from savoirfairelinux/master
Sync
2017-10-23 14:42:19 -05:00
Blaž Bregar
2ee0e49a8b Added Slovene 2017-10-22 18:06:49 +02:00
Blaž Bregar
1176539b62 Merge branch 'master' of https://github.com/savoirfairelinux/num2words
Conflicts:
	num2words/__init__.py
2017-10-22 15:59:04 +02:00
Blaž Bregar
5d7697a85e resolved merge 2017-10-22 15:50:55 +02:00
Marc Ducobu
2f3acee36f lang_DK do not depends on num2words 2017-10-19 11:57:37 +02:00
Ernesto Rodriguez Ortiz
49a39fc253 Allow call to other convertes as to_currency, to_year
There are at least to issues related with questions about how to use other convertes.
This changes should allow the use of this converters
2017-09-29 15:29:25 -04:00
Ernesto Rodriguez Ortiz
659920c881 Merge pull request #91 from olix20/master
Added support for Dutch language (NL)
2017-09-20 09:14:28 -04:00
Armin Oliya
d96175b58e Merge branch 'master' into master 2017-09-20 14:35:27 +02:00
Ernesto Rodriguez Ortiz
f1838bf2de Merge pull request #93 from Sergeyzhol/master
Add Ukrainian language
2017-09-19 12:59:15 -04:00
Armin Oliya
aca6256a1f Merge branch 'master' into master 2017-09-12 00:57:01 +02:00
Sergio Zholudov
28f3d3bcff update uk_test (utf-8 issue resolved) 2017-09-11 15:05:11 +03:00
Sergio Zholudov
23b1961fe5 updated test_uk 2017-09-11 14:32:16 +03:00
Sergio Zholudov
865a311437 Ukrainian language test update 2017-09-11 13:48:18 +03:00
Sergio Zholudov
71419ffa0e update lang_uk.py 2017-09-11 13:43:39 +03:00
Sergio Zholudov
88eb77c927 update test_uk.py 2017-09-11 13:40:56 +03:00
Sergio Zholudov
b93c716597 update test_uk 2017-09-11 13:38:00 +03:00
Sergio Zholudov
279b63ed50 update test_uk 2017-09-11 13:01:59 +03:00
Sergio Zholudov
90b85a366c Tests Ukrainian language 2017-09-11 12:43:30 +03:00
Armin
4b58b1ee25 updated readme 2017-09-08 19:29:37 +02:00
Armin
7fe315eb64 fixed bug with 12 and 11 2017-09-08 17:54:25 +02:00
Armin
63fe589b98 fixed test bug 2017-09-08 17:47:23 +02:00
Armin
294d350fb9 added NL test cases 2017-09-08 17:42:30 +02:00
Sergio Zholudov
1d580f1be7 Updated README.rst, added Ukrainian 2017-09-08 17:47:42 +03:00
Sergio Zholudov
8b12fa7dc3 Updated __init__.py, added Ukrainian 2017-09-08 17:44:27 +03:00
Sergio Zholudov
77df034a70 Ukrainian language 2017-09-08 17:37:38 +03:00
Ernesto Rodriguez Ortiz
18f906dc48 Merge pull request #89 from Framras/master
readme corrected
2017-09-08 09:29:32 -04:00
Armin
d7378f310e Merge branch 'master' of https://github.com/olix20/num2words 2017-09-08 13:40:51 +02:00
Armin
4047d6526a added support for Dutch (NL) language 2017-09-08 13:17:14 +02:00
Tufan Kaynak
a9546c608b readme corrected 2017-09-07 09:39:20 +03:00
Ernesto Rodriguez Ortiz
6dc3686116 Merge pull request #88 from piranna/master
Added reference to `fr_DZ` locale on readme & clean-up
2017-09-06 22:02:26 -04:00
Jesús Leganés-Combarro
49b9db4e56 Merge branch 'master' into master 2017-09-06 23:01:34 +02:00
Jesús Leganés-Combarro 'piranna
fc05dcdd2a Added reference to fr_DZ locale on readme & clean-up 2017-09-06 22:59:20 +02:00
Ernesto Rodriguez Ortiz
757daaa222 Merge pull request #87 from Framras/master
README update
2017-09-06 16:46:30 -04:00
Ernesto Rodriguez Ortiz
301b7ff075 Merge pull request #86 from piranna/master
Add `fr_DZ` locale
2017-09-06 16:45:43 -04:00
Tufan Kaynak
849b55d95c README update 2017-09-06 14:37:28 +03:00
Jesús Leganés-Combarro 'piranna
97e1464550 Minor fix to make code Python 3 compatible 2017-09-06 09:13:14 +02:00
Ernesto Rodriguez Ortiz
c9e22ad45a Merge pull request #85 from Framras/master
Turkish language added to list on Readme
2017-09-05 20:39:05 -04:00
Jesús Leganés-Combarro 'piranna
614255bbde Add fr_DZ locale 2017-09-05 22:43:21 +02:00
Jesús Leganés-Combarro 'piranna
8ecd10f055 [fix] Allow to pass floats to Num2Word_Base.to_splitnum() 2017-09-05 22:42:45 +02:00
Jesús Leganés-Combarro 'piranna
29d9d2a336 Converted tabs indention to spaces 2017-09-05 22:36:37 +02:00
Tufan Kaynak
3e95697b08 Turkish language added to list 2017-09-05 21:50:43 +03:00
Jesús Leganés-Combarro 'piranna
873a3cc840 Use lang_FR as base class for lang_FR_CH & clean-up linting for french 2017-09-05 17:35:30 +02:00
Ernesto Rodriguez Ortiz
e6b2dbc4b9 Merge pull request #84 from Framras/master
Add Turkish language support.
2017-09-05 08:44:23 -04:00
Tufan Kaynak
935d95a87f removed ineffective splitnum function 2017-09-05 14:53:42 +03:00
Tufan Kaynak
c3cec93c4d correction of 0.0n reading 2017-09-05 14:50:32 +03:00
Tufan Kaynak
5ff8e343a0 unused elements stripped 2017-09-05 08:10:42 +03:00
Tufan Kaynak
bdc9b8e8ea remove the last comma in dictionary 2017-09-04 23:11:39 +03:00
Tufan Kaynak
a235058ba6 refactoring data elements 2017-09-02 14:22:50 +03:00
Tufan Kaynak
969c5daf9b var names changed to English 2017-09-01 00:46:23 +03:00
Tufan Kaynak
a659e63eb5 TR translation
TR translation of num2word reading all cardinals and ordinals up to 10**21-1
2017-08-30 19:36:29 +03:00
Ernesto Rodriguez Ortiz
39356b495d v0.5.5 2017-07-02 19:39:09 -04:00
Ernesto Rodriguez Ortiz
d41b1b6b07 Merge pull request #72 from dalwadani/master
Support Arabic
2017-06-28 15:46:56 -04:00
Dhaifallah Alwadani
21db1b32c3 Set currencies and fix strings 2017-06-28 16:33:17 +03:00
Dhaifallah Alwadani
7f3f65d9f4 Add arabic tests 2017-06-22 23:49:07 +03:00
Dhaifallah Alwadani
6c3e75d4c8 fix missing words 2017-06-22 23:48:44 +03:00
Dhaifallah Alwadani
eea901734a fix encoding 2017-06-22 23:22:33 +03:00
Dhaifallah Alwadani
7921560514 Add arabic to README 2017-06-21 22:22:27 +03:00
Dhaifallah Alwadani
f423a9398f add support for Arabic 2017-06-21 22:20:22 +03:00
Ernesto Rodriguez Ortiz
eb465df78a Merge pull request #67 from 10537/master
[IMP]Adds es_CO and es_VE support.
2017-04-27 12:41:06 -04:00
Ernesto Rodriguez Ortiz
48c25da767 Merge pull request #68 from cclauss/patch-1
classifiers=CLASSIFIERS
2017-04-14 14:17:01 -04:00
cclauss
dd1a3f09a3 classifiers=CLASSIFIERS,
This will populate the lower left of https://pypi.org/project/num2words
2017-04-12 21:20:37 +02:00
José Moreno
bccd3c0508 [MERGE]Conflicts resolved. 2017-04-04 10:48:09 -05:00
Ernesto Rodriguez Ortiz
b77414053b Merge pull request #62 from dazre/master
fixed some spelling problems for Russian
2017-04-04 10:42:06 -04:00
dazre
4225663bd2 Merge branch 'master' into master 2017-04-04 17:34:26 +03:00
dazre
e226cf7d73 add test 2017-04-04 17:32:55 +03:00
Ernesto Rodriguez Ortiz
caa8903599 Merge pull request #61 from anothingguy/master
[ADD] support VietNam
2017-04-03 18:04:45 -04:00
Ernesto Rodriguez Ortiz
9028a5e90b Made to_ordinal() implementation python3 compatible for lang es
Ref: issue # 10537
2017-04-03 17:43:07 -04:00
Ernesto Rodriguez Ortiz
76fd9d905f Fix the tests after the changes proposed by @10537
Ref: issuer # 10537
2017-04-03 17:29:03 -04:00
Diep Huu Hoang
c200d97bd7 [IMP] Improve convert number method and add unittest for Vietnam lang 2017-04-01 12:39:26 +07:00
Ernesto Rodriguez Ortiz
dac18f8928 Merge branch 'master' of git://github.com/10537/num2words into 10537-master 2017-03-31 17:49:24 -04:00
José Moreno
fb2911deea [FIX]Fixed typo errors and PEP8 errors.
[DEL]Deleted test_case currency.
2017-03-31 10:53:55 -05:00
José Moreno
afcaff8100 [IMP] Adds a better test cases. 2017-03-31 10:38:39 -05:00
José Moreno
19d0a903ab [IMP] Adds test files for es, es_co and es_ve. 2017-03-31 10:15:53 -05:00
José Moreno
91f3dc6854 [IMP]Adds new languages in init file. 2017-03-30 14:59:48 -05:00
dazre
ba8db25898 add leading Ones
It's more more correctly in Russian:
num2words(1135, lang='ru') -> одна тысяча сто тридцать пять
num2words(1000139, lang='ru') -> один миллион сто тридцать девять
2017-03-30 15:37:42 +03:00
dazre
321dfd3bca remove middle THOUSANDS in case of zero digits
Error:
num2words(1000139, lang='ru') -> миллион *тысяч* сто тридцать девять
Fix:
num2words(1000139, lang='ru') -> миллион сто тридцать девять
2017-03-30 15:33:37 +03:00
José Moreno
02b73fd444 [IMP]Deleted unnecessary super return. 2017-03-27 10:30:13 -05:00
José Moreno
aff876c4a6 [IMP]Reworked the files ES_CO and ES_VE. 2017-03-27 10:23:34 -05:00
Diep Huu Hoang
c2148d15ef [ADD] support VietNam 2017-03-19 22:41:41 +07:00
Filippo Costa
90e7c9dc7d Improvements, corrections, and bug fixes for the lang_IT module. (#59)
* General refactoring and bug fixes for lang_IT

* Added Python3 support for lang_IT

* Bug fixes for ordinal numerals in lang_IT

* Fixed lang_IT for negative values and added tests

* Fixes and minor adjustments for floats in lang_IT

* Decimal => float in tests for lang_IT

* Moved a comment

* 'tre's accentuated, big numbers support, ordinal bug fix, comments, tests

* 'meno' and 'virgola' and now class values

* Destroyed EU inheritance
2017-03-17 09:12:44 -04:00
José Moreno
b0bca26924 [IMP]Adds new files for ES_CO and ES_VE. 2017-03-16 16:33:33 -05:00
José Moreno
905faa20fc [IMP]Adds new files for ES_CO and ES_VE. 2017-03-16 16:31:43 -05:00
Ernesto Rodriguez Ortiz
907ebbc812 Update README.rst to show TravisCI build status. 2017-02-27 16:05:21 -05:00
Ernesto Rodriguez Ortiz
710a3b60c1 Merge pull request #58 from kszys/master
Fixed issues with wrong text for currency in Polish language
2017-02-27 15:58:59 -05:00
Krzysztof Socha
7fdb61351b Cleaned-up whitespaces around operators 2017-02-27 21:57:11 +01:00
Krzysztof Socha
4d5a114cf3 Fixed integer division operator (/->//) to work also in python3 2017-02-27 21:44:43 +01:00
Krzysztof Socha
1667511ff3 Merge remote-tracking branch 'upstream/master' 2017-02-27 18:14:11 +01:00
Krzysztof Socha
c459d9ba82 Cleaned-up some test files 2017-02-27 17:23:52 +01:00
Krzysztof Socha
94d4e85992 Cleaned-up some test files 2017-02-27 17:22:31 +01:00
Krzysztof Socha
d586f620c5 Added unit tests for Polish language 2017-02-27 17:18:06 +01:00
Krzysztof Socha
f67d641968 Fixed issues with wrong text for currency conversion with whole 10s (e.g., 123.50) 2017-02-25 22:44:27 +01:00
Virgil Dupras
f29e792757 Merge pull request #57 from savoirfairelinux/show-build-status
Show the TravisCI build status in the project page.
2017-02-02 12:16:14 -05:00
Ernesto Rodriguez Ortiz
fb281568b2 Show the TravisCI build status in the project page. 2017-02-01 15:01:53 -05:00
Virgil Dupras
8468654d86 tox.ini: add py35 and py36 envs 2017-02-01 10:32:10 -05:00
Virgil Dupras
0f21d8f825 README: Add Italian to the list of supported languages 2017-02-01 10:31:41 -05:00
Virgil Dupras
903a69cfa9 Merge pull request #56 from anb/master
Italian support
2017-02-01 10:30:05 -05:00
Brett Anthoine
0b80fd4285 Use in operator instead of has_key for python3 support 2017-02-01 16:13:24 +01:00
Brett Anthoine
58a4e8e18b Fix syntax error 2017-02-01 08:49:34 +01:00
Virgil Dupras
08e9154366 Add travis config 2017-01-18 11:15:03 -05:00
Brett Anthoine
bd1f4faf1d Update license header 2017-01-10 14:39:09 +01:00
Brett Anthoine
c9ecd07cbf Add italian ordinals. 2016-12-29 16:16:45 +01:00
Brett Anthoine
08779b28b2 Add support for italian. 2016-12-29 16:16:45 +01:00
Virgil Dupras
f7f1ba4583 Fix python3 syntax in lang_HE 2016-11-22 10:29:51 -05:00
Noah Santacruz
182b82cf1f Added Hebrew ordinal numbers #54
Squashed commit of the following:

commit 88b946ef72928e859d078f3febaf9c76ce0849b9
Merge: bca0277 79ab811
Author: Noah Santacruz <noahssantacruz@gmail.com>
Date:   Tue Nov 22 09:41:05 2016 +0200

    merge

commit bca0277424c074af217df5e86abfd2def3a30bc7
Author: Noah Santacruz <noahssantacruz@gmail.com>
Date:   Tue Nov 22 09:40:03 2016 +0200

    removed out.txt

commit 79ab811e97fd14bc5899174b198e86f5c6ba2c5f
Author: Noah Santacruz <noahssantacruz@gmail.com>
Date:   Mon Nov 21 18:09:42 2016 +0200

    Update README.rst

commit 507e4d4cec5b5458b2546ebebe5e49d376b88646
Author: Noah Santacruz <noahssantacruz@gmail.com>
Date:   Mon Nov 21 18:08:39 2016 +0200

    updated init

commit 7d3aa5ab33d92b0b374ed1bfbf17807836e465bf
Author: Noah Santacruz <noahssantacruz@gmail.com>
Date:   Mon Nov 21 16:05:06 2016 +0200

    changed init

commit 29b4c54047ff9ab84b4c95e9ff05ebcb12c15f49
Author: Noah Santacruz <noahssantacruz@gmail.com>
Date:   Mon Nov 21 16:01:17 2016 +0200

    added Hebrew
2016-11-22 10:29:28 -05:00
Virgil Dupras
20f634028d Convert to single codebase for py2 and py3
No more 2to3. Also, added tox config for easy cross-python testing.
2016-11-22 09:13:18 -05:00
Virgil Dupras
0e06eb81dd v0.5.4 2016-10-18 09:46:11 -04:00
Virgil Dupras
572789ac87 Merge pull request #52 from alpo/lt-euro
add actual Lithuanian currency (euro since 1 January 2015)
2016-10-18 09:35:00 -04:00
Virgil Dupras
4f3891abca Merge pull request #49 from paintdog/patch-1
Translation of error messages
2016-10-18 09:32:07 -04:00
Alexey Porotnikov
2207226873 add actual Lithuanian currency (euro since 1 January 2015) 2016-09-13 10:05:43 +03:00
mr
273349a234 Translation of error messages
See https://github.com/savoirfairelinux/num2words/pull/45
2016-08-15 13:09:18 +02:00
Virgil Dupras
02bb4bcf13 Merge pull request #27 from isnani/master
correction on lang_DE: ordnum, plural and ord form of >= 10**6
2016-08-10 13:21:57 -04:00
Virgil Dupras
2d18b40150 Merge pull request #47 from akretion/pt_BR-change_point_to_comma
In Brazilian Portuguese the decimal sign is comma ','
2016-08-10 13:17:51 -04:00
Virgil Dupras
85d3c99ce5 Merge pull request #48 from AntonKorobkov/ru_negative
added support for negative integers for Russian language
2016-08-10 13:15:33 -04:00
Virgil Dupras
0192259a0a Merge pull request #46 from AntonKorobkov/ru_test
Tested RU
2016-08-10 13:12:57 -04:00
AntonKorobkov
f98341731e added support for negative integers for Russian language 2016-08-10 18:06:46 +03:00
Magno Costa - Akretion
4e5c07522c In Brazilian Portuguese the decimal sign is comma ',' instead of dot '.'. Ex.: we use 1,01 instead of 1.01 2016-08-09 18:30:46 -03:00
AntonKorobkov
a63cee01da floating point numbers test added 2016-08-07 20:28:14 +03:00
AntonKorobkov
3cafa38ddb added Russian language test with some basic coverage 2016-08-04 18:47:13 +03:00
Ernesto Rodriguez Ortiz
f967e09877 Merge branch 'filwaitman-language_pt_BR' 2016-03-31 14:26:58 -04:00
Ernesto Rodriguez Ortiz
89ca2b7e8c Merge branch 'language_pt_BR' of https://github.com/filwaitman/num2words into filwaitman-language_pt_BR 2016-03-31 14:26:22 -04:00
Ernesto Rodriguez Ortiz
266fb9d2df Fix regression added in the PR Iss24. 2016-03-31 14:18:29 -04:00
Virgil Dupras
071ad5177b Merge PR #40 2016-03-31 11:04:47 -04:00
Virgil Dupras
f22b5d1ad7 Merge https://github.com/orjanv/num2words into master 2016-03-31 10:24:48 -04:00
isnani
d3d0af3040 add indonesian ('id') 2016-03-31 10:11:04 -04:00
alexpantyukhin
b9b6a8de42 add ru lang into supported languages 2016-03-31 09:29:05 -04:00
mdc
b1bbe109fc Corrected for special cases of currency and year 2016-03-21 16:11:54 +01:00
mdc
8fff34e318 Added og to hundreds, and a lot of other adjustments in the merge algorithm 2016-03-21 14:16:06 +01:00
mdc
cce1455846 Added the German algorithms, and begun adjusting them. 2016-03-21 11:09:30 +01:00
mdc
51d34ce78e Added functions that need to be overriden to lang_DK, created TODO's, added lang_DK to __init__ and added documentation to README 2016-03-19 22:21:14 +01:00
Ernesto Rodriguez Ortiz
eacf57fd26 Merge branch 'anb-master' 2016-03-18 16:22:16 -04:00
Ernesto Rodriguez Ortiz
023187b3cf Merge branch 'master' of https://github.com/anb/num2words into anb-master 2016-03-18 16:21:58 -04:00
Ernesto Rodriguez Ortiz
9baf1b9de4 Merge branch 'isnani-iss24' 2016-03-18 15:55:58 -04:00
Ernesto Rodriguez Ortiz
995c153d47 Merge branch 'iss24' of https://github.com/isnani/num2words into isnani-iss24 2016-03-18 15:55:25 -04:00
Ernesto Rodriguez Ortiz
06b3c0ee2e Merge pull request #35 from Michael-Reschke/patch-1
Update README.rst
2016-03-18 11:05:21 -04:00
Brett Anthoine
e8bcc0ef2d Add Swiss-French variants of numbers between 60 and 100. 2016-03-18 15:52:30 +01:00
Filipe Waitman
17cf62729e Update README.rst 2016-02-27 12:36:33 -03:00
Filipe Waitman
eeadcc7d5b Add support to pt_BR language 2016-02-26 23:13:40 -03:00
Michael Reschke
3d1b8ae42c Update README.rst 2016-02-24 19:14:22 +01:00
isnani
073925b1d4 address issue 24: floating point spelling 2016-01-13 16:06:16 +01:00
Ørjan Vøllestad
1589d9bb79 added norwegian support 2016-01-11 19:35:11 +01:00
Ørjan Vøllestad
01b87602c8 added norwegian support 2016-01-11 19:33:22 +01:00
isnani
9d99647e17 remove unnecessary self.ordflag 2015-12-14 08:40:32 +01:00
isnani
41a97d6931 add tests for lang_DE 2015-12-14 08:26:08 +01:00
isnani
797e74d1fc correction on lang_DE: ordnum, plural and ord form of >= 10**6 2015-12-12 16:54:30 +01:00
Virgil Dupras
848f9d26b1 Merge pull request #25 from anb/master
Fix typo for 18 in german.
2015-10-30 08:45:57 -04:00
Brett Anthoine
fc5c0dbdde Fix typo for 18 in german. 2015-10-29 16:11:58 +01:00
David Cormier
f5fc17917c Add polish to the list of supported languages 2015-07-07 13:40:05 -04:00
David Cormier
c210611e79 Merge pull request #23 from kszys/master
Added Polish language support
2015-07-07 13:38:02 -04:00
kszys
da74847df1 Added missing import of land_PL 2015-07-06 17:32:13 +02:00
kszys
f0418a3da5 Added the actual file for Polish language conversion 2015-07-05 11:59:11 +02:00
kszys
97a175b212 Added Polish language conversion 2015-07-05 11:52:13 +02:00
Blaž Bregar
b796aab4eb Added Slovenščina (sl_SI) 2015-06-20 20:21:37 +02:00
Blaž Bregar
f030d7ec69 Slovenščina 2015-06-20 20:18:26 +02:00
Virgil Dupras
65280cd61f v0.5.3 2015-06-09 14:49:01 -04:00
Virgil Dupras
732ead22b9 Include license is PyPI package
fixes #21
2015-06-09 14:47:33 -04:00
Virgil Dupras
cecf3954b1 Don't include test folder in installed packages
Otherwise, we end up with a `tests` folder polluting site-packages!

fixes #22
2015-06-09 12:06:46 -04:00
Virgil Dupras
f64a6e48be Mention tests in README 2015-04-06 15:11:59 -04:00
Virgil Dupras
fdeb061eca Fix 5 and 9 ordinals in french
fixes #18
2015-04-06 15:07:39 -04:00
Virgil Dupras
90cce9a0eb Merge pull request #17 from stefanw/patch-1
Fix spelling error of German number tausend (1000)
2015-02-04 13:39:34 -05:00
Stefan Wehrmeyer
08760cf4d6 Fix spelling error of German number tausend 2015-02-04 19:14:08 +01:00
Virgil Dupras
486f5415af v0.5.2 2015-01-23 12:21:33 -05:00
Virgil Dupras
4b35f533da Merge pull request #14 from frappe/master
Add Indian locale
2015-01-22 15:59:00 -05:00
Virgil Dupras
4c53549959 Merge pull request #13 from cesarizu/master
Updated spanish translations
2015-01-22 15:57:10 -05:00
Pratik Vyas
904c3c7e1b Add Indian locale 2015-01-22 20:05:30 +05:30
César Izurieta
3bc43a190d Updated spanish translations 2015-01-21 13:44:31 -02:00
Virgil Dupras
a1802b59bc Merge pull request #12 from marltu/master
Made lithuanian language more formal
2014-10-22 15:03:35 -04:00
Marius Grigaitis
4b779b830f python3 support for tests 2014-10-22 15:23:53 +03:00
Marius Grigaitis
b4e00ea5b5 Made lithuanian language more formal 2014-10-22 15:03:56 +03:00
Carlos Blanco
567f293aa3 In Spanish, the number 100000 should be "Cien mil" and not "Ceinto mil" 2014-08-12 12:53:34 -04:00
Virgil Dupras
a52b9b7ad5 Reformatted the list of supported languages 2014-06-02 12:48:23 -04:00
Virgil Dupras
fa93e45ce5 Added "lv" to the list of supported languages in the README 2014-06-02 11:41:38 -04:00
Virgil Dupras
b87197e3d9 Added Latvian to the list of supported languages 2014-06-02 11:33:04 -04:00
Artis Avotins
5e0a6b3f5c Added latvian translation 2014-06-02 13:56:20 +03:00
Virgil Dupras
539de2fd6e Added changelog to PyPI description 2014-03-14 10:57:06 -04:00
116 changed files with 25407 additions and 732 deletions

5
.coveragerc Normal file
View File

@@ -0,0 +1,5 @@
[run]
branch = true
source =
num2words
tests

45
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,45 @@
name: CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.6, 3.7, 3.8, 3.9, '3.10']
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install tox tox-gh-actions coveralls
pip install -r requirements-test.txt
- name: Test with tox
run: |
tox
- name: Upload coverage data to coveralls.io
run: coveralls --service=github
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COVERALLS_FLAG_NAME: ${{ matrix.python-version }}
COVERALLS_PARALLEL: true
coveralls:
name: Indicate completion to coveralls.io
needs: build
runs-on: ubuntu-latest
container: python:3-slim
steps:
- name: Finished
run: |
pip3 install --upgrade coveralls
coveralls --service=github --finish
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

5
.gitignore vendored
View File

@@ -1,4 +1,7 @@
*.pyc *.pyc
build build
dist dist
*.egg-info .idea/
*.egg-info
/.tox
.eggs/

View File

@@ -1,6 +1,153 @@
Changelog Changelog
========= =========
Version 0.5.12 -- 2022/08/19
----------------------------
* Support Japanese Reiwa (令和/れいわ) era. (#412)
* Add basic farsi support (#354)
* Added Tajik language support (#406)
* Fix Amharic language support (#465)
* Fix Hebrew pluralize and implement to_currency (#330)
* Add support to translate some currencies in italian language (#434)
* Fix Polish twenties (#345)
* Add uzs for ru and en (#422)
* Added support for Esperanto numbers. (#387)
* [ADD] to ordinal number for Turkish (#468)
* Fix zeroth in Dutch to nulde fixing (#326)
Version 0.5.11 -- 2022/08/03
----------------------------
* Add KZT and UAH currencies to lang RU (#264)
* Add es_NI currency (#276)
* Update .gitignore to add .eggs/ directory (#280)
* Fix Hebrew support (#289)
* Update test_tr.py to increase coverage (#298)
* Add ordinal 12,345 to ES test suite to increase coverage (#287)
* Add simple tests for lang_DK.py (#286)
* Add testcase for lang_EN.py (#288)
* Add more tests to base.py (#283)
* Fixed misspelling of 21 (cardinal and ordinal number) in IT language (#270)
* Romanian issues 259 (#260)
* Adding Language Support for Telugu / Bug Fix in Kannada (#263)
* Add support of Kazakh language (KZ) (#306)
* Update README.rst (#307)
* Added support for Hungarian language (#310)
* [UPD] Readme file (#363)
* [ADD] num2words: add traslation to spanish of several currencies (#356)
* added swedish language including test cases (#352)
* Remove dupplicated line in lang_PT_BR (#355)
* Fix ordinal_num output for Dutch (NL) (#369)
* Polishordinals (#367)
* [tr] return Turkish 0 ordinal and cardinal (#347)
* Improve Ukrainian support and minor fixes in CZ, KZ, LT, LV, PL, RU, SR languages (#400)
* feat: ci: replace travis by github workflows (#448)
* [ES] Added missing accents ("dieciséis", "dólar", "dólares", "veintiún"), improved currency gender handling, fixed pound cent names (#443)
Version 0.5.10 -- 2019/05/12
----------------------------
* Add Kannada language localization (#243)
* Revert some copyrights changed by mistake (#254)
* Add indian rupee to the supported currencies (#248)
* Improve currency functions for German and French (#247)
* Improve Slovene localization (#246)
* Improve Spanish localization (#240)
* Fix typo 'seperator' on source code (#238)
* Convert string to decimal values (#223)
* Improve German localization and test coverage (#237)
* Improve Polish localization (#233)
* Fix ordinal number for French ending on 1 (#236)
Version 0.5.9 -- 2019/01/10
---------------------------
* Fix encoding issue on release 0.5.8 (#229)
* Improve Polish localization (#228)
Version 0.5.8 -- 2018/11/17
---------------------------
* Add Portuguese (Portugal) localization (#198)
* Add a command line tool to use num2words
* Use language iso code for Vietnamese
* Improve Korean localization (#219)
* Improve Serbian (Latin) localization (#207)
* Improve testing setup (#220)
* Improve German localization (#214) (#222)
* Improve Romanian localization (#215)
* Improve Spanish localization (#187) (#200)
* Improve Russian localization (#211) (#212)
* Improve French localization (23902ab)
* Improve Arabic localization (#176)
* Improve Lithuanian and Latvian localization (#185)
* Improve Ukrainian localization (#183)
Version 0.5.7 -- 2018/06/27
---------------------------
* Add Finnish localization. (#170)
* Add Japanese localization. (#171)
* Add belgian-french localization. (#151)
* Add Czech localization. (#154)
* Add Thai localization. (#139)
* Improve English localization. (#144)
* Improve Spanish localization. (#167)
* Improve Italian localization. (#143)
* Improve documentation. (#155, #145, #174)
Version 0.5.6 -- 2017/11/22
---------------------------
* Refactor to_currency (#135)
* Allow the use of other convertes to_currency, to_year (#95)
* Fix code to respect PEP8 (#98, #105)
* Add Slovene localization (#97)
* Add Ukrainian localization (#93)
* Add Dutch localization (#91)
* Add Algeria-French localization (#86)
* Add Turkish localization (#85)
Version 0.5.5 -- 2017/07/02
---------------------------
* Add Arabic localization (#72)
* Add Spanish-Colombian and Spanish-Venezuelan localization (#67)
* Add VietNam localization (#61)
* Add Italian localization (#56, #59)
* Improve Russian localization (#62)
* Improve Polish localization (#58)
Version 0.5.4 -- 2016/10/18
---------------------------
* Tons of new languages!
* Add Polish localization. (#23)
* Add Swiss-French localization. (#38)
* Add Russian localization. (#28, #46, #48)
* Add Indonesian localization. (#29)
* Add Norwegian localization. (#33)
* Add Danish localization. (#40)
* Add Brazilian localization. (#37, #47)
* Improve German localization. (#25, #27, #49)
* Improve Lithuanian localization. (#52)
* Improve floating point spelling. (#24)
Version 0.5.3 -- 2015/06/09
---------------------------
* Fix packaging issues. (#21, #22)
Version 0.5.2 -- 2015/01/23
---------------------------
* Added Latvian localization. (#9)
* Improved Spanish localization. (#10, #13, #14)
* Improved Lithuanian localization. (#12)
Version 0.5.1 -- 2014/03/14 Version 0.5.1 -- 2014/03/14
--------------------------- ---------------------------

46
CODE_OF_CONDUCT.md Normal file
View File

@@ -0,0 +1,46 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at support@savoirfairelinux.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/

53
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,53 @@
## How can I contribute ?
### Code contribution
#### Issues
If you are unsure where to begin contribution to Num2Words, you can start by looking through the issues page.
Numerous issues are created and waiting for your love on the [issue board](https://github.com/savoirfairelinux/num2words/issues).
#### Pull Requests
Contributions will be accepted through the creation of Pull Requests. Here is the workflow:
* Fork the repository into yours and work from there
* Commit and push your changes into your fork
* When you are done, create a [Pull Request](https://github.com/savoirfairelinux/num2words/compare) on the **master** branch
A template is provided to create your Pull Request. Try to fill the information at the best of your knowledge.
#### Pull request checklist
For your pull request to be merged, the answer to the following questions must be 'yes':
##### General
* Can the branch be merged automatically?
##### Testing
* Do the unit tests pass?
##### Adding new code
* Is the code PEP8 compliant?
* Is the code covered by tests?
[TravisCI](https://travis-ci.org/) is configured to run those checks on every Pull-Request. It is recommended you configure your fork to do the same.
### Reporting bugs
Bugs are tracked as [GitHub issues](https://guides.github.com/features/issues/).
#### How to submit a good bug report
Please include as many details as possible. An issue template is automatically loaded when you create an issue.
* Use a clear and comprehensive title for the issue
* Describe the expected behaviour in as many details as possible
* Describe the actual behaviour in as many details as possible
### Testing the application
Our development process is based on Continuous Integration. We love to have a nice code coverage!

13
ISSUE_TEMPLATE.md Normal file
View File

@@ -0,0 +1,13 @@
### Expected Behaviour
Fill me in ...
### Actual Behaviour
Fill me in ...
### Steps to reproduce
* step 1
* step 2
* ...

View File

@@ -1 +1,4 @@
include CHANGES.rst include CHANGES.rst
include COPYING
include tests/*
include bin/num2words

21
PULL_REQUEST_TEMPLATE.md Normal file
View File

@@ -0,0 +1,21 @@
## Fixes # by...
### Changes proposed in this pull request:
* ...
* ...
### Status
- [ ] READY
- [ ] HOLD
- [X] WIP (Work-In-Progress)
### How to verify this change
*Fill out this section so that a reviewer can know how to verify your change.*
### Additional notes
*If applicable, explain the rationale behind your change.*

View File

@@ -1,11 +1,24 @@
num2words - Convert numbers to words in multiple languages num2words library - Convert numbers to words in multiple languages
========================================================== ==================================================================
``num2words`` is a library that converts numbers like ``42`` to words like ``forty-two``. It .. image:: https://img.shields.io/pypi/v/num2words.svg
supports multiple languages (English, French, Spanish, German and Lithuanian) and can even generate :target: https://pypi.python.org/pypi/num2words
ordinal numbers like ``forty-second`` (altough this last feature is a bit buggy at the moment).
The project is hosted on https://github.com/savoirfairelinux/num2words .. image:: https://travis-ci.org/savoirfairelinux/num2words.svg?branch=master
:target: https://travis-ci.org/savoirfairelinux/num2words
.. image:: https://coveralls.io/repos/github/savoirfairelinux/num2words/badge.svg?branch=master
:target: https://coveralls.io/github/savoirfairelinux/num2words?branch=master
``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).
The project is hosted on GitHub_. Contributions are welcome.
.. _GitHub: https://github.com/savoirfairelinux/num2words
Installation Installation
------------ ------------
@@ -18,26 +31,98 @@ Otherwise, you can download the source package and then execute::
python setup.py install python setup.py install
The test suite in this library is new, so it's rather thin, but it can be run with::
python setup.py test
To run the full CI test suite which includes linting and multiple python environments::
pip install tox
tox
Usage Usage
----- -----
Command line::
There's only one function to use:: $ num2words 10001
ten thousand and one
$ num2words 24,120.10
twenty-four thousand, one hundred and twenty point one
$ num2words 24,120.10 -l es
veinticuatro mil ciento veinte punto uno
$num2words 2.14 -l es --to currency
dos euros con catorce céntimos
In code there's only one function to use::
>>> from num2words import num2words >>> from num2words import num2words
>>> num2words(42) >>> num2words(42)
forty-two forty-two
>>> num2words(42, ordinal=True) >>> num2words(42, to='ordinal')
forty-second forty-second
>>> num2words(42, lang='fr') >>> num2words(42, lang='fr')
quarante-deux quarante-deux
Besides the numerical argument, there's two optional arguments. Besides the numerical argument, there are two main optional arguments.
**ordinal:** A boolean flag indicating to return an ordinal number instead of a cardinal one. **to:** The converter to use. Supported values are:
**lang:** The language in which to convert the number. Supported languages are ``en``, ``fr``, * ``cardinal`` (default)
``de``, ``es``, ``lt`` and ``en_GB``. You can supply values like ``fr_FR``, the code will be * ``ordinal``
correctly interpreted. If you supply an unsupported language, ``NotImplementedError`` is raised. * ``ordinal_num``
* ``year``
* ``currency``
**lang:** The language in which to convert the number. Supported values are:
* ``en`` (English, default)
* ``am`` (Amharic)
* ``ar`` (Arabic)
* ``cz`` (Czech)
* ``de`` (German)
* ``dk`` (Danish)
* ``en_GB`` (English - Great Britain)
* ``en_IN`` (English - India)
* ``es`` (Spanish)
* ``es_CO`` (Spanish - Colombia)
* ``es_VE`` (Spanish - Venezuela)
* ``eu`` (EURO)
* ``fa`` (Farsi)
* ``fi`` (Finnish)
* ``fr`` (French)
* ``fr_CH`` (French - Switzerland)
* ``fr_BE`` (French - Belgium)
* ``fr_DZ`` (French - Algeria)
* ``he`` (Hebrew)
* ``hu`` (Hungarian)
* ``id`` (Indonesian)
* ``it`` (Italian)
* ``ja`` (Japanese)
* ``kn`` (Kannada)
* ``ko`` (Korean)
* ``kz`` (Kazakh)
* ``lt`` (Lithuanian)
* ``lv`` (Latvian)
* ``no`` (Norwegian)
* ``pl`` (Polish)
* ``pt`` (Portuguese)
* ``pt_BR`` (Portuguese - Brazilian)
* ``sl`` (Slovene)
* ``sr`` (Serbian)
* ``sv`` (Swedish)
* ``ro`` (Romanian)
* ``ru`` (Russian)
* ``te`` (Telugu)
* ``tg`` (Tajik)
* ``tr`` (Turkish)
* ``th`` (Thai)
* ``vi`` (Vietnamese)
* ``nl`` (Dutch)
* ``uk`` (Ukrainian)
You can supply values like ``fr_FR``; if the country doesn't exist but the
language does, the code will fall back to the base language (i.e. ``fr``). If
you supply an unsupported language, ``NotImplementedError`` is raised.
Therefore, if you want to call ``num2words`` with a fallback, you can do:: Therefore, if you want to call ``num2words`` with a fallback, you can do::
try: try:
@@ -45,15 +130,25 @@ Therefore, if you want to call ``num2words`` with a fallback, you can do::
except NotImplementedError: except NotImplementedError:
return num2words(42, lang='en') return num2words(42, lang='en')
Additionally, some converters and languages support other optional arguments
that are needed to make the converter useful in practice.
Wiki
----
For additional information on some localization please check the Wiki_.
And feel free to propose wiki enhancement.
.. _Wiki: https://github.com/savoirfairelinux/num2words/wiki
History History
------- -------
``num2words`` is based on an old library , ``pynum2word`` created by Taro Ogawa in 2003. ``num2words`` is based on an old library, ``pynum2word``, created by Taro Ogawa
Unfortunately, the library stopped being maintained and the author can't be reached. There was in 2003. Unfortunately, the library stopped being maintained and the author
another developer, Marius Grigaitis, who in 2011 added Lithuanian support, but didn't take over can't be reached. There was another developer, Marius Grigaitis, who in 2011
maintenance of the project. added Lithuanian support, but didn't take over maintenance of the project.
I am thus basing myself on Marius Grigaitis' improvements and re-publishing ``pynum2word`` as I am thus basing myself on Marius Grigaitis' improvements and re-publishing
``num2words``. ``pynum2word`` as ``num2words``.
Virgil Dupras, Savoir-faire Linux Virgil Dupras, Savoir-faire Linux

95
bin/num2words Executable file
View File

@@ -0,0 +1,95 @@
#!/usr/bin/env python
# -*- coding: 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
"""num2words: convert numbers into words.
Usage:
num2words [options] <number>
num2words --list-languages
num2words --list-converters
num2words --help
Arguments:
<number> Number you want to convert into words
Options:
-L --list-languages Show all languages.
-C --list-converters Show all converters.
-l --lang=<lang> Output language [default: en].
-t --to=<to> Output converter [default: cardinal].
-h --help Show this message.
-v --version Show version.
Examples:
$ num2words 10001
ten thousand and one
$ num2words 24,120.10
twenty-four thousand, one hundred and twenty point one
$ num2words 24,120.10 -l es
veinticuatro mil ciento veinte punto uno
$num2words 2.14 -l es --to currency
dos euros con catorce céntimos
"""
from __future__ import print_function, unicode_literals
import os
import sys
from docopt import docopt
import num2words
__version__ = "0.5.12"
__license__ = "LGPL"
def get_languages():
return sorted(list(num2words.CONVERTER_CLASSES.keys()))
def get_converters():
return sorted(list(num2words.CONVERTES_TYPES))
def main():
version = "{}=={}".format(os.path.basename(__file__), __version__)
args = docopt(__doc__, argv=None, help=True, version=version, options_first=False)
if args["--list-languages"]:
for lang in get_languages():
sys.stdout.write(lang)
sys.stdout.write(os.linesep)
sys.exit(0)
if args["--list-converters"]:
for lang in get_converters():
sys.stdout.write(lang)
sys.stdout.write(os.linesep)
sys.exit(0)
try:
words = num2words.num2words(args['<number>'], lang=args['--lang'], to=args['--to'])
sys.stdout.write(words+os.linesep)
sys.exit(0)
except Exception as err:
sys.stderr.write(str(args['<number>']))
sys.stderr.write(str(err) + os.linesep)
sys.stderr.write(__doc__)
sys.exit(1)
if __name__ == '__main__':
main()

7
docker-compose.yml Normal file
View File

@@ -0,0 +1,7 @@
version: '3.0'
services:
web:
image: python:3-alpine
command: python3 -m http.server 8080
volumes:
- .:/num2words

View File

@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
@@ -16,23 +17,66 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from . import lang_EN from . import (lang_AM, lang_AR, lang_CZ, lang_DE, lang_DK, lang_EN,
from . import lang_EN_GB lang_EN_IN, lang_EO, lang_ES, lang_ES_CO, lang_ES_NI,
from . import lang_FR lang_ES_VE, lang_FA, lang_FI, lang_FR, lang_FR_BE, lang_FR_CH,
from . import lang_DE lang_FR_DZ, lang_HE, lang_HU, lang_ID, lang_IT, lang_JA,
from . import lang_ES lang_KN, lang_KO, lang_KZ, lang_LT, lang_LV, lang_NL, lang_NO,
from . import lang_LT lang_PL, lang_PT, lang_PT_BR, lang_RO, lang_RU, lang_SL,
lang_SR, lang_SV, lang_TE, lang_TG, lang_TH, lang_TR, lang_UK,
lang_VI)
CONVERTER_CLASSES = { CONVERTER_CLASSES = {
'am': lang_AM.Num2Word_AM(),
'ar': lang_AR.Num2Word_AR(),
'cz': lang_CZ.Num2Word_CZ(),
'en': lang_EN.Num2Word_EN(), 'en': lang_EN.Num2Word_EN(),
'en_GB': lang_EN_GB.Num2Word_EN_GB(), 'en_IN': lang_EN_IN.Num2Word_EN_IN(),
'fa': lang_FA.Num2Word_FA(),
'fr': lang_FR.Num2Word_FR(), 'fr': lang_FR.Num2Word_FR(),
'fr_CH': lang_FR_CH.Num2Word_FR_CH(),
'fr_BE': lang_FR_BE.Num2Word_FR_BE(),
'fr_DZ': lang_FR_DZ.Num2Word_FR_DZ(),
'de': lang_DE.Num2Word_DE(), 'de': lang_DE.Num2Word_DE(),
'fi': lang_FI.Num2Word_FI(),
'eo': lang_EO.Num2Word_EO(),
'es': lang_ES.Num2Word_ES(), 'es': lang_ES.Num2Word_ES(),
'es_CO': lang_ES_CO.Num2Word_ES_CO(),
'es_NI': lang_ES_NI.Num2Word_ES_NI(),
'es_VE': lang_ES_VE.Num2Word_ES_VE(),
'id': lang_ID.Num2Word_ID(),
'ja': lang_JA.Num2Word_JA(),
'kn': lang_KN.Num2Word_KN(),
'ko': lang_KO.Num2Word_KO(),
'kz': lang_KZ.Num2Word_KZ(),
'lt': lang_LT.Num2Word_LT(), 'lt': lang_LT.Num2Word_LT(),
'lv': lang_LV.Num2Word_LV(),
'pl': lang_PL.Num2Word_PL(),
'ro': lang_RO.Num2Word_RO(),
'ru': lang_RU.Num2Word_RU(),
'sl': lang_SL.Num2Word_SL(),
'sr': lang_SR.Num2Word_SR(),
'sv': lang_SV.Num2Word_SV(),
'no': lang_NO.Num2Word_NO(),
'dk': lang_DK.Num2Word_DK(),
'pt': lang_PT.Num2Word_PT(),
'pt_BR': lang_PT_BR.Num2Word_PT_BR(),
'he': lang_HE.Num2Word_HE(),
'it': lang_IT.Num2Word_IT(),
'vi': lang_VI.Num2Word_VI(),
'tg': lang_TG.Num2Word_TG(),
'th': lang_TH.Num2Word_TH(),
'tr': lang_TR.Num2Word_TR(),
'nl': lang_NL.Num2Word_NL(),
'uk': lang_UK.Num2Word_UK(),
'te': lang_TE.Num2Word_TE(),
'hu': lang_HU.Num2Word_HU()
} }
def num2words(number, ordinal=False, lang='en'): CONVERTES_TYPES = ['cardinal', 'ordinal', 'ordinal_num', 'year', 'currency']
def num2words(number, ordinal=False, lang='en', to='cardinal', **kwargs):
# We try the full language first # We try the full language first
if lang not in CONVERTER_CLASSES: if lang not in CONVERTER_CLASSES:
# ... and then try only the first 2 letters # ... and then try only the first 2 letters
@@ -40,7 +84,15 @@ def num2words(number, ordinal=False, lang='en'):
if lang not in CONVERTER_CLASSES: if lang not in CONVERTER_CLASSES:
raise NotImplementedError() raise NotImplementedError()
converter = CONVERTER_CLASSES[lang] converter = CONVERTER_CLASSES[lang]
if isinstance(number, str):
number = converter.str_to_number(number)
# backwards compatible
if ordinal: if ordinal:
return converter.to_ordinal(number) return converter.to_ordinal(number)
else:
return converter.to_cardinal(number) if to not in CONVERTES_TYPES:
raise NotImplementedError()
return getattr(converter, 'to_{}'.format(to))(number, **kwargs)

View File

@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
@@ -15,12 +16,20 @@
# MA 02110-1301 USA # MA 02110-1301 USA
from __future__ import unicode_literals from __future__ import unicode_literals
from .orderedmapping import OrderedMapping
import math
from collections import OrderedDict
from decimal import Decimal
from .compat import to_s
from .currency import parse_currency_parts, prefix_currency
class Num2Word_Base(object): class Num2Word_Base(object):
CURRENCY_FORMS = {}
CURRENCY_ADJECTIVES = {}
def __init__(self): def __init__(self):
self.cards = OrderedMapping()
self.is_title = False self.is_title = False
self.precision = 2 self.precision = 2
self.exclude_title = [] self.exclude_title = []
@@ -31,40 +40,36 @@ class Num2Word_Base(object):
self.errmsg_negord = "Cannot treat negative num %s as ordinal." self.errmsg_negord = "Cannot treat negative num %s as ordinal."
self.errmsg_toobig = "abs(%s) must be less than %s." self.errmsg_toobig = "abs(%s) must be less than %s."
self.base_setup()
self.setup() self.setup()
self.set_numwords()
self.MAXVAL = 1000 * self.cards.order[0] # uses cards
if any(hasattr(self, field) for field in
['high_numwords', 'mid_numwords', 'low_numwords']):
self.cards = OrderedDict()
self.set_numwords()
self.MAXVAL = 1000 * list(self.cards.keys())[0]
def set_numwords(self): def set_numwords(self):
self.set_high_numwords(self.high_numwords) self.set_high_numwords(self.high_numwords)
self.set_mid_numwords(self.mid_numwords) self.set_mid_numwords(self.mid_numwords)
self.set_low_numwords(self.low_numwords) self.set_low_numwords(self.low_numwords)
def set_high_numwords(self, *args):
def gen_high_numwords(self, units, tens, lows): raise NotImplementedError
out = [u + t for t in tens for u in units]
out.reverse()
return out + lows
def set_mid_numwords(self, mid): def set_mid_numwords(self, mid):
for key, val in mid: for key, val in mid:
self.cards[key] = val self.cards[key] = val
def set_low_numwords(self, numwords): def set_low_numwords(self, numwords):
for word, n in zip(numwords, range(len(numwords) - 1, -1, -1)): for word, n in zip(numwords, range(len(numwords) - 1, -1, -1)):
self.cards[n] = word self.cards[n] = word
def splitnum(self, value): def splitnum(self, value):
for elem in self.cards: for elem in self.cards:
if elem > value: if elem > value:
continue continue
out = [] out = []
if value == 0: if value == 0:
div, mod = 1, 0 div, mod = 1, 0
@@ -75,7 +80,7 @@ class Num2Word_Base(object):
out.append((self.cards[1], 1)) out.append((self.cards[1], 1))
else: else:
if div == value: # The system tallies, eg Roman Numerals if div == value: # The system tallies, eg Roman Numerals
return [(div * self.cards[elem], div*elem)] return [(div * self.cards[elem], div*elem)]
out.append(self.splitnum(div)) out.append(self.splitnum(div))
out.append((self.cards[elem], elem)) out.append((self.cards[elem], elem))
@@ -85,15 +90,22 @@ class Num2Word_Base(object):
return out return out
def parse_minus(self, num_str):
"""Detach minus and return it as symbol with new num_str."""
if num_str.startswith('-'):
# Extra spacing to compensate if there is no minus.
return '%s ' % self.negword, num_str[1:]
return '', num_str
def str_to_number(self, value):
return Decimal(value)
def to_cardinal(self, value): def to_cardinal(self, value):
try: try:
assert long(value) == value assert int(value) == value
except (ValueError, TypeError, AssertionError): except (ValueError, TypeError, AssertionError):
return self.to_cardinal_float(value) return self.to_cardinal_float(value)
self.verify_num(value)
out = "" out = ""
if value < 0: if value < 0:
value = abs(value) value = abs(value)
@@ -101,39 +113,53 @@ class Num2Word_Base(object):
if value >= self.MAXVAL: if value >= self.MAXVAL:
raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL)) raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL))
val = self.splitnum(value) val = self.splitnum(value)
words, num = self.clean(val) words, num = self.clean(val)
return self.title(out + words) return self.title(out + words)
def float2tuple(self, value):
pre = int(value)
# Simple way of finding decimal places to update the precision
self.precision = abs(Decimal(str(value)).as_tuple().exponent)
post = abs(value - pre) * 10**self.precision
if abs(round(post) - post) < 0.01:
# We generally floor all values beyond our precision (rather than
# rounding), but in cases where we have something like 1.239999999,
# which is probably due to python's handling of floats, we actually
# want to consider it as 1.24 instead of 1.23
post = int(round(post))
else:
post = int(math.floor(post))
return pre, post
def to_cardinal_float(self, value): def to_cardinal_float(self, value):
try: try:
float(value) == value float(value) == value
except (ValueError, TypeError, AssertionError): except (ValueError, TypeError, AssertionError, AttributeError):
raise TypeError(self.errmsg_nonnum % value) raise TypeError(self.errmsg_nonnum % value)
pre = int(value) pre, post = self.float2tuple(float(value))
post = abs(value - pre)
post = str(post)
post = '0' * (self.precision - len(post)) + post
out = [self.to_cardinal(pre)] out = [self.to_cardinal(pre)]
if self.precision: if self.precision:
out.append(self.title(self.pointword)) out.append(self.title(self.pointword))
for i in range(self.precision): for i in range(self.precision):
post *= 10 curr = int(post[i])
curr = int(post) out.append(to_s(self.to_cardinal(curr)))
out.append(str(self.to_cardinal(curr)))
post -= curr
return " ".join(out) return " ".join(out)
def merge(self, curr, next): def merge(self, curr, next):
raise NotImplementedError raise NotImplementedError
def clean(self, val): def clean(self, val):
out = val out = val
while len(val) != 1: while len(val) != 1:
@@ -155,7 +181,6 @@ class Num2Word_Base(object):
val = out val = out
return out[0] return out[0]
def title(self, value): def title(self, value):
if self.is_title: if self.is_title:
out = [] out = []
@@ -168,30 +193,18 @@ class Num2Word_Base(object):
value = " ".join(out) value = " ".join(out)
return value return value
def verify_ordinal(self, value): def verify_ordinal(self, value):
if not value == long(value): if not value == int(value):
raise TypeError, self.errmsg_floatord %(value) raise TypeError(self.errmsg_floatord % value)
if not abs(value) == value: if not abs(value) == value:
raise TypeError, self.errmsg_negord %(value) raise TypeError(self.errmsg_negord % value)
def to_ordinal(self, value):
def verify_num(self, value):
return 1
def set_wordnums(self):
pass
def to_ordinal(value):
return self.to_cardinal(value) return self.to_cardinal(value)
def to_ordinal_num(self, value): def to_ordinal_num(self, value):
return value return value
# Trivial version # Trivial version
def inflect(self, value, text): def inflect(self, value, text):
text = text.split("/") text = text.split("/")
@@ -199,15 +212,19 @@ class Num2Word_Base(object):
return text[0] return text[0]
return "".join(text) return "".join(text)
# //CHECK: generalise? Any others like pounds/shillings/pence?
#//CHECK: generalise? Any others like pounds/shillings/pence?
def to_splitnum(self, val, hightxt="", lowtxt="", jointxt="", def to_splitnum(self, val, hightxt="", lowtxt="", jointxt="",
divisor=100, longval=True, cents = True): divisor=100, longval=True, cents=True):
out = [] out = []
try:
high, low = val if isinstance(val, float):
except TypeError: high, low = self.float2tuple(val)
high, low = divmod(val, divisor) else:
try:
high, low = val
except TypeError:
high, low = divmod(val, divisor)
if high: if high:
hightxt = self.title(self.inflect(high, hightxt)) hightxt = self.title(self.inflect(high, hightxt))
out.append(self.to_cardinal(high)) out.append(self.to_cardinal(high))
@@ -219,6 +236,7 @@ class Num2Word_Base(object):
out.append(self.title(jointxt)) out.append(self.title(jointxt))
elif hightxt: elif hightxt:
out.append(hightxt) out.append(hightxt)
if low: if low:
if cents: if cents:
out.append(self.to_cardinal(low)) out.append(self.to_cardinal(low))
@@ -226,40 +244,67 @@ class Num2Word_Base(object):
out.append("%02d" % low) out.append("%02d" % low)
if lowtxt and longval: if lowtxt and longval:
out.append(self.title(self.inflect(low, lowtxt))) out.append(self.title(self.inflect(low, lowtxt)))
return " ".join(out)
return " ".join(out)
def to_year(self, value, **kwargs): def to_year(self, value, **kwargs):
return self.to_cardinal(value) return self.to_cardinal(value)
def pluralize(self, n, forms):
"""
Should resolve gettext form:
http://docs.translatehouse.org/projects/localization-guide/en/latest/l10n/pluralforms.html
"""
raise NotImplementedError
def to_currency(self, value, **kwargs): def _money_verbose(self, number, currency):
return self.to_cardinal(value) return self.to_cardinal(number)
def _cents_verbose(self, number, currency):
return self.to_cardinal(number)
def base_setup(self): def _cents_terse(self, number, currency):
pass return "%02d" % number
def to_currency(self, val, currency='EUR', cents=True, separator=',',
adjective=False):
"""
Args:
val: Numeric value
currency (str): Currency code
cents (bool): Verbose cents
separator (str): Cent separator
adjective (bool): Prefix currency name with adjective
Returns:
str: Formatted string
"""
left, right, is_negative = parse_currency_parts(val)
try:
cr1, cr2 = self.CURRENCY_FORMS[currency]
except KeyError:
raise NotImplementedError(
'Currency code "%s" not implemented for "%s"' %
(currency, self.__class__.__name__))
if adjective and currency in self.CURRENCY_ADJECTIVES:
cr1 = prefix_currency(self.CURRENCY_ADJECTIVES[currency], cr1)
minus_str = "%s " % self.negword if is_negative else ""
money_str = self._money_verbose(left, currency)
cents_str = self._cents_verbose(right, currency) \
if cents else self._cents_terse(right, currency)
return u'%s%s %s%s %s %s' % (
minus_str,
money_str,
self.pluralize(left, cr1),
separator,
cents_str,
self.pluralize(right, cr2)
)
def setup(self): def setup(self):
pass pass
def test(self, value):
try:
_card = self.to_cardinal(value)
except:
_card = "invalid"
try:
_ord = self.to_ordinal(value)
except:
_ord = "invalid"
try:
_ordnum = self.to_ordinal_num(value)
except:
_ordnum = "invalid"
print ("For %s, card is %s;\n\tord is %s; and\n\tordnum is %s." %
(value, _card, _ord, _ordnum))

View File

@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
@@ -14,22 +15,15 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA # MA 02110-1301 USA
class OrderedMapping(dict):
def __init__(self, *pairs):
self.order = []
for key, val in pairs:
self[key] = val
def __setitem__(self, key, val):
if key not in self:
self.order.append(key)
super(OrderedMapping, self).__setitem__(key, val)
def __iter__(self): try:
for item in self.order: strtype = basestring
yield item except NameError:
strtype = str
def __repr__(self):
out = ["%s: %s"%(repr(item), repr(self[item])) for item in self] def to_s(val):
out = ", ".join(out) try:
return "{%s}"%out return unicode(val)
except NameError:
return str(val)

50
num2words/currency.py Normal file
View File

@@ -0,0 +1,50 @@
# -*- coding: 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 division
from decimal import ROUND_HALF_UP, Decimal
def parse_currency_parts(value, is_int_with_cents=True):
if isinstance(value, int):
if is_int_with_cents:
# assume cents if value is integer
negative = value < 0
value = abs(value)
integer, cents = divmod(value, 100)
else:
negative = value < 0
integer, cents = abs(value), 0
else:
value = Decimal(value)
value = value.quantize(
Decimal('.01'),
rounding=ROUND_HALF_UP
)
negative = value < 0
value = abs(value)
integer, fraction = divmod(value, 1)
integer = int(integer)
cents = int(fraction * 100)
return integer, cents, negative
def prefix_currency(prefix, base):
return tuple("%s %s" % (prefix, i) for i in base)

129
num2words/lang_AM.py Normal file
View File

@@ -0,0 +1,129 @@
# -*- coding: 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 division, print_function, unicode_literals
from . import lang_EU
class Num2Word_AM(lang_EU.Num2Word_EU):
CURRENCY_FORMS = {'ETB': (('ብር', 'ብር'), ('ሳንቲም', 'ሳንቲም'))}
GIGA_SUFFIX = 'ቢሊዮን'
MEGA_SUFFIX = 'ሚሊዮን'
def set_high_numwords(self, high):
cap = 3 * (len(high) + 1)
for word, n in zip(high, range(cap, 5, -3)):
if n == 9:
self.cards[10 ** n] = word + self.GIGA_SUFFIX
else:
self.cards[10 ** n] = word + self.MEGA_SUFFIX
def setup(self):
super(Num2Word_AM, self).setup()
self.negword = 'አሉታዊ '
self.pointword = 'ነጥብ'
self.exclude_title = ['እና', 'ነጥብ', 'አሉታዊ']
self.mid_numwords = [(1000, 'ሺህ'), (100, 'መቶ'), (90, 'ዘጠና'),
(80, 'ሰማኒያ'), (70, 'ሰባ'), (60, 'ስድሳ'),
(50, 'አምሳ'), (40, 'አርባ'), (30, 'ሠላሳ')]
self.low_numwords = ['ሃያ', 'አሥራ ዘጠኝ', 'አሥራ ስምንት', 'አሥራ ሰባት',
'አስራ ስድስት', 'አሥራ አምስት', 'አሥራ አራት', 'አሥራ ሦስት',
'አሥራ ሁለት', 'አሥራ አንድ', 'አሥር', 'ዘጠኝ', 'ስምንት',
'ሰባት', 'ስድስት', 'አምስት', 'አራት', 'ሦስት', 'ሁለት',
'አንድ', 'ዜሮ']
self.ords = {'አንድ': 'አንደኛ',
'ሁለት': 'ሁለተኛ',
'ሦስት': 'ሦስተኛ',
'አራት': 'አራተኛ',
'አምስት': 'አምስተኛ',
'ስድስት': 'ስድስተኛ',
'ሰባት': 'ሰባተኛ',
'ስምንት': 'ስምንተኛ',
'ዘጠኝ': 'ዘጠነኛ',
'አሥር': 'አሥረኛ',
'አሥራ አንድ': 'አሥራ አንደኛ',
'አሥራ ሁለት': 'አሥራ ሁለተኛ',
'አሥራ ሦስት': 'አሥራ ሦስተኛ',
'አሥራ አራት': 'አሥራ አራተኛ',
'አሥራ አምስት': 'አሥራ አምስተኛ',
'አሥራ ስድስት': 'አሥራ ስድስተኛ',
'አሥራ ሰባት': 'አሥራ ሰባተኛ',
'አሥራ ስምንት': 'አሥራ ስምንተኛ',
'አሥራ ዘጠኝ': 'አሥራ ዘጠነኛ'}
def to_cardinal(self, value):
try:
assert int(value) == value
except (ValueError, TypeError, AssertionError):
return self.to_cardinal_float(value)
out = ''
if value >= self.MAXVAL:
raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL))
if value == 100:
return self.title(out + 'መቶ')
else:
val = self.splitnum(value)
words, num = self.clean(val)
return self.title(out + words)
def merge(self, lpair, rpair):
ltext, lnum = lpair
rtext, rnum = rpair
if lnum == 1 and rnum < 100:
return rtext, rnum
elif 100 > lnum > rnum:
return '%s %s' % (ltext, rtext), lnum + rnum
elif lnum >= 100 > rnum:
return '%s %s' % (ltext, rtext), lnum + rnum
elif rnum > lnum:
return '%s %s' % (ltext, rtext), lnum * rnum
def to_ordinal(self, value):
self.verify_ordinal(value)
outwords = self.to_cardinal(value).split(' ')
lastwords = outwords[-1].split('-')
lastword = lastwords[-1].lower()
try:
lastword = self.ords[lastword]
except KeyError:
lastword += ''
lastwords[-1] = self.title(lastword)
outwords[-1] = ' '.join(lastwords)
return ' '.join(outwords)
def to_ordinal_num(self, value):
self.verify_ordinal(value)
return '%s%s' % (value, self.to_ordinal(value)[-1:])
def to_currency(self, val, currency='ብር', cents=True, separator='',
adjective=True):
result = super(Num2Word_AM, self).to_currency(
val, currency=currency, cents=cents, separator=separator,
adjective=adjective)
return result
def to_year(self, val, longval=True):
if not (val // 100) % 10:
return self.to_cardinal(val)
return self.to_splitnum(val, hightxt='መቶ', longval=longval)

352
num2words/lang_AR.py Normal file
View File

@@ -0,0 +1,352 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# Copyright (c) 2018, Abdullah Alhazmy, Alhazmy13. 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
import re
from decimal import Decimal
from math import floor
CURRENCY_SR = [("ريال", "ريالان", "ريالات", "ريالاً"),
("هللة", "هللتان", "هللات", "هللة")]
CURRENCY_EGP = [("جنيه", "جنيهان", "جنيهات", "جنيهاً"),
("قرش", "قرشان", "قروش", "قرش")]
CURRENCY_KWD = [("دينار", "ديناران", "دينارات", "ديناراً"),
("فلس", "فلسان", "فلس", "فلس")]
ARABIC_ONES = [
"", "واحد", "اثنان", "ثلاثة", "أربعة", "خمسة", "ستة", "سبعة", "ثمانية",
"تسعة",
"عشرة", "أحد عشر", "اثنا عشر", "ثلاثة عشر", "أربعة عشر", "خمسة عشر",
"ستة عشر", "سبعة عشر", "ثمانية عشر",
"تسعة عشر"
]
class Num2Word_AR(object):
errmsg_too_big = "Too large"
max_num = 10 ** 36
def __init__(self):
self.number = 0
self.arabicPrefixText = ""
self.arabicSuffixText = ""
self.integer_value = 0
self._decimalValue = ""
self.partPrecision = 2
self.currency_unit = CURRENCY_SR[0]
self.currency_subunit = CURRENCY_SR[1]
self.isCurrencyPartNameFeminine = True
self.isCurrencyNameFeminine = False
self.separator = 'و'
self.arabicOnes = ARABIC_ONES
self.arabicFeminineOnes = [
"", "إحدى", "اثنتان", "ثلاث", "أربع", "خمس", "ست", "سبع", "ثمان",
"تسع",
"عشر", "إحدى عشرة", "اثنتا عشرة", "ثلاث عشرة", "أربع عشرة",
"خمس عشرة", "ست عشرة", "سبع عشرة", "ثماني عشرة",
"تسع عشرة"
]
self.arabicOrdinal = [
"", "اول", "ثاني", "ثالث", "رابع", "خامس", "سادس", "سابع", "ثامن",
"تاسع", "عاشر", "حادي عشر", "ثاني عشر", "ثالث عشر", "رابع عشر",
"خامس عشر", "سادس عشر", "سابع عشر", "ثامن عشر", "تاسع عشر"
]
self.arabicTens = [
"عشرون", "ثلاثون", "أربعون", "خمسون", "ستون", "سبعون", "ثمانون",
"تسعون"
]
self.arabicHundreds = [
"", "مائة", "مئتان", "ثلاثمائة", "أربعمائة", "خمسمائة", "ستمائة",
"سبعمائة", "ثمانمائة", "تسعمائة"
]
self.arabicAppendedTwos = [
"مئتا", "ألفا", "مليونا", "مليارا", "تريليونا", "كوادريليونا",
"كوينتليونا", "سكستيليونا"
]
self.arabicTwos = [
"مئتان", "ألفان", "مليونان", "ملياران", "تريليونان",
"كوادريليونان", "كوينتليونان", "سكستيليونان"
]
self.arabicGroup = [
"مائة", "ألف", "مليون", "مليار", "تريليون", "كوادريليون",
"كوينتليون", "سكستيليون"
]
self.arabicAppendedGroup = [
"", "ألفاً", "مليوناً", "ملياراً", "تريليوناً", "كوادريليوناً",
"كوينتليوناً", "سكستيليوناً"
]
self.arabicPluralGroups = [
"", "آلاف", "ملايين", "مليارات", "تريليونات", "كوادريليونات",
"كوينتليونات", "سكستيليونات"
]
def number_to_arabic(self, arabic_prefix_text, arabic_suffix_text):
self.arabicPrefixText = arabic_prefix_text
self.arabicSuffixText = arabic_suffix_text
self.extract_integer_and_decimal_parts()
def extract_integer_and_decimal_parts(self):
re.split('\\.', str(self.number))
splits = re.split('\\.', str(self.number))
self.integer_value = int(splits[0])
if len(splits) > 1:
self._decimalValue = int(self.decimal_value(splits[1]))
else:
self._decimalValue = 0
def decimal_value(self, decimal_part):
if self.partPrecision is not len(decimal_part):
decimal_part_length = len(decimal_part)
decimal_part_builder = decimal_part
for i in range(0, self.partPrecision - decimal_part_length):
decimal_part_builder += '0'
decimal_part = decimal_part_builder
if len(decimal_part) <= self.partPrecision:
dec = len(decimal_part)
else:
dec = self.partPrecision
result = decimal_part[0: dec]
else:
result = decimal_part
for i in range(len(result), self.partPrecision):
result += '0'
return result
def digit_feminine_status(self, digit, group_level):
if group_level == -1:
if self.isCurrencyPartNameFeminine:
return self.arabicFeminineOnes[int(digit)]
else:
return self.arabicOnes[int(digit)]
elif group_level == 0:
if self.isCurrencyNameFeminine:
return self.arabicFeminineOnes[int(digit)]
else:
return self.arabicOnes[int(digit)]
else:
return self.arabicOnes[int(digit)]
def process_arabic_group(self, group_number, group_level,
remaining_number):
tens = Decimal(group_number) % Decimal(100)
hundreds = Decimal(group_number) / Decimal(100)
ret_val = ""
if int(hundreds) > 0:
if tens == 0 and int(hundreds) == 2:
ret_val = "{}".format(self.arabicAppendedTwos[0])
else:
ret_val = "{}".format(self.arabicHundreds[int(hundreds)])
if tens > 0:
if tens < 20:
if tens == 2 and int(hundreds) == 0 and group_level > 0:
if self.integer_value in [2000, 2000000, 2000000000,
2000000000000, 2000000000000000,
2000000000000000000]:
ret_val = "{}".format(
self.arabicAppendedTwos[int(group_level)])
else:
ret_val = "{}".format(
self.arabicTwos[int(group_level)])
else:
if ret_val != "":
ret_val += " و "
if tens == 1 and group_level > 0 and hundreds == 0:
ret_val += ""
elif (tens == 1 or tens == 2) and (
group_level == 0 or group_level == -1) and \
hundreds == 0 and remaining_number == 0:
ret_val += ""
else:
ret_val += self.digit_feminine_status(int(tens),
group_level)
else:
ones = tens % 10
tens = (tens / 10) - 2
if ones > 0:
if ret_val != "" and tens < 4:
ret_val += " و "
ret_val += self.digit_feminine_status(ones, group_level)
if ret_val != "" and ones != 0:
ret_val += " و "
ret_val += self.arabicTens[int(tens)]
return ret_val
def convert(self, value):
self.number = "{:.9f}".format(value)
self.number_to_arabic(self.arabicPrefixText, self.arabicSuffixText)
return self.convert_to_arabic()
def convert_to_arabic(self):
temp_number = Decimal(self.number)
if temp_number == Decimal(0):
return "صفر"
decimal_string = self.process_arabic_group(self._decimalValue,
-1,
Decimal(0))
ret_val = ""
group = 0
while temp_number > Decimal(0):
number_to_process = int(
Decimal(str(temp_number)) % Decimal(str(1000)))
temp_number = int(Decimal(temp_number) / Decimal(1000))
group_description = \
self.process_arabic_group(number_to_process,
group,
Decimal(floor(temp_number)))
if group_description != '':
if group > 0:
if ret_val != "":
ret_val = "{} و {}".format("", ret_val)
if number_to_process != 2:
if number_to_process % 100 != 1:
if 3 <= number_to_process <= 10:
ret_val = "{} {}".format(
self.arabicPluralGroups[group], ret_val)
else:
if ret_val != "":
ret_val = "{} {}".format(
self.arabicAppendedGroup[group],
ret_val)
else:
ret_val = "{} {}".format(
self.arabicGroup[group], ret_val)
else:
ret_val = "{} {}".format(self.arabicGroup[group],
ret_val)
ret_val = "{} {}".format(group_description, ret_val)
group += 1
formatted_number = ""
if self.arabicPrefixText != "":
formatted_number += "{} ".format(self.arabicPrefixText)
formatted_number += ret_val
if self.integer_value != 0:
remaining100 = int(self.integer_value % 100)
if remaining100 == 0:
formatted_number += self.currency_unit[0]
elif remaining100 == 1:
formatted_number += self.currency_unit[0]
elif remaining100 == 2:
if self.integer_value == 2:
formatted_number += self.currency_unit[1]
else:
formatted_number += self.currency_unit[0]
elif 3 <= remaining100 <= 10:
formatted_number += self.currency_unit[2]
elif 11 <= remaining100 <= 99:
formatted_number += self.currency_unit[3]
if self._decimalValue != 0:
formatted_number += " {} ".format(self.separator)
formatted_number += decimal_string
if self._decimalValue != 0:
formatted_number += " "
remaining100 = int(self._decimalValue % 100)
if remaining100 == 0:
formatted_number += self.currency_subunit[0]
elif remaining100 == 1:
formatted_number += self.currency_subunit[0]
elif remaining100 == 2:
formatted_number += self.currency_subunit[1]
elif 3 <= remaining100 <= 10:
formatted_number += self.currency_subunit[2]
elif 11 <= remaining100 <= 99:
formatted_number += self.currency_subunit[3]
if self.arabicSuffixText != "":
formatted_number += " {}".format(self.arabicSuffixText)
return formatted_number
def validate_number(self, number):
if number >= self.max_num:
raise OverflowError(self.errmsg_too_big)
return number
def set_currency_prefer(self, currency):
if currency == 'EGP':
self.currency_unit = CURRENCY_EGP[0]
self.currency_subunit = CURRENCY_EGP[1]
elif currency == 'KWD':
self.currency_unit = CURRENCY_KWD[0]
self.currency_subunit = CURRENCY_KWD[1]
else:
self.currency_unit = CURRENCY_SR[0]
self.currency_subunit = CURRENCY_SR[1]
def to_currency(self, value, currency='SR', prefix='', suffix=''):
self.set_currency_prefer(currency)
self.isCurrencyNameFeminine = False
self.separator = "و"
self.arabicOnes = ARABIC_ONES
self.arabicPrefixText = prefix
self.arabicSuffixText = suffix
return self.convert(value=value)
def to_ordinal(self, number, prefix=''):
if number <= 19:
return "{}".format(self.arabicOrdinal[number])
if number < 100:
self.isCurrencyNameFeminine = True
else:
self.isCurrencyNameFeminine = False
self.currency_subunit = ('', '', '', '')
self.currency_unit = ('', '', '', '')
self.arabicPrefixText = prefix
self.arabicSuffixText = ""
return "{}".format(self.convert(abs(number)).strip())
def to_year(self, value):
value = self.validate_number(value)
return self.to_cardinal(value)
def to_ordinal_num(self, value):
return self.to_ordinal(value).strip()
def to_cardinal(self, number):
number = self.validate_number(number)
minus = ''
if number < 0:
minus = 'سالب '
self.separator = ','
self.currency_subunit = ('', '', '', '')
self.currency_unit = ('', '', '', '')
self.arabicPrefixText = ""
self.arabicSuffixText = ""
self.arabicOnes = ARABIC_ONES
return minus + self.convert(value=abs(number)).strip()

157
num2words/lang_CZ.py Normal file
View File

@@ -0,0 +1,157 @@
# -*- coding: 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 to_cardinal(self, number):
n = str(number).replace(',', '.')
if '.' in n:
left, right = n.split('.')
leading_zero_count = len(right) - len(right.lstrip('0'))
decimal_part = ((ZERO[0] + ' ') * leading_zero_count +
self._int2word(int(right)))
return u'%s %s %s' % (
self._int2word(int(left)),
self.pointword,
decimal_part
)
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
if x == 0:
continue
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)

View File

@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
@@ -14,128 +15,143 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA # MA 02110-1301 USA
from __future__ import unicode_literals from __future__ import print_function, unicode_literals
import re
from .lang_EU import Num2Word_EU from .lang_EU import Num2Word_EU
#//TODO: Use German error messages
class Num2Word_DE(Num2Word_EU): class Num2Word_DE(Num2Word_EU):
def set_high_numwords(self, high): CURRENCY_FORMS = {
max = 3 + 6*len(high) 'EUR': (('Euro', 'Euro'), ('Cent', 'Cent')),
'GBP': (('Pfund', 'Pfund'), ('Penny', 'Pence')),
for word, n in zip(high, range(max, 3, -6)): 'USD': (('Dollar', 'Dollar'), ('Cent', 'Cent')),
self.cards[10**n] = word + "illiarde" 'CNY': (('Yuan', 'Yuan'), ('Jiao', 'Fen')),
self.cards[10**(n-3)] = word + "illion" 'DEM': (('Mark', 'Mark'), ('Pfennig', 'Pfennig')),
}
GIGA_SUFFIX = "illiarde"
MEGA_SUFFIX = "illion"
def setup(self): def setup(self):
self.negword = "minus " self.negword = "minus "
self.pointword = "Komma" self.pointword = "Komma"
self.errmsg_nonnum = "Only numbers may be converted to words." # "Cannot treat float %s as ordinal."
self.errmsg_toobig = "Number is too large to convert to words." self.errmsg_floatord = (
"Die Gleitkommazahl %s kann nicht in eine Ordnungszahl " +
"konvertiert werden."
)
# "type(((type(%s)) ) not in [long, int, float]"
self.errmsg_nonnum = (
"Nur Zahlen (type(%s)) können in Wörter konvertiert werden."
)
# "Cannot treat negative num %s as ordinal."
self.errmsg_negord = (
"Die negative Zahl %s kann nicht in eine Ordnungszahl " +
"konvertiert werden."
)
# "abs(%s) must be less than %s."
self.errmsg_toobig = "Die Zahl %s muss kleiner als %s sein."
self.exclude_title = [] self.exclude_title = []
lows = ["non", "okt", "sept", "sext", "quint", "quadr", "tr", "b", "m"] lows = ["Non", "Okt", "Sept", "Sext", "Quint", "Quadr", "Tr", "B", "M"]
units = ["", "un", "duo", "tre", "quattuor", "quin", "sex", "sept", units = ["", "un", "duo", "tre", "quattuor", "quin", "sex", "sept",
"okto", "novem"] "okto", "novem"]
tens = ["dez", "vigint", "trigint", "quadragint", "quinquagint", tens = ["dez", "vigint", "trigint", "quadragint", "quinquagint",
"sexagint", "septuagint", "oktogint", "nonagint"] "sexagint", "septuagint", "oktogint", "nonagint"]
self.high_numwords = ["zent"]+self.gen_high_numwords(units, tens, lows) self.high_numwords = (
self.mid_numwords = [(1000, "tausand"), (100, "hundert"), ["zent"] + self.gen_high_numwords(units, tens, lows)
)
self.mid_numwords = [(1000, "tausend"), (100, "hundert"),
(90, "neunzig"), (80, "achtzig"), (70, "siebzig"), (90, "neunzig"), (80, "achtzig"), (70, "siebzig"),
(60, "sechzig"), (50, "f\xFCnfzig"), (40, "vierzig"), (60, "sechzig"), (50, "f\xFCnfzig"),
(30, "drei\xDFig")] (40, "vierzig"), (30, "drei\xDFig")]
self.low_numwords = ["zwanzig", "neunzehn", "achtzen", "siebzehn", self.low_numwords = ["zwanzig", "neunzehn", "achtzehn", "siebzehn",
"sechzehn", "f\xFCnfzehn", "vierzehn", "dreizehn", "sechzehn", "f\xFCnfzehn", "vierzehn", "dreizehn",
"zw\xF6lf", "elf", "zehn", "neun", "acht", "sieben", "zw\xF6lf", "elf", "zehn", "neun", "acht",
"sechs", "f\xFCnf", "vier", "drei", "zwei", "eins", "sieben", "sechs", "f\xFCnf", "vier", "drei",
"null"] "zwei", "eins", "null"]
self.ords = { "eins" : "ers", self.ords = {"eins": "ers",
"drei" : "drit", "drei": "drit",
"acht" : "ach", "acht": "ach",
"sieben" : "sieb", "sieben": "sieb",
"ig" : "igs" } "ig": "igs",
self.ordflag = False "ert": "erts",
"end": "ends",
"ion": "ions",
"nen": "ns",
"rde": "rds",
"rden": "rds"}
def merge(self, curr, next): def merge(self, curr, next):
ctext, cnum, ntext, nnum = curr + next ctext, cnum, ntext, nnum = curr + next
if cnum == 1: if cnum == 1:
if nnum < 10**6 or self.ordflag: if nnum == 100 or nnum == 1000:
return ("ein" + ntext, nnum)
elif nnum < 10 ** 6:
return next return next
ctext = "eine" ctext = "eine"
if nnum > cnum: if nnum > cnum:
if nnum >= 10**6: if nnum >= 10 ** 6:
if cnum > 1: if cnum > 1:
if ntext.endswith("e") or self.ordflag: if ntext.endswith("e"):
ntext += "s" ntext += "n"
else: else:
ntext += "es" ntext += "en"
ctext += " " ctext += " "
val = cnum * nnum val = cnum * nnum
else: else:
if nnum < 10 < cnum < 100: if nnum < 10 < cnum < 100:
if nnum == 1: if nnum == 1:
ntext = "ein" ntext = "ein"
ntext, ctext = ctext, ntext + "und" ntext, ctext = ctext, ntext + "und"
elif cnum >= 10**6: elif cnum >= 10 ** 6:
ctext += " " ctext += " "
val = cnum + nnum val = cnum + nnum
word = ctext + ntext word = ctext + ntext
return (word, val) return (word, val)
def to_ordinal(self, value): def to_ordinal(self, value):
self.verify_ordinal(value) self.verify_ordinal(value)
self.ordflag = True outword = self.to_cardinal(value).lower()
outword = self.to_cardinal(value)
self.ordflag = False
for key in self.ords: for key in self.ords:
if outword.endswith(key): if outword.endswith(key):
outword = outword[:len(outword) - len(key)] + self.ords[key] outword = outword[:len(outword) - len(key)] + self.ords[key]
break break
return outword + "te"
res = outword + "te"
# Exception: "hundertste" is usually preferred over "einhundertste"
if res == "eintausendste" or res == "einhundertste":
res = res.replace("ein", "", 1)
# ... similarly for "millionste" etc.
res = re.sub(r'eine ([a-z]+(illion|illiard)ste)$',
lambda m: m.group(1), res)
# Ordinals involving "Million" etc. are written without a space.
# see https://de.wikipedia.org/wiki/Million#Sprachliches
res = re.sub(r' ([a-z]+(illion|illiard)ste)$',
lambda m: m.group(1), res)
return res
# Is this correct??
def to_ordinal_num(self, value): def to_ordinal_num(self, value):
self.verify_ordinal(value) self.verify_ordinal(value)
return str(value) + "te" return str(value) + "."
def to_currency(self, val, currency='EUR', cents=True, separator=' und',
def to_currency(self, val, longval=True, old=False): adjective=False):
if old: result = super(Num2Word_DE, self).to_currency(
return self.to_splitnum(val, hightxt="mark/s", lowtxt="pfennig/e", val, currency=currency, cents=cents, separator=separator,
jointxt="und",longval=longval) adjective=adjective)
return super(Num2Word_DE, self).to_currency(val, jointxt="und", # Handle exception, in german is "ein Euro" and not "eins Euro"
longval=longval) return result.replace("eins ", "ein ")
def to_year(self, val, longval=True): def to_year(self, val, longval=True):
if not (val//100)%10: if not (val // 100) % 10:
return self.to_cardinal(val) return self.to_cardinal(val)
return self.to_splitnum(val, hightxt="hundert", longval=longval) return self.to_splitnum(val, hightxt="hundert", longval=longval)\
.replace(' ', '')
n2w = Num2Word_DE()
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(2000)
if __name__ == "__main__":
main()

133
num2words/lang_DK.py Normal file
View File

@@ -0,0 +1,133 @@
# -*- coding: 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 division, print_function, unicode_literals
from . import lang_EU
class Num2Word_DK(lang_EU.Num2Word_EU):
GIGA_SUFFIX = "illiarder"
MEGA_SUFFIX = "illioner"
def setup(self):
super(Num2Word_DK, self).setup()
self.negword = "minus "
self.pointword = "komma"
self.exclude_title = ["og", "komma", "minus"]
self.mid_numwords = [(1000, "tusind"), (100, "hundrede"),
(90, "halvfems"), (80, "firs"),
(70, "halvfjerds"), (60, "treds"),
(50, "halvtreds"), (40, "fyrre"), (30, "tredive")]
self.low_numwords = ["tyve", "nitten", "atten", "sytten",
"seksten", "femten", "fjorten", "tretten",
"tolv", "elleve", "ti", "ni", "otte",
"syv", "seks", "fem", "fire", "tre", "to",
"et", "nul"]
self.ords = {"nul": "nul",
"et": "f\xf8rste",
"to": "anden",
"tre": "tredje",
"fire": "fjerde",
"fem": "femte",
"seks": "sjette",
"syv": "syvende",
"otte": "ottende",
"ni": "niende",
"ti": "tiende",
"elleve": "ellevte",
"tolv": "tolvte",
"tretten": "trett",
"fjorten": "fjort",
"femten": "femt",
"seksten": "sekst",
"sytten": "sytt",
"atten": "att",
"nitten": "nitt",
"tyve": "tyv"}
self.ordflag = False
def merge(self, curr, next):
ctext, cnum, ntext, nnum = curr + next
if next[1] == 100 or next[1] == 1000:
lst = list(next)
lst[0] = 'et' + lst[0]
next = tuple(lst)
if cnum == 1:
if nnum < 10 ** 6 or self.ordflag:
return next
ctext = "en"
if nnum > cnum:
if nnum >= 10 ** 6:
ctext += " "
val = cnum * nnum
else:
if cnum >= 100 and cnum < 1000:
ctext += " og "
elif cnum >= 1000 and cnum <= 100000:
ctext += "e og "
if nnum < 10 < cnum < 100:
if nnum == 1:
ntext = "en"
ntext, ctext = ctext, ntext + "og"
elif cnum >= 10 ** 6:
ctext += " "
val = cnum + nnum
word = ctext + ntext
return (word, val)
def to_ordinal(self, value):
self.verify_ordinal(value)
self.ordflag = True
outword = self.to_cardinal(value)
self.ordflag = False
for key in self.ords:
if outword.endswith(key):
outword = outword[:len(outword) - len(key)] + self.ords[key]
break
if value % 100 >= 30 and value % 100 <= 39 or value % 100 == 0:
outword += "te"
elif value % 100 > 12 or value % 100 == 0:
outword += "ende"
return outword
def to_ordinal_num(self, value):
self.verify_ordinal(value)
vaerdte = (0, 1, 5, 6, 11, 12)
if value % 100 >= 30 and value % 100 <= 39 or value % 100 in vaerdte:
return str(value) + "te"
elif value % 100 == 2:
return str(value) + "en"
return str(value) + "ende"
def to_currency(self, val, longval=True):
if val // 100 == 1 or val == 1:
ret = self.to_splitnum(val, hightxt="kr", lowtxt="\xf8re",
jointxt="og", longval=longval)
return "en " + ret[3:]
return self.to_splitnum(val, hightxt="kr", lowtxt="\xf8re",
jointxt="og", longval=longval)
def to_year(self, val, longval=True):
if val == 1:
return 'en'
if not (val // 100) % 10:
return self.to_cardinal(val)
return self.to_splitnum(val, hightxt="hundrede", longval=longval)

View File

@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
@@ -14,19 +15,22 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA # MA 02110-1301 USA
from __future__ import division, unicode_literals from __future__ import division, print_function, unicode_literals
from . import lang_EU from . import lang_EU
class Num2Word_EN(lang_EU.Num2Word_EU): class Num2Word_EN(lang_EU.Num2Word_EU):
def set_high_numwords(self, high): def set_high_numwords(self, high):
max = 3 + 3*len(high) max = 3 + 3 * len(high)
for word, n in zip(high, range(max, 3, -3)): for word, n in zip(high, range(max, 3, -3)):
self.cards[10**n] = word + "illion" self.cards[10 ** n] = word + "illion"
def setup(self): def setup(self):
super(Num2Word_EN, self).setup()
self.negword = "minus " self.negword = "minus "
self.pointword = "point" self.pointword = "point"
self.errmsg_nornum = "Only numbers may be converted to words."
self.exclude_title = ["and", "point", "minus"] self.exclude_title = ["and", "point", "minus"]
self.mid_numwords = [(1000, "thousand"), (100, "hundred"), self.mid_numwords = [(1000, "thousand"), (100, "hundred"),
@@ -38,26 +42,31 @@ class Num2Word_EN(lang_EU.Num2Word_EU):
"twelve", "eleven", "ten", "nine", "eight", "twelve", "eleven", "ten", "nine", "eight",
"seven", "six", "five", "four", "three", "two", "seven", "six", "five", "four", "three", "two",
"one", "zero"] "one", "zero"]
self.ords = { "one" : "first", self.ords = {"one": "first",
"two" : "second", "two": "second",
"three" : "third", "three": "third",
"five" : "fifth", "four": "fourth",
"eight" : "eighth", "five": "fifth",
"nine" : "ninth", "six": "sixth",
"twelve" : "twelfth" } "seven": "seventh",
"eight": "eighth",
"nine": "ninth",
"ten": "tenth",
"eleven": "eleventh",
"twelve": "twelfth"}
def merge(self, lpair, rpair):
def merge(self, (ltext, lnum), (rtext, rnum)): ltext, lnum = lpair
rtext, rnum = rpair
if lnum == 1 and rnum < 100: if lnum == 1 and rnum < 100:
return (rtext, rnum) return (rtext, rnum)
elif 100 > lnum > rnum : elif 100 > lnum > rnum:
return ("%s-%s"%(ltext, rtext), lnum + rnum) return ("%s-%s" % (ltext, rtext), lnum + rnum)
elif lnum >= 100 > rnum: elif lnum >= 100 > rnum:
return ("%s and %s"%(ltext, rtext), lnum + rnum) return ("%s and %s" % (ltext, rtext), lnum + rnum)
elif rnum > lnum: elif rnum > lnum:
return ("%s %s"%(ltext, rtext), lnum * rnum) return ("%s %s" % (ltext, rtext), lnum * rnum)
return ("%s, %s"%(ltext, rtext), lnum + rnum) return ("%s, %s" % (ltext, rtext), lnum + rnum)
def to_ordinal(self, value): def to_ordinal(self, value):
self.verify_ordinal(value) self.verify_ordinal(value)
@@ -68,46 +77,34 @@ class Num2Word_EN(lang_EU.Num2Word_EU):
lastword = self.ords[lastword] lastword = self.ords[lastword]
except KeyError: except KeyError:
if lastword[-1] == "y": if lastword[-1] == "y":
lastword = lastword[:-1] + "ie" lastword = lastword[:-1] + "ie"
lastword += "th" lastword += "th"
lastwords[-1] = self.title(lastword) lastwords[-1] = self.title(lastword)
outwords[-1] = "-".join(lastwords) outwords[-1] = "-".join(lastwords)
return " ".join(outwords) return " ".join(outwords)
def to_ordinal_num(self, value): def to_ordinal_num(self, value):
self.verify_ordinal(value) self.verify_ordinal(value)
return "%s%s"%(value, self.to_ordinal(value)[-2:]) return "%s%s" % (value, self.to_ordinal(value)[-2:])
def to_year(self, val, suffix=None, longval=True):
def to_year(self, val, longval=True): if val < 0:
if not (val//100)%10: val = abs(val)
return self.to_cardinal(val) suffix = 'BC' if not suffix else suffix
return self.to_splitnum(val, hightxt="hundred", jointxt="and", high, low = (val // 100, val % 100)
longval=longval) # If year is 00XX, X00X, or beyond 9999, go cardinal.
if (high == 0
def to_currency(self, val, longval=True): or (high % 10 == 0 and low < 10)
return self.to_splitnum(val, hightxt="dollar/s", lowtxt="cent/s", or high >= 100):
jointxt="and", longval=longval, cents = True) valtext = self.to_cardinal(val)
else:
hightext = self.to_cardinal(high)
n2w = Num2Word_EN() if low == 0:
to_card = n2w.to_cardinal lowtext = "hundred"
to_ord = n2w.to_ordinal elif low < 10:
to_ordnum = n2w.to_ordinal_num lowtext = "oh-%s" % self.to_cardinal(low)
to_year = n2w.to_year else:
lowtext = self.to_cardinal(low)
def main(): valtext = "%s %s" % (hightext, lowtext)
for val in [ 1, 11, 12, 21, 31, 33, 71, 80, 81, 91, 99, 100, 101, 102, 155, return (valtext if not suffix
180, 300, 308, 832, 1000, 1001, 1061, 1100, 1500, 1701, 3000, else "%s %s" % (valtext, suffix))
8280, 8291, 150000, 500000, 1000000, 2000000, 2000001,
-21212121211221211111, -2.121212, -1.0000100]:
n2w.test(val)
n2w.test(1325325436067876801768700107601001012212132143210473207540327057320957032975032975093275093275093270957329057320975093272950730)
for val in [1,120,1000,1120,1800, 1976,2000,2010,2099,2171]:
print val, "is", n2w.to_currency(val)
print val, "is", n2w.to_year(val)
if __name__ == "__main__":
main()

View File

@@ -1,46 +0,0 @@
# 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_EN import Num2Word_EN
class Num2Word_EN_EUR(Num2Word_EN):
def to_currency(self, val, longval=True, cents=True, jointxt="and"):
return self.to_splitnum(val, hightxt="euro/s", lowtxt="cents",
jointxt=jointxt, longval=longval, cents = cents)
n2w = Num2Word_EN_EUR()
to_card = n2w.to_cardinal
to_ord = n2w.to_ordinal
to_ordnum = n2w.to_ordinal_num
to_year = n2w.to_year
to_currency = n2w.to_currency
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)
for val in [1,120,1000,1120,1800, 1976,2000,2010,2099,2171]:
print val, "is", n2w.to_currency(val)
print val, "is", n2w.to_year(val)
if __name__ == "__main__":
main()

View File

@@ -1,46 +0,0 @@
# 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_EN import Num2Word_EN
class Num2Word_EN_GB(Num2Word_EN):
def to_currency(self, val, longval=True):
return self.to_splitnum(val, hightxt="pound/s", lowtxt="pence",
jointxt="and", longval=longval)
n2w = Num2Word_EN_GB()
to_card = n2w.to_cardinal
to_ord = n2w.to_ordinal
to_ordnum = n2w.to_ordinal_num
to_year = n2w.to_year
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)
for val in [1,120,1000,1120,1800, 1976,2000,2010,2099,2171]:
print val, "is", n2w.to_currency(val)
print val, "is", n2w.to_year(val)
if __name__ == "__main__":
main()

View File

@@ -1,45 +0,0 @@
# 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_EN_GB import Num2Word_EN_GB
class Num2Word_EN_GB_old(Num2Word_EN_GB):
def base_setup(self):
sclass = super(Num2Word_EN_GB, self)
self.set_high_numwords = sclass.set_high_numwords
sclass.base_setup()
n2w = Num2Word_EN_GB_old()
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)
for val in [1,120,1000,1120,1800, 1976,2000,2010,2099,2171]:
print val, "is", n2w.to_currency(val)
print val, "is", n2w.to_year(val)
if __name__ == "__main__":
main()

26
num2words/lang_EN_IN.py Normal file
View File

@@ -0,0 +1,26 @@
# -*- coding: 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_EN import Num2Word_EN
class Num2Word_EN_IN(Num2Word_EN):
def set_high_numwords(self, high):
self.cards[10 ** 7] = "crore"
self.cards[10 ** 5] = "lakh"

130
num2words/lang_EO.py Normal file
View File

@@ -0,0 +1,130 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021, 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 print_function, unicode_literals
from .base import Num2Word_Base
class Num2Word_EO(Num2Word_Base):
CURRENCY_FORMS = {
"EUR": (("eŭro", "eŭroj"), ("centimo", "centimoj")),
"USD": (("dolaro", "dolaroj"), ("cendo", "cendoj")),
"FRF": (("franko", "frankoj"), ("centimo", "centimoj")),
"GBP": (("pundo", "pundoj"), ("penco", "pencoj")),
"CNY": (("juano", "juanoj"), ("feno", "fenoj")),
}
GIGA_SUFFIX = "iliardo"
MEGA_SUFFIX = "iliono"
def set_high_numwords(self, high):
cap = 3 + 6 * len(high)
for word, n in zip(high, range(cap, 3, -6)):
if self.GIGA_SUFFIX:
self.cards[10 ** n] = word + self.GIGA_SUFFIX
if self.MEGA_SUFFIX:
self.cards[10 ** (n - 3)] = word + self.MEGA_SUFFIX
def gen_high_numwords(self, units, tens, lows):
out = [u + t for t in tens for u in units]
out.reverse()
return out + lows
def setup(self):
lows = ["naŭ", "ok", "sep", "ses", "kvin", "kvar", "tr", "b", "m"]
units = ["", "un", "duo", "tre", "kvatuor",
"kvin", "seks", "septen", "okto", "novem"]
tens = ["dek", "vigint", "trigint", "kvadragint", "kvinkvagint",
"seksagint", "septuagint", "oktogint", "nonagint"]
self.high_numwords = ["cent"] + self.gen_high_numwords(units, tens,
lows)
self.negword = "minus "
self.pointword = "komo"
self.errmsg_nonnum = u"Sole nombroj povas esti konvertita en vortojn."
self.errmsg_toobig = (
u"Tro granda nombro por esti konvertita en vortojn."
)
self.exclude_title = ["kaj", "komo", "minus"]
self.mid_numwords = [(1000, "mil"), (100, "cent"), (90, "naŭdek"),
(80, "okdek"), (70, "sepdek"), (60, "sesdek"),
(50, "kvindek"), (40, "kvardek"), (30, "tridek")]
self.low_numwords = ["dudek", "dek naŭ", "dek ok", "dek sep",
"dek ses", "dek kvin", "dek kvar", "dek tri",
"dek du", "dek unu", "dek", "naŭ", "ok", "sep",
"ses", "kvin", "kvar", "tri", "du", "unu", "nul"]
self.ords = {
"unu": "unua",
"du": "dua",
"tri": "tria",
"kvar": "kvara",
"kvin": "kvina",
"ses": "sesa",
"sep": "sepa",
"ok": "oka",
"naŭ": "naŭa",
"dek": "deka"
}
def merge(self, curr, next):
ctext, cnum, ntext, nnum = curr + next
if cnum == 1 and nnum < 1000000:
return next
if nnum >= 10**6 and cnum > 1:
return ("%s %sj" % (ctext, ntext), cnum + nnum)
if nnum == 100:
return ("%s%s" % (ctext, ntext), cnum + nnum)
return ("%s %s" % (ctext, ntext), cnum + nnum)
def to_ordinal(self, value):
self.verify_ordinal(value)
word = self.to_cardinal(value)
for src, repl in self.ords.items():
if word.endswith(src):
word = word[:-len(src)] + repl
return word
if word.endswith("o"):
word = word[:-1] + "a"
elif word.endswith("oj"):
word = word[:-2] + "a"
else:
word = word + "a"
return word
def to_ordinal_num(self, value):
self.verify_ordinal(value)
out = str(value)
out += "a"
return out
def to_currency(self, val, currency="EUR", cents=True, separator=" kaj",
adjective=False):
result = super(Num2Word_EO, self).to_currency(
val, currency=currency, cents=cents, separator=separator,
adjective=adjective)
return result
def pluralize(self, n, forms):
form = 0 if n <= 1 else 1
return forms[form]

View File

@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
@@ -14,52 +15,261 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA # MA 02110-1301 USA
from __future__ import unicode_literals from __future__ import division, print_function, unicode_literals
import math
from .lang_EU import Num2Word_EU from .lang_EU import Num2Word_EU
#//TODO: correct orthographics GENERIC_DOLLARS = ('dólar', 'dólares')
#//TODO: error messages GENERIC_CENTS = ('centavo', 'centavos')
CURRENCIES_UNA = ('SLL', 'SEK', 'NOK', 'CZK', 'DKK', 'ISK',
'SKK', 'GBP', 'CYP', 'EGP', 'FKP', 'GIP',
'LBP', 'SDG', 'SHP', 'SSP', 'SYP', 'INR',
'IDR', 'LKR', 'MUR', 'NPR', 'PKR', 'SCR',
'ESP', 'TRY', 'ITL')
CENTS_UNA = ('EGP', 'JOD', 'LBP', 'SDG', 'SSP', 'SYP')
class Num2Word_ES(Num2Word_EU): class Num2Word_ES(Num2Word_EU):
CURRENCY_FORMS = {
'EUR': (('euro', 'euros'), ('céntimo', 'céntimos')),
'ESP': (('peseta', 'pesetas'), ('céntimo', 'céntimos')),
'USD': (GENERIC_DOLLARS, GENERIC_CENTS),
'PEN': (('sol', 'soles'), ('céntimo', 'céntimos')),
'CRC': (('colón', 'colones'), GENERIC_CENTS),
'AUD': (GENERIC_DOLLARS, GENERIC_CENTS),
'CAD': (GENERIC_DOLLARS, GENERIC_CENTS),
'GBP': (('libra', 'libras'), ('penique', 'peniques')),
'RUB': (('rublo', 'rublos'), ('kopeyka', 'kopeykas')),
'SEK': (('corona', 'coronas'), ('öre', 'öre')),
'NOK': (('corona', 'coronas'), ('øre', 'øre')),
'PLN': (('zloty', 'zlotys'), ('grosz', 'groszy')),
'MXN': (('peso', 'pesos'), GENERIC_CENTS),
'RON': (('leu', 'leus'), ('ban', 'bani')),
'INR': (('rupia', 'rupias'), ('paisa', 'paisas')),
'HUF': (('florín', 'florines'), ('fillér', 'fillér')),
'FRF': (('franco', 'francos'), ('céntimo', 'céntimos')),
'CNY': (('yuan', 'yuanes'), ('fen', 'jiaos')),
'CZK': (('corona', 'coronas'), ('haléř', 'haléř')),
'NIO': (('córdoba', 'córdobas'), GENERIC_CENTS),
'VES': (('bolívar', 'bolívares'), ('céntimo', 'céntimos')),
'BRL': (('real', 'reales'), GENERIC_CENTS),
'CHF': (('franco', 'francos'), ('céntimo', 'céntimos')),
'JPY': (('yen', 'yenes'), ('sen', 'sen')),
'KRW': (('won', 'wones'), ('jeon', 'jeon')),
'KPW': (('won', 'wones'), ('chon', 'chon')),
'TRY': (('lira', 'liras'), ('kuruş', 'kuruş')),
'ZAR': (('rand', 'rands'), ('céntimo', 'céntimos')),
'KZT': (('tenge', 'tenges'), ('ın', 'ın')),
'UAH': (('hryvnia', 'hryvnias'), ('kopiyka', 'kopiykas')),
'THB': (('baht', 'bahts'), ('satang', 'satang')),
'AED': (('dirham', 'dirhams'), ('fils', 'fils')),
'AFN': (('afghani', 'afghanis'), ('pul', 'puls')),
'ALL': (('lek ', 'leke'), ('qindarkë', 'qindarka')),
'AMD': (('dram', 'drams'), ('luma', 'lumas')),
'ANG': (('florín', 'florines'), GENERIC_CENTS),
'AOA': (('kwanza', 'kwanzas'), ('céntimo', 'céntimos')),
'ARS': (('peso', 'pesos'), GENERIC_CENTS),
'AWG': (('florín', 'florines'), GENERIC_CENTS),
'AZN': (('manat', 'manat'), ('qəpik', 'qəpik')),
'BBD': (GENERIC_DOLLARS, GENERIC_CENTS),
'BDT': (('taka', 'takas'), ('paisa', 'paisas')),
'BGN': (('lev', 'leva'), ('stotinka', 'stotinki')),
'BHD': (('dinar', 'dinares'), ('fils', 'fils')),
'BIF': (('franco', 'francos'), ('céntimo', 'céntimos')),
'BMD': (GENERIC_DOLLARS, GENERIC_CENTS),
'BND': (GENERIC_DOLLARS, GENERIC_CENTS),
'BOB': (('boliviano', 'bolivianos'), GENERIC_CENTS),
'BSD': (GENERIC_DOLLARS, GENERIC_CENTS),
'BTN': (('ngultrum', 'ngultrum'), ('chetrum', 'chetrum')),
'BWP': (('pula', 'pulas'), ('thebe', 'thebes')),
'BYN': (('rublo', 'rublos'), ('kópek', 'kópeks')),
'BYR': (('rublo', 'rublos'), ('kópek', 'kópeks')),
'BZD': (GENERIC_DOLLARS, ('céntimo', 'céntimos')),
'CDF': (('franco', 'francos'), ('céntimo', 'céntimos')),
'CLP': (('peso', 'pesos'), GENERIC_CENTS),
'COP': (('peso', 'pesos'), GENERIC_CENTS),
'CUP': (('peso', 'pesos'), GENERIC_CENTS),
'CVE': (('escudo', 'escudos'), GENERIC_CENTS),
'CYP': (('libra', 'libras'), ('céntimo', 'céntimos')),
'DJF': (('franco', 'francos'), ('céntimo', 'céntimos')),
'DKK': (('corona', 'coronas'), ('øre', 'øre')),
'DOP': (('peso', 'pesos'), GENERIC_CENTS),
'DZD': (('dinar', 'dinares'), ('céntimo', 'céntimos')),
'ECS': (('sucre', 'sucres'), GENERIC_CENTS),
'EGP': (('libra', 'libras'), ('piastra', 'piastras')),
'ERN': (('nakfa', 'nakfas'), ('céntimo', 'céntimos')),
'ETB': (('birr', 'birrs'), ('céntimo', 'céntimos')),
'FJD': (GENERIC_DOLLARS, GENERIC_CENTS),
'FKP': (('libra', 'libras'), ('penique', 'peniques')),
'GEL': (('lari', 'laris'), ('tetri', 'tetris')),
'GHS': (('cedi', 'cedis'), ('pesewa', 'pesewas')),
'GIP': (('libra', 'libras'), ('penique', 'peniques')),
'GMD': (('dalasi', 'dalasis'), ('butut', 'bututs')),
'GNF': (('franco', 'francos'), ('céntimo', 'céntimos')),
'GTQ': (('quetzal', 'quetzales'), GENERIC_CENTS),
'GYD': (GENERIC_DOLLARS, GENERIC_CENTS),
'HKD': (GENERIC_DOLLARS, GENERIC_CENTS),
'HNL': (('lempira', 'lempiras'), GENERIC_CENTS),
'HRK': (('kuna', 'kunas'), ('lipa', 'lipas')),
'HTG': (('gourde', 'gourdes'), ('céntimo', 'céntimos')),
'IDR': (('rupia', 'rupias'), ('céntimo', 'céntimos')),
'ILS': (('séquel', 'séqueles'), ('agora', 'agoras')),
'IQD': (('dinar', 'dinares'), ('fils', 'fils')),
'IRR': (('rial', 'riales'), ('dinar', 'dinares')),
'ISK': (('corona', 'coronas'), ('eyrir', 'aurar')),
'ITL': (('lira', 'liras'), ('céntimo', 'céntimos')),
'JMD': (GENERIC_DOLLARS, ('céntimo', 'céntimos')),
'JOD': (('dinar', 'dinares'), ('piastra', 'piastras')),
'KES': (('chelín', 'chelines'), ('céntimo', 'céntimos')),
'KGS': (('som', 'som'), ('tyiyn', 'tyiyn')),
'KHR': (('riel', 'rieles'), ('céntimo', 'céntimos')),
'KMF': (('franco', 'francos'), ('céntimo', 'céntimos')),
'KWD': (('dinar', 'dinares'), ('fils', 'fils')),
'KYD': (GENERIC_DOLLARS, ('céntimo', 'céntimos')),
'LAK': (('kip', 'kips'), ('att', 'att')),
'LBP': (('libra', 'libras'), ('piastra', 'piastras')),
'LKR': (('rupia', 'rupias'), ('céntimo', 'céntimos')),
'LRD': (GENERIC_DOLLARS, ('céntimo', 'céntimos')),
'LSL': (('loti', 'lotis'), ('céntimo', 'céntimos')),
'LTL': (('lita', 'litas'), ('céntimo', 'céntimos')),
'LVL': (('lat', 'lats'), ('céntimo', 'céntimos')),
'LYD': (('dinar', 'dinares'), ('dírham', 'dírhams')),
'MAD': (('dírham', 'dirhams'), ('céntimo', 'céntimos')),
'MDL': (('leu', 'lei'), ('ban', 'bani')),
'MGA': (('ariary', 'ariaris'), ('iraimbilanja', 'iraimbilanja')),
'MKD': (('denar', 'denares'), ('deni', 'denis')),
'MMK': (('kiat', 'kiats'), ('pya', 'pyas')),
'MNT': (('tugrik', 'tugriks'), ('möngö', 'möngö')),
'MOP': (('pataca', 'patacas'), ('avo', 'avos')),
'MRO': (('ouguiya', 'ouguiyas'), ('khoums', 'khoums')),
'MRU': (('ouguiya', 'ouguiyas'), ('khoums', 'khoums')),
'MUR': (('rupia', 'rupias'), ('céntimo', 'céntimos')),
'MVR': (('rufiyaa', 'rufiyaas'), ('laari', 'laari')),
'MWK': (('kuacha', 'kuachas'), ('tambala', 'tambalas')),
'MYR': (('ringgit', 'ringgit'), ('céntimo', 'céntimos')),
'MZN': (('metical', 'metical'), GENERIC_CENTS),
'NAD': (GENERIC_DOLLARS, ('céntimo', 'céntimos')),
'NGN': (('naira', 'nairas'), ('kobo', 'kobo')),
'NPR': (('rupia', 'rupias'), ('paisa', 'paisas')),
'NZD': (GENERIC_DOLLARS, GENERIC_CENTS),
'OMR': (('rial', 'riales'), ('baisa', 'baisa')),
'PAB': (('balboa', 'balboas'), ('centésimo', 'centésimos')),
'PGK': (('kina', 'kinas'), ('toea', 'toea')),
'PHP': (('peso', 'pesos'), GENERIC_CENTS),
'PKR': (('rupia', 'rupias'), ('paisa', 'paisas')),
'PLZ': (('zloty', 'zlotys'), ('grosz', 'groszy')),
'PYG': (('guaraní', 'guaranís'), ('céntimo', 'céntimos')),
'QAR': (('rial', 'riales'), ('dírham', 'dírhams')),
'QTQ': (('quetzal', 'quetzales'), GENERIC_CENTS),
'RSD': (('dinar', 'dinares'), ('para', 'para')),
'RUR': (('rublo', 'rublos'), ('kopek', 'kopeks')),
'RWF': (('franco', 'francos'), ('céntimo', 'céntimos')),
'SAR': (('riyal', 'riales'), ('halala', 'halalas')),
'SBD': (GENERIC_DOLLARS, ('céntimo', 'céntimos')),
'SCR': (('rupia', 'rupias'), ('céntimo', 'céntimos')),
'SDG': (('libra', 'libras'), ('piastra', 'piastras')),
'SGD': (GENERIC_DOLLARS, ('céntimo', 'céntimos')),
'SHP': (('libra', 'libras'), ('penique', 'peniques')),
'SKK': (('corona', 'coronas'), ('halier', 'haliers')),
'SLL': (('leona', 'leonas'), ('céntimo', 'céntimos')),
'SRD': (GENERIC_DOLLARS, ('céntimo', 'céntimos')),
'SSP': (('libra', 'libras'), ('piastra', 'piastras')),
'STD': (('dobra', 'dobras'), ('céntimo', 'céntimos')),
'SVC': (('colón', 'colones'), GENERIC_CENTS),
'SYP': (('libra', 'libras'), ('piastra', 'piastras')),
'SZL': (('lilangeni', 'emalangeni'), ('céntimo', 'céntimos')),
'TJS': (('somoni', 'somonis'), ('dirame', 'dirames')),
'TMT': (('manat', 'manat'), ('tenge', 'tenge')),
'TND': (('dinar', 'dinares'), ('milésimo', 'milésimos')),
'TOP': (('paanga', 'paangas'), ('céntimo', 'céntimos')),
'TTD': (GENERIC_DOLLARS, ('céntimo', 'céntimos')),
'TWD': (('nuevo dólar', 'nuevos dólares'), ('céntimo', 'céntimos')),
'TZS': (('chelín', 'chelines'), ('céntimo', 'céntimos')),
'UAG': (('hryvnia', 'hryvnias'), ('kopiyka', 'kopiykas')),
'UGX': (('chelín', 'chelines'), ('céntimo', 'céntimos')),
'UYU': (('peso', 'pesos'), ('centésimo', 'centésimos')),
'UZS': (('sum', 'sum'), ('tiyin', 'tiyin')),
'VEF': (('bolívar fuerte', 'bolívares fuertes'),
('céntimo', 'céntimos')),
'VND': (('dong', 'dongs'), ('xu', 'xu')),
'VUV': (('vatu', 'vatu'), ('nenhum', 'nenhum')),
'WST': (('tala', 'tala'), GENERIC_CENTS),
'XAF': (('franco CFA', 'francos CFA'), ('céntimo', 'céntimos')),
'XCD': (GENERIC_DOLLARS, ('céntimo', 'céntimos')),
'XOF': (('franco CFA', 'francos CFA'), ('céntimo', 'céntimos')),
'XPF': (('franco CFP', 'francos CFP'), ('céntimo', 'céntimos')),
'YER': (('rial', 'riales'), ('fils', 'fils')),
'YUM': (('dinar', 'dinares'), ('para', 'para')),
'ZMW': (('kwacha', 'kwachas'), ('ngwee', 'ngwee')),
'ZRZ': (('zaire', 'zaires'), ('likuta', 'makuta')),
'ZWL': (GENERIC_DOLLARS, ('céntimo', 'céntimos')),
'ZWL': (GENERIC_DOLLARS, ('céntimo', 'céntimos')),
}
#//CHECK: Is this sufficient?? # //CHECK: Is this sufficient??
def set_high_numwords(self, high): GIGA_SUFFIX = None
max = 3 + 6*len(high) MEGA_SUFFIX = "illón"
for word, n in zip(high, range(max, 3, -6)):
self.cards[10**(n-3)] = word + "ill\xf2n"
def setup(self): def setup(self):
lows = ["cuatr", "tr", "b", "m"] lows = ["cuatr", "tr", "b", "m"]
self.high_numwords = self.gen_high_numwords([], [], lows) self.high_numwords = self.gen_high_numwords([], [], lows)
self.negword = "menos " self.negword = "menos "
self.pointword = "punto" self.pointword = "punto"
self.errmsg_nonnum = "Only numbers may be converted to words." self.errmsg_nonnum = "type(%s) no es [long, int, float]"
self.errmsg_toobig = "Number is too large to convert to words." self.errmsg_floatord = "El float %s no puede ser tratado como un" \
" ordinal."
self.errmsg_negord = "El número negativo %s no puede ser tratado" \
" como un ordinal."
self.errmsg_toobig = (
"abs(%s) deber ser inferior a %s."
)
self.gender_stem = "o" self.gender_stem = "o"
self.exclude_title = ["y", "menos", "punto"] self.exclude_title = ["y", "menos", "punto"]
self.mid_numwords = [(1000, "mil"), (100, "cien"), (90, "noventa"), self.mid_numwords = [(1000, "mil"), (100, "cien"), (90, "noventa"),
(80, "ochenta"), (70, "setenta"), (60, "sesenta"), (80, "ochenta"), (70, "setenta"), (60, "sesenta"),
(50,"cincuenta"), (40,"cuarenta"), (30,"treinta")] (50, "cincuenta"), (40, "cuarenta"),
self.low_numwords = ["vientinueve", "vientiocho", "vientisiete", (30, "treinta")]
"vientis\xE8is", "vienticinco", "vienticuatro", self.low_numwords = ["veintinueve", "veintiocho", "veintisiete",
"vientitr\xE8s", "vientid\xF2s", "vientiuno", "veintiséis", "veinticinco", "veinticuatro",
"viente", "diecinueve", "dieciocho", "diecisiete", "veintitrés", "veintidós", "veintiuno",
"dieciseis", "quince", "catorce", "trece", "doce", "veinte", "diecinueve", "dieciocho", "diecisiete",
"dieciséis", "quince", "catorce", "trece", "doce",
"once", "diez", "nueve", "ocho", "siete", "seis", "once", "diez", "nueve", "ocho", "siete", "seis",
"cinco", "cuatro", "tres", "dos", "uno", "cero"] "cinco", "cuatro", "tres", "dos", "uno", "cero"]
self.ords = { 1 : "primer", self.ords = {1: "primer",
2 : "segund", 2: "segund",
3 : "tercer", 3: "tercer",
4 : "cuart", 4: "cuart",
5 : "quint", 5: "quint",
6 : "sext", 6: "sext",
7 : "s\xE8ptim", 7: "séptim",
8 : "octav", 8: "octav",
9 : "noven", 9: "noven",
10 : "d\xE8cim" } 10: "décim",
20: "vigésim",
30: "trigésim",
40: "quadragésim",
50: "quincuagésim",
60: "sexagésim",
70: "septuagésim",
80: "octogésim",
90: "nonagésim",
100: "centésim",
200: "ducentésim",
300: "tricentésim",
400: "cuadrigentésim",
500: "quingentésim",
600: "sexcentésim",
700: "septigentésim",
800: "octigentésim",
900: "noningentésim",
1e3: "milésim",
1e6: "millonésim",
1e9: "billonésim",
1e12: "trillonésim",
1e15: "cuadrillonésim"}
def merge(self, curr, next): def merge(self, curr, next):
ctext, cnum, ntext, nnum = curr + next ctext, cnum, ntext, nnum = curr + next
@@ -68,13 +278,13 @@ class Num2Word_ES(Num2Word_EU):
if nnum < 1000000: if nnum < 1000000:
return next return next
ctext = "un" ctext = "un"
elif cnum == 100: elif cnum == 100 and not nnum % 1000 == 0:
ctext += "t" + self.gender_stem ctext += "t" + self.gender_stem
if nnum < cnum: if nnum < cnum:
if cnum < 100: if cnum < 100:
return ("%s y %s"%(ctext, ntext), cnum + nnum) return "%s y %s" % (ctext, ntext), cnum + nnum
return ("%s %s"%(ctext, ntext), cnum + nnum) return "%s %s" % (ctext, ntext), cnum + nnum
elif (not nnum % 1000000) and cnum > 1: elif (not nnum % 1000000) and cnum > 1:
ntext = ntext[:-3] + "lones" ntext = ntext[:-3] + "lones"
@@ -92,44 +302,107 @@ class Num2Word_ES(Num2Word_EU):
return (ctext + ntext, cnum * nnum) return (ctext + ntext, cnum * nnum)
def to_ordinal(self, value): def to_ordinal(self, value):
self.verify_ordinal(value) self.verify_ordinal(value)
try: if value == 0:
return self.ords[value] + self.gender_stem text = ""
except KeyError: elif value <= 10:
return self.to_cardinal(value) text = "%s%s" % (self.ords[value], self.gender_stem)
elif value <= 12:
text = (
"%s%s%s" % (self.ords[10], self.gender_stem,
self.to_ordinal(value - 10))
)
elif value <= 100:
dec = (value // 10) * 10
text = (
"%s%s %s" % (self.ords[dec], self.gender_stem,
self.to_ordinal(value - dec))
)
elif value <= 1e3:
cen = (value // 100) * 100
text = (
"%s%s %s" % (self.ords[cen], self.gender_stem,
self.to_ordinal(value - cen))
)
elif value < 1e18:
# Round down to the nearest 1e(3n)
# dec contains the following:
# [ 1e3, 1e6): 1e3
# [ 1e6, 1e9): 1e6
# [ 1e9, 1e12): 1e9
# [1e12, 1e15): 1e12
# [1e15, 1e18): 1e15
dec = 1000 ** int(math.log(int(value), 1000))
# Split the parts before and after the word for 'dec'
# eg (12, 345) = divmod(12_345, 1_000)
high_part, low_part = divmod(value, dec)
cardinal = self.to_cardinal(high_part) if high_part != 1 else ""
text = (
"%s%s%s %s" % (cardinal, self.ords[dec], self.gender_stem,
self.to_ordinal(low_part))
)
else:
text = self.to_cardinal(value)
return text.strip()
def to_ordinal_num(self, value): def to_ordinal_num(self, value):
self.verify_ordinal(value) self.verify_ordinal(value)
# Correct for fem? return "%s%s" % (value, "º" if self.gender_stem == 'o' else "ª")
return "%s\xB0"%value
def to_currency(self, val, currency='EUR', cents=True, separator=' con',
adjective=False):
result = super(Num2Word_ES, self).to_currency(
val, currency=currency, cents=cents, separator=separator,
adjective=adjective)
# Handle exception: In Spanish it's "un euro" and not "uno euro",
# except in these currencies, where it's "una": leona, corona,
# libra, lira, rupia, lempira, peseta.
# The same goes for "veintiuna", "treinta y una"...
# Also, this needs to be handled separately for "dollars" and
# "cents".
# All "cents" are masculine except for: piastra.
# Source: https://www.rae.es/dpd/una (section 2.2)
def to_currency(self, val, longval=True, old=False): # split "dollars" part from "cents" part
if old: list_result = result.split(separator + " ")
return self.to_splitnum(val, hightxt="peso/s", lowtxt="peseta/s",
divisor=1000, jointxt="y", longval=longval)
return super(Num2Word_ES, self).to_currency(val, jointxt="y",
longval=longval)
# "DOLLARS" PART (list_result[0])
n2w = Num2Word_ES() # Feminine currencies ("una libra", "trescientas libras"...)
to_card = n2w.to_cardinal if currency in CURRENCIES_UNA:
to_ord = n2w.to_ordinal
to_ordnum = n2w.to_ordinal_num
def main(): # "una libra", "veintiuna libras", "treinta y una libras"...
for val in [ 1, 11, 12, 21, 31, 33, 71, 80, 81, 91, 99, 100, 101, 102, 155, list_result[0] = list_result[0].replace("uno", "una")
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) # "doscientas libras", "trescientas libras"...
print n2w.to_currency(1222) list_result[0] = list_result[0].replace("cientos", "cientas")
print n2w.to_currency(1222, old=True)
print n2w.to_year(1222)
if __name__ == "__main__": # Masc.: Correct orthography for the specific case of "veintiún":
main() list_result[0] = list_result[0].replace("veintiuno", "veintiún")
# Masculine currencies: general case ("un euro", "treinta y un
# euros"...):
list_result[0] = list_result[0].replace("uno", "un")
# "CENTS" PART (list_result[1])
# Feminine "cents" ("una piastra", "veintiuna piastras"...)
if currency in CENTS_UNA:
# "una piastra", "veintiuna piastras", "treinta y una piastras"...
list_result[1] = list_result[1].replace("uno", "una")
# Masc.: Correct orthography for the specific case of "veintiún":
list_result[1] = list_result[1].replace("veintiuno", "veintiún")
# Masculine "cents": general case ("un centavo", "treinta y un
# centavos"...):
list_result[1] = list_result[1].replace("uno", "un")
# join back "dollars" part with "cents" part
result = (separator + " ").join(list_result)
return result

29
num2words/lang_ES_CO.py Normal file
View File

@@ -0,0 +1,29 @@
# -*- coding: 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 print_function, unicode_literals
from .lang_ES import Num2Word_ES
class Num2Word_ES_CO(Num2Word_ES):
def to_currency(self, val, longval=True, old=False):
result = self.to_splitnum(val, hightxt="peso/s", lowtxt="centavo/s",
divisor=1, jointxt="y", longval=longval)
# Handle exception, in spanish is "un euro" and not "uno euro"
return result.replace("uno", "un")

33
num2words/lang_ES_NI.py Normal file
View File

@@ -0,0 +1,33 @@
# -*- coding: 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 print_function, unicode_literals
from .lang_ES import Num2Word_ES
class Num2Word_ES_NI(Num2Word_ES):
CURRENCY_FORMS = {
'NIO': (('córdoba', 'córdobas'), ('centavo', 'centavos')),
}
def to_currency(self, val, currency='NIO', cents=True, separator=' con',
adjective=False):
result = super(Num2Word_ES, self).to_currency(
val, currency=currency, cents=cents, separator=separator,
adjective=adjective)
return result.replace("uno", "un")

32
num2words/lang_ES_VE.py Normal file
View File

@@ -0,0 +1,32 @@
# -*- coding: 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 print_function, unicode_literals
from .lang_ES import Num2Word_ES
class Num2Word_ES_VE(Num2Word_ES):
def to_currency(self, val, longval=True, old=False):
hightxt = "bolívar/es" if old else "bolívar/es fuerte/s"
result = self.to_splitnum(
val, hightxt=hightxt, lowtxt="centavo/s",
divisor=1, jointxt="y", longval=longval
)
# Handle exception, in spanish is "un euro" and not "uno euro"
return result.replace("uno", "un")

View File

@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
@@ -15,26 +16,78 @@
# MA 02110-1301 USA # MA 02110-1301 USA
from __future__ import unicode_literals from __future__ import unicode_literals
from .base import Num2Word_Base from .base import Num2Word_Base
GENERIC_DOLLARS = ('dollar', 'dollars')
GENERIC_CENTS = ('cent', 'cents')
class Num2Word_EU(Num2Word_Base): class Num2Word_EU(Num2Word_Base):
CURRENCY_FORMS = {
'AUD': (GENERIC_DOLLARS, GENERIC_CENTS),
'CAD': (GENERIC_DOLLARS, GENERIC_CENTS),
# repalced by EUR
'EEK': (('kroon', 'kroons'), ('sent', 'senti')),
'EUR': (('euro', 'euro'), GENERIC_CENTS),
'GBP': (('pound sterling', 'pounds sterling'), ('penny', 'pence')),
# replaced by EUR
'LTL': (('litas', 'litas'), GENERIC_CENTS),
# replaced by EUR
'LVL': (('lat', 'lats'), ('santim', 'santims')),
'USD': (GENERIC_DOLLARS, GENERIC_CENTS),
'RUB': (('rouble', 'roubles'), ('kopek', 'kopeks')),
'SEK': (('krona', 'kronor'), ('öre', 'öre')),
'NOK': (('krone', 'kroner'), ('øre', 'øre')),
'PLN': (('zloty', 'zlotys', 'zlotu'), ('grosz', 'groszy')),
'MXN': (('peso', 'pesos'), GENERIC_CENTS),
'RON': (('leu', 'lei', 'de lei'), ('ban', 'bani', 'de bani')),
'INR': (('rupee', 'rupees'), ('paisa', 'paise')),
'HUF': (('forint', 'forint'), ('fillér', 'fillér')),
'UZS': (('sum', 'sums'), ('tiyin', 'tiyins'))
}
CURRENCY_ADJECTIVES = {
'AUD': 'Australian',
'CAD': 'Canadian',
'EEK': 'Estonian',
'USD': 'US',
'RUB': 'Russian',
'NOK': 'Norwegian',
'MXN': 'Mexican',
'RON': 'Romanian',
'INR': 'Indian',
'HUF': 'Hungarian',
'UZS': 'Uzbekistan'
}
GIGA_SUFFIX = "illiard"
MEGA_SUFFIX = "illion"
def set_high_numwords(self, high): def set_high_numwords(self, high):
max = 3 + 6*len(high) cap = 3 + 6 * len(high)
for word, n in zip(high, range(max, 3, -6)): for word, n in zip(high, range(cap, 3, -6)):
self.cards[10**n] = word + "illiard" if self.GIGA_SUFFIX:
self.cards[10**(n-3)] = word + "illion" self.cards[10 ** n] = word + self.GIGA_SUFFIX
if self.MEGA_SUFFIX:
def base_setup(self): self.cards[10 ** (n - 3)] = word + self.MEGA_SUFFIX
lows = ["non","oct","sept","sext","quint","quadr","tr","b","m"]
def gen_high_numwords(self, units, tens, lows):
out = [u + t for t in tens for u in units]
out.reverse()
return out + lows
def pluralize(self, n, forms):
form = 0 if n == 1 else 1
return forms[form]
def setup(self):
lows = ["non", "oct", "sept", "sext", "quint", "quadr", "tr", "b", "m"]
units = ["", "un", "duo", "tre", "quattuor", "quin", "sex", "sept", units = ["", "un", "duo", "tre", "quattuor", "quin", "sex", "sept",
"octo", "novem"] "octo", "novem"]
tens = ["dec", "vigint", "trigint", "quadragint", "quinquagint", tens = ["dec", "vigint", "trigint", "quadragint", "quinquagint",
"sexagint", "septuagint", "octogint", "nonagint"] "sexagint", "septuagint", "octogint", "nonagint"]
self.high_numwords = ["cent"]+self.gen_high_numwords(units, tens, lows) self.high_numwords = ["cent"] + self.gen_high_numwords(units, tens,
lows)
def to_currency(self, val, longval=True, jointxt=""):
return self.to_splitnum(val, hightxt="Euro/s", lowtxt="Euro cent/s",
jointxt=jointxt, longval=longval)

165
num2words/lang_FA.py Normal file
View File

@@ -0,0 +1,165 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# Copyright (c) 2018, Abdullah Alhazmy, Alhazmy13. All Rights Reserved.
# Copyright (c) 2020, Hamidreza Kalbasi. 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 decimal import Decimal
from math import floor
farsiOnes = [
"", "یک", "دو", "سه", "چهار", "پنج", "شش", "هفت", "هشت",
"نه",
"ده",
"یازده",
"دوازده",
"سیزده",
"چهارده",
"پونزده",
"شونزده",
"هیفده",
"هیجده",
"نوزده",
]
farsiTens = [
"",
"ده",
"بیست",
"سی",
"چهل",
"پنجاه",
"شصت",
"هفتاد",
"هشتاد",
"نود",
]
farsiHundreds = [
"",
"صد",
"دویست",
"سیصد",
"چهارصد",
"پانصد",
"ششصد",
"هفتصد",
"هشتصد",
"نهصد",
]
farsiBig = [
'',
' هزار',
' میلیون',
" میلیارد",
' تریلیون',
" تریلیارد",
]
farsiFrac = ["", "دهم", "صدم"]
farsiFracBig = ["", "هزارم", "میلیونیم", "میلیاردیم"]
farsiSeperator = ' و '
class Num2Word_FA(object):
errmsg_too_big = "Too large"
max_num = 10 ** 36
def __init__(self):
self.number = 0
def float2tuple(self, value):
pre = int(value)
# Simple way of finding decimal places to update the precision
self.precision = abs(Decimal(str(value)).as_tuple().exponent)
post = abs(value - pre) * 10**self.precision
if abs(round(post) - post) < 0.01:
# We generally floor all values beyond our precision (rather than
# rounding), but in cases where we have something like 1.239999999,
# which is probably due to python's handling of floats, we actually
# want to consider it as 1.24 instead of 1.23
post = int(round(post))
else:
post = int(floor(post))
return pre, post, self.precision
def cardinal3(self, number):
if (number < 19):
return farsiOnes[number]
if (number < 100):
x, y = divmod(number, 10)
if y == 0:
return farsiTens[x]
return farsiTens[x] + farsiSeperator + farsiOnes[y]
x, y = divmod(number, 100)
if y == 0:
return farsiHundreds[x]
return farsiHundreds[x] + farsiSeperator + self.cardinal3(y)
def cardinalPos(self, number):
x = number
res = ''
for b in farsiBig:
x, y = divmod(x, 1000)
if (y == 0):
continue
yx = self.cardinal3(y) + b
if b == ' هزار' and y == 1:
yx = 'هزار'
if (res == ''):
res = yx
else:
res = yx + farsiSeperator + res
return res
def fractional(self, number, level):
if (number == 5):
return "نیم"
x = self.cardinalPos(number)
ld3, lm3 = divmod(level, 3)
ltext = (farsiFrac[lm3] + " " + farsiFracBig[ld3]).strip()
return x + " " + ltext
def to_currency(self, value):
return self.to_cardinal(value) + " تومان"
def to_ordinal(self, number):
r = self.to_cardinal(number)
if (r[-1] == 'ه' and r[-2] == 'س'):
return r[:-1] + 'وم'
return r + 'م'
def to_year(self, value):
return self.to_cardinal(value)
def to_ordinal_num(self, value):
return str(value)+"م"
def to_cardinal(self, number):
if number < 0:
return "منفی " + self.to_cardinal(-number)
if (number == 0):
return "صفر"
x, y, level = self.float2tuple(number)
if y == 0:
return self.cardinalPos(x)
if x == 0:
return self.fractional(y, level)
return self.cardinalPos(x) + farsiSeperator + self.fractional(y, level)

736
num2words/lang_FI.py Normal file
View File

@@ -0,0 +1,736 @@
# -*- coding: 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 division, print_function, unicode_literals
from collections import OrderedDict
from . import lang_EU
GENERIC_CENTS = ('sentti', 'senttiä')
GENERIC_CENTAVOS = ('centavo', 'centavoa')
# grammatical cases
NOM = 10 # nominative: the dictionary form
GEN = 11 # genitive: ~of/'s
ACC = 12 # accusative: not used; either nominative or genitive
PTV = 13 # partitive: as an object
# locative cases (internal)
INE = 14 # inessive: in
ELA = 15 # elative: from/out of
ILL = 16 # illative: into
# locative cases (external)
ADE = 17 # adessive: at/on
ABL = 18 # ablative: from (after being at/on, not in)
ALL = 19 # allative: to
# essive
ESS = 20 # essive: as (in the role of)
TRANSL = 21 # translative: to (the role of; being sth)
# rare
INSTRUC = 22 # instructive: with (plural is the same as singular)
ABE = 23 # abessive: without
COM = 24 # comitative: together with (plural = singular)
NAME_TO_CASE = {
'nominative': NOM,
'genitive': GEN,
'accusative': ACC,
'partitive': PTV,
'inessive': INE,
'elative': ELA,
'illative': ILL,
'adessive': ADE,
'ablative': ABL,
'allative': ALL,
'essive': ESS,
'translative': TRANSL,
'instructive': INSTRUC,
'abessive': ABE,
'comitative': COM,
}
# https://en.wikibooks.org/wiki/Finnish/Grammar-Vowel_harmony
BACK_TO_FRONT = {
'a': 'ä',
'o': 'ö',
'u': 'y',
}
# https://en.wiktionary.org/wiki/Appendix:Finnish_nominal_inflection
# CASE: (SINGULAR_SUFFIX+, PLURAL_SUFFIX+)
KOTUS_TYPE = {
# Kotus type 5/risti, no gradation
5: {
# grammatical
NOM: ('i', 'it'),
GEN: ('in', 'ien'),
PTV: ('ia', 'eja'),
# locative, internal
INE: ('issa', 'eissa'),
ELA: ('ista', 'eista'),
ILL: ('iin', 'eihin'),
# locative, external
ADE: ('illa', 'eilla'),
ABL: ('ilta', 'eilta'),
ALL: ('ille', 'eille'),
# essive
ESS: ('ina', 'eina'),
TRANSL: ('iksi', 'eiksi'),
# rare
INSTRUC: ('ein', 'ein'),
ABE: ('itta', 'eitta'),
COM: ('eine', 'eine'), # works better
},
# Kotus type 7/ovi, no gradation
7: {
# grammatical
NOM: ('i', 'et'),
GEN: ('en', 'ien'),
PTV: ('ea', 'ia'),
# locative, internal
INE: ('essa', 'issa'),
ELA: ('esta', 'ista'),
ILL: ('een', 'iin'),
# locative, external
ADE: ('ella', 'illa'),
ABL: ('elta', 'ilta'),
ALL: ('elle', 'ille'),
# essive
ESS: ('ena', 'ina'),
TRANSL: ('eksi', 'iksi'),
# rare
INSTRUC: ('in', 'in'),
ABE: ('etta', 'itta'),
COM: ('ine', 'ine'), # works better
},
# Kotus type 8/nalle, no gradation
8: {
# grammatical
NOM: ('e', 'et'),
GEN: ('en', ('ejen', 'ein')),
PTV: ('ea', 'eja'),
# locative, internal
INE: ('essa', 'eissa'),
ELA: ('esta', 'eista'),
ILL: ('een', 'eihin'),
# locative, external
ADE: ('ella', 'eilla'),
ABL: ('elta', 'eilta'),
ALL: ('elle', 'eille'),
# essive
ESS: ('ena', 'eina'),
TRANSL: ('eksi', 'eiksi'),
# rare
INSTRUC: ('ein', 'ein'),
ABE: ('etta', 'eitta'),
COM: ('eine', 'eine'), # works better
},
# Kotus type 9/kala, t-d gradation (sata)
109: {
# grammatical
NOM: ('ta', 'dat'),
GEN: ('dan', ('tojen', 'tain')),
PTV: ('taa', 'toja'),
# locative, internal
INE: ('dassa', 'doissa'),
ELA: ('dasta', 'doista'),
ILL: ('taan', 'toihin'),
# locative, external
ADE: ('dalla', 'doilla'),
ABL: ('dalta', 'doilta'),
ALL: ('dalle', 'doille'),
# essive
ESS: ('tana', 'toina'),
TRANSL: ('daksi', 'doiksi'),
# rare
INSTRUC: ('doin', 'doin'),
ABE: ('datta', 'doitta'),
COM: ('toine', 'toine'), # works better
},
# Kotus type 10/koira, no gradation
10: {
# grammatical
NOM: ('a', 'at'),
GEN: ('an', ('ien', 'ain')),
PTV: ('aa', 'ia'),
# locative, internal
INE: ('assa', 'issa'),
ELA: ('asta', 'ista'),
ILL: ('aan', 'iin'),
# locative, external
ADE: ('alla', 'illa'),
ABL: ('alta', 'ilta'),
ALL: ('alle', 'ille'),
# essive
ESS: ('ana', 'ina'),
TRANSL: ('aksi', 'iksi'),
# rare
INSTRUC: ('in', 'in'),
ABE: ('atta', 'itta'),
COM: ('ine', 'ine'), # works better
},
# Kotus type 27/käsi, t-d gradation
27: {
# grammatical
NOM: ('si', 'det'),
GEN: ('den', ('sien', 'tten')),
PTV: ('tta', 'sia'),
# locative, internal
INE: ('dessa', 'sissa'),
ELA: ('desta', 'sista'),
ILL: ('teen', 'siin'),
# locative, external
ADE: ('della', 'silla'),
ABL: ('delta', 'silta'),
ALL: ('delle', 'sille'),
# essive
ESS: ('tena', 'sina'),
TRANSL: ('deksi', 'siksi'),
# rare
INSTRUC: ('sin', 'sin'),
ABE: ('detta', 'sitta'),
COM: ('sine', 'sine'), # works better
},
# Kotus type 31/kaksi, t-d gradation
31: {
# grammatical
NOM: ('ksi', 'hdet'),
GEN: ('hden', 'ksien'),
PTV: ('hta', 'ksia'),
# locative, internal
INE: ('hdessa', 'ksissa'),
ELA: ('hdesta', 'ksista'),
ILL: ('hteen', 'ksiin'),
# locative, external
ADE: ('hdella', 'ksilla'),
ABL: ('hdelta', 'ksilta'),
ALL: ('hdelle', 'ksille'),
# essive
ESS: ('htena', 'ksina'),
TRANSL: ('hdeksi', 'ksiksi'),
# rare
INSTRUC: ('ksin', 'ksin'),
ABE: ('hdetta', 'ksitta'),
COM: ('ksine', 'ksine'), # works better
},
# Kotus type 32/sisar, no gradation
32: {
# grammatical
NOM: ('', 'et'),
GEN: ('en', ('ien', 'ten')),
PTV: ('ta', 'ia'),
# locative, internal
INE: ('essa', 'issa'),
ELA: ('esta', 'ista'),
ILL: ('een', 'iin'),
# locative, external
ADE: ('ella', 'illa'),
ABL: ('elta', 'ilta'),
ALL: ('elle', 'ille'),
# essive
ESS: ('ena', 'ina'),
TRANSL: ('eksi', 'iksi'),
# rare
INSTRUC: ('in', 'in'),
ABE: ('etta', 'itta'),
COM: ('ine', 'ine'), # works better
},
# Kotus type 38/nainen, no gradation
38: {
# grammatical
NOM: ('nen', 'set'),
GEN: ('sen', ('sten', 'sien')),
PTV: ('sta', 'sia'),
# locative, internal
INE: ('sessa', 'sissa'),
ELA: ('sesta', 'sista'),
ILL: ('seen', 'siin'),
# locative, external
ADE: ('sella', 'silla'),
ABL: ('selta', 'silta'),
ALL: ('selle', 'sille'),
# essive
ESS: ('sena', 'sina'),
TRANSL: ('seksi', 'siksi'),
# rare
INSTRUC: ('sin', 'sin'),
ABE: ('setta', 'sitta'),
COM: ('sine', 'sine'), # works better
},
# Kotus type 45/kahdeksas, nt-nn gradation
45: {
# grammatical
NOM: ('s', 'nnet'),
GEN: ('nnen', 'nsien'),
PTV: ('tta', 'nsia'),
# locative, internal
INE: ('nnessa', 'nsissa'),
ELA: ('nnesta', 'nsista'),
ILL: ('nteen', 'nsiin'),
# locative, external
ADE: ('nnella', 'nsilla'),
ABL: ('nnelta', 'nsilta'),
ALL: ('nnelle', 'nsille'),
# essive
ESS: ('ntena', 'nsina'),
TRANSL: ('nneksi', 'nsiksi'),
# rare
INSTRUC: ('nsin', 'nsin'),
ABE: ('nnetta', 'nsitta'),
COM: ('nsine', 'nsine'), # works better
},
# Kotus type 46/tuhat, nt-nn gradation
46: {
# grammatical
NOM: ('t', 'nnet'),
GEN: ('nnen', ('nsien', 'nten')),
PTV: ('tta', 'nsia'),
# locative, internal
INE: ('nnessa', 'nsissa'),
ELA: ('nnesta', 'nsista'),
ILL: ('nteen', 'nsiin'),
# locative, external
ADE: ('nnella', 'nsilla'),
ABL: ('nnelta', 'nsilta'),
ALL: ('nnelle', 'nsille'),
# essive
ESS: ('ntena', 'nsina'),
TRANSL: ('nneksi', 'nsiksi'),
# rare
INSTRUC: ('nsin', 'nsin'),
ABE: ('nnetta', 'nsitta'),
COM: ('nsine', 'nsine'), # works better
},
}
# kolme
KOTUS_TYPE[108] = {
c: (KOTUS_TYPE[8][c][0], KOTUS_TYPE[7][c][1])
for c in KOTUS_TYPE[8]
}
KOTUS_TYPE[108][INSTRUC] = ('en', 'in')
KOTUS_TYPE[108][ABE] = ('etta', 'itta')
KOTUS_TYPE[108][COM] = ('ine', 'ine')
# seitsemän, kahdeksan, yhdeksän
KOTUS_TYPE[110] = KOTUS_TYPE[10].copy()
KOTUS_TYPE[110][NOM] = ('an', 'at')
# kymmenen
KOTUS_TYPE[132] = KOTUS_TYPE[32].copy()
KOTUS_TYPE[132][NOM] = ('en', 'et')
def inflect(parts, options):
if not isinstance(parts, list):
parts = [parts]
out = ''
for part in parts:
# part is plain text, concat and continue
if not isinstance(part, tuple):
out += part
continue
# predefined case (kaksikymmentä, ...)
tmp_case = options.case
if len(part) == 3:
# override singular nominative only
if options.case == NOM and not options.plural:
tmp_case = part[2]
part = part[:2]
# stem and suffix
stem, kotus_type = part
suffix = KOTUS_TYPE[kotus_type][tmp_case][options.plural]
# many choices, choose preferred or first
if isinstance(suffix, tuple):
common = set(suffix) & set(options.prefer or set())
if len(common) == 1:
suffix = common.pop()
else:
suffix = suffix[0]
# apply vowel harmony
if not set(BACK_TO_FRONT) & set(stem):
for back, front in BACK_TO_FRONT.items():
suffix = suffix.replace(back, front)
# concat
out += stem + suffix
return out
class Options(object):
def __init__(self, ordinal, case, plural, prefer):
self.ordinal = ordinal
self.case = case
self.plural = plural
self.prefer = prefer
def variation(self, ordinal=None, case=None, plural=None, prefer=None):
return Options(
ordinal if ordinal is not None else self.ordinal,
case if case is not None else self.case,
plural if plural is not None else self.plural,
prefer if prefer is not None else self.prefer,
)
class Num2Word_FI(lang_EU.Num2Word_EU):
CURRENCY_FORMS = {
'BRL': (('real', 'realia'), GENERIC_CENTAVOS),
'CHF': (('frangi', 'frangia'), ('rappen', 'rappenia')),
'CNY': (('juan', 'juania'), ('fen', 'feniä')),
'EUR': (('euro', 'euroa'), GENERIC_CENTS),
'FIM': (('markka', 'markkaa'), ('penni', 'penniä')), # historical
'INR': (('rupia', 'rupiaa'), ('paisa', 'paisaa')),
'JPY': (('jeni', 'jeniä'), ('sen', 'seniä')), # rare subunit
'KRW': (('won', 'wonia'), ('jeon', 'jeonia')), # rare subunit
'KPW': (('won', 'wonia'), ('chon', 'chonia')), # rare subunit
'MXN': (('peso', 'pesoa'), GENERIC_CENTAVOS),
'RUB': (('rupla', 'ruplaa'), ('kopeekka', 'kopeekkaa')),
'TRY': (('liira', 'liiraa'), ('kuruş', 'kuruşia')),
'ZAR': (('randi', 'randia'), GENERIC_CENTS),
}
# crowns
for curr_code in 'DKK', 'ISK', 'NOK', 'SEK':
CURRENCY_FORMS[curr_code] = (('kruunu', 'kruunua'), ('äyri', 'äyriä'))
# dollars
for curr_code in 'AUD', 'CAD', 'HKD', 'NZD', 'SGD', 'USD':
CURRENCY_FORMS[curr_code] = (
('dollari', 'dollaria'), GENERIC_CENTS)
# pounds
for curr_code in ('GBP',):
CURRENCY_FORMS[curr_code] = (('punta', 'puntaa'), ('penny', 'pennyä'))
CURRENCY_ADJECTIVES = {
'AUD': 'Australian',
'BRL': 'Brasilian',
'CAD': 'Kanadan',
'CHF': 'Sveitsin',
'DKK': 'Tanskan',
'FIM': 'Suomen', # historical
'GBP': 'Englannin',
'HKD': 'Hongkongin',
'INR': 'Intian',
'ISK': 'Islannin',
'KRW': 'Etelä-Korean',
'KPW': 'Pohjois-Korean',
'MXN': 'Meksikon',
'NOK': 'Norjan',
'NZD': 'Uuden-Seelannin',
'RUB': 'Venäjän',
'SEK': 'Ruotsin',
'SGD': 'Singaporen',
'TRY': 'Turkin',
'USD': 'Yhdysvaltain',
'ZAR': 'Etelä-Afrikan',
}
def __init__(self):
self.ords = OrderedDict()
super(Num2Word_FI, self).__init__()
def set_numwords(self):
self.set_high_numwords(self.high_numwords)
self.set_mid_numwords(self.mid_numwords, self.mid_ords)
self.set_low_numwords(self.low_numwords, self.low_ords)
def set_high_numwords(self, high):
# references:
# https://fi.wikipedia.org/wiki/Suurten_lukujen_nimet
# https://en.wikipedia.org/wiki/Names_of_large_numbers#Standard_dictionary_numbers
# translate to Finnish
replacements = [
("qu", "kv"),
("x", "ks"),
("c", "k"),
("kent", "sent"), # applied after c -> k to cent
]
translated = []
for i, numword in enumerate(high):
# notes:
# - 1e6**9 can be either noviljoona or noniljoona
# - 1e6**38 and above are untested
# 1e6**6 is sekstiljoona but 1e6**16 is sedekiljoona
if numword.startswith("sex") and numword != "sext":
numword = numword.replace("sex", "se")
# 1e6**7 is septiljoona but 1e6**17 is septendekiljoona
elif numword.startswith("sept") and numword != "sept":
numword = "septen" + numword[len("sept"):]
# 1e6**8 is oktiljoona but 1e6**18 is duodevigintiljoona
# (2 from 20)
elif numword.startswith("octo"):
numword = high[i + -10]
numword = "duode" + numword[len("octo"):]
# 1e6**9 is noniljoona but 1e6**19 is undevigintiljoona (1 from 20)
elif numword.startswith("nove"):
numword = high[i + -10]
numword = "unde" + numword[len("nove") + 1:]
# apply general replacements to all numwords
for repl in replacements:
numword = numword.replace(repl[0], repl[1])
translated.append(numword)
max = 6 * len(translated)
for word, n in zip(translated, range(max, 0, -6)):
if n == 6:
# irregularity considering short scale and long scale
self.cards[10 ** 9] = ("miljard", 5)
self.ords[10 ** 9] = ("miljardi", 45)
self.cards[10 ** n] = (word + "iljoon", 10)
self.ords[10 ** n] = (word + "iljoona", 45)
def set_mid_numwords(self, cards, ords):
for key, val in cards:
self.cards[key] = val
for key, val in ords:
self.ords[key] = val
def set_low_numwords(self, cards, ords):
for key, val in cards:
self.cards[key] = val
for key, val in ords:
self.ords[key] = val
def setup(self):
super(Num2Word_FI, self).setup()
self.negword = "miinus "
self.pointword = "pilkku"
self.exclude_title = ["pilkku", "miinus"]
self.mid_numwords = [
(1000, ("tuha", 46)),
(100, ("sa", 109)),
(90, [("yhdeks", 110), ("kymmen", 132, PTV)]),
(80, [("kahdeks", 110), ("kymmen", 132, PTV)]),
(70, [("seitsem", 110), ("kymmen", 132, PTV)]),
(60, [("kuu", 27), ("kymmen", 132, PTV)]),
(50, [("vii", 27), ("kymmen", 132, PTV)]),
(40, [("nelj", 10), ("kymmen", 132, PTV)]),
(30, [("kolm", 108), ("kymmen", 132, PTV)]),
]
self.mid_ords = [
(1000, ("tuhanne", 45)),
(100, ("sada", 45)),
(90, [("yhdeksä", 45), ("kymmene", 45)]),
(80, [("kahdeksa", 45), ("kymmene", 45)]),
(70, [("seitsemä", 45), ("kymmene", 45)]),
(60, [("kuude", 45), ("kymmene", 45)]),
(50, [("viide", 45), ("kymmene", 45)]),
(40, [("neljä", 45), ("kymmene", 45)]),
(30, [("kolma", 45), ("kymmene", 45)]),
]
self.low_numwords = [
(20, [("ka", 31), ("kymmen", 132, PTV)]),
(19, [("yhdeks", 110), "toista"]),
(18, [("kahdeks", 110), "toista"]),
(17, [("seitsem", 110), "toista"]),
(16, [("kuu", 27), "toista"]),
(15, [("vii", 27), "toista"]),
(14, [("nelj", 10), "toista"]),
(13, [("kolm", 108), "toista"]),
(12, [("ka", 31), "toista"]),
(11, [("y", 31), "toista"]),
(10, ("kymmen", 132)),
(9, ("yhdeks", 110)),
(8, ("kahdeks", 110)),
(7, ("seitsem", 110)),
(6, ("kuu", 27)),
(5, ("vii", 27)),
(4, ("nelj", 10)),
(3, ("kolm", 108)),
(2, ("ka", 31)),
(1, ("y", 31)),
(0, ("noll", 10)),
]
self.low_ords = [
(20, [("kahde", 45), ("kymmene", 45)]),
(19, [("yhdeksä", 45), "toista"]),
(18, [("kahdeksa", 45), "toista"]),
(17, [("seitsemä", 45), "toista"]),
(16, [("kuude", 45), "toista"]),
(15, [("viide", 45), "toista"]),
(14, [("neljä", 45), "toista"]),
(13, [("kolma", 45), "toista"]),
(12, [("kahde", 45), "toista"]),
(11, [("yhde", 45), "toista"]),
(10, ("kymmene", 45)),
(9, ("yhdeksä", 45)),
(8, ("kahdeksa", 45)),
(7, ("seitsemä", 45)),
(6, ("kuude", 45)),
(5, ("viide", 45)),
(4, ("neljä", 45)),
(3, ("kolma", 45)),
(2, ("toi", 38)),
(1, ("ensimmäi", 38)),
(0, ("nolla", 45)),
]
def merge(self, lpair, rpair, options):
ltext, lnum = lpair
rtext, rnum = rpair
# http://www.kielitoimistonohjepankki.fi/ohje/49
fmt = "%s%s"
# ignore lpair if lnum is 1
if lnum == 1:
rtext = inflect(rtext, options)
return (rtext, rnum)
# rnum is added to lnum
elif lnum > rnum:
ltext = inflect(ltext, options)
rtext = inflect(rtext, options)
# separate groups with space
if lnum >= 1000:
fmt = "%s %s"
return (fmt % (ltext, rtext), lnum + rnum)
# rnum is multiplied by lnum
elif lnum < rnum:
if options.ordinal:
# kahdessadas, not toinensadas
if lnum == 2:
ltext = ("kahde", 45)
rtext = inflect(rtext, options)
else:
# kaksituhatta but kahdettuhannet
rcase = options.case
if options.case == NOM and not options.plural:
rcase = PTV
rtext = inflect(rtext, options.variation(case=rcase))
ltext = inflect(ltext, options)
return (fmt % (ltext, rtext), lnum * rnum)
def to_cardinal(self, value, case='nominative', plural=False, prefer=None):
case = NAME_TO_CASE[case]
options = Options(False, case, plural, prefer)
try:
assert int(value) == value
except (ValueError, TypeError, AssertionError):
if case != NOM:
raise NotImplementedError(
"Cases other than nominative are not implemented for "
"cardinal floating point numbers.")
return self.to_cardinal_float(value)
out = ""
if value < 0:
value = abs(value)
out = self.negword
if value >= self.MAXVAL:
raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL))
val = self.splitnum(value, options)
words, num = self.clean(val, options)
return self.title(out + words)
def to_ordinal(self, value, case='nominative', plural=False, prefer=None):
case = NAME_TO_CASE[case]
options = Options(True, case, plural, prefer)
self.verify_ordinal(value)
if value >= self.MAXVAL:
raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL))
val = self.splitnum(value, options)
words, num = self.clean(val, options)
return self.title(words)
def to_ordinal_num(self, value, case='nominative', plural=False):
case = NAME_TO_CASE[case]
raise NotImplementedError
def to_year(self, val, suffix=None, longval=True):
suffix = suffix or ""
if val < 0:
val = abs(val)
suffix = suffix or " ennen ajanlaskun alkua"
return self.to_cardinal(val).replace(" ", "") + suffix
def to_currency(self, val, currency="EUR", cents=True, separator=" ja",
adjective=False):
return super(Num2Word_FI, self).to_currency(
val, currency=currency, cents=cents, separator=separator,
adjective=adjective)
def splitnum(self, value, options):
elems = self.ords if options.ordinal else self.cards
for elem in elems:
if elem > value:
continue
out = []
if value == 0:
div, mod = 1, 0
else:
div, mod = divmod(value, elem)
if div == 1:
out.append((elems[1], 1))
else:
if div == value: # The system tallies, eg Roman Numerals
return [(div * elems[elem], div*elem)]
out.append(self.splitnum(div, options))
out.append((elems[elem], elem))
if mod:
out.append(self.splitnum(mod, options))
return out
def clean(self, val, options):
out = val
while len(val) != 1:
out = []
left, right = val[:2]
if isinstance(left, tuple) and isinstance(right, tuple):
out.append(self.merge(left, right, options))
if val[2:]:
out.append(val[2:])
else:
for elem in val:
if isinstance(elem, list):
if len(elem) == 1:
out.append(elem[0])
else:
out.append(self.clean(elem, options))
else:
out.append(elem)
val = out
return out[0]

View File

@@ -1,4 +1,4 @@
# -*- encoding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
@@ -15,17 +15,29 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA # MA 02110-1301 USA
from __future__ import unicode_literals from __future__ import print_function, unicode_literals
from .lang_EU import Num2Word_EU from .lang_EU import Num2Word_EU
#//TODO: error messages in French
#//TODO: ords
class Num2Word_FR(Num2Word_EU): class Num2Word_FR(Num2Word_EU):
CURRENCY_FORMS = {
'EUR': (('euro', 'euros'), ('centime', 'centimes')),
'USD': (('dollar', 'dollars'), ('cent', 'cents')),
'FRF': (('franc', 'francs'), ('centime', 'centimes')),
'GBP': (('livre', 'livres'), ('penny', 'pence')),
'CNY': (('yuan', 'yuans'), ('fen', 'jiaos')),
}
def setup(self): def setup(self):
Num2Word_EU.setup(self)
self.negword = "moins " self.negword = "moins "
self.pointword = "virgule" self.pointword = "virgule"
self.errmsg_nonnum = "Only numbers may be converted to words." self.errmsg_nonnum = (
self.errmsg_toobig = "Number is too large to convert to words." 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.exclude_title = ["et", "virgule", "moins"]
self.mid_numwords = [(1000, "mille"), (100, "cent"), self.mid_numwords = [(1000, "mille"), (100, "cent"),
(80, "quatre-vingts"), (60, "soixante"), (80, "quatre-vingts"), (60, "soixante"),
@@ -35,7 +47,10 @@ class Num2Word_FR(Num2Word_EU):
"seize", "quinze", "quatorze", "treize", "douze", "seize", "quinze", "quatorze", "treize", "douze",
"onze", "dix", "neuf", "huit", "sept", "six", "onze", "dix", "neuf", "huit", "sept", "six",
"cinq", "quatre", "trois", "deux", "un", "zéro"] "cinq", "quatre", "trois", "deux", "un", "zéro"]
self.ords = {
"cinq": "cinquième",
"neuf": "neuvième",
}
def merge(self, curr, next): def merge(self, curr, next):
ctext, cnum, ntext, nnum = curr + next ctext, cnum, ntext, nnum = curr + next
@@ -44,63 +59,50 @@ class Num2Word_FR(Num2Word_EU):
if nnum < 1000000: if nnum < 1000000:
return next return next
else: else:
if (not (cnum - 80)%100 or not cnum%100) and ctext[-1] == "s": if (not (cnum - 80) % 100
or (not cnum % 100 and cnum < 1000))\
and nnum < 1000000 \
and ctext[-1] == "s":
ctext = ctext[:-1] ctext = ctext[:-1]
if (cnum<1000 and nnum != 1000 and ntext[-1] != "s" if cnum < 1000 and nnum != 1000 and \
and not nnum%100): ntext[-1] != "s" and not nnum % 100:
ntext += "s" ntext += "s"
if nnum < cnum < 100: if nnum < cnum < 100:
if nnum % 10 == 1 and cnum != 80: if nnum % 10 == 1 and cnum != 80:
return ("%s et %s"%(ctext, ntext), cnum + nnum) return ("%s et %s" % (ctext, ntext), cnum + nnum)
return ("%s-%s"%(ctext, ntext), cnum + nnum) return ("%s-%s" % (ctext, ntext), cnum + nnum)
elif nnum > cnum: if nnum > cnum:
return ("%s %s"%(ctext, ntext), cnum * nnum) return ("%s %s" % (ctext, ntext), cnum * nnum)
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 # Is this right for such things as 1001 - "mille unième" instead of
# "mille premier"?? "millième"?? # "mille premier"?? "millième"??
def to_ordinal(self,value): def to_ordinal(self, value):
self.verify_ordinal(value) self.verify_ordinal(value)
if value == 1: if value == 1:
return "premier" return "premier"
word = self.to_cardinal(value) word = self.to_cardinal(value)
if word[-1] == "e": for src, repl in self.ords.items():
word = word[:-1] if word.endswith(src):
return word + "ième" 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): def to_ordinal_num(self, value):
self.verify_ordinal(value) self.verify_ordinal(value)
out = str(value) out = str(value)
out += {"1" : "er" }.get(out[-1], "me") out += "er" if value == 1 else "me"
return out return out
def to_currency(self, val, longval=True, old=False): def to_currency(self, val, currency='EUR', cents=True, separator=' et',
hightxt = "Euro/s" adjective=False):
if old: result = super(Num2Word_FR, self).to_currency(
hightxt="franc/s" val, currency=currency, cents=cents, separator=separator,
return self.to_splitnum(val, hightxt=hightxt, lowtxt="centime/s", adjective=adjective)
jointxt="et",longval=longval) return result
n2w = Num2Word_FR()
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()

49
num2words/lang_FR_BE.py Normal file
View File

@@ -0,0 +1,49 @@
# -*- coding: 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 print_function, unicode_literals
from .lang_FR import Num2Word_FR
class Num2Word_FR_BE(Num2Word_FR):
def setup(self):
Num2Word_FR.setup(self)
self.mid_numwords = [(1000, "mille"), (100, "cent"), (90, "nonante"),
(80, "quatre-vingt"), (70, "septante"),
(60, "soixante"), (50, "cinquante"),
(40, "quarante"), (30, "trente")]
def merge(self, curr, next):
ctext, cnum, ntext, nnum = curr + next
if cnum == 1:
if nnum < 1000000:
return next
if cnum < 1000 and nnum != 1000 and\
ntext[-1] != "s" and not nnum % 100:
ntext += "s"
if nnum < cnum < 100:
if nnum % 10 == 1:
return ("%s et %s" % (ctext, ntext), cnum + nnum)
return ("%s-%s" % (ctext, ntext), cnum + nnum)
if nnum > cnum:
return ("%s %s" % (ctext, ntext), cnum * nnum)
return ("%s %s" % (ctext, ntext), cnum + nnum)

48
num2words/lang_FR_CH.py Normal file
View File

@@ -0,0 +1,48 @@
# -*- coding: 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 print_function, unicode_literals
from .lang_FR import Num2Word_FR
class Num2Word_FR_CH(Num2Word_FR):
def setup(self):
Num2Word_FR.setup(self)
self.mid_numwords = [(1000, "mille"), (100, "cent"), (90, "nonante"),
(80, "huitante"), (70, "septante"),
(60, "soixante"), (50, "cinquante"),
(40, "quarante"), (30, "trente")]
def merge(self, curr, next):
ctext, cnum, ntext, nnum = curr + next
if cnum == 1:
if nnum < 1000000:
return next
if cnum < 1000 and nnum != 1000 and\
ntext[-1] != "s" and not nnum % 100:
ntext += "s"
if nnum < cnum < 100:
if nnum % 10 == 1:
return ("%s et %s" % (ctext, ntext), cnum + nnum)
return ("%s-%s" % (ctext, ntext), cnum + nnum)
if nnum > cnum:
return ("%s %s" % (ctext, ntext), cnum * nnum)
return ("%s %s" % (ctext, ntext), cnum + nnum)

33
num2words/lang_FR_DZ.py Normal file
View File

@@ -0,0 +1,33 @@
# -*- coding: 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_FR import Num2Word_FR
class Num2Word_FR_DZ(Num2Word_FR):
CURRENCY_FORMS = {
'DIN': (('dinard', 'dinards'), ('centime', 'centimes')),
}
def to_currency(self, val, currency='DIN', cents=True, separator=' et',
adjective=False):
result = super(Num2Word_FR, self).to_currency(
val, currency=currency, cents=cents, separator=separator,
adjective=adjective)
return result

168
num2words/lang_HE.py Normal file
View File

@@ -0,0 +1,168 @@
# -*- coding: 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 print_function, unicode_literals
from .base import Num2Word_Base
from .utils import get_digits, splitbyx
ZERO = (u'אפס',)
ONES = {
1: (u'אחת',),
2: (u'שתים',),
3: (u'שלש',),
4: (u'ארבע',),
5: (u'חמש',),
6: (u'שש',),
7: (u'שבע',),
8: (u'שמונה',),
9: (u'תשע',),
}
TENS = {
0: (u'עשר',),
1: (u'אחת עשרה',),
2: (u'שתים עשרה',),
3: (u'שלש עשרה',),
4: (u'ארבע עשרה',),
5: (u'חמש עשרה',),
6: (u'שש עשרה',),
7: (u'שבע עשרה',),
8: (u'שמונה עשרה',),
9: (u'תשע עשרה',),
}
TWENTIES = {
2: (u'עשרים',),
3: (u'שלשים',),
4: (u'ארבעים',),
5: (u'חמישים',),
6: (u'ששים',),
7: (u'שבעים',),
8: (u'שמונים',),
9: (u'תשעים',),
}
HUNDRED = {
1: (u'מאה',),
2: (u'מאתיים',),
3: (u'מאות',)
}
THOUSANDS = {
1: (u'אלף',),
2: (u'אלפיים',),
3: (u'שלשת אלפים',),
4: (u'ארבעת אלפים',),
5: (u'חמשת אלפים',),
6: (u'ששת אלפים',),
7: (u'שבעת אלפים',),
8: (u'שמונת אלפים',),
9: (u'תשעת אלפים',),
}
AND = u'ו'
def pluralize(n, forms):
form = 1 if n == 0 else 0 if n == 1 else 1
return forms[form]
def int2word(n):
if n > 9999: # doesn't yet work for numbers this big
raise NotImplementedError()
if n == 0:
return ZERO[0]
words = []
chunks = list(splitbyx(str(n), 3))
i = len(chunks)
for x in chunks:
i -= 1
if x == 0:
continue
n1, n2, n3 = get_digits(x)
if i > 0:
words.append(THOUSANDS[n1][0])
continue
if n3 > 0:
if n3 <= 2:
words.append(HUNDRED[n3][0])
else:
words.append(ONES[n3][0] + ' ' + HUNDRED[3][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(THOUSANDS[i][0])
# source: https://hebrew-academy.org.il/2017/01/30/ו-החיבור-במספרים/
if len(words) > 1:
words[-1] = AND + words[-1]
return ' '.join(words)
def n2w(n):
return int2word(int(n))
class Num2Word_HE(Num2Word_Base):
CURRENCY_FORMS = {
'NIS': (('שקל', 'שקלים'), ('אגורה', 'אגורות')),
'EUR': (('אירו', 'אירו'), ('סנט', 'סנט')),
'USD': (('דולר', 'דולרים'), ('סנט', 'סנט')),
}
def to_cardinal(self, number):
return n2w(number)
def to_ordinal(self, number):
raise NotImplementedError()
def pluralize(self, n, forms):
return pluralize(n, forms)
def to_currency(self, val, currency='NIS', cents=True, separator=' ו',
adjective=False):
result = super(Num2Word_HE, self).to_currency(
val, currency=currency, cents=cents, separator=separator,
adjective=adjective)
# In Hebrew the separator is along with the following word
return result.replace(" ו ", " ו")
if __name__ == '__main__':
yo = Num2Word_HE()
nums = [1, 11, 21, 24, 99, 100, 101, 200, 211, 345, 1000, 1011]
for num in nums:
print(num, yo.to_cardinal(num))

165
num2words/lang_HU.py Normal file
View File

@@ -0,0 +1,165 @@
# -*- coding: 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 division, print_function, unicode_literals
from . import lang_EU
ZERO = 'nulla'
class Num2Word_HU(lang_EU.Num2Word_EU):
GIGA_SUFFIX = "illiárd"
MEGA_SUFFIX = "illió"
def setup(self):
super(Num2Word_HU, self).setup()
self.negword = "mínusz "
self.pointword = "egész"
self.mid_numwords = [(1000, "ezer"), (100, "száz"), (90, "kilencven"),
(80, "nyolcvan"), (70, "hetven"), (60, "hatvan"),
(50, "ötven"), (40, "negyven"), (30, "harminc")]
low_numwords = ["kilenc", "nyolc", "hét", "hat", "öt", "négy", "három",
"kettő", "egy"]
self.low_numwords = (['tizen' + w for w in low_numwords]
+ ['tíz']
+ low_numwords)
self.low_numwords = (['huszon' + w for w in low_numwords]
+ ['húsz']
+ self.low_numwords
+ [ZERO])
self.partial_ords = {
'nulla': 'nullad',
'egy': 'egyed',
'kettő': 'ketted',
'három': 'harmad',
'négy': 'negyed',
'öt': 'ötöd',
'hat': 'hatod',
'hét': 'heted',
'nyolc': 'nyolcad',
'kilenc': 'kilenced',
'tíz': 'tized',
'húsz': 'huszad',
'harminc': 'harmincad',
'negyven': 'negyvened',
'ötven': 'ötvened',
'hatvan': 'hatvanad',
'hetven': 'hetvened',
'nyolcvan': 'nyolcvanad',
'kilencven': 'kilencvened',
'száz': 'század',
'ezer': 'ezred',
'illió': 'milliomod',
'illiárd': 'milliárdod'
}
def to_cardinal(self, value, zero=ZERO):
if int(value) != value:
return self.to_cardinal_float(value)
elif value < 0:
out = self.negword + self.to_cardinal(-value)
elif value == 0:
out = zero
elif zero == '' and value == 2:
out = 'két'
elif value < 30:
out = self.cards[value]
elif value < 100:
out = self.tens_to_cardinal(value)
elif value < 1000:
out = self.hundreds_to_cardinal(value)
elif value < 10**6:
out = self.thousands_to_cardinal(value)
else:
out = self.big_number_to_cardinal(value)
return out
def tens_to_cardinal(self, value):
try:
return self.cards[value]
except KeyError:
return self.cards[value // 10 * 10] + self.to_cardinal(value % 10)
def hundreds_to_cardinal(self, value):
hundreds = value // 100
prefix = "száz"
if hundreds != 1:
prefix = self.to_cardinal(hundreds, zero="") + prefix
postfix = self.to_cardinal(value % 100, zero="")
return prefix + postfix
def thousands_to_cardinal(self, value):
thousands = value // 1000
prefix = "ezer"
if thousands != 1:
prefix = self.to_cardinal(thousands, zero="") + prefix
postfix = self.to_cardinal(value % 1000, zero="")
return prefix + ('' if value <= 2000 or not postfix else '-') + postfix
def big_number_to_cardinal(self, value):
digits = len(str(value))
digits = digits if digits % 3 != 0 else digits - 2
exp = 10 ** (digits // 3 * 3)
rest = self.to_cardinal(value % exp, '')
return (self.to_cardinal(value // exp, '') + self.cards[exp]
+ ('-' + rest if rest else ''))
def to_ordinal(self, value):
if value < 0:
return self.negword + self.to_ordinal(-value)
if value == 1:
return 'első'
elif value == 2:
return 'második'
else:
out = self.to_cardinal(value)
for card_word, ord_word in self.partial_ords.items():
if out[-len(card_word):] == card_word:
out = out[:-len(card_word)] + ord_word
break
return out + 'ik'
def to_ordinal_num(self, value):
self.verify_ordinal(value)
return str(value) + '.'
def to_year(self, val, suffix=None, longval=True):
# suffix is prefix here
prefix = ''
if val < 0 or suffix is not None:
val = abs(val)
prefix = (suffix + ' ' if suffix is not None else 'i. e. ')
return prefix + self.to_cardinal(val)
def to_currency(self, val, currency='HUF', cents=True, separator=',',
adjective=False):
return super(Num2Word_HU, self).to_currency(
val, currency, cents, separator, adjective)
def to_cardinal_float(self, value):
if abs(value) != value:
return self.negword + self.to_cardinal_float(-value)
left, right = str(value).split('.')
return (self.to_cardinal(int(left))
+ ' egész '
+ self.to_cardinal(int(right))
+ ' ' + self.partial_ords[self.cards[10 ** len(right)]])

204
num2words/lang_ID.py Normal file
View File

@@ -0,0 +1,204 @@
# -*- coding: 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 print_function, unicode_literals
class Num2Word_ID():
BASE = {0: [],
1: ["satu"],
2: ["dua"],
3: ["tiga"],
4: ["empat"],
5: ["lima"],
6: ["enam"],
7: ["tujuh"],
8: ["delapan"],
9: ["sembilan"]}
TENS_TO = {3: "ribu",
6: "juta",
9: "miliar",
12: "triliun",
15: "kuadriliun",
18: "kuantiliun",
21: "sekstiliun",
24: "septiliun",
27: "oktiliun",
30: "noniliun",
33: "desiliun"}
errmsg_floatord = "Cannot treat float number as ordinal"
errmsg_negord = "Cannot treat negative number as ordinal"
errmsg_toobig = "Too large"
max_num = 10 ** 36
def split_by_koma(self, number):
return str(number).split('.')
def split_by_3(self, number):
"""
starting here, it groups the number by three from the tail
'1234567' -> (('1',),('234',),('567',))
:param number:str
:rtype:tuple
"""
blocks = ()
length = len(number)
if length < 3:
blocks += ((number,),)
else:
len_of_first_block = length % 3
if len_of_first_block > 0:
first_block = number[0:len_of_first_block],
blocks += first_block,
for i in range(len_of_first_block, length, 3):
next_block = (number[i:i + 3],),
blocks += next_block
return blocks
def spell(self, blocks):
"""
it adds the list of spelling to the blocks
(
('1',),('034',)) -> (('1',['satu']),('234',['tiga', 'puluh', 'empat'])
)
:param blocks: tuple
:rtype: tuple
"""
word_blocks = ()
first_block = blocks[0]
if len(first_block[0]) == 1:
if first_block[0] == '0':
spelling = ['nol']
else:
spelling = self.BASE[int(first_block[0])]
elif len(first_block[0]) == 2:
spelling = self.puluh(first_block[0])
else:
spelling = (
self.ratus(first_block[0][0]) + self.puluh(first_block[0][1:3])
)
word_blocks += (first_block[0], spelling),
for block in blocks[1:]:
spelling = self.ratus(block[0][0]) + self.puluh(block[0][1:3])
block += spelling,
word_blocks += block,
return word_blocks
def ratus(self, number):
# it is used to spell
if number == '1':
return ['seratus']
elif number == '0':
return []
else:
return self.BASE[int(number)] + ['ratus']
def puluh(self, number):
# it is used to spell
if number[0] == '1':
if number[1] == '0':
return ['sepuluh']
elif number[1] == '1':
return ['sebelas']
else:
return self.BASE[int(number[1])] + ['belas']
elif number[0] == '0':
return self.BASE[int(number[1])]
else:
return (
self.BASE[int(number[0])] + ['puluh']
+ self.BASE[int(number[1])]
)
def spell_float(self, float_part):
# spell the float number
word_list = []
for n in float_part:
if n == '0':
word_list += ['nol']
continue
word_list += self.BASE[int(n)]
return ' '.join(['', 'koma'] + word_list)
def join(self, word_blocks, float_part):
"""
join the words by first join lists in the tuple
:param word_blocks: tuple
:rtype: str
"""
word_list = []
length = len(word_blocks) - 1
first_block = word_blocks[0],
start = 0
if length == 1 and first_block[0][0] == '1':
word_list += ['seribu']
start = 1
for i in range(start, length + 1, 1):
word_list += word_blocks[i][1]
if not word_blocks[i][1]:
continue
if i == length:
break
word_list += [self.TENS_TO[(length - i) * 3]]
return ' '.join(word_list) + float_part
def to_cardinal(self, number):
if number >= self.max_num:
raise OverflowError(self.errmsg_toobig % (number, self.max_num))
minus = ''
if number < 0:
minus = 'min '
float_word = ''
n = self.split_by_koma(abs(number))
if len(n) == 2:
float_word = self.spell_float(n[1])
return minus + self.join(self.spell(self.split_by_3(n[0])), float_word)
def to_ordinal(self, number):
self.verify_ordinal(number)
out_word = self.to_cardinal(number)
if out_word == "satu":
return "pertama"
return "ke" + out_word
def to_ordinal_num(self, number):
self.verify_ordinal(number)
return "ke-" + str(number)
def to_currency(self, value):
return self.to_cardinal(value) + " rupiah"
def to_year(self, value):
return self.to_cardinal(value)
def verify_ordinal(self, value):
if not value == int(value):
raise TypeError(self.errmsg_floatord % value)
if not abs(value) == value:
raise TypeError(self.errmsg_negord % value)

241
num2words/lang_IT.py Normal file
View File

@@ -0,0 +1,241 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2018-2019, Filippo Costa. 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
# Globals
# -------
ZERO = "zero"
CARDINAL_WORDS = [
ZERO, "uno", "due", "tre", "quattro", "cinque", "sei", "sette", "otto",
"nove", "dieci", "undici", "dodici", "tredici", "quattordici", "quindici",
"sedici", "diciassette", "diciotto", "diciannove"
]
ORDINAL_WORDS = [
ZERO, "primo", "secondo", "terzo", "quarto", "quinto", "sesto", "settimo",
"ottavo", "nono", "decimo", "undicesimo", "dodicesimo", "tredicesimo",
"quattordicesimo", "quindicesimo", "sedicesimo", "diciassettesimo",
"diciottesimo", "diciannovesimo"
]
# The script can extrapolate the missing numbers from the base forms.
STR_TENS = {2: "venti", 3: "trenta", 4: "quaranta", 6: "sessanta"}
# These prefixes are used for extremely big numbers.
EXPONENT_PREFIXES = [
ZERO, "m", "b", "tr", "quadr", "quint", "sest", "sett", "ott", "nov", "dec"
]
GENERIC_DOLLARS = ('dollaro', 'dollari')
GENERIC_CENTS = ('centesimo', 'centesimi')
CURRENCIES_UNA = ('GBP')
# Main class
# ==========
class Num2Word_IT(Num2Word_EU):
CURRENCY_FORMS = {
'EUR': (('euro', 'euro'), GENERIC_CENTS),
'USD': (GENERIC_DOLLARS, GENERIC_CENTS),
'GBP': (('sterlina', 'sterline'), ('penny', 'penny')),
'CNY': (('yuan', 'yuan'), ('fen', 'fen')),
}
MINUS_PREFIX_WORD = "meno "
FLOAT_INFIX_WORD = " virgola "
def setup(self):
Num2Word_EU.setup(self)
def __init__(self):
pass
def float_to_words(self, float_number, ordinal=False):
if ordinal:
prefix = self.to_ordinal(int(float_number))
else:
prefix = self.to_cardinal(int(float_number))
float_part = str(float_number).split('.')[1]
postfix = " ".join(
# Drops the trailing zero and comma
[self.to_cardinal(int(c)) for c in float_part]
)
return prefix + Num2Word_IT.FLOAT_INFIX_WORD + postfix
def tens_to_cardinal(self, number):
tens = number // 10
units = number % 10
if tens in STR_TENS:
prefix = STR_TENS[tens]
else:
prefix = CARDINAL_WORDS[tens][:-1] + "anta"
postfix = omitt_if_zero(CARDINAL_WORDS[units])
return phonetic_contraction(prefix + postfix)
def hundreds_to_cardinal(self, number):
hundreds = number // 100
prefix = "cento"
if hundreds != 1:
prefix = CARDINAL_WORDS[hundreds] + prefix
postfix = omitt_if_zero(self.to_cardinal(number % 100))
return phonetic_contraction(prefix + postfix)
def thousands_to_cardinal(self, number):
thousands = number // 1000
if thousands == 1:
prefix = "mille"
else:
prefix = self.to_cardinal(thousands) + "mila"
postfix = omitt_if_zero(self.to_cardinal(number % 1000))
# "mille" and "mila" don't need any phonetic contractions
return prefix + postfix
def big_number_to_cardinal(self, number):
digits = [c for c in str(number)]
length = len(digits)
if length >= 66:
raise NotImplementedError("The given number is too large.")
# This is how many digits come before the "illion" term.
# cento miliardi => 3
# dieci milioni => 2
# un miliardo => 1
predigits = length % 3 or 3
multiplier = digits[:predigits]
exponent = digits[predigits:]
# Default infix string: "milione", "biliardo", "sestilione", ecc.
infix = exponent_length_to_string(len(exponent))
if multiplier == ["1"]:
prefix = "un "
else:
prefix = self.to_cardinal(int("".join(multiplier)))
# Plural form ~~~~~~~~~~~
infix = " " + infix[:-1] + "i"
# Read as: Does the value of exponent equal 0?
if set(exponent) != set("0"):
postfix = self.to_cardinal(int("".join(exponent)))
if " e " in postfix:
infix += ", "
else:
infix += " e "
else:
postfix = ""
return prefix + infix + postfix
def to_cardinal(self, number):
if number < 0:
string = Num2Word_IT.MINUS_PREFIX_WORD + self.to_cardinal(-number)
elif isinstance(number, float):
string = self.float_to_words(number)
elif number < 20:
string = CARDINAL_WORDS[number]
elif number < 100:
string = self.tens_to_cardinal(number)
elif number < 1000:
string = self.hundreds_to_cardinal(number)
elif number < 1000000:
string = self.thousands_to_cardinal(number)
else:
string = self.big_number_to_cardinal(number)
return accentuate(string)
def to_ordinal(self, number):
tens = number % 100
# Italian grammar is poorly defined here ¯\_(ツ)_/¯:
# centodecimo VS centodieciesimo VS centesimo decimo?
is_outside_teens = not 10 < tens < 20
if number < 0:
return Num2Word_IT.MINUS_PREFIX_WORD + self.to_ordinal(-number)
elif number % 1 != 0:
return self.float_to_words(number, ordinal=True)
elif number < 20:
return ORDINAL_WORDS[number]
elif is_outside_teens and tens % 10 == 3:
# Gets ride of the accent ~~~~~~~~~~
return self.to_cardinal(number)[:-1] + "eesimo"
elif is_outside_teens and tens % 10 == 6:
return self.to_cardinal(number) + "esimo"
else:
string = self.to_cardinal(number)[:-1]
if string[-3:] == "mil":
string += "l"
return string + "esimo"
def to_currency(self, val, currency='EUR', cents=True, separator=' e',
adjective=False):
result = super(Num2Word_IT, self).to_currency(
val, currency=currency, cents=cents, separator=separator,
adjective=adjective)
# Handle exception. In italian language is "un euro",
# "un dollaro" etc. (not "uno euro", "uno dollaro").
# There is an exception, some currencies need "una":
# e.g. "una sterlina"
if currency in CURRENCIES_UNA:
list_result = result.split(" ")
if list_result[0] == "uno":
list_result[0] = list_result[0].replace("uno", "una")
result = " ".join(list_result)
result = result.replace("uno", "un")
return result
# Utils
# =====
def phonetic_contraction(string):
return (string
.replace("oo", "o") # ex. "centootto"
.replace("ao", "o") # ex. "settantaotto"
.replace("io", "o") # ex. "ventiotto"
.replace("au", "u") # ex. "trentauno"
.replace("iu", "u") # ex. "ventiunesimo"
)
def exponent_length_to_string(exponent_length):
# We always assume `exponent` to be a multiple of 3. If it's not true, then
# Num2Word_IT.big_number_to_cardinal did something wrong.
prefix = EXPONENT_PREFIXES[exponent_length // 6]
if exponent_length % 6 == 0:
return prefix + "ilione"
else:
return prefix + "iliardo"
def accentuate(string):
# This is inefficient: it may do several rewritings when deleting
# half-sentence accents. However, it is the easiest method and speed is
# not crucial (duh), so...
return " ".join(
# Deletes half-sentence accents and accentuates the last "tre"
[w.replace("tré", "tre")[:-3] + "tré"
# We shouldn't accentuate a single "tre": is has to be a composite
# word. ~~~~~~~~~~
if w[-3:] == "tre" and len(w) > 3
# Deletes half-sentence accents anyway
# ~~~~~~~~~~~~~~~~~~~~~~
else w.replace("tré", "tre")
for w in string.split()
])
def omitt_if_zero(number_to_string):
return "" if number_to_string == ZERO else number_to_string

590
num2words/lang_JA.py Normal file
View File

@@ -0,0 +1,590 @@
# -*- coding: 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 division, print_function, unicode_literals
from .base import Num2Word_Base
from .compat import strtype, to_s
from .currency import parse_currency_parts, prefix_currency
def select_text(text, reading=False, prefer=None):
"""Select the correct text from the Japanese number, reading and
alternatives"""
# select kanji number or kana reading
if reading:
text = text[1]
else:
text = text[0]
# select the preferred one or the first one from multiple alternatives
if not isinstance(text, strtype):
common = set(text) & set(prefer or set())
if len(common) == 1:
text = common.pop()
else:
text = text[0]
return text
def rendaku_merge_pairs(lpair, rpair):
"""Merge lpair < rpair while applying semi-irregular rendaku rules"""
ltext, lnum = lpair
rtext, rnum = rpair
if lnum > rnum:
raise ValueError
if rpair == ("ひゃく", 100):
if lpair == ("さん", 3):
rtext = "びゃく"
elif lpair == ("ろく", 6):
ltext = "ろっ"
rtext = "ぴゃく"
elif lpair == ("はち", 8):
ltext = "はっ"
rtext = "ぴゃく"
elif rpair == ("せん", 1000):
if lpair == ("さん", 3):
rtext = "ぜん"
elif lpair == ("はち", 8):
ltext = "はっ"
elif rpair == ("ちょう", 10**12):
if lpair == ("いち", 1):
ltext = "いっ"
elif lpair == ("はち", 8):
ltext = "はっ"
elif lpair == ("じゅう", 10):
ltext = "じゅっ"
elif rpair == ("けい", 10**16):
if lpair == ("いち", 1):
ltext = "いっ"
elif lpair == ("ろく", 6):
ltext = "ろっ"
elif lpair == ("はち", 8):
ltext = "はっ"
elif lpair == ("じゅう", 10):
ltext = "じゅっ"
elif lpair == ("ひゃく", 100):
ltext = "ひゃっ"
return ("%s%s" % (ltext, rtext), lnum * rnum)
# Source: https://www.sljfaq.org/afaq/era-list.html
# if there are multiple eras for the same year, use the last one
ERA_START = [
(645, ("大化", "たいか")),
(650, ("白雉", "はくち")),
(686, ("朱鳥", "しゅちょう")),
(701, ("大宝", "たいほう")),
(704, ("慶雲", "けいうん")),
(708, ("和銅", "わどう")),
(715, ("霊亀", "れいき")),
(717, ("養老", "ようろう")),
(724, ("神亀", "じんき")),
(729, ("天平", "てんぴょう")),
(749, ("天平感宝", "てんぴょうかんぽう")),
(749, ("天平勝宝", "てんぴょうしょうほう")),
(757, ("天平宝字", "てんぴょうじょうじ")),
(765, ("天平神護", "てんぴょうじんご")),
(767, ("神護景雲", "じんごけいうん")),
(770, ("宝亀", "ほうき")),
(781, ("天応", "てんおう")),
(782, ("延暦", "えんりゃく")),
(806, ("大同", "だいどう")),
(810, ("弘仁", "こうにん")),
(823, ("天長", "てんちょう")),
(834, ("承和", "じょうわ")),
(848, ("嘉祥", "かしょう")),
(851, ("仁寿", "にんじゅ")),
(855, ("斉衡", "さいこう")),
(857, ("天安", "てんあん")),
(859, ("貞観", "じょうがん")),
(877, ("元慶", "がんぎょう")),
(885, ("仁和", "にんな")),
(889, ("寛平", "かんぴょう")),
(898, ("昌泰", "しょうたい")),
(901, ("延喜", "えんぎ")),
(923, ("延長", "えんちょう")),
(931, ("承平", "じょうへい")),
(938, ("天慶", "てんぎょう")),
(947, ("天暦", "てんりゃく")),
(957, ("天徳", "てんとく")),
(961, ("応和", "おうわ")),
(964, ("康保", "こうほう")),
(968, ("安和", "あんな")),
(970, ("天禄", "てんろく")),
(974, ("天延", "てんえん")),
(976, ("貞元", "じょうげん")),
(979, ("天元", "てんげん")),
(983, ("永観", "えいかん")),
(985, ("寛和", "かんな")),
(987, ("永延", "えいえん")),
(989, ("永祚", "えいそ")),
(990, ("正暦", "しょうりゃく")),
(995, ("長徳", "ちょうとく")),
(999, ("長保", "ちょうほう")),
(1004, ("寛弘", "かんこう")),
(1013, ("長和", "ちょうわ")),
(1017, ("寛仁", "かんにん")),
(1021, ("治安", "じあん")),
(1024, ("万寿", "まんじゅ")),
(1028, ("長元", "ちょうげん")),
(1037, ("長暦", "ちょうりゃく")),
(1040, ("長久", "ちょうきゅう")),
(1045, ("寛徳", "かんとく")),
(1046, ("永承", "えいしょう")),
(1053, ("天喜", "てんぎ")),
(1058, ("康平", "こうへい")),
(1065, ("治暦", "じりゃく")),
(1069, ("延久", "えんきゅう")),
(1074, ("承保", "じょうほう")),
(1078, ("承暦", "じょうりゃく")),
(1081, ("永保", "えいほう")),
(1084, ("応徳", "おうとく")),
(1087, ("寛治", "かんじ")),
(1095, ("嘉保", "かほう")),
(1097, ("永長", "えいちょう")),
(1098, ("承徳", "じょうとく")),
(1099, ("康和", "こうわ")),
(1104, ("長治", "ちょうじ")),
(1106, ("嘉承", "かじょう")),
(1108, ("天仁", "てんにん")),
(1110, ("天永", "てんねい")),
(1113, ("永久", "えいきゅう")),
(1118, ("元永", "げんえい")),
(1120, ("保安", "ほうあん")),
(1124, ("天治", "てんじ")),
(1126, ("大治", "だいじ")),
(1131, ("天承", "てんしょう")),
(1132, ("長承", "ちょうしょう")),
(1135, ("保延", "ほうえん")),
(1141, ("永治", "えいじ")),
(1142, ("康治", "こうじ")),
(1144, ("天養", "てんよう")),
(1145, ("久安", "きゅうあん")),
(1151, ("仁平", "にんぺい")),
(1154, ("久寿", "きゅうじゅ")),
(1156, ("保元", "ほうげん")),
(1159, ("平治", "へいじ")),
(1160, ("永暦", "えいりゃく")),
(1161, ("応保", "おうほう")),
(1163, ("長寛", "ちょうかん")),
(1165, ("永万", "えいまん")),
(1166, ("仁安", "にんあん")),
(1169, ("嘉応", "かおう")),
(1171, ("承安", "しょうあん")),
(1175, ("安元", "あんげん")),
(1177, ("治承", "じしょう")),
(1181, ("養和", "ようわ")),
(1182, ("寿永", "じゅえい")),
(1184, ("元暦", "げんりゃく")),
(1185, ("文治", "ぶんじ")),
(1190, ("建久", "けんきゅう")),
(1199, ("正治", "しょうじ")),
(1201, ("建仁", "けんにん")),
(1204, ("元久", "げんきゅう")),
(1206, ("建永", "けんえい")),
(1207, ("承元", "じょうげん")),
(1211, ("建暦", "けんりゃく")),
(1214, ("建保", "けんぽう")),
(1219, ("承久", "じょうきゅう")),
(1222, ("貞応", "じょうおう")),
(1225, ("元仁", "げんにん")),
(1225, ("嘉禄", "かろく")),
(1228, ("安貞", "あんてい")),
(1229, ("寛喜", "かんき")),
(1232, ("貞永", "じょうえい")),
(1233, ("天福", "てんぷく")),
(1235, ("文暦", "ぶんりゃく")),
(1235, ("嘉禎", "かてい")),
(1239, ("暦仁", "りゃくにん")),
(1239, ("延応", "えんおう")),
(1240, ("仁治", "にんじ")),
(1243, ("寛元", "かんげん")),
(1247, ("宝治", "ほうじ")),
(1249, ("建長", "けんちょう")),
(1256, ("康元", "こうげん")),
(1257, ("正嘉", "しょうか")),
(1259, ("正元", "しょうげん")),
(1260, ("文応", "ぶんおう")),
(1261, ("弘長", "こうちょう")),
(1264, ("文永", "ぶんえい")),
(1275, ("健治", "けんじ")),
(1278, ("弘安", "こうあん")),
(1288, ("正応", "しょうおう")),
(1293, ("永仁", "えいにん")),
(1299, ("正安", "しょうあん")),
(1303, ("乾元", "けんげん")),
(1303, ("嘉元", "かげん")),
(1307, ("徳治", "とくじ")),
(1308, ("延慶", "えんきょう")),
(1311, ("応長", "おうちょう")),
(1312, ("正和", "しょうわ")),
(1317, ("文保", "ぶんぽう")),
(1319, ("元応", "げんおう")),
(1321, ("元亨", "げんこう")),
(1325, ("正中", "しょうちゅ")),
(1326, ("嘉暦", "かりゃく")),
(1329, ("元徳", "げんとく")),
(1331, ("元弘", "げんこう")),
(1332, ("正慶", "しょうけい")),
(1334, ("建武", "けんむ")),
(1336, ("延元", "えいげん")),
(1338, ("暦応", "りゃくおう")),
(1340, ("興国", "こうこく")),
(1342, ("康永", "こうえい")),
(1345, ("貞和", "じょうわ")),
(1347, ("正平", "しょうへい")),
(1350, ("観応", "かんおう")),
(1352, ("文和", "ぶんな")),
(1356, ("延文", "えんぶん")),
(1361, ("康安", "こうあん")),
(1362, ("貞治", "じょうじ")),
(1368, ("応安", "おうあん")),
(1370, ("建徳", "けんとく")),
(1372, ("文中", "ぶんちゅう")),
(1375, ("永和", "えいわ")),
(1375, ("天授", "てんじゅ")),
(1379, ("康暦", "こうりゃく")),
(1381, ("永徳", "えいとく")),
(1381, ("弘和", "こうわ")),
(1384, ("至徳", "しとく")),
(1384, ("元中", "げんちゅう")),
(1387, ("嘉慶", "かけい")),
(1389, ("康応", "こうおう")),
(1390, ("明徳", "めいとく")),
(1394, ("応永", "おうえい")),
(1428, ("正長", "しょうちょう")),
(1429, ("永享", "えいきょう")),
(1441, ("嘉吉", "かきつ")),
(1444, ("文安", "ぶんあん")),
(1449, ("宝徳", "ほうとく")),
(1452, ("享徳", "きょうとく")),
(1455, ("康正", "こうしょう")),
(1457, ("長禄", "ちょうろく")),
(1461, ("寛正", "かんしょう")),
(1466, ("文正", "ぶんしょう")),
(1467, ("応仁", "おうにん")),
(1469, ("文明", "ぶんめい")),
(1487, ("長享", "ちょうきょう")),
(1489, ("延徳", "えんとく")),
(1492, ("明応", "めいおう")),
(1501, ("文亀", "ぶんき")),
(1504, ("永正", "えいしょう")),
(1521, ("大永", "だいえい")),
(1528, ("享禄", "きょうろく")),
(1532, ("天文", "てんぶん")),
(1555, ("弘治", "こうじ")),
(1558, ("永禄", "えいろく")),
(1570, ("元亀", "げんき")),
(1573, ("天正", "てんしょう")),
(1593, ("文禄", "ぶんろく")),
(1596, ("慶長", "けいちょう")),
(1615, ("元和", "げんな")),
(1624, ("寛永", "かんえい")),
(1645, ("正保", "しょうほう")),
(1648, ("慶安", "けいあん")),
(1652, ("承応", "じょうおう")),
(1655, ("明暦", "めいれき")),
(1658, ("万治", "まんじ")),
(1661, ("寛文", "かんぶん")),
(1673, ("延宝", "えんぽう")),
(1681, ("天和", "てんな")),
(1684, ("貞享", "じょうきょう")),
(1688, ("元禄", "げんろく")),
(1704, ("宝永", "ほうえい")),
(1711, ("正徳", "しょうとく")),
(1716, ("享保", "きょうほう")),
(1736, ("元文", "げんぶん")),
(1741, ("寛保", "かんぽう")),
(1744, ("延享", "えんきょう")),
(1748, ("寛延", "かんえん")),
(1751, ("宝暦", "ほうれき")),
(1764, ("明和", "めいわ")),
(1773, ("安永", "あんえい")),
(1781, ("天明", "てんめい")),
(1801, ("寛政", "かんせい")),
(1802, ("享和", "きょうわ")),
(1804, ("文化", "ぶんか")),
(1818, ("文政", "ぶんせい")),
(1831, ("天保", "てんぽう")),
(1845, ("弘化", "こうか")),
(1848, ("嘉永", "かえい")),
(1855, ("安政", "あんせい")),
(1860, ("万延", "まんえい")),
(1861, ("文久", "ぶんきゅう")),
(1864, ("元治", "げんじ")),
(1865, ("慶応", "けいおう")),
(1868, ("明治", "めいじ")),
(1912, ("大正", "たいしょう")),
(1926, ("昭和", "しょうわ")),
(1989, ("平成", "へいせい")),
(2019, ("令和", "れいわ")),
]
class Num2Word_JA(Num2Word_Base):
CURRENCY_FORMS = {
'JPY': (('', 'えん'), ()),
}
def set_high_numwords(self, high):
max = 4 * len(high)
for word, n in zip(high, range(max, 0, -4)):
self.cards[10 ** n] = word
def setup(self):
self.negword = "マイナス"
self.pointword = ("", "てん")
self.exclude_title = ["", "マイナス"]
self.high_numwords = [
("", "まん"), # 10**4 man
("", "おく"), # 10**8 oku
("", "ちょう"), # 10**12 chō
("", "けい"), # 10**16 kei
("", "がい"), # 10**20 gai
("", ""), # 10**24 shi
("", "じょう"), # 10**28 jō
("", "こう"), # 10**32 kō
("", "かん"), # 10**36 kan
("", "せい"), # 10**40 sei
("", "さい"), # 10**44 sai
("", "ごく"), # 10**48 goku
]
self.high_numwords.reverse()
self.mid_numwords = [
(1000, ("", "せん")),
(100, ("", "ひゃく")),
]
self.low_numwords = [
("", "じゅう"), # 10 jū
("", "きゅう"), # 9 kyū
("", "はち"), # 8 hachi
("", ("なな", "しち")), # 7 nana, shichi
("", "ろく"), # 6 roku
("", ""), # 5 go
("", ("よん", "")), # 4 yon, shi
("", "さん"), # 3 san
("", ""), # 2 ni
("", "いち"), # 1 ichi
# both are alternatives, 零 doesn't map to ゼロ or to れい
(("", ""), ("ゼロ", "れい")), # 0 ZERO, rei
]
def merge(self, lpair, rpair):
ltext, lnum = lpair
rtext, rnum = rpair
fmt = "%s%s"
# ignore lpair if lnum is 1 and rnum is less than 10000
if lnum == 1 and rnum < 10000:
return rpair
# rnum is added to lnum
elif lnum > rnum:
return (fmt % (ltext, rtext), lnum + rnum)
# rnum is multiplied by lnum
elif lnum < rnum:
return rendaku_merge_pairs(lpair, rpair)
def _ordinal_suffix(self, reading, counter):
if reading:
if counter == "":
return "ばんめ"
else:
raise NotImplementedError(
"Reading not implemented for %s" % counter)
else:
return counter + ""
def to_ordinal(self, value, reading=False, prefer=None, counter=""):
self.verify_ordinal(value)
base = self.to_cardinal(value, reading=reading, prefer=prefer)
return "%s%s" % (base, self._ordinal_suffix(reading, counter))
def to_ordinal_num(self, value, reading=False, counter=""):
return "%s%s" % (value, self._ordinal_suffix(reading, counter))
def to_year(self, val, suffix=None, longval=True, reading=False,
prefer=None, era=True):
year = val
# Gregorian calendar
if not era:
prefix = ""
if year < 0:
year = abs(year)
prefix = "きげんぜん" if reading else "紀元前"
year_words = self.to_cardinal(year, reading=reading, prefer=prefer)
if reading and year % 10 == 9:
year_words = year_words[:-3] + ""
return "%s%s%s" % (prefix, year_words, "ねん" if reading else "")
# Era calendar (default)
min_year = ERA_START[0][0]
last_era_idx = len(ERA_START) - 1
if year < min_year:
raise ValueError(
"Can't convert years less than %s to era" % min_year)
first = 0
last = last_era_idx
era_idx = None
while era_idx is None:
mid = (first + last) // 2
if mid == last_era_idx or (ERA_START[mid][0] <= year and
ERA_START[mid + 1][0] > year):
era_idx = mid
# if an era lasting less than a year is preferred, choose it
if prefer:
i = mid - 1
while i >= 0 and ERA_START[i][0] == year:
# match kanji or hiragana
if set(ERA_START[i][1]) & set(prefer):
era_idx = i
break
i -= 1
# ends up at the last index where year >= ERA_START[mid][0]
if year < ERA_START[mid][0]:
last = mid - 1
else:
first = mid + 1
era = ERA_START[era_idx]
era_name = era[1][0]
era_year = year - era[0] + 1
fmt = "%s%s"
if reading == "arabic":
era_year_words = str(era_year)
elif reading:
era_name = era[1][1]
era_year_words = (self.to_cardinal(era_year, reading=True,
prefer=prefer)
if era_year != 1 else "がん")
if era_year % 10 == 9:
era_year_words = era_year_words[:-3] + ""
fmt = "%s%sねん"
else:
era_year_words = (self.to_cardinal(era_year, reading=False,
prefer=prefer)
if era_year != 1 else "")
return fmt % (era_name, era_year_words)
def to_currency(self, val, currency="JPY", cents=False, separator="",
adjective=False, reading=False, prefer=None):
left, right, is_negative = parse_currency_parts(
val, is_int_with_cents=cents)
try:
cr1, cr2 = self.CURRENCY_FORMS[currency]
if (cents or abs(val) != left) and not cr2:
raise ValueError('Decimals not supported for "%s"' % currency)
except KeyError:
raise NotImplementedError(
'Currency code "%s" not implemented for "%s"' %
(currency, self.__class__.__name__))
if adjective and currency in self.CURRENCY_ADJECTIVES:
cr1 = prefix_currency(self.CURRENCY_ADJECTIVES[currency], cr1)
minus_str = self.negword if is_negative else ""
return '%s%s%s%s%s' % (
minus_str,
self.to_cardinal(left, reading=reading, prefer=prefer),
cr1[1] if reading else cr1[0],
self.to_cardinal(right, reading=reading, prefer=prefer)
if cr2 else '',
(cr2[1] if reading else cr2[0]) if cr2 else '',
)
def splitnum(self, value, reading, prefer):
for elem in self.cards:
if elem > value:
continue
out = []
if value == 0:
div, mod = 1, 0
else:
div, mod = divmod(value, elem)
if div == 1:
out.append((select_text(self.cards[1], reading, prefer), 1))
else:
if div == value: # The system tallies, eg Roman Numerals
return [(
div * select_text(self.cards[elem], reading, prefer),
div * elem)]
out.append(self.splitnum(div, reading, prefer))
out.append((select_text(self.cards[elem], reading, prefer), elem))
if mod:
out.append(self.splitnum(mod, reading, prefer))
return out
def to_cardinal(self, value, reading=False, prefer=None):
try:
assert int(value) == value
except (ValueError, TypeError, AssertionError):
return self.to_cardinal_float(value, reading=reading,
prefer=prefer)
out = ""
if value < 0:
value = abs(value)
out = self.negword
if value >= self.MAXVAL:
raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL))
val = self.splitnum(value, reading, prefer)
words, _ = self.clean(val)
return self.title(out + words)
def to_cardinal_float(self, value, reading=False, prefer=None):
prefer = prefer or ["れい"]
try:
float(value) == value
except (ValueError, TypeError, AssertionError):
raise TypeError(self.errmsg_nonnum % value)
pre, post = self.float2tuple(float(value))
post = str(post)
post = '0' * (self.precision - len(post)) + post
out = [self.to_cardinal(pre, reading=reading, prefer=prefer)]
if self.precision:
out.append(self.title(self.pointword[1 if reading else 0]))
for i in range(self.precision):
curr = int(post[i])
out.append(to_s(
self.to_cardinal(curr, reading=reading, prefer=prefer)))
return "".join(out)

182
num2words/lang_KN.py Normal file
View File

@@ -0,0 +1,182 @@
# -*- 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_KN(Num2Word_EU):
def set_high_numwords(self, high):
for n, word in self.high_numwords:
self.cards[10**n] = word
def setup(self):
self.low_numwords = [
"ತೊಂಬತ್ತೊಂಬತ್ತು",
"ತೊಂಬತ್ತೆಂಟು",
"ತೊಂಬತ್ತೇಳು",
"ತೊಂಬತ್ತಾರು",
"ತೊಂಬತ್ತೈದು",
"ತೊಂಬತ್ತ ನಾಲ್ಕು",
"ತೊಂಬತ್ತ ಮೂರು",
"ತೊಂಬತ್ತೆರಡು",
"ತೊಂಬತ್ತೊಂದು",
"ತೊಂಬತ್ತು",
"ಎಂಬತ್ತೊಂಬತ್ತು",
"ಎಂಬತ್ತೆಂಟು",
"ಎಂಬತ್ತೇಳು",
"ಎಂಬತ್ತಾರು",
"ಎಂಬತ್ತೈದು",
"ಎಂಬತ್ತ್ ನಾಲ್ಕು",
"ಎಂಬತ್ತ್ ಮೂರು",
"ಎಂಬತ್ತೆರಡು",
"ಎಂಬತ್ತೊಂದು",
"ಎಂಬತ್ತು",
"ಎಪ್ಪತ್ತೊಂಬತ್ತು",
"ಎಪ್ಪತ್ತೆಂಟು",
"ಎಪ್ಪತ್ತೇಳು",
"ಎಪ್ಪತ್ತಾರು",
"ಎಪ್ಪತ್ತೈದು",
"ಎಪ್ಪತ್ತ್ ನಾಲ್ಕು",
"ಎಪ್ಪತ್ತ್ ಮೂರು",
"ಎಪ್ಪತ್ತೆರಡು",
"ಎಪ್ಪತ್ತೊಂದು",
"ಎಪ್ಪತ್ತು",
"ಅರವತ್ತೊಂಬತ್ತು",
"ಅರವತ್ತೆಂಟು",
"ಅರವತ್ತೇಳು",
"ಅರವತ್ತಾರು",
"ಅರವತ್ತೈದು",
"ಅರವತ್ತ್ ನಾಲ್ಕು",
"ಅರವತ್ತ್ ಮೂರು",
"ಅರವತ್ತೆರಡು",
"ಅರವತ್ತೊಂದು",
"ಅರವತ್ತು",
"ಐವತ್ತೊಂಬತ್ತು",
"ಐವತ್ತೆಂಟು",
"ಐವತ್ತೇಳು",
"ಐವತ್ತಾರು",
"ಐವತ್ತೈದು",
"ಐವತ್ತ್ನಾಲ್ಕು",
"ಐವತ್ತಮೂರು",
"ಐವತ್ತೆರಡು",
"ಐವತ್ತೊಂದು",
"ಐವತ್ತು",
"ನಲವತ್ತೊಂಬತ್ತು",
"ನಲವತ್ತೆಂಟು",
"ನಲವತ್ತೇಳು",
"ನಲವತ್ತಾರು",
"ನಲವತ್ತೈದು",
"ನಲವತ್ತ್ ನಾಲ್ಕು",
"ನಲವತ್ತ್ ಮೂರು",
"ನಲವತ್ತ್ ಎರಡು",
"ನಲವತ್ತೊಂದು",
"ನಲವತ್ತು",
"ಮೂವತ್ತ್ ಒಂಬತ್ತು",
"ಮೂವತ್ಎಂಟು",
"ಮೂವತ್ಏಳು",
"ಮೂವತ್ಆರು",
"ಮೂವತ್ತ್ ಐದು",
"ಮೂವತ್ತ್ ನಾಲ್ಕು",
"ಮೂವತ್ತ್ ಮೂರು",
"ಮೂವತ್ತ್ಎರಡು",
"ಮೂವತ್ತ್ಒಂದು",
"ಮೂವತ್ತು",
"ಇಪ್ಪತ್ತ್ಒಂಬತ್ತು",
"ಇಪ್ಪತ್ತ್ಎಂಟು",
"ಇಪ್ಪತ್ತ್ಏಳು",
"ಇಪ್ಪತ್ತ್ಆರು",
"ಇಪ್ಪತ್ತ್ ಐದು",
"ಇಪ್ಪತ್ತ್ ನಾಲ್ಕು",
"ಇಪ್ಪತ್ತ್ ಮೂರು",
"ಇಪ್ಪತ್ತ್ ಎರಡು",
"ಇಪ್ಪತ್ತ್ ಒಂದು",
"ಇಪ್ಪತ್ತು",
"ಹತ್ತೊಂಬತ್ತು",
"ಹದಿನೆಂಟು",
"ಹದಿನೇಳು",
"ಹದಿನಾರು",
"ಹದಿನೈದು",
"ಹದಿನಾಲ್ಕು",
"ಹದಿಮೂರು",
"ಹನ್ನೆರಡು",
"ಹನ್ನೊಂದು",
"ಹತ್ತು",
"ಒಂಬತ್ತು",
"ಎಂಟು",
"ಏಳು",
"ಆರು",
"ಐದು",
"ನಾಲ್ಕು",
"ಮೂರು",
"ಎರಡು",
"ಒಂದು",
"ಸೊನ್ನೆ",
]
self.mid_numwords = [(100, "ನೂರು")]
self.high_numwords = [(7, "ಕೋಟಿ"), (5, "ಒಂದು ಲಕ್ಷ"), (3, "ಸಾವಿರ")]
self.pointword = "ಬಿಂದು"
self.modifiers = [
"",
"",
"ಿ",
"ೀ",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
]
def merge(self, lpair, rpair):
ltext, lnum = lpair
rtext, rnum = rpair
if lnum == 1 and rnum < 100:
return (rtext, rnum)
elif 100 > lnum > rnum:
return ("%s-%s" % (ltext, rtext), lnum + rnum)
elif lnum >= 100 > rnum:
if ltext[-1] in self.modifiers:
return ("%s %s" % (ltext[:-1], rtext), lnum + rnum)
else:
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_num(self, value):
self.verify_ordinal(value)
return "%s%s" % (value, self.to_ordinal(value))
def to_ordinal(self, value):
self.verify_ordinal(value)
outwords = self.to_cardinal(value)
if outwords[-1] in self.modifiers:
outwords = outwords[:-1]
ordinal_num = outwords + "ನೇ"
return ordinal_num

148
num2words/lang_KO.py Normal file
View File

@@ -0,0 +1,148 @@
# -*- coding: 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 division, print_function, unicode_literals
from .base import Num2Word_Base
from .currency import parse_currency_parts
class Num2Word_KO(Num2Word_Base):
CURRENCY_FORMS = {
'KRW': ('', None),
'USD': ('달러', '센트'),
'JPY': ('', None)
}
def set_high_numwords(self, high):
max = 4 * len(high)
for word, n in zip(high, range(max, 0, -4)):
self.cards[10 ** n] = word
def setup(self):
super(Num2Word_KO, self).setup()
self.negword = "마이너스 "
self.pointword = ""
self.high_numwords = [
'무량대수',
'불가사의',
'나유타',
'아승기',
'항하사',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'']
self.mid_numwords = [(1000, ""), (100, "")]
self.low_numwords = ["", "", "", "", "", "", "", "", "",
"", ""]
self.ords = {"": "",
"": "",
"": "",
"": "",
"": "다섯",
"": "여섯",
"": "일곱",
"": "여덟",
"": "아홉",
"": "",
"이십": "스물",
"삼십": "서른",
"사십": "마흔",
"오십": "",
"육십": "예순",
"칠십": "일흔",
"팔십": "여든",
"구십": "아흔"}
def merge(self, lpair, rpair):
ltext, lnum = lpair
rtext, rnum = rpair
if lnum == 1 and rnum <= 10000:
return rpair
elif 10000 > lnum > rnum:
return ("%s%s" % (ltext, rtext), lnum + rnum)
elif lnum >= 10000 and lnum > rnum:
return ("%s %s" % (ltext, rtext), lnum + rnum)
else:
return ("%s%s" % (ltext, rtext), lnum * rnum)
def to_ordinal(self, value):
self.verify_ordinal(value)
if value == 1:
return "첫 번째"
outwords = self.to_cardinal(value).split(" ")
lastwords = outwords[-1].split("")
if "" in lastwords[-1]:
ten_one = lastwords[-1].split("")
ten_one[0] = self.ords[ten_one[0] + ""]
try:
ten_one[1] = self.ords[ten_one[1]]
ten_one[0] = ten_one[0].replace("스무", "스물")
except KeyError:
pass
lastwords[-1] = ''.join(ten_one)
else:
lastwords[-1] = self.ords[lastwords[-1]]
outwords[-1] = "".join(lastwords)
return " ".join(outwords) + " 번째"
def to_ordinal_num(self, value):
self.verify_ordinal(value)
return "%s 번째" % (value)
def to_year(self, val, suffix=None, longval=True):
if val < 0:
val = abs(val)
suffix = '기원전' if not suffix else suffix
valtext = self.to_cardinal(val)
return ("%s" % valtext if not suffix
else "%s %s" % (suffix, valtext))
def to_currency(self, val, currency="KRW", cents=False, separator="",
adjective=False):
left, right, is_negative = parse_currency_parts(
val, is_int_with_cents=cents)
try:
cr1, cr2 = self.CURRENCY_FORMS[currency]
if (cents or right) and not cr2:
raise ValueError('Decimals not supported for "%s"' % currency)
except KeyError:
raise NotImplementedError(
'Currency code "%s" not implemented for "%s"' %
(currency, self.__class__.__name__))
minus_str = self.negword if is_negative else ""
return '%s%s%s%s%s' % (
minus_str,
''.join(self.to_cardinal(left).split()),
cr1,
' ' + self.to_cardinal(right)
if cr2 else '',
cr2 if cr2 else '',
)

133
num2words/lang_KZ.py Normal file
View File

@@ -0,0 +1,133 @@
# -*- coding: 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 = 'нөл'
ONES = {
1: 'бір',
2: 'екі',
3: 'үш',
4: 'төрт',
5: 'бес',
6: 'алты',
7: 'жеті',
8: 'сегіз',
9: 'тоғыз',
}
TEN = 'он'
TWENTIES = {
2: 'жиырма',
3: 'отыз',
4: 'қырық',
5: 'елу',
6: 'алпыс',
7: 'жетпіс',
8: 'сексен',
9: 'тоқсан',
}
HUNDRED = 'жүз'
THOUSANDS = {
1: 'мың',
2: 'миллион',
3: 'миллиард',
4: 'триллион',
5: 'квадриллион',
6: 'квинтиллион',
7: 'секстиллион',
8: 'септиллион',
9: 'октиллион',
10: 'нониллион',
}
class Num2Word_KZ(Num2Word_Base):
CURRENCY_FORMS = {
'USD': ('доллар', 'цент'),
'KZT': ('теңге', 'тиын'),
}
def setup(self):
self.negword = "минус"
self.pointword = "бүтін"
def to_cardinal(self, number):
n = str(number).replace(',', '.')
if '.' in n:
left, right = n.split('.')
leading_zero_count = len(right) - len(right.lstrip('0'))
return u'%s %s %s' % (
self._int2word(int(left)),
self.pointword,
(ZERO + ' ') * leading_zero_count + self._int2word(int(right))
)
else:
return self._int2word(int(n))
def pluralize(self, n, form):
return form
def _cents_verbose(self, number, currency):
return self._int2word(number, currency == 'KZT')
def _int2word(self, n, feminine=False):
if n < 0:
return ' '.join([self.negword, self._int2word(abs(n))])
if n == 0:
return ZERO
words = []
chunks = list(splitbyx(str(n), 3))
i = len(chunks)
for x in chunks:
i -= 1
if x == 0:
continue
n1, n2, n3 = get_digits(x)
if n3 > 0:
if n3 > 1:
words.append(ONES[n3])
words.append(HUNDRED)
if n2 == 1:
words.append(TEN)
elif n2 > 1:
words.append(TWENTIES[n2])
if n1 > 0:
words.append(ONES[n1])
if i > 0:
words.append(THOUSANDS[i])
return ' '.join(words)
def to_ordinal(self, number):
# TODO: Implement to_ordinal
raise NotImplementedError()

View File

@@ -1,4 +1,4 @@
# -*- encoding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved. # Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
@@ -14,241 +14,169 @@
# License along with this library; if not, write to the Free Software # License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301 USA # MA 02110-1301 USA
u"""
>>> from textwrap import fill
>>> ' '.join([str(i) for i in splitby3('1')])
'1'
>>> ' '.join([str(i) for i in splitby3('1123')])
'1 123'
>>> ' '.join([str(i) for i in splitby3('1234567890')])
'1 234 567 890'
>>> print(' '.join([n2w(i) for i in range(10)]))
nulis vienas du trys keturi penki šeši septyni aštuoni devyni
>>> print(fill(' '.join([n2w(i+10) for i in range(10)])))
dešimt vienuolika dvylika trylika keturiolika penkiolika šešiolika
septyniolika aštuoniolika devyniolika
>>> print(fill(' '.join([n2w(i*10) for i in range(10)])))
nulis dešimt dvidešimt trisdešimt keturiasdešimt penkiasdešimt
šešiasdešimt septyniasdešimt aštuoniasdešimt devyniasdešimt
>>> print(n2w(100))
šimtas
>>> print(n2w(101))
šimtas vienas
>>> print(n2w(110))
šimtas dešimt
>>> print(n2w(115))
šimtas penkiolika
>>> print(n2w(123))
šimtas dvidešimt trys
>>> print(n2w(1000))
tūkstantis
>>> print(n2w(1001))
tūkstantis vienas
>>> print(n2w(2012))
du tūkstančiai dvylika
>>> print(fill(n2w(1234567890)))
milijardas du šimtai trisdešimt keturi milijonai penki šimtai
šešiasdešimt septyni tūkstančiai aštuoni šimtai devyniasdešimt
>>> print(fill(n2w(215461407892039002157189883901676)))
du šimtai penkiolika naintilijonų keturi šimtai šešiasdešimt vienas
oktilijonas keturi šimtai septyni septilijonai aštuoni šimtai
devyniasdešimt du sikstilijonai trisdešimt devyni kvintilijonai du
kvadrilijonai šimtas penkiasdešimt septyni trilijonai šimtas
aštuoniasdešimt devyni milijardai aštuoni šimtai aštuoniasdešimt trys
milijonai devyni šimtai vienas tūkstantis šeši šimtai septyniasdešimt
šeši
>>> print(fill(n2w(719094234693663034822824384220291)))
septyni šimtai devyniolika naintilijonų devyniasdešimt keturi
oktilijonai du šimtai trisdešimt keturi septilijonai šeši šimtai
devyniasdešimt trys sikstilijonai šeši šimtai šešiasdešimt trys
kvintilijonai trisdešimt keturi kvadrilijonai aštuoni šimtai dvidešimt
du trilijonai aštuoni šimtai dvidešimt keturi milijardai trys šimtai
aštuoniasdešimt keturi milijonai du šimtai dvidešimt tūkstančių du
šimtai devyniasdešimt vienas
# TODO: fix this:
>>> print(fill(n2w(1000000000000000000000000000000)))
naintilijonas
>>> print(to_currency(1.0, 'LTL'))
vienas litas, nulis centų
>>> print(to_currency(1234.56, 'LTL'))
tūkstantis du šimtai trisdešimt keturi litai, penkiasdešimt šeši centai
>>> print(to_currency(-1251985, cents = False))
minus dvylika tūkstančių penki šimtai devyniolika litų, 85 centai
"""
from __future__ import unicode_literals from __future__ import unicode_literals
ZERO = (u'nulis',) from .base import Num2Word_Base
from .utils import get_digits, splitbyx
ZERO = ('nulis',)
ONES_FEMININE = {
1: ('viena',),
2: ('dvi',),
3: ('trys',),
4: ('keturios',),
5: ('penkios',),
6: ('šešios',),
7: ('septynios',),
8: ('aštuonios',),
9: ('devynios',),
}
ONES = { ONES = {
1: (u'vienas',), 1: ('vienas',),
2: (u'du',), 2: ('du',),
3: (u'trys',), 3: ('trys',),
4: (u'keturi',), 4: ('keturi',),
5: (u'penki',), 5: ('penki',),
6: (u'šeši',), 6: ('šeši',),
7: (u'septyni',), 7: ('septyni',),
8: (u'aštuoni',), 8: ('aštuoni',),
9: (u'devyni',), 9: ('devyni',),
} }
TENS = { TENS = {
0: (u'dešimt',), 0: ('dešimt',),
1: (u'vienuolika',), 1: ('vienuolika',),
2: (u'dvylika',), 2: ('dvylika',),
3: (u'trylika',), 3: ('trylika',),
4: (u'keturiolika',), 4: ('keturiolika',),
5: (u'penkiolika',), 5: ('penkiolika',),
6: (u'šešiolika',), 6: ('šešiolika',),
7: (u'septyniolika',), 7: ('septyniolika',),
8: (u'aštuoniolika',), 8: ('aštuoniolika',),
9: (u'devyniolika',), 9: ('devyniolika',),
} }
TWENTIES = { TWENTIES = {
2: (u'dvidešimt',), 2: ('dvidešimt',),
3: (u'trisdešimt',), 3: ('trisdešimt',),
4: (u'keturiasdešimt',), 4: ('keturiasdešimt',),
5: (u'penkiasdešimt',), 5: ('penkiasdešimt',),
6: (u'šešiasdešimt',), 6: ('šešiasdešimt',),
7: (u'septyniasdešimt',), 7: ('septyniasdešimt',),
8: (u'aštuoniasdešimt',), 8: ('aštuoniasdešimt',),
9: (u'devyniasdešimt',), 9: ('devyniasdešimt',),
} }
HUNDRED = (u'šimtas', u'šimtai') HUNDRED = ('šimtas', 'šimtai')
THOUSANDS = { THOUSANDS = {
1: (u'tūkstantis', u'tūkstančiai', u'tūkstančių'), 1: ('tūkstantis', 'tūkstančiai', 'tūkstančių'),
2: (u'milijonas', u'milijonai', u'milijonų'), 2: ('milijonas', 'milijonai', 'milijonų'),
3: (u'milijardas', u'milijardai', u'milijardų'), 3: ('milijardas', 'milijardai', 'milijardų'),
4: (u'trilijonas', u'trilijonai', u'trilijonų'), 4: ('trilijonas', 'trilijonai', 'trilijonų'),
5: (u'kvadrilijonas', u'kvadrilijonai', u'kvadrilijonų'), 5: ('kvadrilijonas', 'kvadrilijonai', 'kvadrilijonų'),
6: (u'kvintilijonas', u'kvintilijonai', u'kvintilijonų'), 6: ('kvintilijonas', 'kvintilijonai', 'kvintilijonų'),
7: (u'sikstilijonas', u'sikstilijonai', u'sikstilijonų'), 7: ('sikstilijonas', 'sikstilijonai', 'sikstilijonų'),
8: (u'septilijonas', u'septilijonai', u'septilijonų'), 8: ('septilijonas', 'septilijonai', 'septilijonų'),
9: (u'oktilijonas', u'oktilijonai', u'oktilijonų'), 9: ('oktilijonas', 'oktilijonai', 'oktilijonų'),
10: (u'naintilijonas', u'naintilijonai', u'naintilijonų'), 10: ('naintilijonas', 'naintilijonai', 'naintilijonų'),
} }
CURRENCIES = { GENERIC_CENTS = ('centas', 'centai', 'centų')
'LTL': ((u'litas', u'litai', u'litų'), (u'centas', u'centai', u'centų')),
}
def splitby3(n):
length = len(n)
if length > 3:
start = length % 3
if start > 0:
yield int(n[:start])
for i in range(start, length, 3):
yield int(n[i:i+3])
else:
yield int(n)
def get_digits(n): class Num2Word_LT(Num2Word_Base):
return [int(x) for x in reversed(list(('%03d' % n)[-3:]))] CURRENCY_FORMS = {
'LTL': (('litas', 'litai', 'litų'), GENERIC_CENTS),
'EUR': (('euras', 'eurai', 'eurų'), GENERIC_CENTS),
'USD': (('doleris', 'doleriai', 'dolerių'), GENERIC_CENTS),
'GBP': (
('svaras sterlingų', 'svarai sterlingų', 'svarų sterlingų'),
('pensas', 'pensai', 'pensų')
),
'PLN': (
('zlotas', 'zlotai', 'zlotų'),
('grašis', 'grašiai', 'grašių')),
'RUB': (
('rublis', 'rubliai', 'rublių'),
('kapeika', 'kapeikos', 'kapeikų')
),
}
def pluralize(n, forms): def setup(self):
n1, n2, n3 = get_digits(n) self.negword = "minus"
if n2 == 1 or n1 == 0 or n == 0: self.pointword = "kablelis"
return forms[2]
elif n1 == 1:
return forms[0]
else:
return forms[1]
def int2word(n): def pluralize(self, n, forms):
if n == 0: n1, n2, n3 = get_digits(n)
return ZERO[0] if n2 == 1 or n1 == 0 or n == 0:
return forms[2]
words = [] elif n1 == 1:
chunks = list(splitby3(str(n))) return forms[0]
i = len(chunks)
for x in chunks:
i -= 1
n1, n2, n3 = get_digits(x)
if n3 > 0:
if n3 > 1:
words.append(ONES[n3][0])
words.append(HUNDRED[1])
else:
words.append(HUNDRED[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(pluralize(x, THOUSANDS[i]))
return ' '.join(words)
def n2w(n):
n = str(n).replace(',', '.')
if '.' in n:
left, right = n.split('.')
return u'%s kablelis %s' % (int2word(int(left)), int2word(int(right)))
else:
return int2word(int(n))
def to_currency(n, currency='LTL', cents = True):
if type(n) == int:
if n < 0:
minus = True
else: else:
minus = False return forms[1]
n = abs(n) def to_cardinal(self, number):
left = n / 100 n = str(number).replace(',', '.')
right = n % 100 base_str, n = self.parse_minus(n)
else:
n = str(n).replace(',', '.')
if '.' in n: if '.' in n:
left, right = n.split('.') left, right = n.split('.')
leading_zero_count = len(right) - len(right.lstrip('0'))
decimal_part = ((ZERO[0] + ' ') * leading_zero_count +
self._int2word(int(right)))
return '%s%s %s %s' % (
base_str,
self._int2word(int(left)),
self.pointword,
decimal_part
)
else: else:
left, right = n, 0 return "%s%s" % (base_str, self._int2word(int(n)))
left, right = int(left), int(right)
minus = False
cr1, cr2 = CURRENCIES[currency]
if minus:
minus_str = "minus "
else:
minus_str = ""
if cents:
cents_str = int2word(right)
else:
cents_str = "%02d" % right
return u'%s%s %s, %s %s' % (minus_str, int2word(left), pluralize(left, cr1),
cents_str, pluralize(right, cr2))
class Num2Word_LT(object):
def to_cardinal(self, number):
return n2w(number)
def to_ordinal(self, number): def to_ordinal(self, number):
raise NotImplementedError() raise NotImplementedError()
if __name__ == '__main__': def _cents_verbose(self, number, currency):
import doctest return self._int2word(number, currency == 'RUB')
doctest.testmod()
def _int2word(self, n, feminine=False):
if n == 0:
return ZERO[0]
words = []
chunks = list(splitbyx(str(n), 3))
i = len(chunks)
for x in chunks:
i -= 1
if x == 0:
continue
n1, n2, n3 = get_digits(x)
if n3 > 0:
words.append(ONES[n3][0])
if n3 > 1:
words.append(HUNDRED[1])
else:
words.append(HUNDRED[0])
if n2 > 1:
words.append(TWENTIES[n2][0])
if n2 == 1:
words.append(TENS[n1][0])
elif n1 > 0:
if (i == 1 or feminine and i == 0) and n < 1000:
words.append(ONES_FEMININE[n1][0])
else:
words.append(ONES[n1][0])
if i > 0:
words.append(self.pluralize(x, THOUSANDS[i]))
return ' '.join(words)

189
num2words/lang_LV.py Normal file
View File

@@ -0,0 +1,189 @@
# -*- coding: 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 = ('nulle',)
ONES = {
1: ('viens',),
2: ('divi',),
3: ('trīs',),
4: ('četri',),
5: ('pieci',),
6: ('seši',),
7: ('septiņi',),
8: ('astoņi',),
9: ('deviņi',),
}
TENS = {
0: ('desmit',),
1: ('vienpadsmit',),
2: ('divpadsmit',),
3: ('trīspadsmit',),
4: ('četrpadsmit',),
5: ('piecpadsmit',),
6: ('sešpadsmit',),
7: ('septiņpadsmit',),
8: ('astoņpadsmit',),
9: ('deviņpadsmit',),
}
TWENTIES = {
2: ('divdesmit',),
3: ('trīsdesmit',),
4: ('četrdesmit',),
5: ('piecdesmit',),
6: ('sešdesmit',),
7: ('septiņdesmit',),
8: ('astoņdesmit',),
9: ('deviņdesmit',),
}
HUNDRED = ('simts', 'simti', 'simtu')
THOUSANDS = {
1: ('tūkstotis', 'tūkstoši', 'tūkstošu'),
2: ('miljons', 'miljoni', 'miljonu'),
3: ('miljards', 'miljardi', 'miljardu'),
4: ('triljons', 'triljoni', 'triljonu'),
5: ('kvadriljons', 'kvadriljoni', 'kvadriljonu'),
6: ('kvintiljons', 'kvintiljoni', 'kvintiljonu'),
7: ('sikstiljons', 'sikstiljoni', 'sikstiljonu'),
8: ('septiljons', 'septiljoni', 'septiljonu'),
9: ('oktiljons', 'oktiljoni', 'oktiljonu'),
10: ('nontiljons', 'nontiljoni', 'nontiljonu'),
}
GENERIC_DOLLARS = ('dolārs', 'dolāri', 'dolāru')
GENERIC_CENTS = ('cents', 'centi', 'centu')
GENERIC_KRONA = ('krona', 'kronas', 'kronu')
GENERIC_ERA = ('ēre', 'ēras', 'ēru')
class Num2Word_LV(Num2Word_Base):
"""
Sadly we have a legal form (used in legal and finance documents):
http://www.eiro.lv/files/upload/files/Eiro_rakstiba-1.pdf
https://likumi.lv/doc.php?id=254741
http://eur-lex.europa.eu/legal-content/LV/TXT/HTML/?uri=CELEX:31998R0974&from=LV
Source: http://publications.europa.eu/code/lv/lv-5000500.htm
"""
CURRENCY_FORMS = {
'AUD': (GENERIC_DOLLARS, GENERIC_CENTS),
'CAD': (GENERIC_DOLLARS, GENERIC_CENTS),
# repalced by EUR
'EEK': (GENERIC_KRONA, GENERIC_CENTS),
'EUR': (('eiro', 'eiro', 'eiro'), GENERIC_CENTS),
'EUR_LEGAL': (('euro', 'euro', 'euro'), GENERIC_CENTS),
'GBP': (
('sterliņu mārciņa', 'sterliņu mārciņas', 'sterliņu mārciņu'),
('penss', 'pensi', 'pensu')),
# replaced by EUR
'LTL': (('lits', 'liti', 'litu'), GENERIC_CENTS),
# replaced by EUR
'LVL': (('lats', 'lati', 'latu'),
('santīms', 'santīmi', 'santīmu')),
'USD': (GENERIC_DOLLARS, GENERIC_CENTS),
'RUB': (('rublis', 'rubļi', 'rubļu'),
('kapeika', 'kapeikas', 'kapeiku')),
'SEK': (GENERIC_KRONA, GENERIC_ERA),
'NOK': (GENERIC_KRONA, GENERIC_ERA),
'PLN': (('zlots', 'zloti', 'zlotu'),
('grasis', 'graši', 'grašu')),
}
CURRENCY_ADJECTIVES = {
'AUD': 'Austrālijas',
'CAD': 'Kanādas',
'EEK': 'Igaunijas',
'USD': 'ASV',
'RUB': 'Kreivijas',
'SEK': 'Zviedrijas',
'NOK': 'Norvēģijas',
}
def setup(self):
self.negword = "mīnus"
self.pointword = "komats"
def to_cardinal(self, number):
n = str(number).replace(',', '.')
base_str, n = self.parse_minus(n)
if '.' in n:
left, right = n.split('.')
leading_zero_count = len(right) - len(right.lstrip('0'))
decimal_part = ((ZERO[0] + ' ') * leading_zero_count +
self._int2word(int(right)))
return '%s%s %s %s' % (
base_str,
self._int2word(int(left)),
self.pointword,
decimal_part
)
else:
return "%s%s" % (base_str, self._int2word(int(n)))
def pluralize(self, n, forms):
form = 0 if (n % 10 == 1 and n % 100 != 11) else 1 if n != 0 else 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
if x == 0:
continue
n1, n2, n3 = get_digits(x)
if n3 > 0:
if n3 == 1 and n2 == 0 and n1 > 0:
words.append(HUNDRED[2])
elif n3 > 1:
words.append(ONES[n3][0])
words.append(HUNDRED[1])
else:
words.append(HUNDRED[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)

158
num2words/lang_NL.py Normal file
View File

@@ -0,0 +1,158 @@
# -*- coding: 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 print_function, unicode_literals
from .lang_EU import Num2Word_EU
class Num2Word_NL(Num2Word_EU):
CURRENCY_FORMS = {
'EUR': (('euro', 'euro'), ('cent', 'cent')),
'GBP': (('pond', 'pond'), ('penny', 'pence')),
'USD': (('dollar', 'dollar'), ('cent', 'cent')),
'CNY': (('yuan', 'yuan'), ('jiao', 'fen')),
}
GIGA_SUFFIX = "iljard"
MEGA_SUFFIX = "iljoen"
def setup(self):
super(Num2Word_NL, self).setup()
self.negword = "min "
self.pointword = "komma"
# "Cannot treat float %s as ordinal."
self.errmsg_floatord = (
"Het zwevende puntnummer %s kan niet omgezet worden " +
"naar een ordernummer."
)
# "type(((type(%s)) ) not in [long, int, float]"
self.errmsg_nonnum = (
"Alleen nummers (type (%s)) kunnen naar " +
"woorden omgezet worden."
)
# "Cannot treat negative num %s as ordinal."
self.errmsg_negord = (
"Het negatieve getal %s kan niet omgezet " +
"worden naar een ordernummer."
)
# "abs(%s) must be less than %s."
self.errmsg_toobig = "Het getal %s moet minder zijn dan %s."
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 = (
["zend"] + self.gen_high_numwords(units, tens, lows))
self.mid_numwords = [(1000, "duizend"), (100, "honderd"),
(90, "negentig"), (80, "tachtig"),
(70, "zeventig"), (60, "zestig"),
(50, "vijftig"), (40, "veertig"),
(30, "dertig")]
self.low_numwords = ["twintig", "negentien", "achttien", "zeventien",
"zestien", "vijftien", "veertien", "dertien",
"twaalf", "elf", "tien", "negen", "acht", "zeven",
"zes", "vijf", "vier", "drie", "twee", "één",
"nul"]
# Wiktionary says it is "nulde", not "nulte" or "nule"
# https://en.wiktionary.org/wiki/nulde
self.ords = {"nul": "nuld",
"één": "eerst",
"twee": "tweed",
"drie": "derd",
"vier": "vierd",
"vijf": "vijfd",
"zes": "zesd",
"zeven": "zevend",
"acht": "achtst",
"negen": "negend",
"tien": "tiend",
"elf": "elfd",
"twaalf": "twaalfd",
"ig": "igst",
"erd": "erdst",
"end": "endst",
"joen": "joenst",
"rd": "rdst"}
def merge(self, curr, next):
ctext, cnum, ntext, nnum = curr + next
if cnum == 1:
if nnum < 10 ** 6:
return next
ctext = "een"
if nnum > cnum:
if nnum >= 10 ** 6:
ctext += " "
val = cnum * nnum
else:
if nnum < 10 < cnum < 100:
if nnum == 1:
ntext = "een"
if ntext.endswith("e"):
ntext += "ën" # "n"
else:
ntext += "en"
ntext, ctext = ctext, ntext # + "en"
elif cnum >= 10 ** 6:
ctext += " "
val = cnum + nnum
word = ctext + ntext
return word, val
def to_ordinal(self, value):
self.verify_ordinal(value)
outword = self.to_cardinal(value)
for key in self.ords:
if outword.endswith(key):
outword = outword[:len(outword) - len(key)] + self.ords[key]
break
return outword + "e"
def to_ordinal_num(self, value):
self.verify_ordinal(value)
return str(value) + "e"
def pluralize(self, n, forms):
"""
:param n:
:param forms:
:return:
gettext form is nplurals=2; plural=(n != 1);
but this claims https://onzetaal.nl/taaladvies/euro-euros/
not sure if it's applied only to euro
"""
return forms[0]
def to_year(self, val, longval=True):
if not (val // 100) % 10:
return self.to_cardinal(val)
return self.to_splitnum(val, hightxt="honderd", longval=longval)

108
num2words/lang_NO.py Normal file
View File

@@ -0,0 +1,108 @@
# -*- coding: 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 division, print_function, unicode_literals
from . import lang_EU
class Num2Word_NO(lang_EU.Num2Word_EU):
GIGA_SUFFIX = "illard"
MEGA_SUFFIX = "illion"
def set_high_numwords(self, high):
cap = 3 + 6 * len(high)
for word, n in zip(high, range(cap, 3, -6)):
if self.GIGA_SUFFIX:
self.cards[10 ** n] = word + self.GIGA_SUFFIX
if self.MEGA_SUFFIX:
self.cards[10 ** (n - 3)] = word + self.MEGA_SUFFIX
def setup(self):
super(Num2Word_NO, self).setup()
self.negword = "minus "
self.pointword = "komma"
self.exclude_title = ["og", "komma", "minus"]
self.mid_numwords = [(1000, "tusen"), (100, "hundre"),
(90, "nitti"), (80, "\xe5tti"), (70, "sytti"),
(60, "seksti"), (50, "femti"), (40, "f\xf8rti"),
(30, "tretti")]
self.low_numwords = ["tjue", "nitten", "atten", "sytten",
"seksten", "femten", "fjorten", "tretten",
"tolv", "elleve", "ti", "ni", "\xe5tte",
"syv", "seks", "fem", "fire", "tre", "to",
"en", "null"]
self.ords = {"en": "f\xf8rste",
"to": "andre",
"tre": "tredje",
"fire": "fjerde",
"fem": "femte",
"seks": "sjette",
"syv": "syvende",
"\xe5tte": "\xe5ttende",
"ni": "niende",
"ti": "tiende",
"elleve": "ellevte",
"tolv": "tolvte",
"tjue": "tjuende"}
def merge(self, lpair, rpair):
ltext, lnum = lpair
rtext, rnum = rpair
if lnum == 1 and rnum < 100:
return (rtext, rnum)
elif 100 > lnum > rnum:
return ("%s-%s" % (ltext, rtext), lnum + rnum)
elif lnum >= 100 > rnum:
return ("%s og %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):
self.verify_ordinal(value)
outwords = self.to_cardinal(value).split(" ")
lastwords = outwords[-1].split("-")
lastword = lastwords[-1].lower()
try:
lastword = self.ords[lastword]
except KeyError:
if lastword[-2:] == "ti":
lastword = lastword + "ende"
else:
lastword += "de"
lastwords[-1] = self.title(lastword)
outwords[-1] = "".join(lastwords)
return " ".join(outwords)
def to_ordinal_num(self, value):
self.verify_ordinal(value)
return "%s%s" % (value, self.to_ordinal(value)[-2:])
def to_year(self, val, longval=True):
if not (val // 100) % 10:
return self.to_cardinal(val)
return self.to_splitnum(val, hightxt="hundre", jointxt="og",
longval=longval)
def to_currency(self, val, longval=True):
return self.to_splitnum(val, hightxt="krone/r", lowtxt="\xf8re/r",
jointxt="og", longval=longval, cents=True)

260
num2words/lang_PL.py Normal file
View File

@@ -0,0 +1,260 @@
# -*- coding: 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 itertools
from .base import Num2Word_Base
from .utils import get_digits, splitbyx
ZERO = ('zero',)
ONES = {
1: ('jeden',),
2: ('dwa',),
3: ('trzy',),
4: ('cztery',),
5: ('pięć',),
6: ('sześć',),
7: ('siedem',),
8: ('osiem',),
9: ('dziewięć',),
}
ONES_ORDINALS = {
1: ('pierwszy', "pierwszo"),
2: ('drugi', "dwu"),
3: ('trzeci', "trzy"),
4: ('czwarty', "cztero"),
5: ('piąty', "pięcio"),
6: ('szósty', "sześcio"),
7: ('siódmy', "siedmio"),
8: ('ósmy', "ośmio"),
9: ('dziewiąty', "dziewięcio"),
10: ('dziesiąty', "dziesięcio"),
11: ('jedenasty', "jedenasto"),
12: ('dwunasty', "dwunasto"),
13: ('trzynasty', "trzynasto"),
14: ('czternasty', "czternasto"),
15: ('piętnasty', "piętnasto"),
16: ('szesnasty', "szesnasto"),
17: ('siedemnasty', "siedemnasto"),
18: ('osiemnasty', "osiemnasto"),
19: ('dziewiętnasty', "dziewiętnasto"),
}
TENS = {
0: ('dziesięć',),
1: ('jedenaście',),
2: ('dwanaście',),
3: ('trzynaście',),
4: ('czternaście',),
5: ('piętnaście',),
6: ('szesnaście',),
7: ('siedemnaście',),
8: ('osiemnaście',),
9: ('dziewiętnaście',),
}
TWENTIES = {
2: ('dwadzieścia',),
3: ('trzydzieści',),
4: ('czterdzieści',),
5: ('pięćdziesiąt',),
6: ('sześćdziesiąt',),
7: ('siedemdziesiąt',),
8: ('osiemdziesiąt',),
9: ('dziewięćdziesiąt',),
}
TWENTIES_ORDINALS = {
2: ('dwudziesty', "dwudziesto"),
3: ('trzydziesty', "trzydiesto"),
4: ('czterdziesty', "czterdziesto"),
5: ('pięćdziesiąty', "pięćdziesięcio"),
6: ('sześćdziesiąty', "sześćdziesięcio"),
7: ('siedemdziesiąty', "siedemdziesięcio"),
8: ('osiemdziesiąty', "osiemdziesięcio"),
9: ('dziewięćdzisiąty', "dziewięćdziesięcio"),
}
HUNDREDS = {
1: ('sto',),
2: ('dwieście',),
3: ('trzysta',),
4: ('czterysta',),
5: ('pięćset',),
6: ('sześćset',),
7: ('siedemset',),
8: ('osiemset',),
9: ('dziewięćset',),
}
HUNDREDS_ORDINALS = {
1: ('setny', "stu"),
2: ('dwusetny', "dwustu"),
3: ('trzysetny', "trzystu"),
4: ('czterysetny', "czterystu"),
5: ('pięćsetny', "pięcset"),
6: ('sześćsetny', "sześćset"),
7: ('siedemsetny', "siedemset"),
8: ('osiemsetny', "ośiemset"),
9: ('dziewięćsetny', "dziewięćset"),
}
THOUSANDS = {
1: ('tysiąc', 'tysiące', 'tysięcy'), # 10^3
}
prefixes_ordinal = {
1: "tysięczny",
2: "milionowy",
3: "milairdowy"
}
prefixes = ( # 10^(6*x)
"mi", # 10^6
"bi", # 10^12
"try", # 10^18
"kwadry", # 10^24
"kwinty", # 10^30
"seksty", # 10^36
"septy", # 10^42
"okty", # 10^48
"nony", # 10^54
"decy" # 10^60
)
suffixes = ("lion", "liard") # 10^x or 10^(x+3)
for idx, (p, s) in enumerate(itertools.product(prefixes, suffixes)):
name = p + s
THOUSANDS[idx+2] = (name, name + 'y', name + 'ów')
class Num2Word_PL(Num2Word_Base):
CURRENCY_FORMS = {
'PLN': (
('złoty', 'złote', 'złotych'), ('grosz', 'grosze', 'groszy')
),
'EUR': (
('euro', 'euro', 'euro'), ('cent', 'centy', 'centów')
),
}
def setup(self):
self.negword = "minus"
self.pointword = "przecinek"
def to_cardinal(self, number):
n = str(number).replace(',', '.')
if '.' in n:
left, right = n.split('.')
leading_zero_count = len(right) - len(right.lstrip('0'))
decimal_part = ((ZERO[0] + ' ') * leading_zero_count +
self._int2word(int(right)))
return u'%s %s %s' % (
self._int2word(int(left)),
self.pointword,
decimal_part
)
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 last_fragment_to_ordinal(self, last, words, level):
n1, n2, n3 = get_digits(last)
last_two = n2*10+n1
if last_two == 0:
words.append(HUNDREDS_ORDINALS[n3][level])
elif level == 1 and last == 1:
return
elif last_two < 20:
if n3 > 0:
words.append(HUNDREDS[n3][level])
words.append(ONES_ORDINALS[last_two][level])
elif last_two % 10 == 0:
if n3 > 0:
words.append(HUNDREDS[n3][level])
words.append(TWENTIES_ORDINALS[n2][level])
else:
if n3 > 0:
words.append(HUNDREDS[n3][0])
words.append(TWENTIES_ORDINALS[n2][0])
words.append(ONES_ORDINALS[n1][0])
def to_ordinal(self, number):
if number % 1 != 0:
raise NotImplementedError()
words = []
fragments = list(splitbyx(str(number), 3))
level = 0
last = fragments[-1]
while last == 0:
level = level+1
fragments.pop()
last = fragments[-1]
if len(fragments) > 1:
pre_part = self._int2word(number-(last*1000**level))
words.append(pre_part)
self.last_fragment_to_ordinal(last, words, 0 if level == 0 else 1)
output = " ".join(words)
if last == 1 and level > 0 and output != "":
output = output + " "
if level > 0:
output = output + prefixes_ordinal[level]
return output
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
if x == 0:
continue
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)

241
num2words/lang_PT.py Normal file
View File

@@ -0,0 +1,241 @@
# -*- coding: 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 division, unicode_literals
import re
from .lang_EU import Num2Word_EU
DOLLAR = ('dólar', 'dólares')
CENTS = ('cêntimo', 'cêntimos')
class Num2Word_PT(Num2Word_EU):
CURRENCY_FORMS = {
'AUD': (DOLLAR, CENTS),
'CAD': (DOLLAR, CENTS),
'EUR': (('euro', 'euros'), CENTS),
'GBP': (('libra', 'libras'), ('péni', 'pence')),
'USD': (DOLLAR, CENTS),
}
GIGA_SUFFIX = None
MEGA_SUFFIX = "ilião"
def setup(self):
super(Num2Word_PT, self).setup()
lows = ["quatr", "tr", "b", "m"]
self.high_numwords = self.gen_high_numwords([], [], lows)
self.negword = "menos "
self.pointword = "vírgula"
self.exclude_title = ["e", "vírgula", "menos"]
self.mid_numwords = [
(1000, "mil"), (100, "cem"), (90, "noventa"),
(80, "oitenta"), (70, "setenta"), (60, "sessenta"),
(50, "cinquenta"), (40, "quarenta"), (30, "trinta")
]
self.low_numwords = [
"vinte", "dezanove", "dezoito", "dezassete", "dezasseis",
"quinze", "catorze", "treze", "doze", "onze", "dez",
"nove", "oito", "sete", "seis", "cinco", "quatro", "três", "dois",
"um", "zero"
]
self.ords = [
{
0: "",
1: "primeiro",
2: "segundo",
3: "terceiro",
4: "quarto",
5: "quinto",
6: "sexto",
7: "sétimo",
8: "oitavo",
9: "nono",
},
{
0: "",
1: "décimo",
2: "vigésimo",
3: "trigésimo",
4: "quadragésimo",
5: "quinquagésimo",
6: "sexagésimo",
7: "septuagésimo",
8: "octogésimo",
9: "nonagésimo",
},
{
0: "",
1: "centésimo",
2: "ducentésimo",
3: "tricentésimo",
4: "quadrigentésimo",
5: "quingentésimo",
6: "seiscentésimo",
7: "septigentésimo",
8: "octigentésimo",
9: "nongentésimo",
},
]
self.thousand_separators = {
3: "milésimo",
6: "milionésimo",
9: "milésimo milionésimo",
12: "bilionésimo",
15: "milésimo bilionésimo"
}
self.hundreds = {
1: "cento",
2: "duzentos",
3: "trezentos",
4: "quatrocentos",
5: "quinhentos",
6: "seiscentos",
7: "setecentos",
8: "oitocentos",
9: "novecentos",
}
def merge(self, curr, next):
ctext, cnum, ntext, nnum = curr + next
if cnum == 1:
if nnum < 1000000:
return next
ctext = "um"
elif cnum == 100 and not nnum % 1000 == 0:
ctext = "cento"
if nnum < cnum:
if cnum < 100:
return ("%s e %s" % (ctext, ntext), cnum + nnum)
return ("%s e %s" % (ctext, ntext), cnum + nnum)
elif (not nnum % 1000000000) and cnum > 1:
ntext = ntext[:-4] + "liões"
elif (not nnum % 1000000) and cnum > 1:
ntext = ntext[:-4] + "lhões"
# correct "milião" to "milhão"
if ntext == 'milião':
ntext = 'milhão'
if nnum == 100:
ctext = self.hundreds[cnum]
ntext = ""
else:
ntext = " " + ntext
return (ctext + ntext, cnum * nnum)
def to_cardinal(self, value):
result = super(Num2Word_PT, self).to_cardinal(value)
# Transforms "mil e cento e catorze" into "mil cento e catorze"
# Transforms "cem milhões e duzentos mil e duzentos e dez" em "cem
# milhões duzentos mil duzentos e dez" but "cem milhões e duzentos
# mil e duzentos" in "cem milhões duzentos mil e duzentos" and not in
# "cem milhões duzentos mil duzentos"
for ext in (
'mil', 'milhão', 'milhões', 'mil milhões',
'bilião', 'biliões', 'mil biliões'):
if re.match('.*{} e \\w*entos? (?=.*e)'.format(ext), result):
result = result.replace(
'{} e'.format(ext), '{}'.format(ext)
)
return result
# for the ordinal conversion the code is similar to pt_BR code,
# although there are other rules that are probably more correct in
# Portugal. Concerning numbers from 2000th on, saying "dois
# milésimos" instead of "segundo milésimo" (the first number
# would be used in the cardinal form instead of the ordinal) is better.
# This was not implemented.
# source:
# https://ciberduvidas.iscte-iul.pt/consultorio/perguntas/a-forma-por-extenso-de-2000-e-de-outros-ordinais/16428
def to_ordinal(self, value):
# Before changing this function remember this is used by pt-BR
# so act accordingly
self.verify_ordinal(value)
result = []
value = str(value)
thousand_separator = ''
for idx, char in enumerate(value[::-1]):
if idx and idx % 3 == 0:
thousand_separator = self.thousand_separators[idx]
if char != '0' and thousand_separator:
# avoiding "segundo milionésimo milésimo" for 6000000,
# for instance
result.append(thousand_separator)
thousand_separator = ''
result.append(self.ords[idx % 3][int(char)])
result = ' '.join(result[::-1])
result = result.strip()
result = re.sub('\\s+', ' ', result)
if result.startswith('primeiro') and value != '1':
# avoiding "primeiro milésimo", "primeiro milionésimo" and so on
result = result[9:]
return result
def to_ordinal_num(self, value):
# Before changing this function remember this is used by pt-BR
# so act accordingly
self.verify_ordinal(value)
return "%sº" % (value)
def to_year(self, val, longval=True):
# Before changing this function remember this is used by pt-BR
# so act accordingly
if val < 0:
return self.to_cardinal(abs(val)) + ' antes de Cristo'
return self.to_cardinal(val)
def to_currency(self, val, currency='EUR', cents=True, separator=' e',
adjective=False):
# change negword because base.to_currency() does not need space after
backup_negword = self.negword
self.negword = self.negword[:-1]
result = super(Num2Word_PT, self).to_currency(
val, currency=currency, cents=cents, separator=separator,
adjective=adjective)
# undo the change on negword
self.negword = backup_negword
# transforms "milhões euros" em "milhões de euros"
cr1, _ = self.CURRENCY_FORMS[currency]
for ext in (
'milhão', 'milhões', 'bilião',
'biliões', 'trilião', 'triliões'):
if re.match('.*{} (?={})'.format(ext, cr1[1]), result):
result = result.replace(
'{}'.format(ext), '{} de'.format(ext), 1
)
# do not print "e zero cêntimos"
result = result.replace(' e zero cêntimos', '')
return result

115
num2words/lang_PT_BR.py Normal file
View File

@@ -0,0 +1,115 @@
# -*- coding: 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 division, unicode_literals
import re
from . import lang_PT
class Num2Word_PT_BR(lang_PT.Num2Word_PT):
def set_high_numwords(self, high):
max = 3 + 3*len(high)
for word, n in zip(high, range(max, 3, -3)):
self.cards[10**n] = word + "ilhão"
def setup(self):
super(Num2Word_PT_BR, self).setup()
self.low_numwords[1] = 'dezenove'
self.low_numwords[3] = 'dezessete'
self.low_numwords[4] = 'dezesseis'
self.thousand_separators = {
3: "milésimo",
6: "milionésimo",
9: "bilionésimo",
12: "trilionésimo",
15: "quadrilionésimo"
}
def merge(self, curr, next):
ctext, cnum, ntext, nnum = curr + next
if cnum == 1:
if nnum < 1000000:
return next
ctext = "um"
elif cnum == 100 and nnum % 1000 != 0:
ctext = "cento"
if nnum < cnum:
if cnum < 100:
return ("%s e %s" % (ctext, ntext), cnum + nnum)
return ("%s e %s" % (ctext, ntext), cnum + nnum)
elif (not nnum % 1000000) and cnum > 1:
ntext = ntext[:-4] + "lhões"
if nnum == 100:
ctext = self.hundreds[cnum]
ntext = ""
else:
ntext = " " + ntext
return (ctext + ntext, cnum * nnum)
def to_cardinal(self, value):
result = lang_PT.Num2Word_EU.to_cardinal(self, value)
# Transforms "mil E cento e catorze reais" into "mil, cento e catorze
# reais"
for ext in (
'mil', 'milhão', 'milhões', 'bilhão', 'bilhões',
'trilhão', 'trilhões', 'quatrilhão', 'quatrilhões'):
if re.match('.*{} e \\w*entos? (?=.*e)'.format(ext), result):
result = result.replace(
'{} e'.format(ext), '{},'.format(ext), 1
)
return result
def to_currency(self, val, longval=True):
integer_part, decimal_part = ('%.2f' % val).split('.')
result = self.to_cardinal(int(integer_part))
appended_currency = False
for ext in (
'milhão', 'milhões', 'bilhão', 'bilhões',
'trilhão', 'trilhões', 'quatrilhão', 'quatrilhões'):
if result.endswith(ext):
result += ' de reais'
appended_currency = True
if result in ['um', 'menos um']:
result += ' real'
appended_currency = True
if not appended_currency:
result += ' reais'
if int(decimal_part):
cents = self.to_cardinal(int(decimal_part))
result += ' e ' + cents
if cents == 'um':
result += ' centavo'
else:
result += ' centavos'
return result

173
num2words/lang_RO.py Normal file
View File

@@ -0,0 +1,173 @@
# -*- coding: 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 division, print_function, unicode_literals
from . import lang_EU
class Num2Word_RO(lang_EU.Num2Word_EU):
GIGA_SUFFIX = "iliard/e"
MEGA_SUFFIX = "ilion"
# inflection for mi/billion follows different rule
MEGA_SUFFIX_I = "ilioane"
GIGA_SUFFIX_I = "iliarde"
def setup(self):
super(Num2Word_RO, self).setup()
self.negword = "minus "
self.pointword = "virgulă"
self.exclude_title = ["și", "virgulă", "minus"]
self.errmsg_toobig = (
"Numărul e prea mare pentru a fi convertit în cuvinte."
)
self.mid_numwords = [(1000, "mie/i"), (100, "sută/e"),
(90, "nouăzeci"), (80, "optzeci"),
(70, "șaptezeci"), (60, "șaizeci"),
(50, "cincizeci"), (40, "patruzeci"),
(30, "treizeci")]
self.low_numwords = ["douăzeci", "nouăsprezece", "optsprezece",
"șaptesprezece", "șaisprezece", "cincisprezece",
"paisprezece", "treisprezece", "doisprezece",
"unsprezece", "zece", "nouă", "opt", "șapte",
"șase", "cinci", "patru", "trei", "doi",
"unu", "zero"]
self.gen_numwords = ["", "o", "două", "trei", "patru", "cinci",
"șase", "șapte", "opt", "nouă"]
self.gen_numwords_n = ["", "un", "două", "trei", "patru", "cinci",
"șase", "șapte", "opt", "nouă"]
self.numwords_inflections = {
100: self.gen_numwords,
1000: self.gen_numwords,
1000000: self.gen_numwords_n,
1000000000: self.gen_numwords_n
}
self.ords = {"unu": "primul",
"doi": "al doilea",
"three": "al treilea",
"cinci": "al cincilea",
"opt": "al optulea",
"nouă": "al nouălea",
"doisprezece": "al doisprezecelea"}
def merge(self, lpair, rpair):
ltext, lnum = lpair
rtext, rnum = rpair
rtext_i = self.inflect(rnum, rtext, lnum)
if 1 <= lnum < 10:
if rnum not in self.numwords_inflections:
return (rtext, rnum)
else:
rtext_i = self.inflect(lnum * rnum, rtext, lnum)
lresult = (self.numwords_inflections[rnum][lnum], rtext_i)
return ("%s %s" % lresult, rnum)
elif 10 < lnum < 100:
if lnum % 10 == 0:
if rnum in self.numwords_inflections:
rtext_i = self.inflect(lnum * rnum, rtext, lnum)
return ("%s %s" % (ltext, rtext_i), lnum * rnum)
else:
return ("%s și %s" % (ltext, rtext), lnum + rnum)
else:
rtext_i = self.inflect(lnum * rnum, rtext, lnum)
ltext_i = ltext if lnum % 10 != 2 \
else ltext.replace("doi", "două")
return ("%s %s" % (ltext_i, rtext_i), lnum * rnum)
else:
if rnum in self.numwords_inflections:
rtext_i = self.inflect(lnum * rnum, rtext, lnum)
return ("%s %s" % (ltext, rtext_i), lnum * rnum)
def to_ordinal(self, value):
self.verify_ordinal(value)
if value == 1:
return "primul"
else:
value = self.to_cardinal(value)
return "al %slea" % (value)
def to_ordinal_num(self, value):
self.verify_ordinal(value)
if value == 1:
return "1-ul"
return "al %s-lea" % (value)
def pluralize(self, n, forms):
if n == 1:
form = 0
elif n == 0 or (n % 100 > 0 and n % 100 < 20):
form = 1
else:
form = 2
return forms[form]
def inflect(self, value, text, side_effect=-1):
text = text.split("/")
result = text[0]
if len(text) > 1:
forms = [
text[0],
text[0][:-1] + text[1],
"de " + text[0][:-1] + text[1]
]
result = self.pluralize(side_effect, forms)
# mega inflections are different
if side_effect > 1 and result.endswith(self.MEGA_SUFFIX):
result = result.replace(self.MEGA_SUFFIX, self.MEGA_SUFFIX_I)
elif side_effect > 1 and result.endswith("iliare"):
result = result.replace("iliare", self.GIGA_SUFFIX_I)
return result
def to_currency(self, val, currency="RON", cents=False, separator=" și",
adjective=False):
# romanian currency has a particularity for numeral: one
self.gen_numwords[1] = "una"
result = super(Num2Word_RO, self).to_currency(
int(round(val*100)),
currency,
True,
separator,
adjective
)
self.gen_numwords[1] = "o" # revert numeral
return result.replace(
"unu leu", "un leu"
).replace(
"unu ban", "un ban"
).replace(
# if the romanian low text is 0, it is not usually printed
separator + " zero bani", ""
)
def to_year(self, val, suffix=None, longval=True):
result = super(Num2Word_RO, self).to_year(
val,
longval=longval
)
# for years we want the era negation e.g. B.C., in our case
# it's î.Hr. or î.e.n
if result.startswith(self.negword):
result = result.replace(self.negword, "")
suffix = "î.Hr." if not suffix else suffix
if suffix:
result = "".join([
result,
" ",
suffix
])
return result

249
num2words/lang_RU.py Normal file
View File

@@ -0,0 +1,249 @@
# -*- coding: 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 = ('ноль',)
ONES_FEMININE = {
1: ('одна',),
2: ('две',),
3: ('три',),
4: ('четыре',),
5: ('пять',),
6: ('шесть',),
7: ('семь',),
8: ('восемь',),
9: ('девять',),
}
ONES = {
1: ('один',),
2: ('два',),
3: ('три',),
4: ('четыре',),
5: ('пять',),
6: ('шесть',),
7: ('семь',),
8: ('восемь',),
9: ('девять',),
}
TENS = {
0: ('десять',),
1: ('одиннадцать',),
2: ('двенадцать',),
3: ('тринадцать',),
4: ('четырнадцать',),
5: ('пятнадцать',),
6: ('шестнадцать',),
7: ('семнадцать',),
8: ('восемнадцать',),
9: ('девятнадцать',),
}
TWENTIES = {
2: ('двадцать',),
3: ('тридцать',),
4: ('сорок',),
5: ('пятьдесят',),
6: ('шестьдесят',),
7: ('семьдесят',),
8: ('восемьдесят',),
9: ('девяносто',),
}
HUNDREDS = {
1: ('сто',),
2: ('двести',),
3: ('триста',),
4: ('четыреста',),
5: ('пятьсот',),
6: ('шестьсот',),
7: ('семьсот',),
8: ('восемьсот',),
9: ('девятьсот',),
}
THOUSANDS = {
1: ('тысяча', 'тысячи', 'тысяч'), # 10^3
2: ('миллион', 'миллиона', 'миллионов'), # 10^6
3: ('миллиард', 'миллиарда', 'миллиардов'), # 10^9
4: ('триллион', 'триллиона', 'триллионов'), # 10^12
5: ('квадриллион', 'квадриллиона', 'квадриллионов'), # 10^15
6: ('квинтиллион', 'квинтиллиона', 'квинтиллионов'), # 10^18
7: ('секстиллион', 'секстиллиона', 'секстиллионов'), # 10^21
8: ('септиллион', 'септиллиона', 'септиллионов'), # 10^24
9: ('октиллион', 'октиллиона', 'октиллионов'), # 10^27
10: ('нониллион', 'нониллиона', 'нониллионов'), # 10^30
}
class Num2Word_RU(Num2Word_Base):
CURRENCY_FORMS = {
'RUB': (
('рубль', 'рубля', 'рублей'), ('копейка', 'копейки', 'копеек')
),
'EUR': (
('евро', 'евро', 'евро'), ('цент', 'цента', 'центов')
),
'USD': (
('доллар', 'доллара', 'долларов'), ('цент', 'цента', 'центов')
),
'UAH': (
('гривна', 'гривны', 'гривен'), ('копейка', 'копейки', 'копеек')
),
'KZT': (
('тенге', 'тенге', 'тенге'), ('тиын', 'тиына', 'тиынов')
),
'UZS': (
('сум', 'сума', 'сумов'), ('тийин', 'тийина', 'тийинов')
),
}
def setup(self):
self.negword = "минус"
self.pointword = "запятая"
self.ords = {"ноль": "нулевой",
"один": "первый",
"два": "второй",
"три": "третий",
"четыре": "четвертый",
"пять": "пятый",
"шесть": "шестой",
"семь": "седьмой",
"восемь": "восьмой",
"девять": "девятый",
"сто": "сотый"}
self.ords_feminine = {"один": "",
"одна": "",
"две": "двух",
"три": "трёх",
"четыре": "четырёх",
"пять": "пяти",
"шесть": "шести",
"семь": "семи",
"восемь": "восьми",
"девять": "девяти"}
def to_cardinal(self, number):
n = str(number).replace(',', '.')
if '.' in n:
left, right = n.split('.')
leading_zero_count = len(right) - len(right.lstrip('0'))
decimal_part = ((ZERO[0] + ' ') * leading_zero_count +
self._int2word(int(right)))
return u'%s %s %s' % (
self._int2word(int(left)),
self.pointword,
decimal_part
)
else:
return self._int2word(int(n))
def pluralize(self, n, forms):
if n % 100 < 10 or n % 100 > 20:
if n % 10 == 1:
form = 0
elif 5 > n % 10 > 1:
form = 1
else:
form = 2
else:
form = 2
return forms[form]
def to_ordinal(self, number):
self.verify_ordinal(number)
outwords = self.to_cardinal(number).split(" ")
lastword = outwords[-1].lower()
try:
if len(outwords) > 1:
if outwords[-2] in self.ords_feminine:
outwords[-2] = self.ords_feminine.get(
outwords[-2], outwords[-2])
elif outwords[-2] == 'десять':
outwords[-2] = outwords[-2][:-1] + 'и'
if len(outwords) == 3:
if outwords[-3] in ['один', 'одна']:
outwords[-3] = ''
lastword = self.ords[lastword]
except KeyError:
if lastword[:-3] in self.ords_feminine:
lastword = self.ords_feminine.get(
lastword[:-3], lastword) + "сотый"
elif lastword[-1] == "ь" or lastword[-2] == "т":
lastword = lastword[:-1] + "ый"
elif lastword[-1] == "к":
lastword = lastword + "овой"
elif lastword[-5:] == "десят":
lastword = lastword.replace('ь', 'и') + 'ый'
elif lastword[-2] == "ч" or lastword[-1] == "ч":
if lastword[-2] == "ч":
lastword = lastword[:-1] + "ный"
if lastword[-1] == "ч":
lastword = lastword + "ный"
elif lastword[-1] == "н" or lastword[-2] == "н":
lastword = lastword[:lastword.rfind('н') + 1] + "ный"
elif lastword[-1] == "д" or lastword[-2] == "д":
lastword = lastword[:lastword.rfind('д') + 1] + "ный"
outwords[-1] = self.title(lastword)
return " ".join(outwords).strip()
def _money_verbose(self, number, currency):
return self._int2word(number, currency == 'UAH')
def _cents_verbose(self, number, currency):
return self._int2word(number, currency in ('UAH', 'RUB'))
def _int2word(self, n, feminine=False):
if n < 0:
return ' '.join([self.negword, self._int2word(abs(n))])
if n == 0:
return ZERO[0]
words = []
chunks = list(splitbyx(str(n), 3))
i = len(chunks)
for x in chunks:
i -= 1
if x == 0:
continue
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:
ones = ONES_FEMININE if i == 1 or feminine and i == 0 else ONES
words.append(ones[n1][0])
if i > 0:
words.append(self.pluralize(x, THOUSANDS[i]))
return ' '.join(words)

169
num2words/lang_SL.py Normal file
View File

@@ -0,0 +1,169 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# Copyright (c) 2015, Blaz Bregar. 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_SL(Num2Word_EU):
GIGA_SUFFIX = "ilijard"
MEGA_SUFFIX = "ilijon"
def setup(self):
super(Num2Word_SL, self).setup()
self.negword = "minus "
self.pointword = "celih"
self.errmsg_nonnum = "Only numbers may be converted to words."
self.errmsg_toobig = "Number is too large to convert to words."
self.exclude_title = []
self.mid_numwords = [(1000, "tisoč"), (900, "devetsto"),
(800, "osemsto"), (700, "sedemsto"),
(600, "šeststo"), (500, "petsto"),
(400, "štiristo"), (300, "tristo"),
(200, "dvesto"), (100, "sto"),
(90, "devetdeset"), (80, "osemdeset"),
(70, "sedemdeset"), (60, "šestdeset"),
(50, "petdeset"), (40, "štirideset"),
(30, "trideset")]
self.low_numwords = ["dvajset", "devetnajst", "osemnajst",
"sedemnajst", "šestnajst", "petnajst",
"štirinajst", "trinajst", "dvanajst",
"enajst", "deset", "devet", "osem", "sedem",
"šest", "pet", "štiri", "tri", "dve", "ena",
"nič"]
self.ords = {"ena": "prv",
"dve": "drug",
"tri": "tretj",
"štiri": "četrt",
"sedem": "sedm",
"osem": "osm",
"sto": "stot",
"tisoč": "tisoč",
"milijon": "milijont"
}
self.ordflag = False
def merge(self, curr, next):
ctext, cnum, ntext, nnum = curr + next
if ctext.endswith("dve") and self.ordflag and nnum <= 1000000:
ctext = ctext[:len(ctext)-1] + "a"
if ctext == "dve" and not self.ordflag and nnum < 1000000000:
ctext = "dva"
if (ctext.endswith("tri") or ctext.endswith("štiri")) and\
nnum == 1000000 and not self.ordflag:
if ctext.endswith("štiri"):
ctext = ctext[:-1]
ctext = ctext + "je"
if cnum >= 20 and cnum < 100 and nnum == 2:
ntext = "dva"
if ctext.endswith("ena") and nnum >= 1000:
ctext = ctext[0:-1]
if cnum == 1:
if nnum < 10**6 or self.ordflag:
return next
ctext = ""
if nnum > cnum:
if nnum >= 10**6:
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"
elif ctext.endswith("en"):
if ntext.endswith("d") or ntext.endswith("n"):
ntext += ""
elif ctext.endswith("dve") and ntext.endswith("n"):
ctext = ctext[:-1] + "a"
ntext += "a"
elif ctext.endswith("je") and ntext.endswith("n"):
ntext += "i"
else:
if ntext.endswith("d"):
ntext += "a"
elif ntext.endswith("n"):
ntext += ""
elif ntext.endswith("d"):
ntext += "e"
else:
ntext += "ov"
if nnum >= 10**2 and self.ordflag is False and ctext:
ctext += " "
val = cnum * nnum
else:
if nnum < 10 < cnum < 100:
ntext, ctext = ctext, ntext + "in"
elif cnum >= 10**2 and self.ordflag is False:
ctext += " "
val = cnum + nnum
word = ctext + ntext
return (word, val)
def to_ordinal(self, value):
self.verify_ordinal(value)
self.ordflag = True
outword = self.to_cardinal(value)
self.ordflag = False
for key in self.ords:
if outword.endswith(key):
outword = outword[:len(outword) - len(key)] + self.ords[key]
break
return outword + "i"
# Is this correct??
def to_ordinal_num(self, value):
self.verify_ordinal(value)
return str(value) + "."
def to_currency(self, val, longval=True, old=False):
if old:
return self.to_splitnum(val, hightxt="evro/a/v",
lowtxt="stotin/a/i/ov",
jointxt="in", longval=longval)
return super(Num2Word_SL, self).to_currency(val, jointxt="in",
longval=longval)
def to_year(self, val, longval=True):
if not (val//100) % 10:
return self.to_cardinal(val)
return self.to_splitnum(val, hightxt="hundert", longval=longval)

219
num2words/lang_SR.py Normal file
View File

@@ -0,0 +1,219 @@
# -*- coding: 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 .currency import parse_currency_parts, prefix_currency
from .utils import get_digits, splitbyx
ZERO = ('nula',)
ONES = {
1: ('jedan', 'jedna'),
2: ('dva', 'dve'),
3: ('tri', 'tri'),
4: ('četiri', 'četiri'),
5: ('pet', 'pet'),
6: ('šest', 'šest'),
7: ('sedam', 'sedam'),
8: ('osam', 'osam'),
9: ('devet', 'devet'),
}
TENS = {
0: ('deset',),
1: ('jedanaest',),
2: ('dvanaest',),
3: ('trinaest',),
4: ('četrnaest',),
5: ('petnaest',),
6: ('šesnaest',),
7: ('sedamnaest',),
8: ('osamnaest',),
9: ('devetnaest',),
}
TWENTIES = {
2: ('dvadeset',),
3: ('trideset',),
4: ('četrdeset',),
5: ('pedeset',),
6: ('šezdeset',),
7: ('sedamdeset',),
8: ('osamdeset',),
9: ('devedeset',),
}
HUNDREDS = {
1: ('sto',),
2: ('dvesta',),
3: ('trista',),
4: ('četristo',),
5: ('petsto',),
6: ('šesto',),
7: ('sedamsto',),
8: ('osamsto',),
9: ('devetsto',),
}
SCALE = {
0: ('', '', '', False),
1: ('hiljada', 'hiljade', 'hiljada', True), # 10^3
2: ('milion', 'miliona', 'miliona', False), # 10^6
3: ('bilion', 'biliona', 'biliona', False), # 10^9
4: ('trilion', 'triliona', 'triliona', False), # 10^12
5: ('kvadrilion', 'kvadriliona', 'kvadriliona', False), # 10^15
6: ('kvintilion', 'kvintiliona', 'kvintiliona', False), # 10^18
7: ('sekstilion', 'sekstiliona', 'sekstiliona', False), # 10^21
8: ('septilion', 'septiliona', 'septiliona', False), # 10^24
9: ('oktilion', 'oktiliona', 'oktiliona', False), # 10^27
10: ('nonilion', 'noniliona', 'noniliona', False), # 10^30
}
class Num2Word_SR(Num2Word_Base):
CURRENCY_FORMS = {
'RUB': (
('rublja', 'rublje', 'rublji', True),
('kopejka', 'kopejke', 'kopejki', True)
),
'EUR': (
('evro', 'evra', 'evra', False),
('cent', 'centa', 'centi', False)
),
'RSD': (
('dinar', 'dinara', 'dinara', False),
('para', 'pare', 'para', True)
),
}
def setup(self):
self.negword = "minus"
self.pointword = "zapeta"
def to_cardinal(self, number, feminine=False):
n = str(number).replace(',', '.')
if '.' in n:
left, right = n.split('.')
leading_zero_count = len(right) - len(right.lstrip('0'))
decimal_part = ((ZERO[0] + ' ') * leading_zero_count +
self._int2word(int(right), feminine))
return u'%s %s %s' % (
self._int2word(int(left), feminine),
self.pointword,
decimal_part
)
else:
return self._int2word(int(n), feminine)
def pluralize(self, number, forms):
if number % 100 < 10 or number % 100 > 20:
if number % 10 == 1:
form = 0
elif 1 < number % 10 < 5:
form = 1
else:
form = 2
else:
form = 2
return forms[form]
def to_ordinal(self, number):
raise NotImplementedError()
def _cents_verbose(self, number, currency):
return self._int2word(
number,
self.CURRENCY_FORMS[currency][1][-1]
)
def _int2word(self, number, feminine=False):
if number < 0:
return ' '.join([self.negword, self._int2word(abs(number))])
if number == 0:
return ZERO[0]
words = []
chunks = list(splitbyx(str(number), 3))
chunk_len = len(chunks)
for chunk in chunks:
chunk_len -= 1
digit_right, digit_mid, digit_left = get_digits(chunk)
if digit_left > 0:
words.append(HUNDREDS[digit_left][0])
if digit_mid > 1:
words.append(TWENTIES[digit_mid][0])
if digit_mid == 1:
words.append(TENS[digit_right][0])
elif digit_right > 0:
is_feminine = feminine or SCALE[chunk_len][-1]
gender_idx = int(is_feminine)
words.append(
ONES[digit_right][gender_idx]
)
if chunk_len > 0 and chunk != 0:
words.append(self.pluralize(chunk, SCALE[chunk_len]))
return ' '.join(words)
def to_currency(self, val, currency='EUR', cents=True, separator=',',
adjective=False):
"""
Args:
val: Numeric value
currency (str): Currency code
cents (bool): Verbose cents
separator (str): Cent separator
adjective (bool): Prefix currency name with adjective
Returns:
str: Formatted string
"""
left, right, is_negative = parse_currency_parts(val)
try:
cr1, cr2 = self.CURRENCY_FORMS[currency]
except KeyError:
raise NotImplementedError(
'Currency code "%s" not implemented for "%s"' %
(currency, self.__class__.__name__))
if adjective and currency in self.CURRENCY_ADJECTIVES:
cr1 = prefix_currency(
self.CURRENCY_ADJECTIVES[currency],
cr1
)
minus_str = "%s " % self.negword if is_negative else ""
cents_str = self._cents_verbose(right, currency) \
if cents else self._cents_terse(right, currency)
return u'%s%s %s%s %s %s' % (
minus_str,
self.to_cardinal(left, feminine=cr1[-1]),
self.pluralize(left, cr1),
separator,
cents_str,
self.pluralize(right, cr2)
)

117
num2words/lang_SV.py Normal file
View File

@@ -0,0 +1,117 @@
# -*- coding: 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 division, print_function, unicode_literals
from . import lang_EU
class Num2Word_SV(lang_EU.Num2Word_EU):
GIGA_SUFFIX = "iljarder"
MEGA_SUFFIX = "iljoner"
def set_high_numwords(self, high):
cap = 3 + 6 * len(high)
for word, n in zip(high, range(cap, 3, -6)):
if self.GIGA_SUFFIX:
self.cards[10 ** n] = word + self.GIGA_SUFFIX
if self.MEGA_SUFFIX:
self.cards[10 ** (n - 3)] = word + self.MEGA_SUFFIX
def setup(self):
super(Num2Word_SV, self).setup()
self.negword = "minus "
self.pointword = "komma"
self.exclude_title = ["och", "komma", "minus"]
self.mid_numwords = [(1000, "tusen"), (100, "hundra"),
(90, "nittio"), (80, "åttio"), (70, "sjuttio"),
(60, "sextio"), (50, "femtio"), (40, "förtio"),
(30, "trettio")]
self.low_numwords = ["tjugo", "nitton", "arton", "sjutton",
"sexton", "femton", "fjorton", "tretton",
"tolv", "elva", "tio", "nio", "åtta",
"sju", "sex", "fem", "fyra", "tre", "två",
"ett", "noll"]
self.ords = {"noll": "nollte",
"ett": "första",
"två": "andra",
"tre": "tredje",
"fyra": "fjärde",
"fem": "femte",
"sex": "sjätte",
"sju": "sjunde",
"åtta": "åttonde",
"nio": "nionde",
"tio": "tionde",
"elva": "elfte",
"tolv": "tolfte",
"tjugo": "tjugonde"}
def merge(self, lpair, rpair):
ltext, lnum = lpair
rtext, rnum = rpair
if lnum == 1 and rnum < 100:
return (rtext, rnum)
elif 100 > lnum > rnum:
return ("%s%s" % (ltext, rtext), lnum + rnum)
elif lnum >= 100 > rnum:
return ("%s%s" % (ltext, rtext), lnum + rnum)
elif rnum >= 1000000 and lnum == 1:
return ("%s %s" % ('en', rtext[:-2]), lnum + rnum)
elif rnum >= 1000000 and lnum > 1:
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):
self.verify_ordinal(value)
outwords = self.to_cardinal(value).split(" ")
lastword = outwords[-1]
ending_length = 0
try:
lastword_ending = self.ords[lastword[-4:]]
ending_length = 4
except KeyError:
try:
lastword_ending = self.ords[lastword[-3:]]
ending_length = 3
except KeyError:
lastword_ending = "de"
if lastword_ending == 'de':
lastword_first_part = self.title(lastword)[:]
else:
lastword_first_part = self.title(lastword)[:-ending_length]
lastword_correct = lastword_first_part + lastword_ending
outwords[-1] = lastword_correct
return " ".join(outwords)
def to_ordinal_num(self, value):
raise NotImplementedError(
"'ordinal_num' is not implemented for swedish language")
def to_year(self, val, longval=True):
raise NotImplementedError(
"'year' is not implemented for swedish language")
def to_currency(self, val, longval=True):
raise NotImplementedError(
"'currency' is not implemented for swedish language")

169
num2words/lang_TE.py Normal file
View File

@@ -0,0 +1,169 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from .lang_EU import Num2Word_EU
class Num2Word_TE(Num2Word_EU):
def set_high_numwords(self, high):
for n, word in self.high_numwords:
self.cards[10**n] = word
def setup(self):
self.low_numwords = [
"తొంభై తొమ్మిది",
"తొంభై ఎనిమిది",
"తొంభై ఏడు",
"తొంభై ఆరు",
"తొంభై అయిదు",
"తొంభై నాలుగు",
"తొంభై మూడు",
"తొంభై రెండు",
"తొంభై ఒకటి",
"తొంభై",
"ఎనభై తొమ్మిది",
"ఎనభై ఎనిమిది",
"ఎనభై ఏడు",
"ఎనభై ఆరు",
"ఎనభై అయిదు",
"ఎనభై నాలుగు",
"ఎనభై మూడు",
"ఎనభై రెండు",
"ఎనభై ఒకటి",
"ఎనభై",
"డెబ్బై తొమ్మిది",
"డెబ్బై ఎనిమిది",
"డెబ్బై ఏడు",
"డెబ్బై ఆరు",
"డెబ్బై అయిదు",
"డెబ్బై నాలుగు",
"డెబ్బై మూడు",
"డెబ్బై రెండు",
"డెబ్బై ఒకటి",
"డెబ్బై",
"అరవై తొమ్మిది",
"అరవై ఎనిమిది",
"అరవై ఏడు",
"అరవై ఆరు",
"అరవై అయిదు",
"అరవై నాలుగు",
"అరవై మూడు",
"అరవై రెండు",
"అరవై ఒకటి",
"అరవై",
"యాభై తొమ్మిది",
"యాభై ఎనిమిది",
"యాభై ఏడు",
"యాభై ఆరు",
"యాభై అయిదు",
"యాభై నాలుగు",
"యాభై మూడు",
"యాభై రెండు",
"యాభై ఒకటి",
"యాభై ",
"నలభై తొమ్మిది",
"నలభై ఎనిమిది",
"నలభై ఏడు",
"నలభై ఆరు",
"నలభై అయిదు",
"నలభై నాలుగు",
"నలభై మూడు",
"నలభై రెండు",
"నలభై ఒకటి",
"నలభై",
"ముప్పై తొమ్మిది",
"ముప్పై ఎనిమిది",
"ముప్పై ఏడు",
"ముప్పై ఆరు",
"ముప్పై ఐదు",
"ముప్పై నాలుగు",
"ముప్పై మూడు",
"ముప్పై రెండు",
"ముప్పై ఒకటి",
"ముప్పై",
"ఇరవై తొమ్మిది",
"ఇరవై ఎనిమిది",
"ఇరవై ఏడు",
"ఇరవై ఆరు",
"ఇరవై అయిదు",
"ఇరవై నాలుగు",
"ఇరవై మూడు",
"ఇరవై రెండు",
"ఇరవై ఒకటి",
"ఇరవై",
"పందొమ్మిది",
"పధ్ధెనిమిది",
"పదిహేడు",
"పదహారు",
"పదునయిదు",
"పధ్నాలుగు",
"పదమూడు",
"పన్నెండు",
"పదకొండు",
"పది",
"తొమ్మిది",
"ఎనిమిది",
"ఏడు",
"ఆరు",
"అయిదు",
"నాలుగు",
"మూడు",
"రెండు",
"ఒకటి",
"సున్న",
]
self.mid_numwords = [(100, "వంద")]
self.high_numwords = [(7, "కోట్ల"), (5, "లక్ష"), (3, "వేయి")]
self.pointword = "బిందువు "
self.modifiers = [
"",
"",
" ి ",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
" ",
"",
]
def merge(self, lpair, rpair):
ltext, lnum = lpair
rtext, rnum = rpair
if lnum == 1 and rnum < 100:
return (rtext, rnum)
elif 100 > lnum > rnum:
return ("%s-%s" % (ltext, rtext), lnum + rnum)
elif lnum >= 100 > rnum:
if ltext[-1] in self.modifiers:
return ("%s %s" % (ltext[:-1], rtext), lnum + rnum)
else:
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_num(self, value):
self.verify_ordinal(value)
return "%s%s" % (value, self.to_ordinal(value)[-1:])
def to_ordinal(self, value):
self.verify_ordinal(value)
outwords = self.to_cardinal(value)
if outwords[-1] in self.modifiers:
outwords = outwords[:-1]
ordinal_num = outwords + ""
return ordinal_num

149
num2words/lang_TG.py Normal file
View File

@@ -0,0 +1,149 @@
# -*- coding: 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 division, print_function, unicode_literals
from . import lang_EU
GENERIC_DOLLARS = ("доллар", "доллар")
GENERIC_CENTS = ("сент", "сент")
class Num2Word_TG(lang_EU.Num2Word_EU):
CURRENCY_FORMS = {
# repalced by EUR
"EUR": (("евро", "евро"), GENERIC_CENTS),
# replaced by EUR
"USD": (GENERIC_DOLLARS, GENERIC_CENTS),
"RUB": (("рубл", "рубл"), ("копейк", "копейк")),
"TJS": (("сомонӣ", "сомонӣ"), ("дирам", "дирам")),
}
GIGA_SUFFIX = "иллиард"
MEGA_SUFFIX = "иллион"
def set_high_numwords(self, high):
cap = 3 * (len(high) + 1)
for word, n in zip(high, range(cap, 5, -3)):
if n == 9:
self.cards[10 ** n] = word + self.GIGA_SUFFIX
else:
self.cards[10 ** n] = word + self.MEGA_SUFFIX
def setup(self):
super(Num2Word_TG, self).setup()
lows = ["квинт", "квадр", "тр", "м", "м"]
self.high_numwords = self.gen_high_numwords([], [], lows)
self.negword = "минус "
self.pointword = "нуқта"
self.exclude_title = ["ва", "минус", "нуқта"]
self.mid_numwords = [
(1000, "ҳазор"),
(100, "сад"),
(90, "навад"),
(80, "ҳаштод"),
(70, "ҳафтод"),
(60, "шаст"),
(50, "панҷоҳ"),
(40, "чил"),
(30, "си"),
]
self.low_numwords = [
"бист",
"нуздаҳ",
"ҳаждаҳ",
"ҳабдаҳ",
"шонздаҳ",
"понздаҳ",
"чордаҳ",
"сенздаҳ",
"дувоздаҳ",
"ёздаҳ",
"даҳ",
"нӯҳ",
"ҳашт",
"ҳафт",
"шаш",
"панҷ",
"чор",
"се",
"ду",
"як",
"сифр",
]
def to_cardinal(self, value):
try:
assert int(value) == value
except (ValueError, TypeError, AssertionError):
return self.to_cardinal_float(value)
out = ""
if value < 0:
value = abs(value)
out = self.negword
if value >= self.MAXVAL:
raise OverflowError(self.errmsg_toobig % (value, self.MAXVAL))
if value == 100:
return self.title(out + "сад")
else:
val = self.splitnum(value)
words, num = self.clean(val)
return self.title(out + words)
def merge(self, lpair, rpair):
ltext, lnum = lpair
rtext, rnum = rpair
if lnum == 1 and rnum < 100:
return (rtext, rnum)
elif 100 > lnum > rnum:
if ltext == "си":
return ("%sю %s" % (ltext, rtext), lnum + rnum)
elif ltext == "панҷоҳ":
return ("панҷову %s" % (rtext), lnum + rnum)
else:
return ("%sу %s" % (ltext, rtext), lnum + rnum)
elif lnum >= 100 > rnum:
return ("%sу %s" % (ltext, rtext), lnum + rnum)
elif rnum > lnum:
if ltext == "яксад" and rtext not in self.low_numwords:
return ("сад %s" % (rtext), lnum * rnum)
if rtext == "сад":
return ("%s%s" % (ltext, rtext), lnum * rnum)
else:
return ("%s %s" % (ltext, rtext), lnum * rnum)
return ("%sу %s" % (ltext, rtext), lnum + rnum)
def to_ordinal(self, value):
self.verify_ordinal(value)
cardinal = self.to_cardinal(value)
outwords = cardinal.split(" ")
lastword = outwords[-1]
if lastword in ["ду", "се", "си"]:
return "%sюм" % (cardinal)
else:
return "%sум" % (cardinal)
def to_ordinal_num(self, value):
self.verify_ordinal(value)
return "%s%s" % (value, self.to_ordinal(value)[-2:])

183
num2words/lang_TH.py Normal file
View File

@@ -0,0 +1,183 @@
# -*- coding: 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 num2words.base import Num2Word_Base
from num2words.currency import parse_currency_parts
from num2words.utils import splitbyx
class Num2Word_TH(Num2Word_Base):
def setup(self):
self.negword = 'ติดลบ'
self.pointword = 'จุด'
self.CURRENCY_FORMS = {
'THB': (('บาท', 'บาท'), ('สตางค์', 'สตางค์')),
'USD': (('ดอลลาร์', 'ดอลลาร์'), ('เซนต์', 'เซนต์')),
'EUR': (('ยูโร', 'ยูโร'), ('เซนต์', 'เซนต์')),
}
self.high_numwords = []
self.mid_numwords = ['', 'สิบ', 'ร้อย', 'พัน', 'หมื่น', 'แสน', 'ล้าน']
self.low_numwords = [
'ศูนย์', 'หนึ่ง', 'สอง', 'สาม', 'สี่',
'ห้า', 'หก', 'เจ็ด', 'แปด', 'เก้า'
]
def set_high_numwords(self, high_numwords):
pass
def set_mid_numwords(self, mid_numwords):
pass
def splitnum(self, six_num):
length = len(six_num) > 1
word_num = ''
for index, num in enumerate(map(int, six_num)):
if num:
if index:
word_num = self.mid_numwords[index] + word_num
if length and num == 1 and index == 0:
word_num += 'เอ็ด'
elif index == 1 and num == 2:
word_num = 'ยี่' + word_num
elif index != 1 or num != 1:
word_num = self.low_numwords[num] + word_num
elif num == 0 and index == 0 and length == 0:
word_num = self.low_numwords[0]
return word_num
def split_six(self, num_txt):
result = splitbyx(num_txt, 6, format_int=False)
result = list(result)[::-1]
number_list = []
for i in result:
number_list.append(i[::-1])
return number_list
def add_text_million(self, word_num):
result = ''
for index, t in enumerate(reversed(word_num)):
if index == 0:
result = t
else:
result = result + 'ล้าน' + t
return result
def round_2_decimal(self, number):
integer, cents, negative = parse_currency_parts(
number, is_int_with_cents=False
)
integer = '{}'.format(integer)
cents = '{}'.format(cents)
if len(cents) < 2:
add_zero = 2 - len(cents)
cents = ('0' * add_zero) + cents
text_num = integer + '.' + cents
return text_num, negative
def left_num_to_text(self, number):
left_num_list = self.split_six(number)
left_text_list = []
for i in left_num_list:
left_text_list.append(self.splitnum(i))
left_text = self.add_text_million(left_text_list)
return left_text
def to_cardinal(self, number):
negative = number < 0
pre, post = self.float2tuple(number)
precision = self.precision
pre = '{}'.format(pre)
post = '{}'.format(post)
if negative:
pre = pre.lstrip('-')
if len(post) < precision:
add_zero = precision - len(post)
post = ('0' * add_zero) + post
result = self.left_num_to_text(pre)
right_text = ''
if not post == '0':
for i in map(int, post):
right_text = right_text + self.low_numwords[i]
result = result + 'จุด' + right_text
if negative:
result = 'ติดลบ' + result
return result
def to_ordinal(self, number):
return self.to_cardinal(number)
def to_currency(self, number, currency='THB'):
number, negative = self.round_2_decimal(number)
split_num = number.split('.')
left_num = split_num[0]
left_text = self.left_num_to_text(left_num)
right_num = split_num[1]
right_text = self.splitnum(right_num[::-1].rstrip('0'))
try:
cr1, cr2 = self.CURRENCY_FORMS[currency]
except KeyError:
raise NotImplementedError(
'Currency code "%s" not implemented for "%s"' %
(currency, self.__class__.__name__))
if right_num == '00':
if currency == 'THB':
result = left_text + cr1[0] + 'ถ้วน'
else:
result = left_text + cr1[0]
else:
if left_num == '0':
result = right_text + cr2[0]
else:
result = left_text + cr1[0] + right_text + cr2[0]
if negative:
result = self.negword + result
return result

856
num2words/lang_TR.py Normal file
View File

@@ -0,0 +1,856 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# Copyright (c) 2017, Tufan Kaynak, Framras. 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
class Num2Word_TR(Num2Word_Base):
def __init__(self):
self.precision = 2
self.negword = u"eksi"
self.pointword = u"virgül"
self.CURRENCY_UNIT = u"lira"
self.CURRENCY_SUBUNIT = u"kuruş"
self.errmsg_nonnum = u"Sadece sayılar yazıya çevrilebilir."
self.errmsg_floatord = u"Tam sayı olmayan {} sıralamada kullanılamaz."
self.errmsg_negord = u"Pozitif olmayan {} sıralamada kullanılamaz."
self.errmsg_toobig = u"abs({}) sayı yazıya çevirmek için çok büyük. " \
u"Yazıya çevrilebilecek en büyük rakam {}."
self.exclude_title = []
self.DECIMAL_SIGN = ","
self.ORDINAL_SIGN = "."
self.ZERO = u"sıfır"
self.CARDINAL_ONES = {
"1": u"bir",
"2": u"iki",
"3": u"üç",
"4": u"dört",
"5": u"beş",
"6": u"altı",
"7": u"yedi",
"8": u"sekiz",
"9": u"dokuz"
}
self.ORDINAL_ONES = {
"1": u"birinci",
"2": u"ikinci",
"3": u"üçüncü",
"4": u"dördüncü",
"5": u"beşinci",
"6": u"altıncı",
"7": u"yedinci",
"8": u"sekizinci",
"9": u"dokuzuncu"
}
self.CARDINAL_TENS = {
"1": u"on",
"2": u"yirmi",
"3": u"otuz",
"4": u"kırk",
"5": u"elli",
"6": u"altmış",
"7": u"yetmiş",
"8": u"seksen",
"9": u"doksan"
}
self.ORDINAL_TENS = {
"1": u"onuncu",
"2": u"yirminci",
"3": u"otuzuncu",
"4": u"kırkıncı",
"5": u"ellinci",
"6": u"altmışıncı",
"7": u"yetmişinci",
"8": u"sekseninci",
"9": u"doksanıncı"
}
self.HUNDREDS = {
"2": u"iki",
"3": u"üç",
"4": u"dört",
"5": u"beş",
"6": u"altı",
"7": u"yedi",
"8": u"sekiz",
"9": u"dokuz"
}
self.CARDINAL_HUNDRED = (u"yüz",)
self.ORDINAL_HUNDRED = (u"yüzüncü",)
self.CARDINAL_TRIPLETS = {
1: u"bin",
2: u"milyon",
3: u"milyar",
4: u"trilyon",
5: u"katrilyon",
6: u"kentilyon"
}
self.ORDINAL_TRIPLETS = {
1: u"bininci",
2: u"milyonuncu",
3: u"milyarıncı",
4: u"trilyonuncu",
5: u"katrilyonuncu",
6: u"kentilyon"
}
self.MAXVAL = (10 ** ((len(self.CARDINAL_TRIPLETS) + 1) * 3)) - 1
self.integers_to_read = []
self.total_triplets_to_read = 0
self.total_digits_outside_triplets = 0
self.order_of_last_zero_digit = 0
def to_cardinal(self, value):
wrd = ""
is_cardinal = self.verify_cardinal(value)
if not is_cardinal:
return wrd
if not int(value) == value:
return self.to_cardinal_float(value)
if str(value).startswith("-"):
pre_word, value = self.negword, float(str(value)[1:])
else:
pre_word, value = "", float(value)
self.to_splitnum(value)
if self.order_of_last_zero_digit >= len(self.integers_to_read[0]):
# number like 00 and all 0s and even more, raise error
return "%s%s" % (pre_word, wrd)
if self.total_triplets_to_read == 1:
if self.total_digits_outside_triplets == 2:
if self.order_of_last_zero_digit == 1:
# number like x0, read cardinal x0 and return
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][0], ""
)
return "%s%s" % (pre_word, wrd)
if self.order_of_last_zero_digit == 0:
# number like xy, read cardinal xy and return
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][1], ""
)
return "%s%s" % (pre_word, wrd)
if self.total_digits_outside_triplets == 1:
if self.order_of_last_zero_digit == 0:
# number like x, read cardinal x and return
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][0], ""
)
if self.integers_to_read[0][0] == "0":
return self.ZERO
return "%s%s" % (pre_word, wrd)
if self.total_digits_outside_triplets == 0:
if self.order_of_last_zero_digit == 2:
# number like x00, read cardinal x00 and return
wrd += self.HUNDREDS.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_HUNDRED[0]
return "%s%s" % (pre_word, wrd)
if self.order_of_last_zero_digit == 1:
# number like xy0, read cardinal xy0 and return
wrd += self.HUNDREDS.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_HUNDRED[0]
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][1], ""
)
return "%s%s" % (pre_word, wrd)
if self.order_of_last_zero_digit == 0:
# number like xyz, read cardinal xyz and return
wrd += self.HUNDREDS.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_HUNDRED[0]
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][1], ""
)
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][2], ""
)
return "%s%s" % (pre_word, wrd)
if self.total_triplets_to_read >= 2:
if self.total_digits_outside_triplets == 2:
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - 1:
# number like x0 and all 0s, read cardinal x0 0..0
# and return
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
return "%s%s" % (pre_word, wrd)
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - 2:
# number like xy and all 0s, read cardinal xy 0..0
# and return
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][1], ""
)
wrd += self.CARDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
return "%s%s" % (pre_word, wrd)
if self.order_of_last_zero_digit < len(
self.integers_to_read[0]) - 2:
# number like xy and others, read cardinal xy n..n
# and return
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][1], ""
)
wrd += self.CARDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
if self.total_digits_outside_triplets == 1:
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - 1:
# number like x and all 0s, read cardinal x 0..0
# and return
if not (self.total_triplets_to_read == 2 and
self.integers_to_read[0][0] == "1"):
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
return "%s%s" % (pre_word, wrd)
if self.order_of_last_zero_digit < len(
self.integers_to_read[0]) - 1:
# number like x and others, read cardinal x n..n
# and return
if not (self.total_triplets_to_read == 2 and
self.integers_to_read[0][0] == "1"):
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
if self.total_digits_outside_triplets == 0:
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - 1:
# number like x00 and all 0s, read cardinal x00 0..0
# and return
wrd += self.HUNDREDS.get(self.integers_to_read[0][0], "")
wrd += self.CARDINAL_HUNDRED[0]
wrd += self.CARDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
return "%s%s" % (pre_word, wrd)
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - 2:
# number like xy0 and all 0s, read cardinal xy0 0..0
# and return
wrd += self.HUNDREDS.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_HUNDRED[0]
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][1], ""
)
wrd += self.CARDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
return "%s%s" % (pre_word, wrd)
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - 3:
# number like xyz and all 0s, read cardinal xyz 0..0
# and return
wrd += self.HUNDREDS.get(self.integers_to_read[0][0], "")
wrd += self.CARDINAL_HUNDRED[0]
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][1], ""
)
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][2], ""
)
wrd += self.CARDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
return "%s%s" % (pre_word, wrd)
if self.order_of_last_zero_digit < len(
self.integers_to_read[0]) - 3:
# number like xyz and all others, read cardinal xyz n..n
wrd += self.HUNDREDS.get(self.integers_to_read[0][0], "")
wrd += self.CARDINAL_HUNDRED[0]
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][1], ""
)
if not (self.total_triplets_to_read == 2 and
self.integers_to_read[0][2] == "1"):
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][2], ""
)
wrd += self.CARDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
for i in list(range(self.total_triplets_to_read - 1, 0, -1)):
reading_triplet_order = self.total_triplets_to_read - i
if self.total_digits_outside_triplets == 0:
last_read_digit_order = reading_triplet_order * 3
else:
last_read_digit_order = (reading_triplet_order - 1) * 3 +\
self.total_digits_outside_triplets
if not self.integers_to_read[0][
last_read_digit_order: last_read_digit_order + 3
] == "000":
if not self.integers_to_read[0][
last_read_digit_order
] == "0":
wrd += self.HUNDREDS.get(
self.integers_to_read[0][last_read_digit_order], ""
)
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - (
last_read_digit_order) - 1:
if i == 1:
wrd += self.CARDINAL_HUNDRED[0]
return "%s%s" % (pre_word, wrd)
elif i > 1:
wrd += self.CARDINAL_HUNDRED[0]
wrd += self.CARDINAL_TRIPLETS[i - 1]
return "%s%s" % (pre_word, wrd)
else:
wrd += self.CARDINAL_HUNDRED[0]
if not self.integers_to_read[0][
last_read_digit_order + 1] == "0":
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - (
last_read_digit_order) - 2:
if i == 1:
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][
last_read_digit_order + 1], ""
)
return "%s%s" % (pre_word, wrd)
elif i > 1:
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][
last_read_digit_order + 1], ""
)
wrd += self.CARDINAL_TRIPLETS[i - 1]
return "%s%s" % (pre_word, wrd)
else:
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][
last_read_digit_order + 1], ""
)
if not self.integers_to_read[0][
last_read_digit_order + 2] == "0":
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - (
last_read_digit_order) - 3:
if i == 1:
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][
last_read_digit_order + 2], ""
)
return "%s%s" % (pre_word, wrd)
if i == 2:
if not self.integers_to_read[0][
last_read_digit_order:
last_read_digit_order + 2
] == "00":
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][
last_read_digit_order + 2], ""
)
elif not self.integers_to_read[0][
last_read_digit_order + 2] == "1":
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][
last_read_digit_order + 2], ""
)
wrd += self.CARDINAL_TRIPLETS[i - 1]
return "%s%s" % (pre_word, wrd)
if i > 2:
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][
last_read_digit_order + 2], ""
)
wrd += self.CARDINAL_TRIPLETS[i - 1]
return "%s%s" % (pre_word, wrd)
else:
if not self.integers_to_read[0][
last_read_digit_order:
last_read_digit_order + 2
] == "00":
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][
last_read_digit_order + 2], ""
)
else:
if i == 2:
if not self.integers_to_read[0][
last_read_digit_order:
last_read_digit_order + 2
] == "00":
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][
last_read_digit_order + 2], ""
)
elif not self.integers_to_read[0][
last_read_digit_order + 2
] == "1":
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][
last_read_digit_order + 2], ""
)
wrd += self.CARDINAL_TRIPLETS[i - 1]
return "%s%s" % (pre_word, wrd)
def to_cardinal_float(self, value):
self.to_splitnum(value)
wrd = ""
wrd += self.pointword
if len(self.integers_to_read[1]) >= 1:
wrd += self.CARDINAL_TENS.get(self.integers_to_read[1][0], "")
if len(self.integers_to_read[1]) == 2:
wrd += self.CARDINAL_ONES.get(self.integers_to_read[1][1], "")
if self.integers_to_read[0] == "0":
wrd = self.ZERO + wrd
else:
wrd = self.to_cardinal(int(self.integers_to_read[0])) + wrd
return wrd
def verify_cardinal(self, value):
iscardinal = True
try:
if not float(value) == value:
iscardinal = False
except (ValueError, TypeError):
raise TypeError(self.errmsg_nonnum)
if abs(value) >= self.MAXVAL:
raise OverflowError(self.errmsg_toobig.format(value, self.MAXVAL))
return iscardinal
def verify_ordinal(self, value):
isordinal = True
try:
if not int(value) == value:
isordinal = False
if not abs(value) == value:
raise TypeError(self.errmsg_negord.format(value))
except (ValueError, TypeError):
raise TypeError(self.errmsg_nonnum)
if abs(value) >= self.MAXVAL:
raise OverflowError(self.errmsg_toobig.format(value, self.MAXVAL))
return isordinal
def to_ordinal(self, value):
wrd = ""
isordinal = self.verify_ordinal(value)
if isordinal:
self.to_splitnum(value)
if self.order_of_last_zero_digit >= len(self.integers_to_read[0]):
# number like 00 and all 0s and even more, raise error
return wrd
if self.total_triplets_to_read == 1:
if self.total_digits_outside_triplets == 2:
if self.order_of_last_zero_digit == 1:
# number like x0, read ordinal x0 and return
wrd += self.ORDINAL_TENS.get(
self.integers_to_read[0][0], ""
)
return wrd
if self.order_of_last_zero_digit == 0:
# number like xy, read ordinal xy and return
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][0], ""
)
wrd += self.ORDINAL_ONES.get(
self.integers_to_read[0][1], ""
)
return wrd
if self.total_digits_outside_triplets == 1:
if self.order_of_last_zero_digit == 0:
# number like x, read ordinal x and return
wrd += self.ORDINAL_ONES.get(
self.integers_to_read[0][0], ""
)
if self.integers_to_read[0][0] == "0":
return u"sıfırıncı"
return wrd
if self.total_digits_outside_triplets == 0:
if self.order_of_last_zero_digit == 2:
# number like x00, read ordinal x00 and return
wrd += self.HUNDREDS.get(
self.integers_to_read[0][0], ""
)
wrd += self.ORDINAL_HUNDRED[0]
return wrd
if self.order_of_last_zero_digit == 1:
# number like xy0, read ordinal xy0 and return
wrd += self.HUNDREDS.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_HUNDRED[0]
wrd += self.ORDINAL_TENS.get(
self.integers_to_read[0][1], ""
)
return wrd
if self.order_of_last_zero_digit == 0:
# number like xyz, read ordinal xyz and return
wrd += self.HUNDREDS.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_HUNDRED[0]
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][1], ""
)
if not self.integers_to_read[0][2] == "0":
wrd += self.ORDINAL_ONES.get(
self.integers_to_read[0][2], ""
)
return wrd
if self.total_triplets_to_read >= 2:
if self.total_digits_outside_triplets == 2:
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - 1:
# number like x0 and all 0s, read ordinal x0 0..0
# and return
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][0], ""
)
wrd += self.ORDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
return wrd
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - 2:
# number like xy and all 0s, read ordinal xy 0..0
# and return
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][1], ""
)
wrd += self.ORDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
return wrd
if self.order_of_last_zero_digit < len(
self.integers_to_read[0]) - 2:
# number like xy and others, read cardinal xy n..n
# and return
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][1], ""
)
wrd += self.CARDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
if self.total_digits_outside_triplets == 1:
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - 1:
# number like x and all 0s, read ordinal x 0..0
# and return
if not (self.total_triplets_to_read == 2 and
self.integers_to_read[0][0] == "1"):
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][0], ""
)
wrd += self.ORDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
return wrd
if self.order_of_last_zero_digit < len(
self.integers_to_read[0]) - 1:
# number like x and others, read cardinal x n..n
# and return
if not (self.total_triplets_to_read == 2 and
self.integers_to_read[0][0] == "1"):
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
if self.total_digits_outside_triplets == 0:
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - 1:
# number like x00 and all 0s, read ordinal x00 0..0
# and return
wrd += self.HUNDREDS.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_HUNDRED[0]
wrd += self.ORDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
return wrd
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - 2:
# number like xy0 and all 0s, read ordinal xy0 0..0
# and return
wrd += self.HUNDREDS.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_HUNDRED[0]
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][1], ""
)
wrd += self.ORDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
return wrd
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - 3:
# number like xyz and all 0s, read ordinal xyz 0..0
# and return
wrd += self.HUNDREDS.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_HUNDRED[0]
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][1], ""
)
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][2], ""
)
wrd += self.ORDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
return wrd
if self.order_of_last_zero_digit < len(
self.integers_to_read[0]) - 3:
# number like xyz and all others, read cardinal
# xyz n..n
wrd += self.HUNDREDS.get(
self.integers_to_read[0][0], ""
)
wrd += self.CARDINAL_HUNDRED[0]
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][1], ""
)
if not (self.total_triplets_to_read == 2 and
self.integers_to_read[0][2] == "1"):
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][2], ""
)
wrd += self.CARDINAL_TRIPLETS[
self.total_triplets_to_read - 1
]
for i in list(range(self.total_triplets_to_read - 1, 0, -1)):
reading_triplet_order = self.total_triplets_to_read - i
if self.total_digits_outside_triplets == 0:
last_read_digit_order = reading_triplet_order * 3
else:
last_read_digit_order = \
(reading_triplet_order - 1) * 3 + \
self.total_digits_outside_triplets
if not self.integers_to_read[0][
last_read_digit_order: last_read_digit_order + 3
] == "000":
if not self.integers_to_read[0][
last_read_digit_order
] == "0":
if not self.integers_to_read[0][
last_read_digit_order
] == "1":
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][
last_read_digit_order
], ""
)
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - (
last_read_digit_order) - 1:
if i == 1:
wrd += self.ORDINAL_HUNDRED[0]
return wrd
elif i > 1:
wrd += self.CARDINAL_HUNDRED[0]
wrd += self.ORDINAL_TRIPLETS[i - 1]
return wrd
else:
wrd += self.CARDINAL_HUNDRED[0]
if not self.integers_to_read[0][
last_read_digit_order + 1
] == "0":
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - (
last_read_digit_order) - 2:
if i == 1:
wrd += self.ORDINAL_TENS.get(
self.integers_to_read[0][
last_read_digit_order + 1], ""
)
return wrd
elif i > 1:
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][
last_read_digit_order + 1], ""
)
wrd += self.ORDINAL_TRIPLETS[i - 1]
return wrd
else:
wrd += self.CARDINAL_TENS.get(
self.integers_to_read[0][
last_read_digit_order + 1], ""
)
if not self.integers_to_read[0][
last_read_digit_order + 2
] == "0":
if self.order_of_last_zero_digit == len(
self.integers_to_read[0]) - (
last_read_digit_order) - 3:
if i == 1:
wrd += self.ORDINAL_ONES.get(
self.integers_to_read[0][
last_read_digit_order + 2], ""
)
return wrd
if i == 2:
if not self.integers_to_read[0][
last_read_digit_order:
last_read_digit_order + 2] == "00":
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][
last_read_digit_order + 2], ""
)
elif not self.integers_to_read[0][
last_read_digit_order + 2
] == "1":
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][
last_read_digit_order + 2], ""
)
wrd += self.ORDINAL_TRIPLETS[i - 1]
return wrd
if i > 2:
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][
last_read_digit_order + 2], ""
)
wrd += self.ORDINAL_TRIPLETS[i - 1]
return wrd
else:
if not self.integers_to_read[0][
last_read_digit_order:
last_read_digit_order + 2] == "00":
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][
last_read_digit_order + 2], ""
)
else:
if not self.integers_to_read[0][
last_read_digit_order:
last_read_digit_order + 2] == "00":
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][
last_read_digit_order + 2], ""
)
elif not self.integers_to_read[0][
last_read_digit_order + 2] == "1":
wrd += self.CARDINAL_ONES.get(
self.integers_to_read[0][
last_read_digit_order + 2], ""
)
wrd += self.CARDINAL_TRIPLETS[i - 1]
return wrd
def to_ordinal_num(self, value):
self.verify_ordinal(value)
return "%s%s" % (value, self.to_ordinal(value)[-4:])
def to_splitnum(self, val):
float_digits = str(int(val * 10 ** self.precision))
if not int(val) == 0:
self.integers_to_read = [
str(int(val)),
float_digits[len(float_digits) - self.precision:]
]
else:
self.integers_to_read = [
"0",
"0" * (self.precision - len(float_digits)) +
float_digits[len(float_digits) - self.precision:]
]
if len(self.integers_to_read[0]) % 3 > 0:
self.total_triplets_to_read = (len(self.integers_to_read[0]) // 3)\
+ 1
elif len(self.integers_to_read[0]) % 3 == 0:
self.total_triplets_to_read = len(self.integers_to_read[0]) // 3
self.total_digits_outside_triplets = len(self.integers_to_read[0]) % 3
okunacak = list(self.integers_to_read[0][::-1])
self.order_of_last_zero_digit = 0
found = 0
for i in range(len(okunacak) - 1):
if int(okunacak[i]) == 0 and found == 0:
self.order_of_last_zero_digit = i + 1
else:
found = 1
def to_currency(self, value):
if int(value) == 0:
return u"bedelsiz"
valueparts = self.to_cardinal(value).split(self.pointword)
if len(valueparts) == 1:
return valueparts[0] + self.CURRENCY_UNIT
if len(valueparts) == 2:
return self.CURRENCY_UNIT.join(valueparts) + \
self.CURRENCY_SUBUNIT

852
num2words/lang_UK.py Normal file
View File

@@ -0,0 +1,852 @@
# -*- coding: 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 = ('нуль',)
ONES_FEMININE = {
1: ('одна',),
2: ('дві',),
3: ('три',),
4: ('чотири',),
5: ('п\'ять',),
6: ('шість',),
7: ('сім',),
8: ('вісім',),
9: ('дев\'ять',),
}
ONES = {
1: ('один',),
2: ('два',),
3: ('три',),
4: ('чотири',),
5: ('п\'ять',),
6: ('шість',),
7: ('сім',),
8: ('вісім',),
9: ('дев\'ять',),
}
ONES_ORDINALS = {
1: ("перший", "одно"),
2: ("другий", "двох"),
3: ("третій", "трьох"),
4: ("четвертий", "чотирьох"),
5: ("п'ятий", "п'яти"),
6: ("шостий", "шести"),
7: ("сьомий", "семи"),
8: ("восьмий", "восьми"),
9: ("дев'ятий", "дев'яти"),
10: ("десятий", "десяти"),
11: ("одинадцятий", "одинадцяти"),
12: ("дванадцятий", "дванадцяти"),
13: ("тринадцятий", "тринадцяти"),
14: ("чотирнадцятий", "чотирнадцяти"),
15: ("п'ятнадцятий", "п'ятнадцяти"),
16: ("шістнадцятий", "шістнадцяти"),
17: ("сімнадцятий", "сімнадцяти"),
18: ("вісімнадцятий", "вісімнадцяти"),
19: ("дев'ятнадцятий", "дев'ятнадцяти"),
}
TENS = {
0: ('десять',),
1: ('одинадцять',),
2: ('дванадцять',),
3: ('тринадцять',),
4: ('чотирнадцять',),
5: ('п\'ятнадцять',),
6: ('шістнадцять',),
7: ('сімнадцять',),
8: ('вісімнадцять',),
9: ('дев\'ятнадцять',),
}
TWENTIES = {
2: ('двадцять',),
3: ('тридцять',),
4: ('сорок',),
5: ('п\'ятдесят',),
6: ('шістдесят',),
7: ('сімдесят',),
8: ('вісімдесят',),
9: ('дев\'яносто',),
}
TWENTIES_ORDINALS = {
2: ("двадцятий", "двадцяти"),
3: ("тридцятий", "тридцяти"),
4: ("сороковий", "сорока"),
5: ("п'ятдесятий", "п'ятдесяти"),
6: ("шістдесятий", "шістдесяти"),
7: ("сімдесятий", "сімдесяти"),
8: ("вісімдесятий", "вісімдесяти"),
9: ("дев'яностий", "дев'яности"),
}
HUNDREDS = {
1: ('сто',),
2: ('двісті',),
3: ('триста',),
4: ('чотириста',),
5: ('п\'ятсот',),
6: ('шістсот',),
7: ('сімсот',),
8: ('вісімсот',),
9: ('дев\'ятсот',),
}
HUNDREDS_ORDINALS = {
1: ("сотий", "сто"),
2: ("двохсотий", "двохсот"),
3: ("трьохсотий", "трьохсот"),
4: ("чотирьохсотий", "чотирьохсот"),
5: ("п'ятисотий", "п'ятсот"),
6: ("шестисотий", "шістсот"),
7: ("семисотий", "сімсот"),
8: ("восьмисотий", "вісімсот"),
9: ("дев'ятисотий", "дев'ятсот"),
}
THOUSANDS = {
1: ('тисяча', 'тисячі', 'тисяч'), # 10^3
2: ('мільйон', 'мільйони', 'мільйонів'), # 10^6
3: ('мільярд', 'мільярди', 'мільярдів'), # 10^9
4: ('трильйон', 'трильйони', 'трильйонів'), # 10^12
5: ('квадрильйон', 'квадрильйони', 'квадрильйонів'), # 10^15
6: ('квінтильйон', 'квінтильйони', 'квінтильйонів'), # 10^18
7: ('секстильйон', 'секстильйони', 'секстильйонів'), # 10^21
8: ('септильйон', 'септильйони', 'септильйонів'), # 10^24
9: ('октильйон', 'октильйони', 'октильйонів'), # 10^27
10: ('нонільйон', 'нонільйони', 'нонільйонів'), # 10^30
}
prefixes_ordinal = {
1: "тисячний",
2: "мільйонний",
3: "мільярдний",
4: "трильйонний",
5: "квадрильйонний",
6: "квінтильйонний",
7: "секстильйонний",
8: "септильйонний",
9: "октильйонний",
10: "нонільйонний",
}
FEMININE_MONEY = ('AOA', 'BAM', 'BDT', 'BWP', 'CZK', 'DKK',
'ERN', 'HNL', 'HRK', 'IDR', 'INR', 'ISK',
'JPY', 'KPW', 'KRW', 'LKR', 'MOP', 'MRU',
'MUR', 'MVR', 'MWK', 'NGN', 'NIO', 'NOK',
'NPR', 'PKR', 'SCR', 'SEK', 'STN', 'TRY',
'WST', 'UAH', 'ZMW')
FEMININE_CENTS = ('ALL', 'BDT', 'BGN', 'BYN', 'GHS', 'HRK',
'ILS', 'INR', 'NPR', 'OMR', 'OMR', 'PKR',
'RSD', 'RUB', 'UAH')
GENERIC_DOLLARS = ('долар', 'долари', 'доларів')
GENERIC_CENTS = ('цент', 'центи', 'центів')
class Num2Word_UK(Num2Word_Base):
CURRENCY_FORMS = {
'AED': (
('дирхам', 'дирхами', 'дирхамів'),
('філс', 'філси', 'філсів')
),
'AFN': (
('афгані', 'афгані', 'афгані'),
('пул', 'пули', 'пулів')
),
'ALL': (
('лек', 'леки', 'леків'),
('кіндарка', 'кіндарки', 'кіндарок')
),
'AMD': (
('драм', 'драми', 'драмів'),
('лум', 'лум', 'лум')
),
'ANG': (
('гульден', 'гульдени', 'гульденів'),
GENERIC_CENTS
),
'AOA': (
('кванза', 'кванзи', 'кванз'),
('сентимо', 'сентимо', 'сентимо')
),
'ARS': (
('песо', 'песо', 'песо'),
('сентаво', 'сентаво', 'сентаво')
),
'AUD': (GENERIC_DOLLARS, GENERIC_CENTS),
'AWG': (
('флорин', 'флорини', 'флоринів'),
GENERIC_CENTS
),
'AZN': (
('манат', 'манати', 'манатів'),
('гяпік', 'гяпіки', 'гяпіків')
),
'BAM': (
('марка', 'марки', 'марок'),
('фенінг', 'фенінги', 'фенінгів')
),
'BBD': (GENERIC_DOLLARS, GENERIC_CENTS),
'BDT': (
('така', 'таки', 'так'),
('пойша', 'пойші', 'пойш')
),
'BGN': (
('лев', 'леви', 'левів'),
('стотинка', 'стотинки', 'стотинок')
),
'BHD': (
('динар', 'динари', 'динарів'),
('філс', 'філси', 'філсів')
),
'BIF': (
('франк', 'франки', 'франків'),
('сантим', 'сантими', 'сантимів')
),
'BMD': (GENERIC_DOLLARS, GENERIC_CENTS),
'BND': (GENERIC_DOLLARS, GENERIC_CENTS),
'BOB': (
('болівіано', 'болівіано', 'болівіано'),
('сентаво', 'сентаво', 'сентаво')
),
'BRL': (
('реал', 'реали', 'реалів'),
('сентаво', 'сентаво', 'сентаво')
),
'BSD': (GENERIC_DOLLARS, GENERIC_CENTS),
'BTN': (
('нгултрум', 'нгултруми', 'нгултрумів'),
('четрум', 'четруми', 'четрумів')
),
'BWP': (
('пула', 'пули', 'пул'),
('тхебе', 'тхебе', 'тхебе')
),
'BYN': (
('рубель', 'рублі', 'рублів'),
('копійка', 'копійки', 'копійок')
),
'BZD': (GENERIC_DOLLARS, GENERIC_CENTS),
'CAD': (GENERIC_DOLLARS, GENERIC_CENTS),
'CDF': (
('франк', 'франки', 'франків'),
('сантим', 'сантими', 'сантимів')
),
'CHF': (
('франк', 'франки', 'франків'),
('сантим', 'сантими', 'сантимів')
),
'CLP': (
('песо', 'песо', 'песо'),
('сентаво', 'сентаво', 'сентаво')
),
'CNY': (
('юань', 'юані', 'юанів'),
('финь', 'фині', 'финів')
),
'COP': (
('песо', 'песо', 'песо'),
('сентаво', 'сентаво', 'сентаво')
),
'CRC': (
('колон', 'колони', 'колонів'),
('сентімо', 'сентімо', 'сентімо')
),
'CUC': (
('песо', 'песо', 'песо'),
('сентаво', 'сентаво', 'сентаво')
),
'CUP': (
('песо', 'песо', 'песо'),
('сентаво', 'сентаво', 'сентаво')
),
'CVE': (
('ескудо', 'ескудо', 'ескудо'),
('сентаво', 'сентаво', 'сентаво')
),
'CZK': (
('крона', 'крони', 'крон'),
('гелер', 'гелери', 'гелерів')
),
'DJF': (
('франк', 'франки', 'франків'),
('сантим', 'сантими', 'сантимів')
),
'DKK': (
('крона', 'крони', 'крон'),
('ере', 'ере', 'ере')
),
'DOP': (
('песо', 'песо', 'песо'),
('сентаво', 'сентаво', 'сентаво')
),
'DZD': (
('динар', 'динари', 'динарів'),
('сантим', 'сантими', 'сантимів')
),
'EGP': (
('фунт', 'фунти', 'фунтів'),
('піастр', 'піастри', 'піастрів')
),
'ERN': (
('накфа', 'накфи', 'накф'),
GENERIC_CENTS
),
'ETB': (
('бир', 'бири', 'бирів'),
GENERIC_CENTS
),
'EUR': (
('євро', 'євро', 'євро'),
GENERIC_CENTS
),
'FJD': (GENERIC_DOLLARS, GENERIC_CENTS),
'FKP': (
('фунт', 'фунти', 'фунтів'),
('пенс', 'пенси', 'пенсів')
),
'GBP': (
('фунт', 'фунти', 'фунтів'),
('пенс', 'пенси', 'пенсів')
),
'GEL': (
('ларі', 'ларі', 'ларі'),
('тетрі', 'тетрі', 'тетрі')
),
'GHS': (
('седі', 'седі', 'седі'),
('песева', 'песеви', 'песев')
),
'GIP': (
('фунт', 'фунти', 'фунтів'),
('пенс', 'пенси', 'пенсів')
),
'GMD': (
('даласі', 'даласі', 'даласі'),
('бутут', 'бутути', 'бутутів')
),
'GNF': (
('франк', 'франки', 'франків'),
('сантим', 'сантими', 'сантимів')
),
'GTQ': (
('кетсаль', 'кетсалі', 'кетсалів'),
('сентаво', 'сентаво', 'сентаво')
),
'GYD': (GENERIC_DOLLARS, GENERIC_CENTS),
'HKD': (GENERIC_DOLLARS, GENERIC_CENTS),
'HNL': (
('лемпіра', 'лемпіри', 'лемпір'),
('сентаво', 'сентаво', 'сентаво')
),
'HRK': (
('куна', 'куни', 'кун'),
('ліпа', 'ліпи', 'ліп')
),
'HTG': (
('гурд', 'гурди', 'гурдів'),
('сантим', 'сантими', 'сантимів')
),
'HUF': (
('форинт', 'форинти', 'форинтів'),
('філлер', 'філлери', 'філлерів')
),
'IDR': (
('рупія', 'рупії', 'рупій'),
GENERIC_CENTS
),
'ILS': (
('шекель', 'шекелі', 'шекелів'),
('агора', 'агори', 'агор')
),
'INR': (
('рупія', 'рупії', 'рупій'),
('пайса', 'пайси', 'пайс')
),
'IQD': (
('динар', 'динари', 'динарів'),
('філс', 'філси', 'філсів')
),
'IRR': (
('ріал', 'ріали', 'ріалів'),
('динар', 'динари', 'динарів')
),
'ISK': (
('крона', 'крони', 'крон'),
('ейре', 'ейре', 'ейре')
),
'JMD': (GENERIC_DOLLARS, GENERIC_CENTS),
'JOD': (
('динар', 'динари', 'динарів'),
('філс', 'філси', 'філсів')
),
'JPY': (
('єна', 'єни', 'єн'),
('сен', 'сен', 'сен')
),
'KES': (
('шилінг', 'шилінги', 'шилінгів'),
GENERIC_CENTS
),
'KGS': (
('сом', 'соми', 'сомів'),
('тиїн', 'тиїни', 'тиїнів')
),
'KHR': (
('рієль', 'рієлі', 'рієлів'),
('су', 'су', 'су')
),
'KMF': (
('франк', 'франки', 'франків'),
('сантим', 'сантими', 'сантимів')
),
'KPW': (
('вона', 'вони', 'вон'),
('чон', 'чони', 'чонів')
),
'KRW': (
('вона', 'вони', 'вон'),
('джеон', 'джеони', 'джеонів')
),
'KWD': (
('динар', 'динари', 'динарів'),
('філс', 'філси', 'філсів')
),
'KYD': (GENERIC_DOLLARS, GENERIC_CENTS),
'KZT': (
('теньге', 'теньге', 'теньге'),
('тиїн', 'тиїни', 'тиїнів')),
'LAK': (
('кіп', 'кіпи', 'кіпів'),
('ат', 'ати', 'атів')
),
'LBP': (
('фунт', 'фунти', 'фунтів'),
('піастр', 'піастри', 'піастрів')
),
'LKR': (
('рупія', 'рупії', 'рупій'),
GENERIC_CENTS
),
'LRD': (GENERIC_DOLLARS, GENERIC_CENTS),
'LSL': (
('лоті', 'малоті', 'малоті'),
('сенте', 'лісенте', 'лісенте')
),
'LYD': (
('динар', 'динари', 'динарів'),
('дирхам', 'дирхами', 'дирхамів')
),
'MAD': (
('дирхам', 'дирхами', 'дирхамів'),
('сантим', 'сантими', 'сантимів')
),
'MDL': (
('лей', 'леї', 'леї'),
('бан', 'бані', 'бані')
),
'MGA': (
('аріарі', 'аріарі', 'аріарі'),
('іраймбіланья', 'іраймбіланья', 'іраймбіланья')
),
'MKD': (
('денар', 'денари', 'денарів'),
('дені', 'дені', 'дені')
),
'MMK': (
('к\'ят', 'к\'ят', 'к\'ят'),
('п\'я', 'п\'я', 'п\'я')
),
'MNT': (
('тугрик', 'тугрики', 'тугриків'),
('мунгу', 'мунгу', 'мунгу')
),
'MOP': (
('патака', 'патакі', 'патак'),
('аво', 'аво', 'аво')
),
'MRU': (
('угія', 'угії', 'угій'),
('хумс', 'хумс', 'хумс')
),
'MUR': (
('рупія', 'рупії', 'рупій'),
GENERIC_CENTS
),
'MVR': (
('руфія', 'руфії', 'руфій'),
('ларі', 'ларі', 'ларі')
),
'MWK': (
('квача', 'квачі', 'квач'),
('тамбала', 'тамбала', 'тамбала')
),
'MXN': (
('песо', 'песо', 'песо'),
('сентаво', 'сентаво', 'сентаво')
),
'MYR': (
('рингіт', 'рингіти', 'рингітів'),
GENERIC_CENTS
),
'MZN': (
('метікал', 'метікали', 'метікалів'),
('сентаво', 'сентаво', 'сентаво')
),
'NAD': (GENERIC_DOLLARS, GENERIC_CENTS),
'NGN': (
('найра', 'найри', 'найр'),
('кобо', 'кобо', 'кобо')
),
'NIO': (
('кордоба', 'кордоби', 'кордоб'),
('сентаво', 'сентаво', 'сентаво')
),
'NOK': (
('крона', 'крони', 'крон'),
('ере', 'ере', 'ере')
),
'NPR': (
('рупія', 'рупії', 'рупій'),
('пайса', 'пайси', 'пайс')
),
'NZD': (GENERIC_DOLLARS, GENERIC_CENTS),
'OMR': (
('ріал', 'ріали', 'ріалів'),
('байза', 'байзи', 'байз')
),
'PAB': (
('бальбоа', 'бальбоа', 'бальбоа'),
('сентесімо', 'сентесімо', 'сентесімо')
),
'PEN': (
('соль', 'соль', 'соль'),
('сентімо', 'сентімо', 'сентімо')
),
'PGK': (
('кіна', 'кіна', 'кіна'),
('тойя', 'тойя', 'тойя')
),
'PHP': (
('песо', 'песо', 'песо'),
('сентаво', 'сентаво', 'сентаво')
),
'PKR': (
('рупія', 'рупії', 'рупій'),
('пайса', 'пайси', 'пайс')
),
'PLN': (
('злотий', 'злоті', 'злотих'),
('грош', 'гроші', 'грошів')
),
'PYG': (
('гуарані', 'гуарані', 'гуарані'),
('сентімо', 'сентімо', 'сентімо')
),
'QAR': (
('ріал', 'ріали', 'ріалів'),
('дирхам', 'дирхами', 'дирхамів')
),
'RON': (
('лей', 'леї', 'леї'),
('бан', 'бані', 'бані')
),
'RSD': (
('динар', 'динари', 'динарів'),
('пара', 'пари', 'пар')
),
'RUB': (
('рубль', 'рублі', 'рублів'),
('копійка', 'копійки', 'копійок')
),
'RWF': (
('франк', 'франки', 'франків'),
('сантим', 'сантими', 'сантимів')
),
'SAR': (
('ріал', 'ріали', 'ріалів'),
('халал', 'халали', 'халалів')
),
'SBD': (GENERIC_DOLLARS, GENERIC_CENTS),
'SCR': (
('рупія', 'рупії', 'рупій'),
GENERIC_CENTS
),
'SDG': (
('фунт', 'фунти', 'фунтів'),
('піастр', 'піастри', 'піастрів')
),
'SEK': (
('крона', 'крони', 'крон'),
('ере', 'ере', 'ере')
),
'SGD': (GENERIC_DOLLARS, GENERIC_CENTS),
'SHP': (
('фунт', 'фунти', 'фунтів'),
('пенс', 'пенси', 'пенсів')
),
'SLL': (
('леоне', 'леоне', 'леоне'),
GENERIC_CENTS
),
'SOS': (
('шилінг', 'шилінги', 'шилінгів'),
GENERIC_CENTS
),
'SRD': (GENERIC_DOLLARS, GENERIC_CENTS),
'SSP': (
('фунт', 'фунти', 'фунтів'),
('піастр', 'піастри', 'піастрів')
),
'STN': (
('добра', 'добри', 'добр'),
('сентімо', 'сентімо', 'сентімо')
),
'SYP': (
('фунт', 'фунти', 'фунтів'),
('піастр', 'піастри', 'піастрів')
),
'SZL': (
('ліланґені', 'ліланґені', 'ліланґені'),
GENERIC_CENTS
),
'THB': (
('бат', 'бати', 'батів'),
('сатанг', 'сатанги', 'сатангів')
),
'TJS': (
('сомоні', 'сомоні', 'сомоні'),
('дірам', 'дірами', 'дірамів')
),
'TMT': (
('манат', 'манати', 'манатів'),
('тенге', 'тенге', 'тенге')
),
'TND': (
('динар', 'динари', 'динарів'),
('міллім', 'мілліми', 'міллімів')
),
'TOP': (
('паанга', 'паанга', 'паанга'),
('сеніті', 'сеніті', 'сеніті')
),
'TRY': (
('ліра', 'ліри', 'лір'),
('куруш', 'куруші', 'курушів')
),
'TTD': (GENERIC_DOLLARS, GENERIC_CENTS),
'TWD': (
('новий долар', 'нові долари', 'нових доларів'),
GENERIC_CENTS
),
'TZS': (
('шилінг', 'шилінги', 'шилінгів'),
GENERIC_CENTS
),
'UAH': (
('гривня', 'гривні', 'гривень'),
('копійка', 'копійки', 'копійок')
),
'UGX': (
('шилінг', 'шилінги', 'шилінгів'),
GENERIC_CENTS
),
'USD': (GENERIC_DOLLARS, GENERIC_CENTS),
'UYU': (
('песо', 'песо', 'песо'),
('сентесімо', 'сентесімо', 'сентесімо')
),
'UZS': (
('сум', 'суми', 'сумів'),
('тиїн', 'тиїни', 'тиїнів')
),
'VND': (
('донг', 'донги', 'донгів'),
('су', 'су', 'су')
),
'WST': (
('тала', 'тали', 'тал'),
('сене', 'сене', 'сене')
),
'XCD': (GENERIC_DOLLARS, GENERIC_CENTS),
'YER': (
('ріал', 'ріали', 'ріалів'),
('філс', 'філси', 'філсів')
),
'ZAR': (
('ранд', 'ранди', 'рандів'),
GENERIC_CENTS
),
'ZMW': (
('квача', 'квачі', 'квач'),
('нгве', 'нгве', 'нгве')
),
}
def setup(self):
self.negword = "мінус"
self.pointword = "кома"
def to_cardinal(self, number):
n = str(number).replace(',', '.')
if '.' in n:
left, right = n.split('.')
leading_zero_count = len(right) - len(right.lstrip('0'))
decimal_part = ((ZERO[0] + ' ') * leading_zero_count +
self._int2word(int(right)))
return u'%s %s %s' % (
self._int2word(int(left)),
self.pointword,
decimal_part
)
else:
return self._int2word(int(n))
def pluralize(self, n, forms):
if n % 100 < 10 or n % 100 > 20:
if n % 10 == 1:
form = 0
elif 5 > n % 10 > 1:
form = 1
else:
form = 2
else:
form = 2
return forms[form]
def _int2word(self, n, feminine=False):
if n < 0:
return ' '.join([self.negword, self._int2word(abs(n))])
if n == 0:
return ZERO[0]
words = []
chunks = list(splitbyx(str(n), 3))
i = len(chunks)
for x in chunks:
i -= 1
if x == 0:
continue
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):
elif n1 > 0:
ones = ONES_FEMININE if i == 1 or feminine and i == 0 else ONES
words.append(ones[n1][0])
if i > 0:
words.append(self.pluralize(x, THOUSANDS[i]))
return ' '.join(words)
def _money_verbose(self, number, currency):
return self._int2word(number, currency in FEMININE_MONEY)
def _cents_verbose(self, number, currency):
return self._int2word(number, currency in FEMININE_CENTS)
@staticmethod
def last_fragment_to_ordinal(last, words, level):
n1, n2, n3 = get_digits(last)
last_two = n2*10+n1
if last_two == 0:
words.append(HUNDREDS_ORDINALS[n3][level])
elif level == 1 and last == 1:
return
elif last_two < 20:
if level == 0:
if n3 > 0:
words.append(HUNDREDS[n3][0])
words.append(ONES_ORDINALS[last_two][0])
else:
last_fragment_string = ''
if n3 > 0:
last_fragment_string += HUNDREDS_ORDINALS[n3][1]
last_fragment_string += ONES_ORDINALS[last_two][1]
words.append(last_fragment_string)
elif last_two % 10 == 0:
if level == 0:
if n3 > 0:
words.append(HUNDREDS[n3][0])
words.append(TWENTIES_ORDINALS[n2][0])
else:
last_fragment_string = ''
if n3 > 0:
last_fragment_string += HUNDREDS_ORDINALS[n3][1]
last_fragment_string += TWENTIES_ORDINALS[n2][1]
words.append(last_fragment_string)
else:
if level == 0:
if n3 > 0:
words.append(HUNDREDS[n3][0])
words.append(TWENTIES[n2][0])
words.append(ONES_ORDINALS[n1][0])
else:
last_fragment_string = ''
if n3 > 0:
last_fragment_string += HUNDREDS_ORDINALS[n3][1]
last_fragment_string += TWENTIES_ORDINALS[n2][1]
last_fragment_string += ONES_ORDINALS[n1][1]
words.append(last_fragment_string)
def to_ordinal(self, number):
self.verify_ordinal(number)
words = []
fragments = list(splitbyx(str(number), 3))
level = 0
last = fragments[-1]
while last == 0:
level = level + 1
fragments.pop()
last = fragments[-1]
if len(fragments) > 1:
pre_part = self._int2word(number - (last * 1000 ** level))
words.append(pre_part)
Num2Word_UK.last_fragment_to_ordinal(
last,
words,
0 if level == 0 else 1
)
output = " ".join(words)
if last == 1 and level > 0 and output != "":
output = output + " "
if level > 0:
output = output + prefixes_ordinal[level]
return output

101
num2words/lang_VI.py Normal file
View File

@@ -0,0 +1,101 @@
# -*- coding: 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
to_19 = (u'không', u'một', u'hai', u'ba', u'bốn', u'năm', u'sáu',
u'bảy', u'tám', u'chín', u'mười', u'mười một', u'mười hai',
u'mười ba', u'mười bốn', u'mười lăm', u'mười sáu', u'mười bảy',
u'mười tám', u'mười chín')
tens = (u'hai mươi', u'ba mươi', u'bốn mươi', u'năm mươi',
u'sáu mươi', u'bảy mươi', u'tám mươi', u'chín mươi')
denom = ('',
u'nghìn', u'triệu', u'tỷ', u'nghìn tỷ', u'trăm nghìn tỷ',
'Quintillion', 'Sextillion', 'Septillion', 'Octillion', 'Nonillion',
'Decillion', 'Undecillion', 'Duodecillion', 'Tredecillion',
'Quattuordecillion', 'Sexdecillion', 'Septendecillion',
'Octodecillion', 'Novemdecillion', 'Vigintillion')
class Num2Word_VI(object):
def _convert_nn(self, val):
if val < 20:
return to_19[val]
for (dcap, dval) in ((k, 20 + (10 * v)) for (v, k) in enumerate(tens)):
if dval + 10 > val:
if val % 10:
a = u'lăm'
if to_19[val % 10] == u'một':
a = u'mốt'
else:
a = to_19[val % 10]
if to_19[val % 10] == u'năm':
a = u'lăm'
return dcap + ' ' + a
return dcap
def _convert_nnn(self, val):
word = ''
(mod, rem) = (val % 100, val // 100)
if rem > 0:
word = to_19[rem] + u' trăm'
if mod > 0:
word = word + ' '
if mod > 0 and mod < 10:
if mod == 5:
word = word != '' and word + u'lẻ năm' or word + u'năm'
else:
word = word != '' and word + u'lẻ ' \
+ self._convert_nn(mod) or word + self._convert_nn(mod)
if mod >= 10:
word = word + self._convert_nn(mod)
return word
def vietnam_number(self, val):
if val < 100:
return self._convert_nn(val)
if val < 1000:
return self._convert_nnn(val)
for (didx, dval) in ((v - 1, 1000 ** v) for v in range(len(denom))):
if dval > val:
mod = 1000 ** didx
lval = val // mod
r = val - (lval * mod)
ret = self._convert_nnn(lval) + u' ' + denom[didx]
if 99 >= r > 0:
ret = self._convert_nnn(lval) + u' ' + denom[didx] + u' lẻ'
if r > 0:
ret = ret + ' ' + self.vietnam_number(r)
return ret
def number_to_text(self, number):
number = '%.2f' % number
the_list = str(number).split('.')
start_word = self.vietnam_number(int(the_list[0]))
final_result = start_word
if len(the_list) > 1 and int(the_list[1]) > 0:
end_word = self.vietnam_number(int(the_list[1]))
final_result = final_result + ' phẩy ' + end_word
return final_result
def to_cardinal(self, number):
return self.number_to_text(number)
def to_ordinal(self, number):
return self.to_cardinal(number)

35
num2words/utils.py Normal file
View File

@@ -0,0 +1,35 @@
# -*- coding: 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
def splitbyx(n, x, format_int=True):
length = len(n)
if length > x:
start = length % x
if start > 0:
result = n[:start]
yield int(result) if format_int else result
for i in range(start, length, x):
result = n[i:i+x]
yield int(result) if format_int else result
else:
yield int(n) if format_int else n
def get_digits(n):
a = [int(x) for x in reversed(list(('%03d' % n)[-3:]))]
return a

7
requirements-test.txt Normal file
View File

@@ -0,0 +1,7 @@
tox
flake8
flake8-copyright
isort
pep8<1.6
coverage
delegator.py

View File

@@ -1,32 +1,83 @@
from setuptools import setup, find_packages # -*- coding: 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
import re
from io import open
from setuptools import find_packages, setup
PACKAGE_NAME = "num2words"
CLASSIFIERS = [ CLASSIFIERS = [
'Development Status :: 5 - Production/Stable', 'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers', 'Intended Audience :: Developers',
'License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)', 'License :: OSI Approved :: GNU Library or Lesser General Public License '
'Programming Language :: Python :: 2.7', '(LGPL)',
'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Topic :: Software Development :: Internationalization', 'Topic :: Software Development :: Internationalization',
'Topic :: Software Development :: Libraries :: Python Modules', 'Topic :: Software Development :: Libraries :: Python Modules',
'Topic :: Software Development :: Localization', 'Topic :: Software Development :: Localization',
'Topic :: Text Processing :: Linguistic', 'Topic :: Text Processing :: Linguistic',
] ]
LONG_DESC = open('README.rst', 'rt').read() + '\n\n' + open('CHANGES.rst', 'rt').read() LONG_DESC = open('README.rst', 'rt', encoding="utf-8").read() + '\n\n' + \
open('CHANGES.rst', 'rt', encoding="utf-8").read()
def find_version(fname):
"""Parse file & return version number matching 0.0.1 regex
Returns str or raises RuntimeError
"""
version = ''
with open(fname, 'r', encoding="utf-8") as fp:
reg = re.compile(r'__version__ = [\'"]([^\'"]*)[\'"]')
for line in fp:
m = reg.match(line)
if m:
version = m.group(1)
break
if not version:
raise RuntimeError('Cannot find version information')
return version
setup( setup(
name='num2words', name=PACKAGE_NAME,
version='0.5.1', version=find_version("bin/num2words"),
description='Modules to convert numbers to words. Easily extensible.', description='Modules to convert numbers to words. Easily extensible.',
long_description=LONG_DESC,
long_description_content_type="text/markdown",
license='LGPL', license='LGPL',
author='Taro Ogawa <tso at users sourceforge net>', author='Taro Ogawa <tso at users sourceforge net>',
author_email='tos@users.sourceforge.net', author_email='tos@users.sourceforge.net',
maintainer='Savoir-faire Linux inc.', maintainer='Savoir-faire Linux inc.',
maintainer_email='virgil.dupras@savoirfairelinux.com', maintainer_email='support@savoirfairelinux.com',
keywords=' number word numbers words convert conversion i18n localisation localization internationalisation internationalization', keywords=' number word numbers words convert conversion i18n '
'localisation localization internationalisation '
'internationalization',
url='https://github.com/savoirfairelinux/num2words', url='https://github.com/savoirfairelinux/num2words',
packages=find_packages(), packages=find_packages(exclude=['tests']),
test_suite='tests', test_suite='tests',
use_2to3=True, classifiers=CLASSIFIERS,
scripts=['bin/num2words'],
install_requires=["docopt>=0.6.2"],
tests_require=['delegator.py'],
) )

94
tests/test_am.py Normal file
View File

@@ -0,0 +1,94 @@
# -*- coding: 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 unittest import TestCase
from num2words import num2words
class Num2WordsAMTest(TestCase):
def test_cardinal(self):
self.assertEqual(num2words(100, lang='am'), 'መቶ')
self.assertEqual(num2words(100000, lang='am'), 'አንድ መቶ ሺህ')
self.assertEqual(num2words(101, lang='am'), 'አንድ መቶ አንድ')
def test_and_join_199(self):
self.assertEqual(num2words(199, lang='am'), 'አንድ መቶ ዘጠና ዘጠኝ')
def test_to_ordinal(self):
self.assertEqual(
num2words(1, lang='am', to='ordinal'),
'አንደኛ'
)
self.assertEqual(
num2words(13, lang='am', to='ordinal'),
'አሥራ ሦስተኛ'
)
self.assertEqual(
num2words(22, lang='am', to='ordinal'),
'ሃያ ሁለተኛ'
)
self.assertEqual(
num2words(10000, lang='am', to='ordinal'),
'አሥር ሺህኛ'
)
def test_to_ordinal_num(self):
self.assertEqual(num2words(10, lang='am', to='ordinal_num'), '10ኛ')
self.assertEqual(num2words(21, lang='am', to='ordinal_num'), '21ኛ')
self.assertEqual(num2words(102, lang='am', to='ordinal_num'), '102ኛ')
def test_cardinal_for_float_number(self):
self.assertEqual(num2words(12.5, lang='am'), 'አሥራ ሁለት ነጥብ አምስት')
self.assertEqual(num2words(12.51, lang='am'), 'አሥራ ሁለት ነጥብ አምስት አንድ')
self.assertEqual(num2words(12.53, lang='am'), 'አሥራ ሁለት ነጥብ አምስት ሦስት')
def test_to_overflow(self):
with self.assertRaises(OverflowError):
num2words('1000000000000000000000000000000000000000000000000000000'
'0000000000000000000000000000000000000000000000000000000'
'0000000000000000000000000000000000000000000000000000000'
'0000000000000000000000000000000000000000000000000000000'
'0000000000000000000000000000000000000000000000000000000'
'00000000000000000000000000000000', lang='am')
def test_to_currency(self):
self.assertEqual(
num2words('38.4', lang='am', to='currency', cents=False,
currency='ETB'), 'ሠላሳ ስምንት ብር ከ 40 ሳንቲም'
)
self.assertEqual(
num2words('0', lang='am', to='currency', separator=' እና',
cents=True, currency='ETB'), 'ዜሮ ብር እና ዜሮ ሳንቲም'
)
self.assertEqual(
num2words('1.50', lang='am', to='currency', cents=True,
currency='ETB'), 'አንድ ብር ከ አምሳ ሳንቲም'
)
def test_to_year(self):
self.assertEqual(num2words(1990, lang='am', to='year'),
'አሥራ ዘጠኝ መቶ ዘጠና')
self.assertEqual(num2words(5555, lang='am', to='year'),
'አምሳ አምስት መቶ አምሳ አምስት')
self.assertEqual(num2words(2017, lang='am', to='year'),
'ሁለት ሺህ አሥራ ሰባት')
self.assertEqual(num2words(1066, lang='am', to='year'),
'አንድ ሺህ ስድሳ ስድስት')
self.assertEqual(num2words(1865, lang='am', to='year'),
'አሥራ ስምንት መቶ ስድሳ አምስት')

113
tests/test_ar.py Normal file
View File

@@ -0,0 +1,113 @@
# -*- coding: 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 unittest import TestCase
from num2words import num2words
class Num2WordsARTest(TestCase):
def test_default_currency(self):
self.assertEqual(num2words(1, to='currency', lang='ar'), 'واحد ريال')
self.assertEqual(num2words(2, to='currency', lang='ar'),
'اثنان ريالان')
self.assertEqual(num2words(10, to='currency', lang='ar'),
'عشرة ريالات')
self.assertEqual(num2words(100, to='currency', lang='ar'), 'مائة ريال')
self.assertEqual(num2words(652.12, to='currency', lang='ar'),
'ستمائة و اثنان و خمسون ريالاً و اثنتا عشرة هللة')
self.assertEqual(num2words(324, to='currency', lang='ar'),
'ثلاثمائة و أربعة و عشرون ريالاً')
self.assertEqual(num2words(2000, to='currency', lang='ar'),
'ألفا ريال')
self.assertEqual(num2words(541, to='currency', lang='ar'),
'خمسمائة و واحد و أربعون ريالاً')
self.assertEqual(num2words(10000, to='currency', lang='ar'),
'عشرة آلاف ريال')
self.assertEqual(num2words(20000.12, to='currency', lang='ar'),
'عشرون ألف ريال و اثنتا عشرة هللة')
self.assertEqual(num2words(1000000, to='currency', lang='ar'),
'واحد مليون ريال')
val = 'تسعمائة و ثلاثة و عشرون ألفاً و أربعمائة و أحد عشر ريالاً'
self.assertEqual(num2words(923411, to='currency', lang='ar'), val)
self.assertEqual(num2words(63411, to='currency', lang='ar'),
'ثلاثة و ستون ألفاً و أربعمائة و أحد عشر ريالاً')
self.assertEqual(num2words(1000000.99, to='currency', lang='ar'),
'واحد مليون ريال و تسع و تسعون هللة')
def test_currency_parm(self):
self.assertEqual(
num2words(1, to='currency', lang='ar', currency="KWD"),
'واحد دينار')
self.assertEqual(
num2words(10, to='currency', lang='ar', currency="EGP"),
'عشرة جنيهات')
self.assertEqual(
num2words(20000.12, to='currency', lang='ar', currency="EGP"),
'عشرون ألف جنيه و اثنتا عشرة قرش')
self.assertEqual(
num2words(923411, to='currency', lang='ar', currency="SR"),
'تسعمائة و ثلاثة و عشرون ألفاً و أربعمائة و أحد عشر ريالاً')
self.assertEqual(
num2words(1000000.99, to='currency', lang='ar', currency="KWD"),
'واحد مليون دينار و تسع و تسعون فلس')
def test_ordinal(self):
self.assertEqual(num2words(1, to='ordinal', lang='ar'), 'اول')
self.assertEqual(num2words(2, to='ordinal', lang='ar'), 'ثاني')
self.assertEqual(num2words(3, to='ordinal', lang='ar'), 'ثالث')
self.assertEqual(num2words(4, to='ordinal', lang='ar'), 'رابع')
self.assertEqual(num2words(5, to='ordinal', lang='ar'), 'خامس')
self.assertEqual(num2words(6, to='ordinal', lang='ar'), 'سادس')
self.assertEqual(num2words(9, to='ordinal', lang='ar'), 'تاسع')
self.assertEqual(num2words(20, to='ordinal', lang='ar'), 'عشرون')
self.assertEqual(num2words(94, to='ordinal', lang='ar'),
'أربع و تسعون')
self.assertEqual(num2words(102, to='ordinal', lang='ar'),
'مائة و اثنان')
self.assertEqual(
num2words(923411, to='ordinal_num', lang='ar'),
'تسعمائة و ثلاثة و عشرون ألفاً و أربعمائة و أحد عشر')
def test_cardinal(self):
self.assertEqual(num2words(12, to='cardinal', lang='ar'), 'اثنا عشر')
self.assertEqual(num2words(-8324, to='cardinal', lang='ar'),
'سالب ثمانية آلاف و ثلاثمائة و أربعة و عشرون')
self.assertEqual(
num2words(3431.12, to='cardinal', lang='ar'),
'ثلاثة آلاف و أربعمائة و واحد و ثلاثون , اثنتا عشرة')
self.assertEqual(num2words(431, to='cardinal', lang='ar'),
'أربعمائة و واحد و ثلاثون')
self.assertEqual(num2words(94231, to='cardinal', lang='ar'),
'أربعة و تسعون ألفاً و مئتان و واحد و ثلاثون')
self.assertEqual(num2words(1431, to='cardinal', lang='ar'),
'واحد ألف و أربعمائة و واحد و ثلاثون')
def test_prefix_and_suffix(self):
self.assertEqual(num2words(645, to='currency',
lang='ar', prefix="فقط", suffix="لاغير"),
'فقط ستمائة و خمسة و أربعون ريالاً لاغير')
def test_year(self):
self.assertEqual(num2words(2000, to='year', lang='ar'), 'ألفا')
def test_max_numbers(self):
with self.assertRaises(Exception) as context:
num2words(10 ** 36, to='year', lang='ar')
self.assertTrue('Too large' in str(context.exception))

65
tests/test_base.py Normal file
View File

@@ -0,0 +1,65 @@
# -*- coding: 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 decimal import Decimal
from unittest import TestCase
from num2words.base import Num2Word_Base
class Num2WordBaseTest(TestCase):
@classmethod
def setUpClass(cls):
super(Num2WordBaseTest, cls).setUpClass()
cls.base = Num2Word_Base()
def test_to_currency_not_implemented(self):
with self.assertRaises(NotImplementedError):
self.base.to_currency(Decimal('1.00'), currency='EUR')
def test_error_to_cardinal_float(self):
from num2words.base import Num2Word_Base
with self.assertRaises(TypeError):
Num2Word_Base.to_cardinal_float(9)
with self.assertRaises(TypeError):
Num2Word_Base.to_cardinal_float("a")
def test_error_merge(self):
from num2words.base import Num2Word_Base
self.base = Num2Word_Base()
with self.assertRaises(NotImplementedError):
self.base.merge(2, 3)
def test_is_title(self):
from num2words.base import Num2Word_Base
self.base = Num2Word_Base()
self.assertEqual(
self.base.title("one"),
"one"
)
self.base.is_title = True
self.assertEqual(
self.base.title("one"),
"One"
)
self.base.exclude_title.append('one')
self.assertEqual(
self.base.title("one"),
"one"
)

113
tests/test_cli.py Normal file
View File

@@ -0,0 +1,113 @@
#!/usr/bin/env python
# -*- coding: 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 os
import unittest
import delegator
import num2words
class CliCaller(object):
def __init__(self):
self.cmd = os.path.realpath(os.path.join(os.path.dirname(__file__),
"..", "bin", "num2words"))
self.cmd_list = ["python", self.cmd]
def run_cmd(self, *args):
cmd_list = self.cmd_list + [str(arg) for arg in args]
cmd = " ".join(cmd_list)
return delegator.run(cmd)
class CliTestCase(unittest.TestCase):
"""Test the command line app"""
def setUp(self):
self.cli = CliCaller()
def test_cli_help(self):
"""num2words without arguments should exit with status 1
and show docopt's default short usage message
"""
output = self.cli.run_cmd()
self.assertEqual(output.return_code, 1)
self.assertTrue(output.err.startswith('Usage:'))
def test_cli_list_langs(self):
"""You should be able to list all availabe languages
"""
output = self.cli.run_cmd('--list-languages')
self.assertEqual(
sorted(list(num2words.CONVERTER_CLASSES.keys())),
output.out.strip().split(os.linesep)
)
output = self.cli.run_cmd('-L')
self.assertEqual(
sorted(list(num2words.CONVERTER_CLASSES.keys())),
output.out.strip().split(os.linesep)
)
def test_cli_list_converters(self):
"""You should be able to list all available converters
"""
output = self.cli.run_cmd('--list-converters')
self.assertEqual(
sorted(list(num2words.CONVERTES_TYPES)),
output.out.strip().split(os.linesep)
)
output = self.cli.run_cmd('-C')
self.assertEqual(
sorted(list(num2words.CONVERTES_TYPES)),
output.out.strip().split(os.linesep)
)
def test_cli_default_lang(self):
"""Default to english
"""
output = self.cli.run_cmd(150)
self.assertEqual(output.return_code, 0)
self.assertEqual(
output.out.strip(),
"one hundred and fifty"
)
def test_cli_with_lang(self):
"""You should be able to specify a language
"""
output = self.cli.run_cmd(150, '--lang', 'es')
self.assertEqual(output.return_code, 0)
self.assertEqual(
output.out.strip(),
"ciento cincuenta"
)
def test_cli_with_lang_to(self):
"""You should be able to specify a language and currency
"""
output = self.cli.run_cmd(150.55, '--lang', 'es', '--to', 'currency')
self.assertEqual(output.return_code, 0)
self.assertEqual(
(output.out.decode('utf-8') if hasattr(output.out, 'decode') else
output.out).strip(),
"ciento cincuenta euros con cincuenta y cinco céntimos"
)

63
tests/test_currency.py Normal file
View File

@@ -0,0 +1,63 @@
# -*- coding: 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 decimal import Decimal
from unittest import TestCase
from num2words.currency import parse_currency_parts
class CurrencyTestCase(TestCase):
def test_parse_currency_parts(self):
# integer with cents
self.assertEqual(parse_currency_parts(101), (1, 1, False))
self.assertEqual(parse_currency_parts(-123), (1, 23, True))
# integer without cents
self.assertEqual(parse_currency_parts(101, is_int_with_cents=False),
(101, 0, False))
self.assertEqual(parse_currency_parts(-123, is_int_with_cents=False),
(123, 0, True))
# float
self.assertEqual(parse_currency_parts(1.01), (1, 1, False))
self.assertEqual(parse_currency_parts(-1.23), (1, 23, True))
self.assertEqual(parse_currency_parts(-1.2), (1, 20, True))
self.assertEqual(parse_currency_parts(0.004), (0, 0, False))
self.assertEqual(parse_currency_parts(0.005), (0, 1, False))
self.assertEqual(parse_currency_parts(0.006), (0, 1, False))
self.assertEqual(parse_currency_parts(0.0005), (0, 0, False))
self.assertEqual(parse_currency_parts(0.984), (0, 98, False))
self.assertEqual(parse_currency_parts(0.989), (0, 99, False))
self.assertEqual(parse_currency_parts(0.994), (0, 99, False))
self.assertEqual(parse_currency_parts(0.999), (1, 0, False))
# self.assertEqual(parse_currency_parts(0.985), (0, 99, False))
# self.assertEqual(parse_currency_parts(0.995), (1, 0, False))
# decimal
self.assertEqual(parse_currency_parts(Decimal("1.01")), (1, 1, False))
self.assertEqual(parse_currency_parts(Decimal("-1.23")), (1, 23, True))
self.assertEqual(parse_currency_parts(Decimal("-1.233")),
(1, 23, True))
self.assertEqual(parse_currency_parts(Decimal("-1.989")),
(1, 99, True))
# string
self.assertEqual(parse_currency_parts("1.01"), (1, 1, False))
self.assertEqual(parse_currency_parts("-1.23"), (1, 23, True))
self.assertEqual(parse_currency_parts("-1.2"), (1, 20, True))
self.assertEqual(parse_currency_parts("1"), (1, 0, False))

114
tests/test_cz.py Normal file
View File

@@ -0,0 +1,114 @@
# -*- coding: 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 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(10.02, lang='cz'),
"deset celá nula dva"
)
self.assertEqual(
num2words(15.007, lang='cz'),
"patnáct celá nula nula sedm"
)
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',
separator=' a'),
"sto jedna euro a jedenáct centů")
self.assertEqual(
num2words(101.21, lang='cz', to='currency', currency='CZK',
separator=' 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',
separator=' 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ů"
)

170
tests/test_de.py Normal file
View File

@@ -0,0 +1,170 @@
# -*- coding: 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 unittest import TestCase
from num2words import num2words
TEST_CASES_TO_CURRENCY_EUR = (
(1.00, 'ein Euro und null Cent'),
(2.01, 'zwei Euro und ein Cent'),
(8.10, 'acht Euro und zehn Cent'),
(12.26, 'zwölf Euro und sechsundzwanzig Cent'),
(21.29, 'einundzwanzig Euro und neunundzwanzig Cent'),
(81.25, 'einundachtzig Euro und fünfundzwanzig Cent'),
(100.00, 'einhundert Euro und null Cent'),
)
TEST_CASES_TO_CURRENCY_USD = (
(1.00, 'ein Dollar und null Cent'),
(2.01, 'zwei Dollar und ein Cent'),
(8.10, 'acht Dollar und zehn Cent'),
(12.26, 'zwölf Dollar und sechsundzwanzig Cent'),
(21.29, 'einundzwanzig Dollar und neunundzwanzig Cent'),
(81.25, 'einundachtzig Dollar und fünfundzwanzig Cent'),
(100.00, 'einhundert Dollar und null Cent'),
)
TEST_CASES_TO_CURRENCY_GBP = (
(1.00, 'ein Pfund und null Pence'),
(2.01, 'zwei Pfund und ein Penny'),
(8.10, 'acht Pfund und zehn Pence'),
(12.26, 'zwölf Pfund und sechsundzwanzig Pence'),
(21.29, 'einundzwanzig Pfund und neunundzwanzig Pence'),
(81.25, 'einundachtzig Pfund und fünfundzwanzig Pence'),
(100.00, 'einhundert Pfund und null Pence'),
)
TEST_CASES_TO_CURRENCY_DEM = (
(1.00, 'ein Mark und null Pfennig'),
(2.01, 'zwei Mark und ein Pfennig'),
(8.10, 'acht Mark und zehn Pfennig'),
(12.26, 'zwölf Mark und sechsundzwanzig Pfennig'),
(21.29, 'einundzwanzig Mark und neunundzwanzig Pfennig'),
(81.25, 'einundachtzig Mark und fünfundzwanzig Pfennig'),
(100.00, 'einhundert Mark und null Pfennig'),
)
class Num2WordsDETest(TestCase):
def test_ordinal_less_than_twenty(self):
self.assertEqual(num2words(0, ordinal=True, lang='de'), "nullte")
self.assertEqual(num2words(1, ordinal=True, lang='de'), "erste")
self.assertEqual(num2words(7, ordinal=True, lang='de'), "siebte")
self.assertEqual(num2words(8, ordinal=True, lang='de'), "achte")
self.assertEqual(num2words(12, ordinal=True, lang='de'), "zwölfte")
self.assertEqual(num2words(17, ordinal=True, lang='de'), "siebzehnte")
def test_ordinal_more_than_twenty(self):
self.assertEqual(
num2words(81, ordinal=True, lang='de'), "einundachtzigste"
)
def test_ordinal_at_crucial_number(self):
self.assertEqual(
num2words(100, ordinal=True, lang='de'), "hundertste"
)
self.assertEqual(
num2words(1000, ordinal=True, lang='de'), "tausendste"
)
self.assertEqual(
num2words(4000, ordinal=True, lang='de'), "viertausendste"
)
self.assertEqual(
num2words(1000000, ordinal=True, lang='de'), "millionste"
)
self.assertEqual(
num2words(2000000, ordinal=True, lang='de'), "zweimillionste"
)
self.assertEqual(
num2words(1000000000, ordinal=True, lang='de'), "milliardste"
)
self.assertEqual(
num2words(5000000000, ordinal=True, lang='de'),
"fünfmilliardste"
)
def test_cardinal_at_some_numbers(self):
self.assertEqual(num2words(100, lang='de'), "einhundert")
self.assertEqual(num2words(1000, lang='de'), "eintausend")
self.assertEqual(num2words(5000, lang='de'), "fünftausend")
self.assertEqual(num2words(10000, lang='de'), "zehntausend")
self.assertEqual(num2words(1000000, lang='de'), "eine Million")
self.assertEqual(num2words(2000000, lang='de'), "zwei Millionen")
self.assertEqual(num2words(4000000000, lang='de'), "vier Milliarden")
self.assertEqual(num2words(1000000000, lang='de'), "eine Milliarde")
def test_cardinal_for_decimal_number(self):
self.assertEqual(
num2words(3.486, lang='de'), "drei Komma vier acht sechs"
)
def test_giant_cardinal_for_merge(self):
self.assertEqual(
num2words(4500072900000111, lang='de'),
"vier Billiarden fünfhundert Billionen " +
"zweiundsiebzig Milliarden neunhundert Millionen einhundertelf"
)
def test_ordinal_num(self):
self.assertEqual(num2words(7, to="ordinal_num", lang='de'), "7.")
self.assertEqual(num2words(81, to="ordinal_num", lang='de'), "81.")
def test_ordinal_for_negative_numbers(self):
self.assertRaises(TypeError, num2words, -12, ordinal=True, lang='de')
def test_ordinal_for_floating_numbers(self):
self.assertRaises(TypeError, num2words, 2.453, ordinal=True, lang='de')
def test_currency_eur(self):
for test in TEST_CASES_TO_CURRENCY_EUR:
self.assertEqual(
num2words(test[0], lang='de', to='currency', currency='EUR'),
test[1]
)
def test_currency_usd(self):
for test in TEST_CASES_TO_CURRENCY_USD:
self.assertEqual(
num2words(test[0], lang='de', to='currency', currency='USD'),
test[1]
)
def test_currency_dem(self):
for test in TEST_CASES_TO_CURRENCY_DEM:
self.assertEqual(
num2words(test[0], lang='de', to='currency', currency='DEM'),
test[1]
)
def test_currency_gbp(self):
for test in TEST_CASES_TO_CURRENCY_GBP:
self.assertEqual(
num2words(test[0], lang='de', to='currency', currency='GBP'),
test[1]
)
def test_year(self):
self.assertEqual(num2words(2002, to='year', lang='de'),
'zweitausendzwei')
def test_year_before_2000(self):
self.assertEqual(num2words(1780, to='year', lang='de'),
'siebzehnhundertachtzig')

37
tests/test_dk.py Normal file
View File

@@ -0,0 +1,37 @@
# coding: 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 unittest import TestCase
from num2words import num2words
class Num2WordsDKTest(TestCase):
def test_ordinal(self):
self.assertEqual(num2words(1, to="ordinal", lang="dk"), "første")
self.assertEqual(num2words(5, to="ordinal", lang="dk"), "femte")
def test_cardinal(self):
self.assertEqual(num2words(0, to="cardinal", lang="dk"), "nul")
self.assertEqual(num2words(1, to="cardinal", lang="dk"), "et")
self.assertEqual(num2words(2, to="cardinal", lang="dk"), "to")
self.assertEqual(num2words(5, to="cardinal", lang="dk"), "fem")
self.assertEqual(num2words(8, to="cardinal", lang="dk"), "otte")
self.assertEqual(num2words(18, to="cardinal", lang="dk"), "atten")
self.assertEqual(num2words(45, to="cardinal", lang="dk"), "femogfyrre")

View File

@@ -1,3 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved. # Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# This library is free software; you can redistribute it and/or # This library is free software; you can redistribute it and/or
@@ -17,7 +19,168 @@ from unittest import TestCase
from num2words import num2words from num2words import num2words
class Num2WordsENTest(TestCase): class Num2WordsENTest(TestCase):
def test_and_join_199(self): def test_and_join_199(self):
# ref https://github.com/savoirfairelinux/num2words/issues/8 # ref https://github.com/savoirfairelinux/num2words/issues/8
self.assertEqual(num2words(199), "one hundred and ninety-nine") self.assertEqual(num2words(199), "one hundred and ninety-nine")
def test_ordinal(self):
self.assertEqual(
num2words(0, lang='en', to='ordinal'),
'zeroth'
)
self.assertEqual(
num2words(1, lang='en', to='ordinal'),
'first'
)
self.assertEqual(
num2words(13, lang='en', to='ordinal'),
'thirteenth'
)
self.assertEqual(
num2words(22, lang='en', to='ordinal'),
'twenty-second'
)
self.assertEqual(
num2words(12, lang='en', to='ordinal'),
'twelfth'
)
self.assertEqual(
num2words(130, lang='en', to='ordinal'),
'one hundred and thirtieth'
)
self.assertEqual(
num2words(1003, lang='en', to='ordinal'),
'one thousand and third'
)
def test_ordinal_num(self):
self.assertEqual(num2words(10, lang='en', to='ordinal_num'), '10th')
self.assertEqual(num2words(21, lang='en', to='ordinal_num'), '21st')
self.assertEqual(num2words(102, lang='en', to='ordinal_num'), '102nd')
self.assertEqual(num2words(73, lang='en', to='ordinal_num'), '73rd')
def test_cardinal_for_float_number(self):
# issue 24
self.assertEqual(num2words(12.5), "twelve point five")
self.assertEqual(num2words(12.51), "twelve point five one")
self.assertEqual(num2words(12.53), "twelve point five three")
self.assertEqual(num2words(12.59), "twelve point five nine")
def test_overflow(self):
with self.assertRaises(OverflowError):
num2words("1000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000"
"00000000000000000000000000000000")
def test_to_currency(self):
self.assertEqual(
num2words('38.4', lang='en', to='currency', separator=' and',
cents=False, currency='USD'),
"thirty-eight dollars and 40 cents"
)
self.assertEqual(
num2words('0', lang='en', to='currency', separator=' and',
cents=False, currency='USD'),
"zero dollars and 00 cents"
)
self.assertEqual(
num2words('1.01', lang='en', to='currency', separator=' and',
cents=True, currency='USD'),
"one dollar and one cent"
)
self.assertEqual(
num2words('4778.00', lang='en', to='currency', separator=' and',
cents=True, currency='USD', adjective=True),
'four thousand, seven hundred and seventy-eight US dollars'
' and zero cents')
self.assertEqual(
num2words('4778.00', lang='en', to='currency', separator=' and',
cents=True, currency='USD'),
'four thousand, seven hundred and seventy-eight dollars and'
' zero cents')
self.assertEqual(
num2words('1.1', lang='en', to='currency', separator=' and',
cents=True, currency='MXN'),
"one peso and ten cents"
)
self.assertEqual(
num2words('158.3', lang='en', to='currency', separator=' and',
cents=True, currency='MXN'),
"one hundred and fifty-eight pesos and thirty cents"
)
self.assertEqual(
num2words('2000.00', lang='en', to='currency', separator=' and',
cents=True, currency='MXN'),
"two thousand pesos and zero cents"
)
self.assertEqual(
num2words('4.01', lang='en', to='currency', separator=' and',
cents=True, currency='MXN'),
"four pesos and one cent"
)
self.assertEqual(
num2words('2000.00', lang='en', to='currency', separator=' and',
cents=True, currency='UZS'),
"two thousand sums and zero tiyins"
)
def test_to_year(self):
# issue 141
# "e2 e2"
self.assertEqual(num2words(1990, lang='en', to='year'),
'nineteen ninety')
self.assertEqual(num2words(5555, lang='en', to='year'),
'fifty-five fifty-five')
self.assertEqual(num2words(2017, lang='en', to='year'),
'twenty seventeen')
self.assertEqual(num2words(1066, lang='en', to='year'),
'ten sixty-six')
self.assertEqual(num2words(1865, lang='en', to='year'),
'eighteen sixty-five')
# "e3 and e1"; "e2 oh-e1"; "e3"
self.assertEqual(num2words(3000, lang='en', to='year'),
'three thousand')
self.assertEqual(num2words(2001, lang='en', to='year'),
'two thousand and one')
self.assertEqual(num2words(1901, lang='en', to='year'),
'nineteen oh-one')
self.assertEqual(num2words(2000, lang='en', to='year'),
'two thousand')
self.assertEqual(num2words(905, lang='en', to='year'),
'nine oh-five')
# "e2 hundred"; "e3"
self.assertEqual(num2words(6600, lang='en', to='year'),
'sixty-six hundred')
self.assertEqual(num2words(1900, lang='en', to='year'),
'nineteen hundred')
self.assertEqual(num2words(600, lang='en', to='year'),
'six hundred')
self.assertEqual(num2words(50, lang='en', to='year'),
'fifty')
self.assertEqual(num2words(0, lang='en', to='year'),
'zero')
# suffixes
self.assertEqual(num2words(-44, lang='en', to='year'),
'forty-four BC')
self.assertEqual(num2words(-44, lang='en', to='year', suffix='BCE'),
'forty-four BCE')
self.assertEqual(num2words(1, lang='en', to='year', suffix='AD'),
'one AD')
self.assertEqual(num2words(66, lang='en', to='year',
suffix='m.y.a.'),
'sixty-six m.y.a.')
self.assertEqual(num2words(-66000000, lang='en', to='year'),
'sixty-six million BC')

27
tests/test_en_in.py Normal file
View File

@@ -0,0 +1,27 @@
# -*- coding: 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 unittest import TestCase
from num2words import num2words
class Num2WordsENINTest(TestCase):
def test_cardinal(self):
self.assertEqual(num2words(1e5, lang="en_IN"), "one lakh")
self.assertEqual(num2words(1e6, lang="en_IN"), "ten lakh")
self.assertEqual(num2words(1e7, lang="en_IN"), "one crore")

190
tests/test_eo.py Normal file
View File

@@ -0,0 +1,190 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2021, 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
TEST_CASES_CARDINAL = (
(1, "unu"),
(2, "du"),
(3, "tri"),
(5.5, "kvin komo kvin"),
(11, "dek unu"),
(12, "dek du"),
(16, "dek ses"),
(17.42, "dek sep komo kvar du"),
(19, "dek naŭ"),
(20, "dudek"),
(21, "dudek unu"),
(26, "dudek ses"),
(27.312, "dudek sep komo tri unu du"),
(28, "dudek ok"),
(30, "tridek"),
(31, "tridek unu"),
(40, "kvardek"),
(44, "kvardek kvar"),
(50, "kvindek"),
(53.486, "kvindek tri komo kvar ok ses"),
(55, "kvindek kvin"),
(60, "sesdek"),
(67, "sesdek sep"),
(70, "sepdek"),
(79, "sepdek naŭ"),
(89, "okdek naŭ"),
(95, "naŭdek kvin"),
(100, "cent"),
(101, "cent unu"),
(199, "cent naŭdek naŭ"),
(203, "ducent tri"),
(287, "ducent okdek sep"),
(300.42, "tricent komo kvar du"),
(356, "tricent kvindek ses"),
(400, "kvarcent"),
(434, "kvarcent tridek kvar"),
(578, "kvincent sepdek ok"),
(689, "sescent okdek naŭ"),
(729, "sepcent dudek naŭ"),
(894, "okcent naŭdek kvar"),
(999, "naŭcent naŭdek naŭ"),
(1000, "mil"),
(1001, "mil unu"),
(1097, "mil naŭdek sep"),
(1104, "mil cent kvar"),
(1243, "mil ducent kvardek tri"),
(2385, "du mil tricent okdek kvin"),
(3766, "tri mil sepcent sesdek ses"),
(4196, "kvar mil cent naŭdek ses"),
(4196.42, "kvar mil cent naŭdek ses komo kvar du"),
(5846, "kvin mil okcent kvardek ses"),
(6459, "ses mil kvarcent kvindek naŭ"),
(7232, "sep mil ducent tridek du"),
(8569, "ok mil kvincent sesdek naŭ"),
(9539, "naŭ mil kvincent tridek naŭ"),
(1000000, "unu miliono"),
(1000001, "unu miliono unu"),
(4000000, "kvar milionoj"),
(4000004, "kvar milionoj kvar"),
(4300000, "kvar milionoj tricent mil"),
(80000000, "okdek milionoj"),
(300000000, "tricent milionoj"),
(10000000000000, "dek bilionoj"),
(10000000000010, "dek bilionoj dek"),
(100000000000000, "cent bilionoj"),
(1000000000000000000, "unu triliono"),
(1000000000000000000000, "unu triliardo"),
(10000000000000000000000000, "dek kvarilionoj")
)
TEST_CASES_ORDINAL = (
(1, "unua"),
(8, "oka"),
(12, "dek dua"),
(14, "dek kvara"),
(28, "dudek oka"),
(100, "centa"),
(1000, "mila"),
(1000000, "unu miliona"),
(1000000000000000, "unu biliarda"),
(1000000000000000000, "unu triliona")
)
TEST_CASES_ORDINAL_NUM = (
(1, "1a"),
(8, "8a"),
(11, "11a"),
(12, "12a"),
(14, "14a"),
(21, "21a"),
(28, "28a"),
(100, "100a"),
(101, "101a"),
(1000, "1000a"),
(1000000, "1000000a")
)
TEST_CASES_TO_CURRENCY_EUR = (
(1.00, "unu eŭro kaj nul centimo"),
(2.01, "du eŭroj kaj unu centimo"),
(8.10, "ok eŭroj kaj dek centimoj"),
(12.26, "dek du eŭroj kaj dudek ses centimoj"),
(21.29, "dudek unu eŭroj kaj dudek naŭ centimoj"),
(81.25, "okdek unu eŭroj kaj dudek kvin centimoj"),
(100.00, "cent eŭroj kaj nul centimo"),
)
TEST_CASES_TO_CURRENCY_FRF = (
(1.00, "unu franko kaj nul centimo"),
(2.01, "du frankoj kaj unu centimo"),
(8.10, "ok frankoj kaj dek centimoj"),
(12.27, "dek du frankoj kaj dudek sep centimoj"),
(21.29, "dudek unu frankoj kaj dudek naŭ centimoj"),
(81.25, "okdek unu frankoj kaj dudek kvin centimoj"),
(100.00, "cent frankoj kaj nul centimo"),
)
TEST_CASES_TO_CURRENCY_USD = (
(1.00, "unu dolaro kaj nul cendo"),
(2.01, "du dolaroj kaj unu cendo"),
(8.10, "ok dolaroj kaj dek cendoj"),
(12.26, "dek du dolaroj kaj dudek ses cendoj"),
(21.29, "dudek unu dolaroj kaj dudek naŭ cendoj"),
(81.25, "okdek unu dolaroj kaj dudek kvin cendoj"),
(100.00, "cent dolaroj kaj nul cendo"),
)
class Num2WordsEOTest(TestCase):
def test_number(self):
for test in TEST_CASES_CARDINAL:
self.assertEqual(num2words(test[0], lang="eo"), test[1])
def test_ordinal(self):
for test in TEST_CASES_ORDINAL:
self.assertEqual(
num2words(test[0], lang="eo", ordinal=True),
test[1]
)
def test_ordinal_num(self):
for test in TEST_CASES_ORDINAL_NUM:
self.assertEqual(
num2words(test[0], lang="eo", to="ordinal_num"),
test[1]
)
def test_currency_eur(self):
for test in TEST_CASES_TO_CURRENCY_EUR:
self.assertEqual(
num2words(test[0], lang="eo", to="currency", currency="EUR"),
test[1]
)
def test_currency_frf(self):
for test in TEST_CASES_TO_CURRENCY_FRF:
self.assertEqual(
num2words(test[0], lang="eo", to="currency", currency="FRF"),
test[1]
)
def test_currency_usd(self):
for test in TEST_CASES_TO_CURRENCY_USD:
self.assertEqual(
num2words(test[0], lang="eo", to="currency", currency="USD"),
test[1]
)

29
tests/test_errors.py Normal file
View File

@@ -0,0 +1,29 @@
# -*- coding: 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 unittest import TestCase
from num2words import num2words
class Num2WordsErrorsTest(TestCase):
def test_NotImplementedError(self):
with self.assertRaises(NotImplementedError):
num2words(100, lang="lalala")

3034
tests/test_es.py Normal file

File diff suppressed because it is too large Load Diff

60
tests/test_es_co.py Normal file
View File

@@ -0,0 +1,60 @@
# -*- coding: 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 num2words import num2words
from . import test_es
TEST_CASES_TO_CURRENCY = (
(1, 'un peso'),
(2, 'dos pesos'),
(8, 'ocho pesos'),
(12, 'doce pesos'),
(21, 'veintiun pesos'),
(81.25, 'ochenta y un pesos y veinticinco centavos'),
(100, 'cien pesos'),
)
class Num2WordsESCOTest(test_es.Num2WordsESTest):
def test_number(self):
for test in test_es.TEST_CASES_CARDINAL:
self.assertEqual(num2words(test[0], lang='es_CO'), test[1])
def test_ordinal(self):
for test in test_es.TEST_CASES_ORDINAL:
self.assertEqual(
num2words(test[0], lang='es_CO', ordinal=True),
test[1]
)
def test_ordinal_num(self):
for test in test_es.TEST_CASES_ORDINAL_NUM:
self.assertEqual(
num2words(test[0], lang='es', to='ordinal_num'),
test[1]
)
def test_currency(self):
for test in TEST_CASES_TO_CURRENCY:
self.assertEqual(
num2words(test[0], lang='es_CO', to='currency'),
test[1]
)

42
tests/test_es_ni.py Normal file
View File

@@ -0,0 +1,42 @@
# -*- coding: 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 num2words import num2words
from . import test_es
TEST_NIO = (
(1.0, 'un córdoba con cero centavos'),
(2.0, 'dos córdobas con cero centavos'),
(8.0, 'ocho córdobas con cero centavos'),
(12.0, 'doce córdobas con cero centavos'),
(21.0, 'veintiun córdobas con cero centavos'),
(81.25, 'ochenta y un córdobas con veinticinco centavos'),
(100.00, 'cien córdobas con cero centavos'),
)
class Num2WordsESNITest(test_es.Num2WordsESTest):
def test_currency(self):
for test in TEST_NIO:
self.assertEqual(
num2words(test[0], lang='es_NI', to='currency'),
test[1]
)

59
tests/test_es_ve.py Normal file
View File

@@ -0,0 +1,59 @@
# -*- coding: 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 num2words import num2words
from . import test_es
TEST_CASES_TO_CURRENCY = (
(1, 'un bolívar'),
(2, 'dos bolívares'),
(8, 'ocho bolívares'),
(12, 'doce bolívares'),
(21, 'veintiun bolívares'),
(81.25, 'ochenta y un bolívares y veinticinco centavos'),
(100, 'cien bolívares'),
)
class Num2WordsESVETest(test_es.Num2WordsESTest):
def test_number(self):
for test in test_es.TEST_CASES_CARDINAL:
self.assertEqual(num2words(test[0], lang='es_VE'), test[1])
def test_ordinal(self):
for test in test_es.TEST_CASES_ORDINAL:
self.assertEqual(
num2words(test[0], lang='es_VE', ordinal=True),
test[1]
)
def test_ordinal_num(self):
for test in test_es.TEST_CASES_ORDINAL_NUM:
self.assertEqual(
num2words(test[0], lang='es', to='ordinal_num'),
test[1]
)
def test_currency(self):
for test in TEST_CASES_TO_CURRENCY:
self.assertEqual(
num2words(test[0], lang='es_VE', to='currency', old=True),
test[1]
)

109
tests/test_fa.py Normal file
View File

@@ -0,0 +1,109 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2003, Taro Ogawa. All Rights Reserved.
# Copyright (c) 2013, Savoir-faire Linux inc. All Rights Reserved.
# Copyright (c) 2020, Hamidreza Kalbasi. 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 unittest import TestCase
from num2words import num2words
class Num2WordsFATest(TestCase):
def test_and_join_199(self):
self.assertEqual(num2words(199, lang='fa'), "صد و نود و نه")
def test_ordinal(self):
self.assertEqual(
num2words(0, lang='fa', to='ordinal'),
'صفرم'
)
self.assertEqual(
num2words(1, lang='fa', to='ordinal'),
'یکم'
)
self.assertEqual(
num2words(13, lang='fa', to='ordinal'),
'سیزدهم'
)
self.assertEqual(
num2words(23, lang='fa', to='ordinal'),
'بیست و سوم'
)
self.assertEqual(
num2words(12, lang='fa', to='ordinal'),
'دوازدهم'
)
self.assertEqual(
num2words(113, lang='fa', to='ordinal'),
'صد و سیزدهم'
)
self.assertEqual(
num2words(103, lang='fa', to='ordinal'),
'صد و سوم'
)
def test_cardinal(self):
self.assertEqual(num2words(130000, lang='fa'), "صد و سی هزار")
self.assertEqual(num2words(242, lang='fa'), "دویست و چهل و دو")
self.assertEqual(num2words(800, lang='fa'), "هشتصد")
self.assertEqual(num2words(-203, lang='fa'), "منفی دویست و سه")
self.assertEqual(
num2words(1234567890, lang='fa'),
"یک میلیارد و دویست و سی و چهار میلیون و"
" پانصد و شصت و هفت هزار و هشتصد و نود"
)
def test_year(self):
self.assertEqual(num2words(1398, lang='fa', to='year'),
"هزار و سیصد و نود و هشت")
self.assertEqual(num2words(1399, lang='fa', to='year'),
"هزار و سیصد و نود و نه")
self.assertEqual(
num2words(1400, lang='fa', to='year'), "هزار و چهارصد")
def test_currency(self):
self.assertEqual(
num2words(1000, lang='fa', to='currency'), 'هزار تومان')
self.assertEqual(
num2words(1500000, lang='fa', to='currency'),
'یک میلیون و پانصد هزار تومان'
)
def test_ordinal_num(self):
self.assertEqual(num2words(10, lang='fa', to='ordinal_num'), '10م')
self.assertEqual(num2words(21, lang='fa', to='ordinal_num'), '21م')
self.assertEqual(num2words(102, lang='fa', to='ordinal_num'), '102م')
self.assertEqual(num2words(73, lang='fa', to='ordinal_num'), '73م')
def test_cardinal_for_float_number(self):
self.assertEqual(num2words(12.5, lang='fa'), "دوازده و نیم")
self.assertEqual(num2words(0.75, lang='fa'), "هفتاد و پنج صدم")
self.assertEqual(num2words(12.51, lang='fa'),
"دوازده و پنجاه و یک صدم")
self.assertEqual(num2words(12.53, lang='fa'),
"دوازده و پنجاه و سه صدم")
self.assertEqual(num2words(12.59, lang='fa'),
"دوازده و پنجاه و نه صدم")
self.assertEqual(num2words(0.000001, lang='fa'), "یک میلیونیم")
def test_overflow(self):
with self.assertRaises(OverflowError):
num2words("1000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000"
"00000000000000000000000000000000")

2762
tests/test_fi.py Normal file

File diff suppressed because it is too large Load Diff

205
tests/test_fr.py Normal file
View File

@@ -0,0 +1,205 @@
# -*- coding: 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 unittest import TestCase
from num2words import num2words
TEST_CASES_CARDINAL = (
(1, 'un'),
(2, 'deux'),
(3, 'trois'),
(5.5, 'cinq virgule cinq'),
(11, 'onze'),
(12, 'douze'),
(16, 'seize'),
(17.42, 'dix-sept virgule quatre deux'),
(19, 'dix-neuf'),
(20, 'vingt'),
(21, 'vingt et un'),
(26, 'vingt-six'),
(27.312, 'vingt-sept virgule trois un deux'),
(28, 'vingt-huit'),
(30, 'trente'),
(31, 'trente et un'),
(40, 'quarante'),
(44, 'quarante-quatre'),
(50, 'cinquante'),
(53.486, 'cinquante-trois virgule quatre huit six'),
(55, 'cinquante-cinq'),
(60, 'soixante'),
(67, 'soixante-sept'),
(70, 'soixante-dix'),
(79, 'soixante-dix-neuf'),
(89, 'quatre-vingt-neuf'),
(95, 'quatre-vingt-quinze'),
(100, 'cent'),
(101, 'cent un'),
(199, 'cent quatre-vingt-dix-neuf'),
(203, 'deux cent trois'),
(287, 'deux cent quatre-vingt-sept'),
(300.42, 'trois cents virgule quatre deux'),
(356, 'trois cent cinquante-six'),
(400, 'quatre cents'),
(434, 'quatre cent trente-quatre'),
(578, 'cinq cent soixante-dix-huit'),
(689, 'six cent quatre-vingt-neuf'),
(729, 'sept cent vingt-neuf'),
(894, 'huit cent quatre-vingt-quatorze'),
(999, 'neuf cent quatre-vingt-dix-neuf'),
(1000, 'mille'),
(1001, 'mille un'),
(1097, 'mille quatre-vingt-dix-sept'),
(1104, 'mille cent quatre'),
(1243, 'mille deux cent quarante-trois'),
(2385, 'deux mille trois cent quatre-vingt-cinq'),
(3766, 'trois mille sept cent soixante-six'),
(4196, 'quatre mille cent quatre-vingt-seize'),
(4196.42, 'quatre mille cent quatre-vingt-seize virgule quatre deux'),
(5846, 'cinq mille huit cent quarante-six'),
(6459, 'six mille quatre cent cinquante-neuf'),
(7232, 'sept mille deux cent trente-deux'),
(8569, 'huit mille cinq cent soixante-neuf'),
(9539, 'neuf mille cinq cent trente-neuf'),
(1000000, 'un million'),
(1000001, 'un million un'),
(4000000, 'quatre millions'),
(4000004, 'quatre millions quatre'),
(4300000, 'quatre millions trois cent mille'),
(80000000, 'quatre-vingts millions'),
(300000000, 'trois cents millions'),
(10000000000000, 'dix billions'),
(10000000000010, 'dix billions dix'),
(100000000000000, 'cent billions'),
(1000000000000000000, 'un trillion'),
(1000000000000000000000, 'un trilliard'),
(10000000000000000000000000, 'dix quadrillions')
)
TEST_CASES_ORDINAL = (
(1, 'premier'),
(8, 'huitième'),
(12, 'douzième'),
(14, 'quatorzième'),
(28, 'vingt-huitième'),
(100, 'centième'),
(1000, 'millième'),
(1000000, 'un millionième'),
(1000000000000000, 'un billiardième'),
(1000000000000000000, 'un trillionième') # over 1e18 is not supported
)
TEST_CASES_ORDINAL_NUM = (
(1, '1er'),
(8, '8me'),
(11, '11me'),
(12, '12me'),
(14, '14me'),
(21, '21me'),
(28, '28me'),
(100, '100me'),
(101, '101me'),
(1000, '1000me'),
(1000000, '1000000me')
)
TEST_CASES_TO_CURRENCY_EUR = (
(1.00, 'un euro et zéro centimes'),
(2.01, 'deux euros et un centime'),
(8.10, 'huit euros et dix centimes'),
(12.26, 'douze euros et vingt-six centimes'),
(21.29, 'vingt et un euros et vingt-neuf centimes'),
(81.25, 'quatre-vingt-un euros et vingt-cinq centimes'),
(100.00, 'cent euros et zéro centimes'),
)
TEST_CASES_TO_CURRENCY_FRF = (
(1.00, 'un franc et zéro centimes'),
(2.01, 'deux francs et un centime'),
(8.10, 'huit francs et dix centimes'),
(12.27, 'douze francs et vingt-sept centimes'),
(21.29, 'vingt et un francs et vingt-neuf centimes'),
(81.25, 'quatre-vingt-un francs et vingt-cinq centimes'),
(100.00, 'cent francs et zéro centimes'),
)
TEST_CASES_TO_CURRENCY_USD = (
(1.00, 'un dollar et zéro cents'),
(2.01, 'deux dollars et un cent'),
(8.10, 'huit dollars et dix cents'),
(12.26, 'douze dollars et vingt-six cents'),
(21.29, 'vingt et un dollars et vingt-neuf cents'),
(81.25, 'quatre-vingt-un dollars et vingt-cinq cents'),
(100.00, 'cent dollars et zéro cents'),
)
class Num2WordsENTest(TestCase):
def test_ordinal_special_joins(self):
# ref https://github.com/savoirfairelinux/num2words/issues/18
self.assertEqual(
num2words(5, ordinal=True, lang='fr'), "cinquième"
)
self.assertEqual(
num2words(35, ordinal=True, lang='fr'), "trente-cinquième"
)
self.assertEqual(
num2words(9, ordinal=True, lang='fr'), "neuvième"
)
self.assertEqual(
num2words(49, ordinal=True, lang='fr'), "quarante-neuvième"
)
def test_number(self):
for test in TEST_CASES_CARDINAL:
self.assertEqual(num2words(test[0], lang='fr'), test[1])
def test_ordinal(self):
for test in TEST_CASES_ORDINAL:
self.assertEqual(
num2words(test[0], lang='fr', ordinal=True),
test[1]
)
def test_ordinal_num(self):
for test in TEST_CASES_ORDINAL_NUM:
self.assertEqual(
num2words(test[0], lang='fr', to='ordinal_num'),
test[1]
)
def test_currency_eur(self):
for test in TEST_CASES_TO_CURRENCY_EUR:
self.assertEqual(
num2words(test[0], lang='fr', to='currency', currency='EUR'),
test[1]
)
def test_currency_frf(self):
for test in TEST_CASES_TO_CURRENCY_FRF:
self.assertEqual(
num2words(test[0], lang='fr', to='currency', currency='FRF'),
test[1]
)
def test_currency_usd(self):
for test in TEST_CASES_TO_CURRENCY_USD:
self.assertEqual(
num2words(test[0], lang='fr', to='currency', currency='USD'),
test[1]
)

129
tests/test_fr_be.py Normal file
View File

@@ -0,0 +1,129 @@
# -*- coding: 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 unittest import TestCase
from num2words import num2words
TEST_CASES_CARDINAL = (
(70, 'septante'),
(79, 'septante-neuf'),
(89, 'quatre-vingt-neuf'),
(95, 'nonante-cinq'),
(729, 'sept cents vingt-neuf'),
(894, 'huit cents nonante-quatre'),
(999, 'neuf cents nonante-neuf'),
(7232, 'sept mille deux cents trente-deux'),
(8569, 'huit mille cinq cents soixante-neuf'),
(9539, 'neuf mille cinq cents trente-neuf'),
(1000000, 'un millions'),
(1000001, 'un millions un'),
(4000000, 'quatre millions'),
(10000000000000, 'dix billions'),
(100000000000000, 'cent billions'),
(1000000000000000000, 'un trillions'),
(1000000000000000000000, 'un trilliards'),
(10000000000000000000000000, 'dix quadrillions')
)
TEST_CASES_ORDINAL = (
(1, 'premier'),
(8, 'huitième'),
(12, 'douzième'),
(14, 'quatorzième'),
(28, 'vingt-huitième'),
(100, 'centième'),
(1000, 'millième'),
(1000000, 'un millionsième'),
(1000000000000000, 'un billiardsième'),
(1000000000000000000, 'un trillionsième') # over 1e18 is not supported
)
TEST_CASES_TO_CURRENCY_EUR = (
(1.00, 'un euro et zéro centimes'),
(2.01, 'deux euros et un centime'),
(8.10, 'huit euros et dix centimes'),
(12.26, 'douze euros et vingt-six centimes'),
(21.29, 'vingt et un euros et vingt-neuf centimes'),
(81.25, 'quatre-vingt et un euros et vingt-cinq centimes'),
(100.00, 'cent euros et zéro centimes'),
)
TEST_CASES_TO_CURRENCY_FRF = (
(1.00, 'un franc et zéro centimes'),
(2.01, 'deux francs et un centime'),
(8.10, 'huit francs et dix centimes'),
(12.27, 'douze francs et vingt-sept centimes'),
(21.29, 'vingt et un francs et vingt-neuf centimes'),
(81.25, 'quatre-vingt et un francs et vingt-cinq centimes'),
(100.00, 'cent francs et zéro centimes'),
)
# Lang to execute current test
LANG = 'fr_BE'
class Num2WordsENTest(TestCase):
def test_ordinal_special_joins(self):
self.assertEqual(
num2words(5, ordinal=True, lang=LANG), "cinquième"
)
self.assertEqual(
num2words(6, ordinal=True, lang=LANG), "sixième"
)
self.assertEqual(
num2words(35, ordinal=True, lang=LANG), "trente-cinquième"
)
self.assertEqual(num2words(9, ordinal=True, lang=LANG), "neuvième")
self.assertEqual(
num2words(49, ordinal=True, lang=LANG), "quarante-neuvième"
)
self.assertEqual(num2words(71, lang=LANG), "septante et un")
self.assertEqual(num2words(81, lang=LANG), "quatre-vingt et un")
self.assertEqual(num2words(80, lang=LANG), "quatre-vingt")
self.assertEqual(
num2words(880, lang=LANG), "huit cents quatre-vingt")
self.assertEqual(
num2words(91, ordinal=True, lang=LANG), "nonante et unième"
)
self.assertEqual(num2words(53, lang=LANG), "cinquante-trois")
def test_number(self):
for test in TEST_CASES_CARDINAL:
self.assertEqual(num2words(test[0], lang=LANG), test[1])
def test_ordinal(self):
for test in TEST_CASES_ORDINAL:
self.assertEqual(
num2words(test[0], lang=LANG, ordinal=True),
test[1]
)
def test_currency_eur(self):
for test in TEST_CASES_TO_CURRENCY_EUR:
self.assertEqual(
num2words(test[0], lang=LANG, to='currency'),
test[1]
)
def test_currency_frf(self):
for test in TEST_CASES_TO_CURRENCY_FRF:
self.assertEqual(
num2words(test[0], lang=LANG, to='currency', currency='FRF'),
test[1]
)

127
tests/test_fr_ch.py Normal file
View File

@@ -0,0 +1,127 @@
# -*- coding: 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 unittest import TestCase
from num2words import num2words
TEST_CASES_CARDINAL = (
(70, 'septante'),
(79, 'septante-neuf'),
(89, 'huitante-neuf'),
(95, 'nonante-cinq'),
(729, 'sept cents vingt-neuf'),
(894, 'huit cents nonante-quatre'),
(999, 'neuf cents nonante-neuf'),
(7232, 'sept mille deux cents trente-deux'),
(8569, 'huit mille cinq cents soixante-neuf'),
(9539, 'neuf mille cinq cents trente-neuf'),
(1000000, 'un millions'),
(1000001, 'un millions un'),
(4000000, 'quatre millions'),
(10000000000000, 'dix billions'),
(100000000000000, 'cent billions'),
(1000000000000000000, 'un trillions'),
(1000000000000000000000, 'un trilliards'),
(10000000000000000000000000, 'dix quadrillions')
)
TEST_CASES_ORDINAL = (
(1, 'premier'),
(8, 'huitième'),
(12, 'douzième'),
(14, 'quatorzième'),
(28, 'vingt-huitième'),
(100, 'centième'),
(1000, 'millième'),
(1000000, 'un millionsième'),
(1000000000000000, 'un billiardsième'),
(1000000000000000000, 'un trillionsième') # over 1e18 is not supported
)
TEST_CASES_TO_CURRENCY_EUR = (
(1.00, 'un euro et zéro centimes'),
(2.01, 'deux euros et un centime'),
(8.10, 'huit euros et dix centimes'),
(12.26, 'douze euros et vingt-six centimes'),
(21.29, 'vingt et un euros et vingt-neuf centimes'),
(81.25, 'huitante et un euros et vingt-cinq centimes'),
(100.00, 'cent euros et zéro centimes'),
)
TEST_CASES_TO_CURRENCY_FRF = (
(1.00, 'un franc et zéro centimes'),
(2.01, 'deux francs et un centime'),
(8.10, 'huit francs et dix centimes'),
(12.27, 'douze francs et vingt-sept centimes'),
(21.29, 'vingt et un francs et vingt-neuf centimes'),
(81.25, 'huitante et un francs et vingt-cinq centimes'),
(100.00, 'cent francs et zéro centimes'),
)
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")
def test_number(self):
for test in TEST_CASES_CARDINAL:
self.assertEqual(num2words(test[0], lang='fr_CH'), test[1])
def test_ordinal(self):
for test in TEST_CASES_ORDINAL:
self.assertEqual(
num2words(test[0], lang='fr_CH', ordinal=True),
test[1]
)
def test_currency_eur(self):
for test in TEST_CASES_TO_CURRENCY_EUR:
self.assertEqual(
num2words(test[0], lang='fr_CH', to='currency'),
test[1]
)
def test_currency_frf(self):
for test in TEST_CASES_TO_CURRENCY_FRF:
self.assertEqual(
num2words(test[0], lang='fr_CH', to='currency',
currency='FRF'),
test[1]
)

65
tests/test_fr_dz.py Normal file
View File

@@ -0,0 +1,65 @@
# -*- coding: 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 unittest import TestCase
from num2words import num2words
from . import test_fr
TEST_CASES_TO_CURRENCY = (
(1, 'un dinard'),
(2, 'deux dinards'),
(8, 'huit dinards'),
(12, 'douze dinards'),
(21, 'vingt et un dinards'),
(81.25, 'quatre-vingt-un dinards et vingt-cinq centimes'),
(100, 'cent dinards'),
)
class Num2WordsPLTest(TestCase):
def test_currency(self):
self.assertEqual(
num2words(1234.12, lang='fr_DZ', to='currency'),
"mille deux cent trente-quatre dinards et douze centimes"
)
self.assertEqual(
num2words(45689.89, lang='fr_DZ', to='currency'),
"quarante-cinq mille six cent quatre-vingt-neuf dinards et "
"quatre-vingt-neuf centimes"
)
def test_number(self):
for test in test_fr.TEST_CASES_CARDINAL:
self.assertEqual(num2words(test[0], lang='fr_DZ'), test[1])
def test_ordinal(self):
for test in test_fr.TEST_CASES_ORDINAL:
self.assertEqual(
num2words(test[0], lang='fr_DZ', ordinal=True),
test[1]
)
def test_ordinal_num(self):
for test in test_fr.TEST_CASES_ORDINAL_NUM:
self.assertEqual(
num2words(test[0], lang='fr_DZ', to='ordinal_num'),
test[1]
)

116
tests/test_he.py Normal file
View File

@@ -0,0 +1,116 @@
# -*- coding: 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 unittest import TestCase
from num2words import num2words
from num2words.lang_HE import Num2Word_HE
class Num2WordsHETest(TestCase):
maxDiff = None
def test_0(self):
self.assertEqual(num2words(0, lang="he"), u'אפס')
def test_1_to_10(self):
self.assertEqual(num2words(1, lang="he"), u'אחת')
self.assertEqual(num2words(2, lang="he"), u'שתים')
self.assertEqual(num2words(7, lang="he"), u'שבע')
self.assertEqual(num2words(10, lang="he"), u'עשר')
def test_11_to_19(self):
self.assertEqual(num2words(11, lang="he"), u'אחת עשרה')
self.assertEqual(num2words(13, lang="he"), u'שלש עשרה')
self.assertEqual(num2words(15, lang="he"), u'חמש עשרה')
self.assertEqual(num2words(16, lang="he"), u'שש עשרה')
self.assertEqual(num2words(19, lang="he"), u'תשע עשרה')
def test_20_to_99(self):
self.assertEqual(num2words(20, lang="he"), u'עשרים')
self.assertEqual(num2words(23, lang="he"), u'עשרים ושלש')
self.assertEqual(num2words(28, lang="he"), u'עשרים ושמונה')
self.assertEqual(num2words(31, lang="he"), u'שלשים ואחת')
self.assertEqual(num2words(40, lang="he"), u'ארבעים')
self.assertEqual(num2words(66, lang="he"), u'ששים ושש')
self.assertEqual(num2words(92, lang="he"), u'תשעים ושתים')
def test_100_to_999(self):
self.assertEqual(num2words(100, lang="he"), u'מאה')
self.assertEqual(num2words(111, lang="he"), u'מאה ואחת עשרה')
self.assertEqual(num2words(150, lang="he"), u'מאה וחמישים')
self.assertEqual(num2words(196, lang="he"), u'מאה תשעים ושש')
self.assertEqual(num2words(200, lang="he"), u'מאתיים')
self.assertEqual(num2words(210, lang="he"), u'מאתיים ועשר')
self.assertEqual(num2words(701, lang="he"), u'שבע מאות ואחת')
def test_1000_to_9999(self):
self.assertEqual(num2words(1000, lang="he"), u'אלף')
self.assertEqual(num2words(1001, lang="he"), u'אלף ואחת')
self.assertEqual(num2words(1500, lang="he"), u'אלף וחמש מאות')
self.assertEqual(
num2words(7378, lang="he"), u'שבעת אלפים שלש מאות שבעים ושמונה'
)
self.assertEqual(num2words(2000, lang="he"), u'אלפיים')
self.assertEqual(num2words(2100, lang="he"), u'אלפיים ומאה')
self.assertEqual(
num2words(6870, lang="he"), u'ששת אלפים שמונה מאות ושבעים'
)
def test_pluralize(self):
n = Num2Word_HE()
cr1, cr2 = n.CURRENCY_FORMS['NIS']
self.assertEqual(n.pluralize(1, cr1), 'שקל')
self.assertEqual(n.pluralize(2, cr1), 'שקלים')
self.assertEqual(n.pluralize(1, cr2), 'אגורה')
self.assertEqual(n.pluralize(2, cr2), 'אגורות')
cr1, cr2 = n.CURRENCY_FORMS['USD']
self.assertEqual(n.pluralize(1, cr1), 'דולר')
self.assertEqual(n.pluralize(2, cr1), 'דולרים')
self.assertEqual(n.pluralize(1, cr2), 'סנט')
self.assertEqual(n.pluralize(2, cr2), 'סנט')
def test_to_currency(self):
n = Num2Word_HE()
self.assertEqual(
n.to_currency(20.0, currency='NIS'), 'עשרים שקלים ואפס אגורות'
)
self.assertEqual(
n.to_currency(100.0, currency='NIS'), 'מאה שקלים ואפס אגורות'
)
self.assertEqual(
n.to_currency(100.50, currency='NIS'), 'מאה שקלים וחמישים אגורות'
)
def test_to_cardinal(self):
n = Num2Word_HE()
self.assertEqual(n.to_cardinal(1500), u'אלף וחמש מאות')
class Num2WordsHETestNotImplementedMethofs(TestCase):
n = Num2Word_HE()
def test_to_ordinal(self):
with self.assertRaises(NotImplementedError):
self.n.to_ordinal('1')
def test_large_number(self):
with self.assertRaises(NotImplementedError):
num2words(2000000, lang="he")

213
tests/test_hu.py Normal file
View File

@@ -0,0 +1,213 @@
# -*- coding: 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 unittest import TestCase
from num2words import num2words
class Num2WordsHUTest(TestCase):
def test_and_join_199(self):
# ref https://github.com/savoirfairelinux/num2words/issues/8
self.assertEqual(num2words(199), "one hundred and ninety-nine")
def test_cardinal(self):
self.assertEqual(
num2words(-1, lang='hu'),
'mínusz egy'
)
self.assertEqual(
num2words(0, lang='hu'),
'nulla'
)
self.assertEqual(
num2words(1, lang='hu'),
'egy'
)
self.assertEqual(
num2words(13, lang='hu'),
'tizenhárom'
)
self.assertEqual(
num2words(22, lang='hu'),
'huszonkettő'
)
self.assertEqual(
num2words(75, lang='hu'),
'hetvenöt'
)
self.assertEqual(
num2words(124, lang='hu'),
'százhuszonnégy'
)
self.assertEqual(
num2words(651, lang='hu'),
'hatszázötvenegy'
)
self.assertEqual(
num2words(2232, lang='hu'),
'kétezer-kétszázharminckettő'
)
self.assertEqual(
num2words(16501, lang='hu'),
'tizenhatezer-ötszázegy'
)
self.assertEqual(
num2words(1900000000000, lang='hu'),
'egybillió-kilencszázmilliárd'
)
self.assertEqual(
num2words(24656451324564987566, lang='hu'),
'huszonnégytrillió-hatszázötvenhatbilliárd-négyszázötvenegybillió'
'-háromszázhuszonnégymilliárd-ötszázhatvannégymillió-'
'kilencszáznyolcvanhétezer-ötszázhatvanhat'
)
def test_ordinal(self):
self.assertEqual(
num2words(0, lang='hu', to='ordinal'),
'nulladik'
)
self.assertEqual(
num2words(1, lang='hu', to='ordinal'),
'első'
)
self.assertEqual(
num2words(2, lang='hu', to='ordinal'),
'második'
)
self.assertEqual(
num2words(-3, lang='hu', to='ordinal'),
'mínusz harmadik'
)
self.assertEqual(
num2words(13, lang='hu', to='ordinal'),
'tizenharmadik'
)
self.assertEqual(
num2words(22, lang='hu', to='ordinal'),
'huszonkettedik'
)
self.assertEqual(
num2words(75, lang='hu', to='ordinal'),
'hetvenötödik'
)
self.assertEqual(
num2words(124, lang='hu', to='ordinal'),
'százhuszonnegyedik'
)
self.assertEqual(
num2words(1532, lang='hu', to='ordinal'),
'ezerötszázharminckettedik'
)
self.assertEqual(
num2words(16501, lang='hu', to='ordinal'),
'tizenhatezer-ötszázegyedik'
)
self.assertEqual(
num2words(458755640120000, lang='hu', to='ordinal'),
'négyszázötvennyolcbillió-hétszázötvenötmilliárd-'
'hatszáznegyvenmillió-százhúszezredik'
)
def test_ordinal_num(self):
self.assertEqual(num2words(10, lang='hu', to='ordinal_num'), '10.')
self.assertEqual(num2words(21, lang='hu', to='ordinal_num'), '21.')
self.assertEqual(num2words(102, lang='hu', to='ordinal_num'), '102.')
self.assertEqual(num2words(73, lang='hu', to='ordinal_num'), '73.')
def test_cardinal_for_float_number(self):
# issue 24
self.assertEqual(num2words(12, lang='hu'),
"tizenkettő")
self.assertEqual(num2words(12.0, lang='hu'),
"tizenkettő")
self.assertEqual(num2words(12.5, lang='hu'),
"tizenkettő egész öt tized")
self.assertEqual(num2words(-12.5, lang='hu'),
"mínusz tizenkettő egész öt tized")
self.assertEqual(num2words(12.51, lang='hu'),
"tizenkettő egész ötvenegy század")
self.assertEqual(num2words(12.53, lang='hu'),
"tizenkettő egész ötvenhárom század")
self.assertEqual(num2words(12.590, lang='hu'),
"tizenkettő egész ötvenkilenc század")
self.assertEqual(num2words(12.005, lang='hu'),
"tizenkettő egész öt ezred")
def test_overflow(self):
with self.assertRaises(OverflowError):
num2words("1000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000"
"00000000000000000000000000000000")
def test_to_currency(self):
self.assertEqual(
num2words('38.4', lang='hu', to='currency', separator=' és',
cents=False, currency='HUF'),
"harmincnyolc forint és 40 fillér"
)
self.assertEqual(
num2words('0', lang='hu', to='currency', separator=' és',
cents=False, currency='HUF'),
"nulla forint és 00 fillér"
)
self.assertEqual(
num2words('1.01', lang='hu', to='currency', separator=' és',
cents=True, currency='HUF'),
"egy forint és egy fillér"
)
self.assertEqual(
num2words('4778.00', lang='hu', to='currency', separator=' és',
cents=True, currency='HUF', adjective=True),
'négyezer-hétszázhetvennyolc Hungarian forint'
' és nulla fillér')
self.assertEqual(
num2words('4778.00', lang='hu', to='currency', separator=' és',
cents=True, currency='HUF'),
'négyezer-hétszázhetvennyolc forint és nulla fillér')
def test_to_year(self):
# issue 141
# "e2 e2"
self.assertEqual(num2words(1990, lang='hu', to='year'),
'ezerkilencszázkilencven')
self.assertEqual(num2words(5555, lang='hu', to='year'),
'ötezer-ötszázötvenöt')
self.assertEqual(num2words(2020, lang='hu', to='year'),
'kétezer-húsz')
self.assertEqual(num2words(905, lang='hu', to='year'),
'kilencszázöt')
self.assertEqual(num2words(0, lang='hu', to='year'),
'nulla')
# suffixes
self.assertEqual(num2words(-44, lang='hu', to='year'),
'i. e. negyvennégy')
self.assertEqual(num2words(-44, lang='hu', to='year', suffix='Kr. e.'),
'Kr. e. negyvennégy')
self.assertEqual(num2words(1, lang='hu', to='year', suffix='Kr. u.'),
'Kr. u. egy')
self.assertEqual(num2words(-66000000, lang='hu', to='year'),
'i. e. hatvanhatmillió')

62
tests/test_id.py Normal file
View File

@@ -0,0 +1,62 @@
# -*- coding: 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 unittest import TestCase
from num2words import num2words
class Num2WordsIDTest(TestCase):
def test_cardinal_for_natural_number(self):
self.assertEqual(num2words(10, lang='id'), "sepuluh")
self.assertEqual(num2words(11, lang='id'), "sebelas")
self.assertEqual(num2words(108, lang='id'), "seratus delapan")
self.assertEqual(num2words(1075, lang='id'), "seribu tujuh puluh lima")
self.assertEqual(
num2words(1087231, lang='id'),
"satu juta delapan puluh tujuh ribu dua ratus tiga puluh satu"
)
self.assertEqual(
num2words(1000000408, lang='id'),
"satu miliar empat ratus delapan"
)
def test_cardinal_for_decimal_number(self):
self.assertEqual(
num2words(12.234, lang='id'), "dua belas koma dua tiga empat"
)
self.assertEqual(
num2words(9.076, lang='id'), "sembilan koma nol tujuh enam"
)
def test_cardinal_for_negative_number(self):
self.assertEqual(
num2words(-923, lang='id'), "min sembilan ratus dua puluh tiga"
)
self.assertEqual(
num2words(-0.234, lang='id'), "min nol koma dua tiga empat"
)
def test_ordinal_for_natural_number(self):
self.assertEqual(num2words(1, ordinal=True, lang='id'), "pertama")
self.assertEqual(num2words(10, ordinal=True, lang='id'), "kesepuluh")
def test_ordinal_for_negative_number(self):
self.assertRaises(TypeError, num2words, -12, ordinal=True, lang='id')
def test_ordinal_for_floating_number(self):
self.assertRaises(TypeError, num2words, 3.243, ordinal=True, lang='id')

293
tests/test_it.py Normal file
View File

@@ -0,0 +1,293 @@
# -*- coding: 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 unittest import TestCase
from num2words import num2words
TEST_CASES_TO_CURRENCY_EUR = (
(1.00, 'un euro e zero centesimi'),
(2.01, 'due euro e un centesimo'),
(8.10, 'otto euro e dieci centesimi'),
(12.26, 'dodici euro e ventisei centesimi'),
(21.29, 'ventun euro e ventinove centesimi'),
(81.25, 'ottantun euro e venticinque centesimi'),
(100.00, 'cento euro e zero centesimi'),
)
TEST_CASES_TO_CURRENCY_USD = (
(1.00, 'un dollaro e zero centesimi'),
(2.01, 'due dollari e un centesimo'),
(8.10, 'otto dollari e dieci centesimi'),
(12.26, 'dodici dollari e ventisei centesimi'),
(21.29, 'ventun dollari e ventinove centesimi'),
(81.25, 'ottantun dollari e venticinque centesimi'),
(100.00, 'cento dollari e zero centesimi'),
)
TEST_CASES_TO_CURRENCY_GBP = (
(1.00, 'una sterlina e zero penny'),
(2.01, 'due sterline e un penny'),
(8.10, 'otto sterline e dieci penny'),
(12.26, 'dodici sterline e ventisei penny'),
(21.29, 'ventun sterline e ventinove penny'),
(81.25, 'ottantun sterline e venticinque penny'),
(100.00, 'cento sterline e zero penny'),
)
class Num2WordsITTest(TestCase):
maxDiff = None
def test_negative(self):
number = 648972145
pos_crd = num2words(+number, lang="it")
neg_crd = num2words(-number, lang="it")
pos_ord = num2words(+number, lang="it", ordinal=True)
neg_ord = num2words(-number, lang="it", ordinal=True)
self.assertEqual("meno " + pos_crd, neg_crd)
self.assertEqual("meno " + pos_ord, neg_ord)
def test_float_to_cardinal(self):
self.assertEqual(
num2words(3.1415, lang="it"), "tre virgola uno quattro uno cinque"
)
self.assertEqual(
num2words(-5.15, lang="it"), "meno cinque virgola uno cinque"
)
self.assertEqual(
num2words(-0.15, lang="it"), "meno zero virgola uno cinque"
)
def test_float_to_ordinal(self):
self.assertEqual(
num2words(3.1415, lang="it", ordinal=True),
"terzo virgola uno quattro uno cinque"
)
self.assertEqual(
num2words(-5.15, lang="it", ordinal=True),
"meno quinto virgola uno cinque"
)
self.assertEqual(
num2words(-0.15, lang="it", ordinal=True),
"meno zero virgola uno cinque"
)
def test_0(self):
self.assertEqual(num2words(0, lang="it"), "zero")
self.assertEqual(num2words(0, lang="it", ordinal=True), "zero")
def test_1_to_10(self):
self.assertEqual(num2words(1, lang="it"), "uno")
self.assertEqual(num2words(2, lang="it"), "due")
self.assertEqual(num2words(7, lang="it"), "sette")
self.assertEqual(num2words(10, lang="it"), "dieci")
def test_11_to_19(self):
self.assertEqual(num2words(11, lang="it"), "undici")
self.assertEqual(num2words(13, lang="it"), "tredici")
self.assertEqual(num2words(15, lang="it"), "quindici")
self.assertEqual(num2words(16, lang="it"), "sedici")
self.assertEqual(num2words(19, lang="it"), "diciannove")
def test_20_to_99(self):
self.assertEqual(num2words(20, lang="it"), "venti")
self.assertEqual(num2words(21, lang="it"), "ventuno")
self.assertEqual(num2words(23, lang="it"), "ventitré")
self.assertEqual(num2words(28, lang="it"), "ventotto")
self.assertEqual(num2words(31, lang="it"), "trentuno")
self.assertEqual(num2words(40, lang="it"), "quaranta")
self.assertEqual(num2words(66, lang="it"), "sessantasei")
self.assertEqual(num2words(92, lang="it"), "novantadue")
def test_100_to_999(self):
self.assertEqual(num2words(100, lang="it"), "cento")
self.assertEqual(num2words(111, lang="it"), "centoundici")
self.assertEqual(num2words(150, lang="it"), "centocinquanta")
self.assertEqual(num2words(196, lang="it"), "centonovantasei")
self.assertEqual(num2words(200, lang="it"), "duecento")
self.assertEqual(num2words(210, lang="it"), "duecentodieci")
self.assertEqual(num2words(701, lang="it"), "settecentouno")
def test_1000_to_9999(self):
self.assertEqual(num2words(1000, lang="it"), "mille")
self.assertEqual(num2words(1001, lang="it"), "milleuno")
self.assertEqual(num2words(1500, lang="it"), "millecinquecento")
self.assertEqual(
num2words(7378, lang="it"), "settemilatrecentosettantotto"
)
self.assertEqual(num2words(2000, lang="it"), "duemila")
self.assertEqual(num2words(2100, lang="it"), "duemilacento")
self.assertEqual(
num2words(6870, lang="it"), "seimilaottocentosettanta"
)
self.assertEqual(num2words(10000, lang="it"), "diecimila")
self.assertEqual(
num2words(98765, lang="it"),
"novantottomilasettecentosessantacinque"
)
self.assertEqual(num2words(100000, lang="it"), "centomila")
self.assertEqual(
num2words(523456, lang="it"),
"cinquecentoventitremilaquattrocentocinquantasei"
)
def test_big(self):
self.assertEqual(num2words(1000000, lang="it"), "un milione")
self.assertEqual(num2words(1000007, lang="it"), "un milione e sette")
self.assertEqual(
num2words(1200000, lang="it"), "un milione e duecentomila"
)
self.assertEqual(num2words(3000000, lang="it"), "tre milioni")
self.assertEqual(num2words(3000005, lang="it"), "tre milioni e cinque")
self.assertEqual(
num2words(3800000, lang="it"), "tre milioni e ottocentomila"
)
self.assertEqual(num2words(1000000000, lang="it"), "un miliardo")
self.assertEqual(
num2words(1000000017, lang="it"), "un miliardo e diciassette"
)
self.assertEqual(num2words(2000000000, lang="it"), "due miliardi")
self.assertEqual(
num2words(2000001000, lang="it"), "due miliardi e mille"
)
self.assertEqual(
num2words(1234567890, lang="it"),
"un miliardo, duecentotrentaquattro milioni e "
"cinquecentosessantasettemilaottocentonovanta"
)
self.assertEqual(num2words(1000000000000, lang="it"), "un bilione")
self.assertEqual(
num2words(123456789012345678901234567890, lang="it"),
"centoventitré quadriliardi, quattrocentocinquantasei "
"quadrilioni, settecentottantanove triliardi, dodici trilioni, "
"trecentoquarantacinque biliardi, seicentosettantotto bilioni, "
"novecentouno miliardi, duecentotrentaquattro milioni e "
"cinquecentosessantasettemilaottocentonovanta"
)
def test_nth_1_to_99(self):
self.assertEqual(num2words(1, lang="it", ordinal=True), "primo")
self.assertEqual(num2words(8, lang="it", ordinal=True), "ottavo")
self.assertEqual(
num2words(21, lang="it", ordinal=True), "ventunesimo"
)
self.assertEqual(
num2words(23, lang="it", ordinal=True), "ventitreesimo"
)
self.assertEqual(
num2words(47, lang="it", ordinal=True), "quarantasettesimo"
)
self.assertEqual(
num2words(99, lang="it", ordinal=True), "novantanovesimo"
)
def test_nth_100_to_999(self):
self.assertEqual(num2words(100, lang="it", ordinal=True), "centesimo")
self.assertEqual(
num2words(112, lang="it", ordinal=True), "centododicesimo"
)
self.assertEqual(
num2words(120, lang="it", ordinal=True), "centoventesimo"
)
self.assertEqual(
num2words(121, lang="it", ordinal=True), "centoventunesimo"
)
self.assertEqual(
num2words(316, lang="it", ordinal=True), "trecentosedicesimo"
)
self.assertEqual(
num2words(700, lang="it", ordinal=True), "settecentesimo"
)
self.assertEqual(
num2words(803, lang="it", ordinal=True), "ottocentotreesimo"
)
self.assertEqual(
num2words(923, lang="it", ordinal=True), "novecentoventitreesimo"
)
def test_nth_1000_to_999999(self):
self.assertEqual(num2words(1000, lang="it", ordinal=True), "millesimo")
self.assertEqual(
num2words(1001, lang="it", ordinal=True), "milleunesimo"
)
self.assertEqual(
num2words(1003, lang="it", ordinal=True), "milletreesimo"
)
self.assertEqual(
num2words(1200, lang="it", ordinal=True), "milleduecentesimo"
)
self.assertEqual(
num2words(8640, lang="it", ordinal=True),
"ottomilaseicentoquarantesimo"
)
self.assertEqual(
num2words(14000, lang="it", ordinal=True), "quattordicimillesimo"
)
self.assertEqual(
num2words(123456, lang="it", ordinal=True),
"centoventitremilaquattrocentocinquantaseiesimo"
)
self.assertEqual(
num2words(987654, lang="it", ordinal=True),
"novecentottantasettemilaseicentocinquantaquattresimo"
)
def test_nth_big(self):
self.assertEqual(
num2words(1000000001, lang="it", ordinal=True),
"un miliardo e unesimo"
)
self.assertEqual(
num2words(123456789012345678901234567890, lang="it", ordinal=True),
"centoventitré quadriliardi, quattrocentocinquantasei "
"quadrilioni, settecentottantanove triliardi, dodici trilioni, "
"trecentoquarantacinque biliardi, seicentosettantotto bilioni, "
"novecentouno miliardi, duecentotrentaquattro milioni e "
"cinquecentosessantasettemilaottocentonovantesimo"
)
def test_with_decimals(self):
self.assertAlmostEqual(
num2words(1.0, lang="it"), "uno virgola zero"
)
self.assertAlmostEqual(
num2words(1.1, lang="it"), "uno virgola uno"
)
def test_currency_eur(self):
for test in TEST_CASES_TO_CURRENCY_EUR:
self.assertEqual(
num2words(test[0], lang='it', to='currency', currency='EUR'),
test[1]
)
def test_currency_usd(self):
for test in TEST_CASES_TO_CURRENCY_USD:
self.assertEqual(
num2words(test[0], lang='it', to='currency', currency='USD'),
test[1]
)
def test_currency_gbp(self):
for test in TEST_CASES_TO_CURRENCY_GBP:
self.assertEqual(
num2words(test[0], lang='it', to='currency', currency='GBP'),
test[1]
)

198
tests/test_ja.py Normal file
View File

@@ -0,0 +1,198 @@
# -*- coding: 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 division, print_function, unicode_literals
from unittest import TestCase
from num2words import num2words
def n2j(*args, **kwargs):
return num2words(*args, lang='ja', **kwargs)
class Num2WordsJATest(TestCase):
def test_low(self):
self.assertEqual(n2j(0), "")
self.assertEqual(n2j(0, prefer=[""]), "")
self.assertEqual(n2j(0, reading=True), "ゼロ")
self.assertEqual(n2j(0, reading=True, prefer=["れい"]), "れい")
self.assertEqual(n2j(1), "")
self.assertEqual(n2j(1, reading=True), "いち")
self.assertEqual(n2j(2), "")
self.assertEqual(n2j(2, reading=True), "")
self.assertEqual(n2j(3), "")
self.assertEqual(n2j(3, reading=True), "さん")
self.assertEqual(n2j(4), "")
self.assertEqual(n2j(4, reading=True), "よん")
self.assertEqual(n2j(4, reading=True, prefer=[""]), "")
self.assertEqual(n2j(5), "")
self.assertEqual(n2j(5, reading=True), "")
self.assertEqual(n2j(6), "")
self.assertEqual(n2j(6, reading=True), "ろく")
self.assertEqual(n2j(7), "")
self.assertEqual(n2j(7, reading=True), "なな")
self.assertEqual(n2j(7, reading=True, prefer=["しち"]), "しち")
self.assertEqual(n2j(8), "")
self.assertEqual(n2j(8, reading=True), "はち")
self.assertEqual(n2j(9), "")
self.assertEqual(n2j(9, reading=True), "きゅう")
self.assertEqual(n2j(10), "")
self.assertEqual(n2j(10, reading=True), "じゅう")
self.assertEqual(n2j(11), "十一")
self.assertEqual(n2j(11, reading=True), "じゅういち")
self.assertEqual(n2j(12), "十二")
self.assertEqual(n2j(12, reading=True), "じゅうに")
self.assertEqual(n2j(13), "十三")
self.assertEqual(n2j(13, reading=True), "じゅうさん")
self.assertEqual(n2j(14), "十四")
self.assertEqual(n2j(14, reading=True), "じゅうよん")
self.assertEqual(n2j(14, reading=True, prefer=[""]), "じゅうし")
self.assertEqual(n2j(15), "十五")
self.assertEqual(n2j(15, reading=True), "じゅうご")
self.assertEqual(n2j(16), "十六")
self.assertEqual(n2j(16, reading=True), "じゅうろく")
self.assertEqual(n2j(17), "十七")
self.assertEqual(n2j(17, reading=True), "じゅうなな")
self.assertEqual(n2j(17, reading=True, prefer=["しち"]), "じゅうしち")
self.assertEqual(n2j(18), "十八")
self.assertEqual(n2j(18, reading=True), "じゅうはち")
self.assertEqual(n2j(19), "十九")
self.assertEqual(n2j(19, reading=True), "じゅうきゅう")
self.assertEqual(n2j(20), "二十")
self.assertEqual(n2j(20, reading=True), "にじゅう")
def test_mid(self):
self.assertEqual(n2j(100), "")
self.assertEqual(n2j(100, reading=True), "ひゃく")
self.assertEqual(n2j(123), "百二十三")
self.assertEqual(n2j(123, reading=True), "ひゃくにじゅうさん")
self.assertEqual(n2j(300), "三百")
self.assertEqual(n2j(300, reading=True), "さんびゃく")
self.assertEqual(n2j(400), "四百")
self.assertEqual(n2j(400, reading=True), "よんひゃく")
# 400 --> しひゃく sounds weird, but can be generated with prefer
self.assertEqual(n2j(600), "六百")
self.assertEqual(n2j(600, reading=True), "ろっぴゃく")
self.assertEqual(n2j(700, reading=True, prefer=["しち"]), "しちひゃく")
self.assertEqual(n2j(800, reading=True), "はっぴゃく")
self.assertEqual(n2j(1000), "")
self.assertEqual(n2j(1000, reading=True), "せん")
self.assertEqual(n2j(3000, reading=True), "さんぜん")
self.assertEqual(n2j(8000, reading=True), "はっせん")
def test_high(self):
self.assertEqual(n2j(10000), "一万")
self.assertEqual(n2j(10000, reading=True), "いちまん")
self.assertEqual(n2j(12345), "一万二千三百四十五")
self.assertEqual(n2j(12345, reading=True),
"いちまん"
"にせん"
"さんびゃく"
"よんじゅうご")
self.assertEqual(n2j(10**8), "一億")
self.assertEqual(n2j(10**8, reading=True), "いちおく")
self.assertEqual(n2j(123456789), "一億二千三百四十五万六千七百八十九")
self.assertEqual(n2j(123456789, reading=True),
"いちおく"
"にせんさんびゃくよんじゅうごまん"
"ろくせんななひゃく"
"はちじゅうきゅう")
self.assertEqual(n2j(10**12), "一兆")
self.assertEqual(n2j(10**12, reading=True), "いっちょう")
self.assertEqual(n2j(1234567890123),
"一兆二千三百四十五億六千七百八十九万百二十三")
self.assertEqual(n2j(1234567890123, reading=True),
"いっちょう"
"にせんさんびゃくよんじゅうごおく"
"ろくせんななひゃくはちじゅうきゅうまん"
"ひゃくにじゅうさん")
# TODO: tests for 10**16 and above
def test_cardinal_float(self):
self.assertEqual(n2j(0.0123456789, prefer=[""]),
"〇点〇一二三四五六七八九")
self.assertEqual(n2j(0.0123456789, reading=True),
"れいてん"
"れいいち"
"にさん"
"よんご"
"ろくなな"
"はちきゅう")
self.assertEqual(n2j(10**8 + 0.01), "一億点零一")
self.assertEqual(n2j(10**8 + 0.01, reading=True),
"いちおくてんれいいち")
def test_ordinal(self):
self.assertEqual(n2j(0, to="ordinal"), "零番目")
self.assertEqual(n2j(0, to="ordinal", reading=True, prefer=["れい"]),
"れいばんめ")
self.assertEqual(n2j(2, to="ordinal", counter=""), "二人目")
self.assertEqual(n2j(3, to="ordinal", counter=""), "三つ目")
with self.assertRaises(NotImplementedError):
n2j(4, to="ordinal", reading=True, counter="")
def test_ordinal_num(self):
self.assertEqual(n2j(0, to="ordinal_num"), "0番目")
self.assertEqual(n2j(0, to="ordinal_num", reading=True), "0ばんめ")
self.assertEqual(n2j(2, to="ordinal_num", counter=""), "2人目")
self.assertEqual(n2j(3, to="ordinal_num", counter=""), "3つ目")
def test_currency(self):
self.assertEqual(n2j(123456789, to="currency"),
"一億二千三百四十五万六千七百八十九円")
self.assertEqual(n2j(123456789, to="currency", reading=True),
"いちおく"
"にせんさんびゃくよんじゅうごまん"
"ろくせんななひゃく"
"はちじゅうきゅうえん")
def test_year(self):
self.assertEqual(n2j(2021, to="year"), "令和三年")
self.assertEqual(n2j(2021, to="year", reading=True),
"れいわさんねん")
self.assertEqual(n2j(2021, to="year", reading="arabic"),
"令和3年")
self.assertEqual(n2j(2019, to="year"), "令和元年")
self.assertEqual(n2j(2019, to="year", reading=True),
"れいわがんねん")
self.assertEqual(n2j(2019, to="year", reading="arabic"),
"令和1年")
self.assertEqual(n2j(2018, to="year"), "平成三十年")
self.assertEqual(n2j(2018, to="year", reading=True),
"へいせいさんじゅうねん")
self.assertEqual(n2j(2018, to="year", reading="arabic"),
"平成30年")
self.assertEqual(n2j(2017, to="year"), "平成二十九年")
self.assertEqual(n2j(2017, to="year", reading=True),
"へいせいにじゅうくねん")
self.assertEqual(n2j(2017, to="year", reading="arabic"),
"平成29年")
self.assertEqual(n2j(2009, to="year", era=False), "二千九年")
self.assertEqual(n2j(2009, to="year", reading=True, era=False),
"にせんくねん")
self.assertEqual(n2j(2000, to="year", era=False), "二千年")
self.assertEqual(n2j(2000, to="year", era=False, reading=True),
"にせんねん")
self.assertEqual(n2j(645, to="year"), "大化元年")
self.assertEqual(n2j(645, to="year", reading=True), "たいかがんねん")
self.assertEqual(n2j(-99, to="year", era=False), "紀元前九十九年")
self.assertEqual(n2j(-99, to="year", era=False, reading=True),
"きげんぜんきゅうじゅうくねん")
self.assertEqual(n2j(1375, to="year"), "天授元年")
self.assertEqual(n2j(1375, to="year", prefer=["えいわ"]), "永和元年")

73
tests/test_kn.py Normal file
View File

@@ -0,0 +1,73 @@
# -*- coding: 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 unittest import TestCase
from num2words import num2words
class Num2WordsKNTest(TestCase):
def test_numbers(self):
self.assertEqual(num2words(42, lang="kn"), u"ನಲವತ್ತ್ ಎರಡು")
self.assertEqual(num2words(893, lang="kn"), u"ಎಂಟು ನೂರ ತೊಂಬತ್ತ ಮೂರು")
self.assertEqual(
num2words(1729, lang="kn"), u"ಒಂದು ಸಾವಿರ ಏಳು ನೂರ ಇಪ್ಪತ್ತ್ಒಂಬತ್ತು"
)
self.assertEqual(num2words(123, lang="kn"), u"ಒಂದು ನೂರ ಇಪ್ಪತ್ತ್ ಮೂರು")
self.assertEqual(num2words(32211, lang="kn"),
u"ಮೂವತ್ತ್ಎರಡು ಸಾವಿರ ಎರಡು ನೂರ ಹನ್ನೊಂದು")
def test_cardinal_for_float_number(self):
self.assertEqual(num2words(3.14, lang="kn"), u"ಮೂರು ಬಿಂದು ಒಂದು ನಾಲ್ಕು")
self.assertEqual(num2words(1.61803, lang="kn"),
u"ಒಂದು ಬಿಂದು ಆರು ಒಂದು ಎಂಟು ಸೊನ್ನೆ ಮೂರು")
def test_ordinal(self):
self.assertEqual(
num2words(1, lang='kn', to='ordinal'),
u'ಒಂದನೇ'
)
self.assertEqual(
num2words(22, lang='kn', to='ordinal'),
u'ಇಪ್ಪತ್ತ್ ಎರಡನೇ'
)
self.assertEqual(
num2words(12, lang='kn', to='ordinal'),
u'ಹನ್ನೆರಡನೇ'
)
self.assertEqual(
num2words(130, lang='kn', to='ordinal'),
u'ಒಂದು ನೂರ ಮೂವತ್ತನೇ'
)
self.assertEqual(
num2words(1003, lang='kn', to='ordinal'),
u'ಒಂದು ಸಾವಿರದ ಮೂರನೇ'
)
self.assertEqual(num2words(2, lang="kn", ordinal=True), u"ಎರಡನೇ")
self.assertEqual(num2words(5, lang="kn", ordinal=True), u"ಐದನೇ")
self.assertEqual(num2words(16, lang="kn", ordinal=True), u"ಹದಿನಾರನೇ")
self.assertEqual(num2words(113, lang="kn", ordinal=True),
u"ಒಂದು ನೂರ ಹದಿಮೂರನೇ")
def test_ordinal_num(self):
self.assertEqual(num2words(2, lang="kn", to='ordinal_num'), u"2ಎರಡನೇ")
self.assertEqual(num2words(5, lang="kn", to='ordinal_num'), u"5ಐದನೇ")
self.assertEqual(num2words(16, lang="kn", to='ordinal_num'),
u"16ಹದಿನಾರನೇ")
self.assertEqual(num2words(113, lang="kn", to='ordinal_num'),
u"113ಒದು ನೂರ ಹದಿಮೂರನೇ")

93
tests/test_ko.py Normal file
View File

@@ -0,0 +1,93 @@
# -*- coding: 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 division, print_function, unicode_literals
from unittest import TestCase
from num2words import num2words
def n2k(*args, **kwargs):
return num2words(*args, lang='ko', **kwargs)
class Num2WordsKOTest(TestCase):
def test_low(self):
cases = [(0, ""), (1, ""), (2, ""), (3, ""), (4, ""), (5, ""),
(6, ""), (7, ""), (8, ""), (9, ""), (10, ""),
(11, "십일"), (12, "십이"), (13, "십삼"), (14, "십사"),
(15, "십오"), (16, "십육"), (17, "십칠"),
(18, "십팔"), (19, "십구"), (20, "이십"), (25, "이십오"),
(31, "삼십일"), (42, "사십이"), (54, "오십사"), (63, "육십삼"),
(76, "칠십육"), (89, "팔십구"), (98, "구십팔")]
for num, out in cases:
self.assertEqual(n2k(num), out)
def test_mid(self):
cases = [(100, ""), (121, "백이십일"), (160, "백육십"), (256, "이백오십육"),
(285, "이백팔십오"), (486, "사백팔십육"), (627, "육백이십칠"),
(808, "팔백팔"), (999, "구백구십구"), (1004, "천사"),
(2018, "이천십팔"), (7063, "칠천육십삼")]
for num, out in cases:
self.assertEqual(n2k(num), out)
def test_high(self):
cases = [(10000, ""), (11020, "만 천이십"), (25891, "이만 오천팔백구십일"),
(64237, "육만 사천이백삼십칠"), (241572, "이십사만 천오백칠십이"),
(100000000, "일억"), (5000500000000, "오조 오억")]
for num, out in cases:
self.assertEqual(n2k(num), out)
def test_negative(self):
cases = [(-11, "마이너스 십일"), (-15, "마이너스 십오"),
(-18, "마이너스 십팔"), (-241572, "마이너스 이십사만 천오백칠십이")]
for num, out in cases:
self.assertEqual(n2k(num), out)
def test_year(self):
cases = [(2000, "이천년"), (2002, "이천이년"), (2018, "이천십팔년"),
(1954, "천구백오십사년"), (1910, "천구백십년"), (-1000, "기원전 천년")]
for num, out in cases:
self.assertEqual(n2k(num, to="year"), out)
def test_currency(self):
cases_krw = [(8350, "팔천삼백오십원"), (14980, "만사천구백팔십원"),
(250004000, "이억오천만사천원")]
cases_usd = [(4, "사달러 영센트"), (19.55, "십구달러 오십오센트")]
cases_jpy = [(15, "십오엔"), (50, "오십엔")]
for num, out in cases_krw:
self.assertEqual(n2k(num, to="currency"), out)
for num, out in cases_usd:
self.assertEqual(n2k(num, to="currency", currency="USD"), out)
for num, out in cases_jpy:
self.assertEqual(n2k(num, to="currency", currency="JPY"), out)
with self.assertRaises(ValueError):
n2k(190.55, to="currency")
with self.assertRaises(NotImplementedError):
n2k(4, to="currency", currency="EUR")
def test_ordinal(self):
cases = [(1, "첫 번째"), (101, "백 한 번째"), (2, "두 번째"), (5, "다섯 번째"),
(10, "열 번째"), (25, "스물다섯 번째"), (137, "백 서른일곱 번째")]
for num, out in cases:
self.assertEqual(n2k(num, to="ordinal"), out)
def test_ordinal_num(self):
cases = [(1, "1 번째"), (101, "101 번째"), (25, "25 번째")]
for num, out in cases:
self.assertEqual(n2k(num, to="ordinal_num"), out)

81
tests/test_kz.py Normal file
View File

@@ -0,0 +1,81 @@
# -*- coding: 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 unittest import TestCase
from num2words import num2words
class Num2WordsKZTest(TestCase):
def test_to_cardinal(self):
self.maxDiff = None
self.assertEqual(num2words(7, lang="kz"), "жеті")
self.assertEqual(num2words(23, lang="kz"), "жиырма үш")
self.assertEqual(num2words(145, lang="kz"), "жүз қырық бес")
self.assertEqual(
num2words(2869, lang="kz"),
"екі мың сегіз жүз алпыс тоғыз"
)
self.assertEqual(
num2words(-789000125, lang="kz"),
"минус жеті жүз сексен тоғыз миллион жүз жиырма бес",
)
self.assertEqual(
num2words(84932, lang="kz"), "сексен төрт мың тоғыз жүз отыз екі"
)
def test_to_cardinal_floats(self):
self.assertEqual(num2words(100.67, lang="kz"), "жүз бүтін алпыс жеті")
self.assertEqual(num2words(0.7, lang="kz"), "нөл бүтін жеті")
self.assertEqual(num2words(1.73, lang="kz"), "бір бүтін жетпіс үш")
self.assertEqual(
num2words(10.02, lang='kz'),
"он бүтін нөл екі"
)
self.assertEqual(
num2words(15.007, lang='kz'),
"он бес бүтін нөл нөл жеті"
)
def test_to_ordinal(self):
with self.assertRaises(NotImplementedError):
num2words(1, lang="kz", to="ordinal")
def test_to_currency(self):
self.assertEqual(
num2words(25.24, lang="kz", to="currency", currency="KZT"),
"жиырма бес теңге, жиырма төрт тиын",
)
self.assertEqual(
num2words(1996.4, lang="kz", to="currency", currency="KZT"),
"бір мың тоғыз жүз тоқсан алты теңге, қырық тиын",
)
self.assertEqual(
num2words(632924.51, lang="kz", to="currency", currency="KZT"),
"алты жүз отыз екі мың тоғыз жүз жиырма төрт теңге, елу бір тиын",
)
self.assertEqual(
num2words(632924.513, lang="kz", to="currency", currency="KZT"),
"алты жүз отыз екі мың тоғыз жүз жиырма төрт теңге, елу бір тиын",
)
self.assertEqual(
num2words(987654321.123, lang="kz", to="currency", currency="KZT"),
"тоғыз жүз сексен жеті миллион алты жүз елу төрт мың "
"үш жүз жиырма бір теңге, он екі тиын",
)

186
tests/test_lt.py Normal file
View File

@@ -0,0 +1,186 @@
# -*- coding: 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 unittest import TestCase
from num2words import num2words
class Num2WordsLTTest(TestCase):
def test_to_cardinal(self):
self.assertEqual(num2words(100, lang='lt'), 'vienas šimtas')
self.assertEqual(num2words(101, lang='lt'), 'vienas šimtas vienas')
self.assertEqual(num2words(110, lang='lt'), 'vienas šimtas dešimt')
self.assertEqual(num2words(115, lang='lt'),
'vienas šimtas penkiolika')
self.assertEqual(num2words(123, lang='lt'),
'vienas šimtas dvidešimt trys')
self.assertEqual(num2words(1000, lang='lt'), 'vienas tūkstantis')
self.assertEqual(num2words(1001, lang='lt'),
'vienas tūkstantis vienas')
self.assertEqual(num2words(2012, lang='lt'),
'du tūkstančiai dvylika')
self.assertEqual(
num2words(1234567890, lang='lt'),
"vienas milijardas du šimtai trisdešimt keturi milijonai "
"penki šimtai šešiasdešimt septyni tūkstančiai aštuoni šimtai "
"devyniasdešimt")
self.assertEqual(
num2words(215461407892039002157189883901676, lang='lt'),
"du šimtai penkiolika naintilijonų keturi šimtai šešiasdešimt "
"vienas oktilijonas keturi šimtai septyni septilijonai aštuoni "
"šimtai devyniasdešimt du sikstilijonai trisdešimt devyni "
"kvintilijonai du kvadrilijonai vienas šimtas penkiasdešimt "
"septyni trilijonai vienas šimtas aštuoniasdešimt devyni "
"milijardai aštuoni šimtai aštuoniasdešimt trys milijonai "
"devyni šimtai vienas tūkstantis šeši šimtai "
"septyniasdešimt šeši")
self.assertEqual(
num2words(719094234693663034822824384220291, lang='lt'),
"septyni šimtai devyniolika naintilijonų devyniasdešimt keturi "
"oktilijonai du šimtai trisdešimt keturi septilijonai šeši "
"šimtai devyniasdešimt trys sikstilijonai šeši šimtai "
"šešiasdešimt trys kvintilijonai trisdešimt keturi kvadrilijonai "
"aštuoni šimtai dvidešimt du trilijonai aštuoni šimtai dvidešimt "
"keturi milijardai trys šimtai aštuoniasdešimt keturi milijonai "
"du šimtai dvidešimt tūkstančių du šimtai devyniasdešimt vienas")
self.assertEqual(
num2words(-5000, lang='lt'),
'minus penki tūkstančiai',
)
self.assertEqual(
num2words(-5000.22, lang='lt'),
'minus penki tūkstančiai kablelis dvidešimt du',
)
self.assertEqual(
num2words(10.02, lang='lt'),
"dešimt kablelis nulis du"
)
self.assertEqual(
num2words(15.007, lang='lt'),
"penkiolika kablelis nulis nulis septyni"
)
def test_to_ordinal(self):
# @TODO: implement to_ordinal
with self.assertRaises(NotImplementedError):
num2words(1, lang='lt', to='ordinal')
def test_to_currency(self):
# Test all available currency forms.
# LTL
self.assertEqual(
num2words(1.0, lang='lt', to='currency', currency='LTL'),
'vienas litas, nulis centų'
)
self.assertEqual(
num2words(10.01, lang='lt', to='currency', currency='LTL'),
'dešimt litų, vienas centas'
)
self.assertEqual(
num2words(1234.56, lang='lt', to='currency', currency='LTL'),
'vienas tūkstantis du šimtai trisdešimt keturi litai, '
'penkiasdešimt šeši centai'
)
# EUR
self.assertEqual(
num2words(-1251981, lang='lt', to='currency', currency='EUR',
cents=False),
'minus dvylika tūkstančių penki šimtai devyniolika eurų, '
'81 centas'
)
self.assertEqual(
num2words(1.0, lang='lt', to='currency', currency='EUR'),
'vienas euras, nulis centų'
)
self.assertEqual(
num2words(1234.56, lang='lt', to='currency', currency='EUR'),
'vienas tūkstantis du šimtai trisdešimt keturi eurai, '
'penkiasdešimt šeši centai'
)
self.assertEqual(
num2words(1122.22, lang='lt', to='currency', currency='EUR'),
'vienas tūkstantis vienas šimtas dvidešimt du eurai, '
'dvidešimt du centai'
)
# USD
self.assertEqual(
num2words(-1281, lang='lt', to='currency', currency='USD',
cents=False),
'minus dvylika dolerių, 81 centas'
)
self.assertEqual(
num2words(1.0, lang='lt', to='currency', currency='USD'),
'vienas doleris, nulis centų'
)
self.assertEqual(
num2words(5.06, lang='lt', to='currency', currency='USD'),
'penki doleriai, šeši centai'
)
# GBP
self.assertEqual(
num2words(-1281, lang='lt', to='currency', currency='GBP',
cents=False),
'minus dvylika svarų sterlingų, 81 pensas'
)
self.assertEqual(
num2words(1.0, lang='lt', to='currency', currency='GBP'),
'vienas svaras sterlingų, nulis pensų'
)
self.assertEqual(
num2words(5.06, lang='lt', to='currency', currency='GBP'),
'penki svarai sterlingų, šeši pensai'
)
# PLN
self.assertEqual(
num2words(-1281, lang='lt', to='currency', currency='PLN',
cents=False),
'minus dvylika zlotų, 81 grašis'
)
self.assertEqual(
num2words(1.0, lang='lt', to='currency', currency='PLN'),
'vienas zlotas, nulis grašių'
)
self.assertEqual(
num2words(5.06, lang='lt', to='currency', currency='PLN'),
'penki zlotai, šeši grašiai'
)
# RUB
self.assertEqual(
num2words(-1281, lang='lt', to='currency', currency='RUB',
cents=False),
'minus dvylika rublių, 81 kapeika'
)
self.assertEqual(
num2words(1.0, lang='lt', to='currency', currency='RUB'),
'vienas rublis, nulis kapeikų'
)
self.assertEqual(
num2words(5.06, lang='lt', to='currency', currency='RUB'),
'penki rubliai, šešios kapeikos'
)
self.assertEqual(
num2words(-12.01, lang='lt', to='currency', currency='RUB'),
'minus dvylika rublių, viena kapeika'
)
self.assertEqual(
num2words(1122.22, lang='lt', to='currency', currency='RUB'),
'vienas tūkstantis vienas šimtas dvidešimt du rubliai, '
'dvidešimt dvi kapeikos'
)

162
tests/test_lv.py Normal file
View File

@@ -0,0 +1,162 @@
# -*- coding: 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 unittest import TestCase
from num2words import num2words
class Num2WordsLVTest(TestCase):
def test_to_cardinal(self):
self.assertEqual(num2words(100, lang='lv'), 'simts')
self.assertEqual(num2words(101, lang='lv'), 'simtu viens')
self.assertEqual(num2words(110, lang='lv'), 'simts desmit')
self.assertEqual(num2words(115, lang='lv'), 'simts piecpadsmit')
self.assertEqual(num2words(123, lang='lv'), 'simts divdesmit trīs')
self.assertEqual(num2words(1000, lang='lv'), 'tūkstotis')
self.assertEqual(num2words(1001, lang='lv'), 'tūkstotis viens')
self.assertEqual(num2words(2012, lang='lv'),
'divi tūkstoši divpadsmit')
self.assertEqual(
num2words(1234567890, lang='lv'),
'miljards divi simti trīsdesmit četri miljoni pieci simti '
'sešdesmit septiņi tūkstoši astoņi simti deviņdesmit')
self.assertEqual(
num2words(215461407892039002157189883901676, lang='lv'),
'divi simti piecpadsmit nontiljoni četri simti sešdesmit '
'viens oktiljons četri simti septiņi septiljoni astoņi '
'simti deviņdesmit divi sikstiljoni trīsdesmit deviņi '
'kvintiljoni divi kvadriljoni simts piecdesmit septiņi '
'triljoni simts astoņdesmit deviņi miljardi astoņi simti '
'astoņdesmit trīs miljoni deviņi simti viens tūkstotis '
'seši simti septiņdesmit seši')
self.assertEqual(
num2words(719094234693663034822824384220291, lang='lv'),
'septiņi simti deviņpadsmit nontiljoni deviņdesmit četri '
'oktiljoni divi simti trīsdesmit četri septiljoni seši simti '
'deviņdesmit trīs sikstiljoni seši simti sešdesmit trīs '
'kvintiljoni trīsdesmit četri kvadriljoni astoņi simti '
'divdesmit divi triljoni astoņi simti divdesmit četri '
'miljardi trīs simti astoņdesmit četri miljoni divi simti '
'divdesmit tūkstoši divi simti deviņdesmit viens')
self.assertEqual(
num2words(-5000, lang='lv'),
'mīnus pieci tūkstoši',
)
self.assertEqual(
num2words(-5000.22, lang='lv'),
'mīnus pieci tūkstoši komats divdesmit divi',
)
self.assertEqual(
num2words(10.02, lang='lv'),
"desmit komats nulle divi"
)
self.assertEqual(
num2words(15.007, lang='lv'),
"piecpadsmit komats nulle nulle septiņi"
)
self.assertEqual(num2words(0, lang='lv'), 'nulle')
self.assertEqual(num2words(5, lang='lv'), "pieci")
self.assertEqual(num2words(15, lang='lv'), "piecpadsmit")
self.assertEqual(num2words(154, lang='lv'), "simts piecdesmit četri")
self.assertEqual(num2words(101, lang='lv'), "simtu viens")
self.assertEqual(
num2words(1135, lang='lv'), "tūkstotis simts trīsdesmit pieci"
)
self.assertEqual(
num2words(418531, lang='lv'),
"četri simti astoņpadsmit tūkstoši pieci simti trīsdesmit viens"
)
self.assertEqual(
num2words(1000139, lang='lv'),
"miljons simts trīsdesmit deviņi"
)
def test_to_ordinal(self):
# @TODO: implement to_ordinal
with self.assertRaises(NotImplementedError):
num2words(1, lang='lv', to='ordinal')
def test_to_currency(self):
self.assertEqual(
num2words(1.0, lang='lv', to='currency', currency='EUR'),
"viens eiro, nulle centu"
)
self.assertEqual(
num2words(1.0, lang='lv', to='currency', currency='LVL'),
"viens lats, nulle santīmu"
)
self.assertEqual(
num2words(1234.56, lang='lv', to='currency', currency='EUR'),
"tūkstotis divi simti trīsdesmit četri eiro, piecdesmit seši centi"
)
self.assertEqual(
num2words(1234.56, lang='lv', to='currency', currency='LVL'),
"tūkstotis divi simti trīsdesmit četri lati, "
"piecdesmit seši santīmi"
)
self.assertEqual(
num2words(10111, lang='lv', to='currency', separator=' un',
currency='EUR'),
"simtu viens eiro un vienpadsmit centi"
)
self.assertEqual(
num2words(10121, lang='lv', to='currency', separator=' un',
currency='LVL'),
"simtu viens lats un divdesmit viens santīms"
)
self.assertEqual(
num2words(-1251985, lang='lv', to='currency', cents=False,
currency='EUR'),
"mīnus divpadsmit tūkstoši pieci simti deviņpadsmit eiro,"
" 85 centi"
)
self.assertEqual(
num2words('38.4', lang='lv', to='currency', separator=' un',
cents=False, currency='EUR'),
"trīsdesmit astoņi eiro un 40 centi"
)
# EUR legal form
self.assertEqual(
num2words('38.4', lang='lv', to='currency', separator=' un',
cents=False, currency='EUR_LEGAL'),
"trīsdesmit astoņi euro un 40 centi"
)
self.assertEqual(
num2words('38.4', lang='lv', to='currency', separator=' un',
cents=False, currency='USD', adjective=False),
"trīsdesmit astoņi dolāri un 40 centi"
)
self.assertEqual(
num2words('38.4', lang='lv', to='currency', separator=' un',
cents=False, currency='USD', adjective=True),
"trīsdesmit astoņi ASV dolāri un 40 centi"
)
def test_fractions(self):
self.assertEqual(num2words(5.2, lang='lv'), "pieci komats divi")
self.assertEqual(
num2words(561.42, lang='lv'),
"pieci simti sešdesmit viens komats četrdesmit divi"
)

132
tests/test_nl.py Normal file
View File

@@ -0,0 +1,132 @@
# -*- coding: 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 unittest import TestCase
from num2words import num2words
from num2words.lang_NL import Num2Word_NL
class Num2WordsNLTest(TestCase):
def test_ordinal_less_than_twenty(self):
self.assertEqual(num2words(7, ordinal=True, lang='nl'), "zevende")
self.assertEqual(num2words(8, ordinal=True, lang='nl'), "achtste")
self.assertEqual(num2words(12, ordinal=True, lang='nl'), "twaalfde")
self.assertEqual(num2words(17, ordinal=True, lang='nl'), "zeventiende")
def test_ordinal_more_than_twenty(self):
self.assertEqual(
num2words(81, ordinal=True, lang='nl'), "eenentachtigste"
)
def test_ordinal_at_crucial_number(self):
self.assertEqual(num2words(0, ordinal=True, lang='nl'), "nulde")
self.assertEqual(num2words(100, ordinal=True, lang='nl'), "honderdste")
self.assertEqual(
num2words(1000, ordinal=True, lang='nl'), "duizendste"
)
self.assertEqual(
num2words(4000, ordinal=True, lang='nl'), "vierduizendste"
)
self.assertEqual(
num2words(2000000, ordinal=True, lang='nl'), "twee miljoenste"
)
self.assertEqual(
num2words(5000000000, ordinal=True, lang='nl'), "vijf miljardste"
)
def test_cardinal_at_some_numbers(self):
self.assertEqual(num2words(82, lang='nl'), u'twee\xebntachtig')
self.assertEqual(num2words(1013, lang='nl'), "duizenddertien")
self.assertEqual(num2words(2000000, lang='nl'), "twee miljoen")
self.assertEqual(num2words(4000000000, lang='nl'), "vier miljard")
def test_cardinal_for_decimal_number(self):
self.assertEqual(
num2words(3.486, lang='nl'), "drie komma vier acht zes"
)
def test_ordinal_for_negative_numbers(self):
self.assertRaises(TypeError, num2words, -12, ordinal=True, lang='nl')
def test_ordinal_for_floating_numbers(self):
self.assertRaises(TypeError, num2words, 2.453, ordinal=True, lang='nl')
def test_to_currency_eur(self):
self.assertEqual(
num2words('38.4', lang='nl', to='currency', separator=' en',
cents=False, currency='EUR'),
"achtendertig euro en 40 cent"
)
self.assertEqual(
num2words('0', lang='nl', to='currency', separator=' en',
cents=False, currency='EUR'),
"nul euro en 00 cent"
)
self.assertEqual(
num2words('1.01', lang='nl', to='currency', separator=' en',
cents=True, currency='EUR'),
"één euro en één cent"
)
self.assertEqual(
num2words('4778.00', lang='nl', to='currency', separator=' en',
cents=True, currency='EUR'),
'vierduizendzevenhonderdachtenzeventig euro en nul cent')
def test_to_currency_usd(self):
self.assertEqual(
num2words('38.4', lang='nl', to='currency', separator=' en',
cents=False, currency='USD'),
"achtendertig dollar en 40 cent"
)
self.assertEqual(
num2words('0', lang='nl', to='currency', separator=' en',
cents=False, currency='USD'),
"nul dollar en 00 cent"
)
self.assertEqual(
num2words('1.01', lang='nl', to='currency', separator=' en',
cents=True, currency='USD'),
"één dollar en één cent"
)
self.assertEqual(
num2words('4778.00', lang='nl', to='currency', separator=' en',
cents=True, currency='USD'),
'vierduizendzevenhonderdachtenzeventig dollar en nul cent')
def test_pluralize(self):
n = Num2Word_NL()
# euros always singular
cr1, cr2 = n.CURRENCY_FORMS['EUR']
self.assertEqual(n.pluralize(1, cr1), 'euro')
self.assertEqual(n.pluralize(2, cr1), 'euro')
self.assertEqual(n.pluralize(1, cr2), 'cent')
self.assertEqual(n.pluralize(2, cr2), 'cent')
# @TODO other currency
def test_to_year(self):
self.assertEqual(num2words(2018, lang='nl', to='year'),
'tweeduizendachttien')
self.assertEqual(num2words(2100, lang='nl', to='year'),
'eenentwintig honderd')

Some files were not shown because too many files have changed in this diff Show More