mirror of
https://github.com/bblaz/num2words.git
synced 2025-12-06 06:42:25 +00:00
Compare commits
567 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
67146ed02c | ||
|
|
46588097f0 | ||
|
|
931d71b4dd | ||
|
|
a7d095c97d | ||
|
|
ddf6a88af6 | ||
|
|
3ffdbec8e0 | ||
|
|
a218b332d2 | ||
|
|
01219318ab | ||
|
|
b28fb086cc | ||
|
|
5142fe851b | ||
|
|
1fd633c4df | ||
|
|
0865ac247e | ||
|
|
7c86a85d25 | ||
|
|
bb1c718906 | ||
|
|
2ee06aa086 | ||
|
|
b6a80e0e2a | ||
|
|
7109e16e73 | ||
|
|
75eec68f3e | ||
|
|
44a2b7cc2d | ||
|
|
593435f21a | ||
|
|
3dda6ee22e | ||
|
|
e4b75bb00d | ||
|
|
5878cd07fe | ||
|
|
d1fe26961c | ||
|
|
084ace67cb | ||
|
|
2ca98971e1 | ||
|
|
a7442708fa | ||
|
|
7bf80d5dd7 | ||
|
|
beb3326bbc | ||
|
|
af97683fdc | ||
|
|
5bfcebd9fb | ||
|
|
8ed54f332d | ||
|
|
83203ed98e | ||
|
|
5948065b36 | ||
|
|
a5a812d421 | ||
|
|
770cd6d1d5 | ||
|
|
736db5149e | ||
|
|
4355e11637 | ||
|
|
16229a31a4 | ||
|
|
5d1e3c7d1a | ||
|
|
4e6a573248 | ||
|
|
464f9ed7af | ||
|
|
3d2fa184cf | ||
|
|
a1f0392beb | ||
|
|
bbd9de8299 | ||
|
|
9f59c5c894 | ||
|
|
b01c44e33c | ||
|
|
c11927b353 | ||
|
|
7993ca5023 | ||
|
|
f820ee5ec1 | ||
|
|
07ea1baca2 | ||
|
|
112e91c35a | ||
|
|
f2acbc2873 | ||
|
|
2cb98d3af1 | ||
|
|
b8a215a991 | ||
|
|
12e8402da4 | ||
|
|
62eba31778 | ||
|
|
db5e1d175f | ||
|
|
d4c979ea52 | ||
|
|
0ee149a4c8 | ||
|
|
fc0c15c4b2 | ||
|
|
4afc68f233 | ||
|
|
1cea15170d | ||
|
|
a61760bd28 | ||
|
|
0b896c5c7d | ||
|
|
5a8a17d144 | ||
|
|
3b27a09a30 | ||
|
|
b5875b81f7 | ||
|
|
6bf14bee7b | ||
|
|
79a9abfaba | ||
|
|
ea82fe11ca | ||
|
|
5cb46055d7 | ||
|
|
f1cfc8e41e | ||
|
|
2039df64cf | ||
|
|
402b1e88e7 | ||
|
|
3e494d71a0 | ||
|
|
469aaff8e6 | ||
|
|
a35effbd1b | ||
|
|
1b35e7fe58 | ||
|
|
cb24e20785 | ||
|
|
9c64d48612 | ||
|
|
8db643a918 | ||
|
|
48dd5bd0f7 | ||
|
|
a05f6e5c1d | ||
|
|
605d82ec34 | ||
|
|
c19ea13145 | ||
|
|
e000cd2dab | ||
|
|
3187fa2e05 | ||
|
|
e08193a367 | ||
|
|
18b00075fc | ||
|
|
ebada15c04 | ||
|
|
0b435c427b | ||
|
|
2ced5f9458 | ||
|
|
8633c0baf2 | ||
|
|
8816154db5 | ||
|
|
2dee99ab1e | ||
|
|
540c5bdfd2 | ||
|
|
6284e71297 | ||
|
|
d8c199b00c | ||
|
|
91e6d76710 | ||
|
|
3715260bc5 | ||
|
|
e239f1a474 | ||
|
|
e3d53c3ff9 | ||
|
|
389bfd555d | ||
|
|
e8425024a6 | ||
|
|
febe8d5175 | ||
|
|
882c08b639 | ||
|
|
66fc44d5db | ||
|
|
cb22eecdc3 | ||
|
|
13c5b1c8d1 | ||
|
|
17cde9b6b8 | ||
|
|
47a4b80215 | ||
|
|
4c873a6a88 | ||
|
|
b7277ffb93 | ||
|
|
992fdf1cc3 | ||
|
|
75fdd6289f | ||
|
|
fbf7dd40ca | ||
|
|
6ea21b8200 | ||
|
|
c966c98337 | ||
|
|
c586bef2d6 | ||
|
|
60ffee907a | ||
|
|
ddc496aa69 | ||
|
|
308965bb99 | ||
|
|
d1a85b315a | ||
|
|
47d63acabf | ||
|
|
c06ff54f64 | ||
|
|
ed97e11bfb | ||
|
|
531afc86bb | ||
|
|
e9c2562509 | ||
|
|
55deaa9cbe | ||
|
|
4b13dfddb7 | ||
|
|
5e9f28c6c9 | ||
|
|
d7199522b9 | ||
|
|
d741a9d790 | ||
|
|
c40b9cf6e6 | ||
|
|
204f6e3d13 | ||
|
|
e9aa9d5606 | ||
|
|
b8a1d3168e | ||
|
|
d4d00e9277 | ||
|
|
99a647cbcc | ||
|
|
4136338554 | ||
|
|
2a0148ba4d | ||
|
|
f89306e32c | ||
|
|
4d4ca043f7 | ||
|
|
ef69a13084 | ||
|
|
72f1f88c2c | ||
|
|
bd699be047 | ||
|
|
996f5ddbd4 | ||
|
|
4f82655c74 | ||
|
|
5602246319 | ||
|
|
b60a58bc85 | ||
|
|
30f23ccd13 | ||
|
|
7d613beb9d | ||
|
|
bba96cf1fa | ||
|
|
4b6b0c7b7f | ||
|
|
edb289c3d0 | ||
|
|
b70a28dab7 | ||
|
|
5f2c988d1d | ||
|
|
31a250eb90 | ||
|
|
74ba6ee3b3 | ||
|
|
86b9a00a67 | ||
|
|
fe0d185059 | ||
|
|
84e6322006 | ||
|
|
9b62e333d7 | ||
|
|
cdb2acb052 | ||
|
|
1d98e0261e | ||
|
|
5374a0ee44 | ||
|
|
40ab739f6c | ||
|
|
1e4470bc24 | ||
|
|
8061cf3b20 | ||
|
|
3e0b89679b | ||
|
|
3f5f6163cd | ||
|
|
52dcb45ded | ||
|
|
8cc0e24596 | ||
|
|
9082085d59 | ||
|
|
21d02eaec9 | ||
|
|
a2abf77232 | ||
|
|
bc80d18203 | ||
|
|
75c1489874 | ||
|
|
94db9521b0 | ||
|
|
219c2a5eb4 | ||
|
|
0f325f8a82 | ||
|
|
5cb823af02 | ||
|
|
e6fb2b128b | ||
|
|
400917aa89 | ||
|
|
5611325b9d | ||
|
|
92158f031f | ||
|
|
3b52c5f924 | ||
|
|
6cbd81cfbb | ||
|
|
5bb2be74a2 | ||
|
|
a51b3e4d2b | ||
|
|
9a45cff4e9 | ||
|
|
ca2651ad0f | ||
|
|
b191c1fe1e | ||
|
|
003800422e | ||
|
|
d90f99d4a4 | ||
|
|
1f6ac0a7e3 | ||
|
|
f65df3fc61 | ||
|
|
e88f3d75e3 | ||
|
|
895af7dccf | ||
|
|
c95fe6260b | ||
|
|
6ea1a3da71 | ||
|
|
92a0915508 | ||
|
|
a6cae07703 | ||
|
|
47a3cac323 | ||
|
|
e5bed36054 | ||
|
|
fb7ac21089 | ||
|
|
4dab316025 | ||
|
|
ebdb52e55f | ||
|
|
7c924fe8ef | ||
|
|
c2abbbec59 | ||
|
|
3bb4ab120a | ||
|
|
d7742442c6 | ||
|
|
d576817c7f | ||
|
|
e06493ceda | ||
|
|
82418b2612 | ||
|
|
ca33d8ba98 | ||
|
|
ff9bd868ba | ||
|
|
d1c2f94132 | ||
|
|
0a88055c4a | ||
|
|
5fe8815fad | ||
|
|
af7882a7bd | ||
|
|
ff6ff0e6a6 | ||
|
|
ede0c42806 | ||
|
|
e674ce70f3 | ||
|
|
a2fe2aa4c9 | ||
|
|
432b763e1d | ||
|
|
cb9fff1189 | ||
|
|
3d14f7a5bb | ||
|
|
b594ac0513 | ||
|
|
234e02dd54 | ||
|
|
0236257876 | ||
|
|
39ef298626 | ||
|
|
3da9fd8705 | ||
|
|
fe0bc1adbd | ||
|
|
6a4e955049 | ||
|
|
739f02d830 | ||
|
|
a7971f1156 | ||
|
|
f5c07d714d | ||
|
|
2fae9512ce | ||
|
|
2c629f8349 | ||
|
|
7c6a716165 | ||
|
|
0b22ac1950 | ||
|
|
1514514ed9 | ||
|
|
8e19dd584b | ||
|
|
12ef620b29 | ||
|
|
9b8a541224 | ||
|
|
ede1db8690 | ||
|
|
ed47b30e99 | ||
|
|
dc7f7907e5 | ||
|
|
09d5da3555 | ||
|
|
b362b7b347 | ||
|
|
f665cb32f4 | ||
|
|
9943be7d71 | ||
|
|
c1e3e854bb | ||
|
|
28c304c2f4 | ||
|
|
b82bf457d4 | ||
|
|
d161b4348d | ||
|
|
6819f5a6ed | ||
|
|
d82f739bc9 | ||
|
|
7cd31a93f1 | ||
|
|
a1d29fc2bc | ||
|
|
e90061af65 | ||
|
|
601e8cee84 | ||
|
|
9290282ca2 | ||
|
|
4f116228b5 | ||
|
|
af199a472c | ||
|
|
7e893f1ef6 | ||
|
|
3cb0b40fd5 | ||
|
|
3202476d55 | ||
|
|
5e15702912 | ||
|
|
ca5989a3ec | ||
|
|
d14f3388ff | ||
|
|
4bd2f0259f | ||
|
|
b89acf6709 | ||
|
|
3c51be6c1f | ||
|
|
0283012532 | ||
|
|
607e270cad | ||
|
|
a2900faccf | ||
|
|
6b3d303332 | ||
|
|
a192afec85 | ||
|
|
bdf651d1fa | ||
|
|
e887530462 | ||
|
|
2d1a318359 | ||
|
|
cbfc8fd5d0 | ||
|
|
f6dc5a3893 | ||
|
|
f4b2bac098 | ||
|
|
a869745813 | ||
|
|
18194b52ef | ||
|
|
eef5b03593 | ||
|
|
aa9b882fe6 | ||
|
|
2eee037648 | ||
|
|
c1292c1499 | ||
|
|
e459021792 | ||
|
|
83cfcdc999 | ||
|
|
a3a0961b7d | ||
|
|
cebcaa6e64 | ||
|
|
38d2752728 | ||
|
|
67d58e7081 | ||
|
|
b71facf3ea | ||
|
|
e321caf392 | ||
|
|
df65296a80 | ||
|
|
0398d16460 | ||
|
|
778786b65b | ||
|
|
218d184583 | ||
|
|
f2fb5bc67f | ||
|
|
52fb935d8c | ||
|
|
cb55d7b91d | ||
|
|
c12131d557 | ||
|
|
53b4518afb | ||
|
|
7f125590f7 | ||
|
|
9bd1bebb0e | ||
|
|
4a0b323fa9 | ||
|
|
d78add4c3a | ||
|
|
b8cd4ba181 | ||
|
|
518ce0b606 | ||
|
|
efde954697 | ||
|
|
f26c3a139a | ||
|
|
a147dc3d34 | ||
|
|
8fde057760 | ||
|
|
562e446716 | ||
|
|
58613e0a18 | ||
|
|
fffb5c2dcf | ||
|
|
66a47e2423 | ||
|
|
4d8c93847c | ||
|
|
1ed09f511d | ||
|
|
446e918e14 | ||
|
|
5c9bce19e4 | ||
|
|
c606fd54e8 | ||
|
|
0f63859572 | ||
|
|
6d30cb9e83 | ||
|
|
ca61c77f3b | ||
|
|
3544e49376 | ||
|
|
f9107c4938 | ||
|
|
dd25a8b4bf | ||
|
|
9a31d900e3 | ||
|
|
dc733cfa1b | ||
|
|
424cf9fda8 | ||
|
|
26a2204f3b | ||
|
|
af49bb360f | ||
|
|
411a92a4fe | ||
|
|
0377347cb9 | ||
|
|
5650d2818d | ||
|
|
f09ad9afdf | ||
|
|
5f91c1420f | ||
|
|
61dd1c9a4f | ||
|
|
26fef2e116 | ||
|
|
03d44f4bc3 | ||
|
|
23902ab7c5 | ||
|
|
b541ee8d8e | ||
|
|
c71d99cddf | ||
|
|
2a99ff1061 | ||
|
|
44354bf9ce | ||
|
|
62f3cad2d6 | ||
|
|
f72c9997c6 | ||
|
|
7639f5a820 | ||
|
|
39f522f34a | ||
|
|
1ca8225ea6 | ||
|
|
e394ca6e9e | ||
|
|
f275d0fde9 | ||
|
|
8975222487 | ||
|
|
8820681169 | ||
|
|
89554ff9e2 | ||
|
|
b492530cfa | ||
|
|
551a980e54 | ||
|
|
569b29af39 | ||
|
|
ce21cb9f18 | ||
|
|
e28394d29f | ||
|
|
1a2b783d31 | ||
|
|
ab54bed93a | ||
|
|
efce631944 | ||
|
|
8ffdc5e49d | ||
|
|
9819498a14 | ||
|
|
1e954c909b | ||
|
|
1c699d1bb4 | ||
|
|
5a131fedc6 | ||
|
|
ee9f767b06 | ||
|
|
c511f499b9 | ||
|
|
a98c75e394 | ||
|
|
dde43cb4e5 | ||
|
|
a1a3c53b39 | ||
|
|
c326d59b2d | ||
|
|
f9d8868794 | ||
|
|
abae0b56a2 | ||
|
|
3da0c54f3b | ||
|
|
c6015db8b4 | ||
|
|
34d5a4cd5a | ||
|
|
14bcd99cab | ||
|
|
3788cb213a | ||
|
|
02a52aab5b | ||
|
|
168707744d | ||
|
|
7461ef6d78 | ||
|
|
f01dfa2de0 | ||
|
|
0600fbb183 | ||
|
|
6462321257 | ||
|
|
9e6015494c | ||
|
|
d65f5b10db | ||
|
|
94c73d277e | ||
|
|
e2ce7c2562 | ||
|
|
27058f5ddc | ||
|
|
55cb0ea3e9 | ||
|
|
d73acaa985 | ||
|
|
096cb45ad9 | ||
|
|
931d7063db | ||
|
|
d9aee6934f | ||
|
|
38db45cc4a | ||
|
|
34de8f7f87 | ||
|
|
e15e7486c4 | ||
|
|
2ee0e49a8b | ||
|
|
1176539b62 | ||
|
|
5d7697a85e | ||
|
|
2f3acee36f | ||
|
|
49a39fc253 | ||
|
|
659920c881 | ||
|
|
d96175b58e | ||
|
|
f1838bf2de | ||
|
|
aca6256a1f | ||
|
|
28f3d3bcff | ||
|
|
23b1961fe5 | ||
|
|
865a311437 | ||
|
|
71419ffa0e | ||
|
|
88eb77c927 | ||
|
|
b93c716597 | ||
|
|
279b63ed50 | ||
|
|
90b85a366c | ||
|
|
4b58b1ee25 | ||
|
|
7fe315eb64 | ||
|
|
63fe589b98 | ||
|
|
294d350fb9 | ||
|
|
1d580f1be7 | ||
|
|
8b12fa7dc3 | ||
|
|
77df034a70 | ||
|
|
18f906dc48 | ||
|
|
d7378f310e | ||
|
|
4047d6526a | ||
|
|
a9546c608b | ||
|
|
6dc3686116 | ||
|
|
49b9db4e56 | ||
|
|
fc05dcdd2a | ||
|
|
757daaa222 | ||
|
|
301b7ff075 | ||
|
|
849b55d95c | ||
|
|
97e1464550 | ||
|
|
c9e22ad45a | ||
|
|
614255bbde | ||
|
|
8ecd10f055 | ||
|
|
29d9d2a336 | ||
|
|
3e95697b08 | ||
|
|
873a3cc840 | ||
|
|
e6b2dbc4b9 | ||
|
|
935d95a87f | ||
|
|
c3cec93c4d | ||
|
|
5ff8e343a0 | ||
|
|
bdc9b8e8ea | ||
|
|
a235058ba6 | ||
|
|
969c5daf9b | ||
|
|
a659e63eb5 | ||
|
|
39356b495d | ||
|
|
d41b1b6b07 | ||
|
|
21db1b32c3 | ||
|
|
7f3f65d9f4 | ||
|
|
6c3e75d4c8 | ||
|
|
eea901734a | ||
|
|
7921560514 | ||
|
|
f423a9398f | ||
|
|
eb465df78a | ||
|
|
48c25da767 | ||
|
|
dd1a3f09a3 | ||
|
|
bccd3c0508 | ||
|
|
b77414053b | ||
|
|
4225663bd2 | ||
|
|
e226cf7d73 | ||
|
|
caa8903599 | ||
|
|
9028a5e90b | ||
|
|
76fd9d905f | ||
|
|
c200d97bd7 | ||
|
|
dac18f8928 | ||
|
|
fb2911deea | ||
|
|
afcaff8100 | ||
|
|
19d0a903ab | ||
|
|
91f3dc6854 | ||
|
|
ba8db25898 | ||
|
|
321dfd3bca | ||
|
|
02b73fd444 | ||
|
|
aff876c4a6 | ||
|
|
c2148d15ef | ||
|
|
90e7c9dc7d | ||
|
|
b0bca26924 | ||
|
|
905faa20fc | ||
|
|
907ebbc812 | ||
|
|
710a3b60c1 | ||
|
|
7fdb61351b | ||
|
|
4d5a114cf3 | ||
|
|
1667511ff3 | ||
|
|
c459d9ba82 | ||
|
|
94d4e85992 | ||
|
|
d586f620c5 | ||
|
|
f67d641968 | ||
|
|
f29e792757 | ||
|
|
fb281568b2 | ||
|
|
8468654d86 | ||
|
|
0f21d8f825 | ||
|
|
903a69cfa9 | ||
|
|
0b80fd4285 | ||
|
|
58a4e8e18b | ||
|
|
08e9154366 | ||
|
|
bd1f4faf1d | ||
|
|
c9ecd07cbf | ||
|
|
08779b28b2 | ||
|
|
f7f1ba4583 | ||
|
|
182b82cf1f | ||
|
|
20f634028d | ||
|
|
0e06eb81dd | ||
|
|
572789ac87 | ||
|
|
4f3891abca | ||
|
|
2207226873 | ||
|
|
273349a234 | ||
|
|
02bb4bcf13 | ||
|
|
2d18b40150 | ||
|
|
85d3c99ce5 | ||
|
|
0192259a0a | ||
|
|
f98341731e | ||
|
|
4e5c07522c | ||
|
|
a63cee01da | ||
|
|
3cafa38ddb | ||
|
|
f967e09877 | ||
|
|
89ca2b7e8c | ||
|
|
266fb9d2df | ||
|
|
071ad5177b | ||
|
|
f22b5d1ad7 | ||
|
|
d3d0af3040 | ||
|
|
b9b6a8de42 | ||
|
|
b1bbe109fc | ||
|
|
8fff34e318 | ||
|
|
cce1455846 | ||
|
|
51d34ce78e | ||
|
|
eacf57fd26 | ||
|
|
023187b3cf | ||
|
|
9baf1b9de4 | ||
|
|
995c153d47 | ||
|
|
06b3c0ee2e | ||
|
|
e8bcc0ef2d | ||
|
|
17cf62729e | ||
|
|
eeadcc7d5b | ||
|
|
3d1b8ae42c | ||
|
|
073925b1d4 | ||
|
|
1589d9bb79 | ||
|
|
01b87602c8 | ||
|
|
9d99647e17 | ||
|
|
41a97d6931 | ||
|
|
797e74d1fc | ||
|
|
848f9d26b1 | ||
|
|
fc5c0dbdde | ||
|
|
f5fc17917c | ||
|
|
c210611e79 | ||
|
|
da74847df1 | ||
|
|
f0418a3da5 | ||
|
|
97a175b212 | ||
|
|
b796aab4eb | ||
|
|
f030d7ec69 | ||
|
|
65280cd61f | ||
|
|
732ead22b9 | ||
|
|
cecf3954b1 | ||
|
|
f64a6e48be | ||
|
|
fdeb061eca | ||
|
|
90cce9a0eb | ||
|
|
08760cf4d6 |
5
.coveragerc
Normal file
5
.coveragerc
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[run]
|
||||||
|
branch = true
|
||||||
|
source =
|
||||||
|
num2words
|
||||||
|
tests
|
||||||
45
.github/workflows/ci.yml
vendored
Normal file
45
.github/workflows/ci.yml
vendored
Normal 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 }}
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,4 +1,7 @@
|
|||||||
*.pyc
|
*.pyc
|
||||||
build
|
build
|
||||||
dist
|
dist
|
||||||
|
.idea/
|
||||||
*.egg-info
|
*.egg-info
|
||||||
|
/.tox
|
||||||
|
.eggs/
|
||||||
|
|||||||
140
CHANGES.rst
140
CHANGES.rst
@@ -1,6 +1,146 @@
|
|||||||
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
|
Version 0.5.2 -- 2015/01/23
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
|
|||||||
46
CODE_OF_CONDUCT.md
Normal file
46
CODE_OF_CONDUCT.md
Normal 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
53
CONTRIBUTING.md
Normal 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
13
ISSUE_TEMPLATE.md
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
### Expected Behaviour
|
||||||
|
|
||||||
|
Fill me in ...
|
||||||
|
|
||||||
|
### Actual Behaviour
|
||||||
|
|
||||||
|
Fill me in ...
|
||||||
|
|
||||||
|
### Steps to reproduce
|
||||||
|
|
||||||
|
* step 1
|
||||||
|
* step 2
|
||||||
|
* ...
|
||||||
@@ -1 +1,4 @@
|
|||||||
include CHANGES.rst
|
include CHANGES.rst
|
||||||
|
include COPYING
|
||||||
|
include tests/*
|
||||||
|
include bin/num2words
|
||||||
|
|||||||
21
PULL_REQUEST_TEMPLATE.md
Normal file
21
PULL_REQUEST_TEMPLATE.md
Normal 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.*
|
||||||
|
|
||||||
127
README.rst
127
README.rst
@@ -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,36 +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:
|
||||||
|
|
||||||
|
* ``cardinal`` (default)
|
||||||
|
* ``ordinal``
|
||||||
|
* ``ordinal_num``
|
||||||
|
* ``year``
|
||||||
|
* ``currency``
|
||||||
|
|
||||||
**lang:** The language in which to convert the number. Supported values are:
|
**lang:** The language in which to convert the number. Supported values are:
|
||||||
|
|
||||||
* ``en`` (English, default)
|
* ``en`` (English, default)
|
||||||
* ``fr`` (French)
|
* ``am`` (Amharic)
|
||||||
|
* ``ar`` (Arabic)
|
||||||
|
* ``cz`` (Czech)
|
||||||
* ``de`` (German)
|
* ``de`` (German)
|
||||||
|
* ``dk`` (Danish)
|
||||||
|
* ``en_GB`` (English - Great Britain)
|
||||||
|
* ``en_IN`` (English - India)
|
||||||
* ``es`` (Spanish)
|
* ``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)
|
* ``lt`` (Lithuanian)
|
||||||
* ``lv`` (Latvian)
|
* ``lv`` (Latvian)
|
||||||
* ``en_GB`` (British English)
|
* ``no`` (Norwegian)
|
||||||
* ``en_IN`` (Indian English)
|
* ``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``, the code will be
|
You can supply values like ``fr_FR``; if the country doesn't exist but the
|
||||||
correctly interpreted. If you supply an unsupported language, ``NotImplementedError`` is raised.
|
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:
|
||||||
@@ -55,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
95
bin/num2words
Executable 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
7
docker-compose.yml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
version: '3.0'
|
||||||
|
services:
|
||||||
|
web:
|
||||||
|
image: python:3-alpine
|
||||||
|
command: python3 -m http.server 8080
|
||||||
|
volumes:
|
||||||
|
- .:/num2words
|
||||||
@@ -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,27 +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_EN_IN
|
lang_ES_VE, lang_FA, lang_FI, lang_FR, lang_FR_BE, lang_FR_CH,
|
||||||
from . import lang_FR
|
lang_FR_DZ, lang_HE, lang_HU, lang_ID, lang_IT, lang_JA,
|
||||||
from . import lang_DE
|
lang_KN, lang_KO, lang_KZ, lang_LT, lang_LV, lang_NL, lang_NO,
|
||||||
from . import lang_ES
|
lang_PL, lang_PT, lang_PT_BR, lang_RO, lang_RU, lang_SL,
|
||||||
from . import lang_LT
|
lang_SR, lang_SV, lang_TE, lang_TG, lang_TH, lang_TR, lang_UK,
|
||||||
from . import lang_LV
|
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(),
|
'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(),
|
'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
|
||||||
@@ -44,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)
|
||||||
|
|||||||
@@ -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,35 +40,31 @@ 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()
|
||||||
|
|
||||||
|
# uses cards
|
||||||
|
if any(hasattr(self, field) for field in
|
||||||
|
['high_numwords', 'mid_numwords', 'low_numwords']):
|
||||||
|
self.cards = OrderedDict()
|
||||||
self.set_numwords()
|
self.set_numwords()
|
||||||
|
self.MAXVAL = 1000 * list(self.cards.keys())[0]
|
||||||
self.MAXVAL = 1000 * self.cards.order[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:
|
||||||
@@ -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)
|
||||||
@@ -102,38 +114,52 @@ 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 = []
|
||||||
|
|
||||||
|
if isinstance(val, float):
|
||||||
|
high, low = self.float2tuple(val)
|
||||||
|
else:
|
||||||
try:
|
try:
|
||||||
high, low = val
|
high, low = val
|
||||||
except TypeError:
|
except TypeError:
|
||||||
high, low = divmod(val, divisor)
|
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))
|
|
||||||
|
|||||||
@@ -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):
|
try:
|
||||||
if key not in self:
|
strtype = basestring
|
||||||
self.order.append(key)
|
except NameError:
|
||||||
super(OrderedMapping, self).__setitem__(key, val)
|
strtype = str
|
||||||
|
|
||||||
def __iter__(self):
|
|
||||||
for item in self.order:
|
|
||||||
yield item
|
|
||||||
|
|
||||||
def __repr__(self):
|
def to_s(val):
|
||||||
out = ["%s: %s"%(repr(item), repr(self[item])) for item in self]
|
try:
|
||||||
out = ", ".join(out)
|
return unicode(val)
|
||||||
return "{%s}"%out
|
except NameError:
|
||||||
|
return str(val)
|
||||||
50
num2words/currency.py
Normal file
50
num2words/currency.py
Normal 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
129
num2words/lang_AM.py
Normal 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
352
num2words/lang_AR.py
Normal 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
157
num2words/lang_CZ.py
Normal 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)
|
||||||
@@ -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,64 +15,92 @@
|
|||||||
# 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:
|
||||||
@@ -86,56 +115,43 @@ class Num2Word_DE(Num2Word_EU):
|
|||||||
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
133
num2words/lang_DK.py
Normal 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)
|
||||||
@@ -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,9 +15,11 @@
|
|||||||
# 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)
|
||||||
@@ -24,9 +27,10 @@ class Num2Word_EN(lang_EU.Num2Word_EU):
|
|||||||
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"),
|
||||||
@@ -41,13 +45,19 @@ class Num2Word_EN(lang_EU.Num2Word_EU):
|
|||||||
self.ords = {"one": "first",
|
self.ords = {"one": "first",
|
||||||
"two": "second",
|
"two": "second",
|
||||||
"three": "third",
|
"three": "third",
|
||||||
|
"four": "fourth",
|
||||||
"five": "fifth",
|
"five": "fifth",
|
||||||
|
"six": "sixth",
|
||||||
|
"seven": "seventh",
|
||||||
"eight": "eighth",
|
"eight": "eighth",
|
||||||
"nine": "ninth",
|
"nine": "ninth",
|
||||||
|
"ten": "tenth",
|
||||||
|
"eleven": "eleventh",
|
||||||
"twelve": "twelfth"}
|
"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:
|
||||||
@@ -58,7 +68,6 @@ class Num2Word_EN(lang_EU.Num2Word_EU):
|
|||||||
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)
|
||||||
outwords = self.to_cardinal(value).split(" ")
|
outwords = self.to_cardinal(value).split(" ")
|
||||||
@@ -74,40 +83,28 @@ class Num2Word_EN(lang_EU.Num2Word_EU):
|
|||||||
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()
|
|
||||||
|
|||||||
@@ -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()
|
|
||||||
@@ -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()
|
|
||||||
@@ -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()
|
|
||||||
@@ -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,28 +16,11 @@
|
|||||||
# MA 02110-1301 USA
|
# MA 02110-1301 USA
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from .lang_EN import Num2Word_EN
|
from .lang_EN import Num2Word_EN
|
||||||
|
|
||||||
|
|
||||||
class Num2Word_EN_IN(Num2Word_EN):
|
class Num2Word_EN_IN(Num2Word_EN):
|
||||||
def set_high_numwords(self, high):
|
def set_high_numwords(self, high):
|
||||||
self.cards[10 ** 7] = "crore"
|
self.cards[10 ** 7] = "crore"
|
||||||
self.cards[10 ** 5] = "lakh"
|
self.cards[10 ** 5] = "lakh"
|
||||||
|
|
||||||
|
|
||||||
n2w = Num2Word_EN_IN()
|
|
||||||
to_card = n2w.to_cardinal
|
|
||||||
to_ord = n2w.to_ordinal
|
|
||||||
to_ordnum = n2w.to_ordinal_num
|
|
||||||
|
|
||||||
def main():
|
|
||||||
for val in (15000,
|
|
||||||
15*10**5,
|
|
||||||
15*10**6,
|
|
||||||
15*10**7,
|
|
||||||
15*10**8,
|
|
||||||
15*10**9,
|
|
||||||
15*10**10):
|
|
||||||
n2w.test(val)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
|
|||||||
130
num2words/lang_EO.py
Normal file
130
num2words/lang_EO.py
Normal 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]
|
||||||
@@ -1,5 +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.
|
||||||
|
|
||||||
@@ -16,36 +15,227 @@
|
|||||||
# 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
|
||||||
|
|
||||||
|
GENERIC_DOLLARS = ('dólar', 'dólares')
|
||||||
|
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'), ('tïın', 'tïı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ón"
|
|
||||||
|
|
||||||
|
|
||||||
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 = "Solo números pueden ser convertidos a palabras."
|
self.errmsg_nonnum = "type(%s) no es [long, int, float]"
|
||||||
self.errmsg_toobig = "Numero muy grande para ser convertido a palabras."
|
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"),
|
||||||
|
(30, "treinta")]
|
||||||
self.low_numwords = ["veintinueve", "veintiocho", "veintisiete",
|
self.low_numwords = ["veintinueve", "veintiocho", "veintisiete",
|
||||||
"veintiséis", "veinticinco", "veinticuatro",
|
"veintiséis", "veinticinco", "veinticuatro",
|
||||||
"veintitrés", "veintidós", "veintiuno",
|
"veintitrés", "veintidós", "veintiuno",
|
||||||
"veinte", "diecinueve", "dieciocho", "diecisiete",
|
"veinte", "diecinueve", "dieciocho", "diecisiete",
|
||||||
"dieciseis", "quince", "catorce", "trece", "doce",
|
"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",
|
||||||
@@ -81,7 +271,6 @@ class Num2Word_ES(Num2Word_EU):
|
|||||||
1e12: "trillonésim",
|
1e12: "trillonésim",
|
||||||
1e15: "cuadrilloné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
|
||||||
|
|
||||||
@@ -89,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 and not nnum == 1000:
|
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"
|
||||||
|
|
||||||
@@ -113,69 +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)
|
||||||
text = ""
|
|
||||||
try:
|
|
||||||
if value == 0:
|
if value == 0:
|
||||||
text = ""
|
text = ""
|
||||||
elif value <= 10:
|
elif value <= 10:
|
||||||
text = "%s%s" % (self.ords[value], self.gender_stem)
|
text = "%s%s" % (self.ords[value], self.gender_stem)
|
||||||
elif value <= 12:
|
elif value <= 12:
|
||||||
text = "%s%s%s" % (self.ords[10], self.gender_stem, self.to_ordinal(value - 10))
|
text = (
|
||||||
|
"%s%s%s" % (self.ords[10], self.gender_stem,
|
||||||
|
self.to_ordinal(value - 10))
|
||||||
|
)
|
||||||
elif value <= 100:
|
elif value <= 100:
|
||||||
dec = (value / 10) * 10
|
dec = (value // 10) * 10
|
||||||
text = "%s%s %s" % (self.ords[dec], self.gender_stem, self.to_ordinal(value - dec))
|
text = (
|
||||||
|
"%s%s %s" % (self.ords[dec], self.gender_stem,
|
||||||
|
self.to_ordinal(value - dec))
|
||||||
|
)
|
||||||
elif value <= 1e3:
|
elif value <= 1e3:
|
||||||
cen = (value / 100) * 100
|
cen = (value // 100) * 100
|
||||||
text = "%s%s %s" % (self.ords[cen], self.gender_stem, self.to_ordinal(value - cen))
|
text = (
|
||||||
|
"%s%s %s" % (self.ords[cen], self.gender_stem,
|
||||||
|
self.to_ordinal(value - cen))
|
||||||
|
)
|
||||||
elif value < 1e18:
|
elif value < 1e18:
|
||||||
|
# Round down to the nearest 1e(3n)
|
||||||
# dec contains the following:
|
# dec contains the following:
|
||||||
# [ 1e3, 1e6): 1e3
|
# [ 1e3, 1e6): 1e3
|
||||||
# [ 1e6, 1e9): 1e6
|
# [ 1e6, 1e9): 1e6
|
||||||
# [ 1e9, 1e12): 1e9
|
# [ 1e9, 1e12): 1e9
|
||||||
# [1e12, 1e15): 1e12
|
# [1e12, 1e15): 1e12
|
||||||
# [1e15, 1e18): 1e15
|
# [1e15, 1e18): 1e15
|
||||||
dec = 10 ** ((((len(str(int(value))) - 1) / 3 - 1) + 1) * 3)
|
dec = 1000 ** int(math.log(int(value), 1000))
|
||||||
part = int(float(value / dec) * dec)
|
|
||||||
cardinal = self.to_cardinal(part / dec) if part / dec != 1 else ""
|
# Split the parts before and after the word for 'dec'
|
||||||
text = "%s%s%s %s" % (cardinal, self.ords[dec], self.gender_stem, self.to_ordinal(value - part))
|
# 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:
|
else:
|
||||||
text = self.to_cardinal(value)
|
text = self.to_cardinal(value)
|
||||||
except KeyError:
|
|
||||||
text = self.to_cardinal(value)
|
|
||||||
return text.strip()
|
return text.strip()
|
||||||
|
|
||||||
def to_ordinal_num(self, value):
|
def to_ordinal_num(self, value):
|
||||||
self.verify_ordinal(value)
|
self.verify_ordinal(value)
|
||||||
return "%s%s" % (value, "º" if self.gender_stem == 'o' else "ª")
|
return "%s%s" % (value, "º" if self.gender_stem == 'o' else "ª")
|
||||||
|
|
||||||
|
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
29
num2words/lang_ES_CO.py
Normal 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
33
num2words/lang_ES_NI.py
Normal 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
32
num2words/lang_ES_VE.py
Normal 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")
|
||||||
@@ -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:
|
||||||
|
self.cards[10 ** (n - 3)] = word + self.MEGA_SUFFIX
|
||||||
|
|
||||||
def base_setup(self):
|
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"]
|
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
165
num2words/lang_FA.py
Normal 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
736
num2words/lang_FI.py
Normal 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]
|
||||||
@@ -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,21 +59,23 @@ 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"??
|
||||||
|
|
||||||
@@ -67,40 +84,25 @@ class Num2Word_FR(Num2Word_EU):
|
|||||||
if value == 1:
|
if value == 1:
|
||||||
return "premier"
|
return "premier"
|
||||||
word = self.to_cardinal(value)
|
word = self.to_cardinal(value)
|
||||||
|
for src, repl in self.ords.items():
|
||||||
|
if word.endswith(src):
|
||||||
|
word = word[:-len(src)] + repl
|
||||||
|
break
|
||||||
|
else:
|
||||||
if word[-1] == "e":
|
if word[-1] == "e":
|
||||||
word = word[:-1]
|
word = word[:-1]
|
||||||
return word + "ième"
|
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
49
num2words/lang_FR_BE.py
Normal 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
48
num2words/lang_FR_CH.py
Normal 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
33
num2words/lang_FR_DZ.py
Normal 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
168
num2words/lang_HE.py
Normal 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
165
num2words/lang_HU.py
Normal 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
204
num2words/lang_ID.py
Normal 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
241
num2words/lang_IT.py
Normal 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
590
num2words/lang_JA.py
Normal 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
182
num2words/lang_KN.py
Normal 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
148
num2words/lang_KO.py
Normal 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
133
num2words/lang_KZ.py
Normal 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()
|
||||||
@@ -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,154 +14,103 @@
|
|||||||
# 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
|
|
||||||
|
|
||||||
>>> print(' '.join([str(i) for i in splitby3('1')]))
|
|
||||||
1
|
|
||||||
>>> print(' '.join([str(i) for i in splitby3('1123')]))
|
|
||||||
1 123
|
|
||||||
>>> print(' '.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))
|
|
||||||
vienas šimtas
|
|
||||||
>>> print(n2w(101))
|
|
||||||
vienas šimtas vienas
|
|
||||||
>>> print(n2w(110))
|
|
||||||
vienas šimtas dešimt
|
|
||||||
>>> print(n2w(115))
|
|
||||||
vienas šimtas penkiolika
|
|
||||||
>>> print(n2w(123))
|
|
||||||
vienas šimtas dvidešimt trys
|
|
||||||
>>> print(n2w(1000))
|
|
||||||
vienas tūkstantis
|
|
||||||
>>> print(n2w(1001))
|
|
||||||
vienas tūkstantis vienas
|
|
||||||
>>> print(n2w(2012))
|
|
||||||
du tūkstančiai dvylika
|
|
||||||
|
|
||||||
>>> print(fill(n2w(1234567890)))
|
|
||||||
vienas 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 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
|
|
||||||
|
|
||||||
>>> 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'))
|
|
||||||
vienas 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ų')),
|
|
||||||
|
|
||||||
|
class Num2Word_LT(Num2Word_Base):
|
||||||
|
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 splitby3(n):
|
def setup(self):
|
||||||
length = len(n)
|
self.negword = "minus"
|
||||||
if length > 3:
|
self.pointword = "kablelis"
|
||||||
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 pluralize(self, n, forms):
|
||||||
def get_digits(n):
|
|
||||||
return [int(x) for x in reversed(list(('%03d' % n)[-3:]))]
|
|
||||||
|
|
||||||
def pluralize(n, forms):
|
|
||||||
n1, n2, n3 = get_digits(n)
|
n1, n2, n3 = get_digits(n)
|
||||||
if n2 == 1 or n1 == 0 or n == 0:
|
if n2 == 1 or n1 == 0 or n == 0:
|
||||||
return forms[2]
|
return forms[2]
|
||||||
@@ -170,16 +119,43 @@ def pluralize(n, forms):
|
|||||||
else:
|
else:
|
||||||
return forms[1]
|
return forms[1]
|
||||||
|
|
||||||
def int2word(n):
|
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 to_ordinal(self, number):
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def _cents_verbose(self, number, currency):
|
||||||
|
return self._int2word(number, currency == 'RUB')
|
||||||
|
|
||||||
|
def _int2word(self, n, feminine=False):
|
||||||
if n == 0:
|
if n == 0:
|
||||||
return ZERO[0]
|
return ZERO[0]
|
||||||
|
|
||||||
words = []
|
words = []
|
||||||
chunks = list(splitby3(str(n)))
|
chunks = list(splitbyx(str(n), 3))
|
||||||
i = len(chunks)
|
i = len(chunks)
|
||||||
|
|
||||||
for x in chunks:
|
for x in chunks:
|
||||||
i -= 1
|
i -= 1
|
||||||
|
|
||||||
|
if x == 0:
|
||||||
|
continue
|
||||||
|
|
||||||
n1, n2, n3 = get_digits(x)
|
n1, n2, n3 = get_digits(x)
|
||||||
|
|
||||||
if n3 > 0:
|
if n3 > 0:
|
||||||
@@ -195,61 +171,12 @@ def int2word(n):
|
|||||||
if n2 == 1:
|
if n2 == 1:
|
||||||
words.append(TENS[n1][0])
|
words.append(TENS[n1][0])
|
||||||
elif 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])
|
words.append(ONES[n1][0])
|
||||||
|
|
||||||
if i > 0:
|
if i > 0:
|
||||||
words.append(pluralize(x, THOUSANDS[i]))
|
words.append(self.pluralize(x, THOUSANDS[i]))
|
||||||
|
|
||||||
return ' '.join(words)
|
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:
|
|
||||||
minus = False
|
|
||||||
|
|
||||||
n = abs(n)
|
|
||||||
left = n / 100
|
|
||||||
right = n % 100
|
|
||||||
else:
|
|
||||||
n = str(n).replace(',', '.')
|
|
||||||
if '.' in n:
|
|
||||||
left, right = n.split('.')
|
|
||||||
else:
|
|
||||||
left, right = n, 0
|
|
||||||
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):
|
|
||||||
raise NotImplementedError()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
import doctest
|
|
||||||
doctest.testmod()
|
|
||||||
|
|||||||
@@ -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,191 +14,157 @@
|
|||||||
# 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')])
|
|
||||||
u'1'
|
|
||||||
>>> ' '.join([str(i) for i in splitby3('1123')])
|
|
||||||
u'1 123'
|
|
||||||
>>> ' '.join([str(i) for i in splitby3('1234567890')])
|
|
||||||
u'1 234 567 890'
|
|
||||||
|
|
||||||
>>> print(' '.join([n2w(i) for i in range(10)]))
|
|
||||||
nulle viens divi trīs četri pieci seši septiņi astoņi deviņi
|
|
||||||
|
|
||||||
>>> print(fill(' '.join([n2w(i+10) for i in range(10)])))
|
|
||||||
desmit vienpadsmit divpadsmit trīspadsmit četrpadsmit piecpadsmit
|
|
||||||
sešpadsmit septiņpadsmit astoņpadsmit deviņpadsmit
|
|
||||||
|
|
||||||
>>> print(fill(' '.join([n2w(i*10) for i in range(10)])))
|
|
||||||
nulle desmit divdesmit trīsdesmit četrdesmit piecdesmit sešdesmit
|
|
||||||
septiņdesmit astoņdesmit deviņdesmit
|
|
||||||
|
|
||||||
>>> print(n2w(100))
|
|
||||||
simts
|
|
||||||
>>> print(n2w(101))
|
|
||||||
simtu viens
|
|
||||||
>>> print(n2w(110))
|
|
||||||
simts desmit
|
|
||||||
>>> print(n2w(115))
|
|
||||||
simts piecpadsmit
|
|
||||||
>>> print(n2w(123))
|
|
||||||
simts divdesmit trīs
|
|
||||||
>>> print(n2w(1000))
|
|
||||||
tūkstotis
|
|
||||||
>>> print(n2w(1001))
|
|
||||||
tūkstotis viens
|
|
||||||
>>> print(n2w(2012))
|
|
||||||
divi tūkstoši divpadsmit
|
|
||||||
|
|
||||||
>>> print(fill(n2w(1234567890)))
|
|
||||||
miljards divi simti trīsdesmit četri miljoni pieci simti sešdesmit
|
|
||||||
septiņi tūkstoši astoņi simti deviņdesmit
|
|
||||||
|
|
||||||
>>> print(fill(n2w(215461407892039002157189883901676)))
|
|
||||||
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
|
|
||||||
|
|
||||||
>>> print(fill(n2w(719094234693663034822824384220291)))
|
|
||||||
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
|
|
||||||
|
|
||||||
# TODO: fix this:
|
|
||||||
# >>> print(fill(n2w(1000000000000000000000000000000)))
|
|
||||||
# nontiljons
|
|
||||||
|
|
||||||
>>> print(to_currency(1.0, 'EUR'))
|
|
||||||
viens eiro, nulle centu
|
|
||||||
|
|
||||||
>>> print(to_currency(1.0, 'LVL'))
|
|
||||||
viens lats, nulle santīmu
|
|
||||||
|
|
||||||
>>> print(to_currency(1234.56, 'EUR'))
|
|
||||||
tūkstotis divi simti trīsdesmit četri eiro, piecdesmit seši centi
|
|
||||||
|
|
||||||
>>> print(to_currency(1234.56, 'LVL'))
|
|
||||||
tūkstotis divi simti trīsdesmit četri lati, piecdesmit seši santīmi
|
|
||||||
|
|
||||||
>>> print(to_currency(10111, 'EUR', seperator=' un'))
|
|
||||||
simtu viens eiro un vienpadsmit centi
|
|
||||||
|
|
||||||
>>> print(to_currency(10121, 'LVL', seperator=' un'))
|
|
||||||
simtu viens lats un divdesmit viens santīms
|
|
||||||
|
|
||||||
>>> print(to_currency(-1251985, cents = False))
|
|
||||||
mīnus divpadsmit tūkstoši pieci simti deviņpadsmit eiro, 85 centi
|
|
||||||
"""
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
ZERO = (u'nulle',)
|
from .base import Num2Word_Base
|
||||||
|
from .utils import get_digits, splitbyx
|
||||||
|
|
||||||
|
ZERO = ('nulle',)
|
||||||
|
|
||||||
ONES = {
|
ONES = {
|
||||||
1: (u'viens',),
|
1: ('viens',),
|
||||||
2: (u'divi',),
|
2: ('divi',),
|
||||||
3: (u'trīs',),
|
3: ('trīs',),
|
||||||
4: (u'četri',),
|
4: ('četri',),
|
||||||
5: (u'pieci',),
|
5: ('pieci',),
|
||||||
6: (u'seši',),
|
6: ('seši',),
|
||||||
7: (u'septiņi',),
|
7: ('septiņi',),
|
||||||
8: (u'astoņi',),
|
8: ('astoņi',),
|
||||||
9: (u'deviņi',),
|
9: ('deviņi',),
|
||||||
}
|
}
|
||||||
|
|
||||||
TENS = {
|
TENS = {
|
||||||
0: (u'desmit',),
|
0: ('desmit',),
|
||||||
1: (u'vienpadsmit',),
|
1: ('vienpadsmit',),
|
||||||
2: (u'divpadsmit',),
|
2: ('divpadsmit',),
|
||||||
3: (u'trīspadsmit',),
|
3: ('trīspadsmit',),
|
||||||
4: (u'četrpadsmit',),
|
4: ('četrpadsmit',),
|
||||||
5: (u'piecpadsmit',),
|
5: ('piecpadsmit',),
|
||||||
6: (u'sešpadsmit',),
|
6: ('sešpadsmit',),
|
||||||
7: (u'septiņpadsmit',),
|
7: ('septiņpadsmit',),
|
||||||
8: (u'astoņpadsmit',),
|
8: ('astoņpadsmit',),
|
||||||
9: (u'deviņpadsmit',),
|
9: ('deviņpadsmit',),
|
||||||
}
|
}
|
||||||
|
|
||||||
TWENTIES = {
|
TWENTIES = {
|
||||||
2: (u'divdesmit',),
|
2: ('divdesmit',),
|
||||||
3: (u'trīsdesmit',),
|
3: ('trīsdesmit',),
|
||||||
4: (u'četrdesmit',),
|
4: ('četrdesmit',),
|
||||||
5: (u'piecdesmit',),
|
5: ('piecdesmit',),
|
||||||
6: (u'sešdesmit',),
|
6: ('sešdesmit',),
|
||||||
7: (u'septiņdesmit',),
|
7: ('septiņdesmit',),
|
||||||
8: (u'astoņdesmit',),
|
8: ('astoņdesmit',),
|
||||||
9: (u'deviņdesmit',),
|
9: ('deviņdesmit',),
|
||||||
}
|
}
|
||||||
|
|
||||||
HUNDRED = (u'simts', u'simti', u'simtu')
|
HUNDRED = ('simts', 'simti', 'simtu')
|
||||||
|
|
||||||
THOUSANDS = {
|
THOUSANDS = {
|
||||||
1: (u'tūkstotis', u'tūkstoši', u'tūkstošu'),
|
1: ('tūkstotis', 'tūkstoši', 'tūkstošu'),
|
||||||
2: (u'miljons', u'miljoni', u'miljonu'),
|
2: ('miljons', 'miljoni', 'miljonu'),
|
||||||
3: (u'miljards', u'miljardi', u'miljardu'),
|
3: ('miljards', 'miljardi', 'miljardu'),
|
||||||
4: (u'triljons', u'triljoni', u'triljonu'),
|
4: ('triljons', 'triljoni', 'triljonu'),
|
||||||
5: (u'kvadriljons', u'kvadriljoni', u'kvadriljonu'),
|
5: ('kvadriljons', 'kvadriljoni', 'kvadriljonu'),
|
||||||
6: (u'kvintiljons', u'kvintiljoni', u'kvintiljonu'),
|
6: ('kvintiljons', 'kvintiljoni', 'kvintiljonu'),
|
||||||
7: (u'sikstiljons', u'sikstiljoni', u'sikstiljonu'),
|
7: ('sikstiljons', 'sikstiljoni', 'sikstiljonu'),
|
||||||
8: (u'septiljons', u'septiljoni', u'septiljonu'),
|
8: ('septiljons', 'septiljoni', 'septiljonu'),
|
||||||
9: (u'oktiljons', u'oktiljoni', u'oktiljonu'),
|
9: ('oktiljons', 'oktiljoni', 'oktiljonu'),
|
||||||
10: (u'nontiljons', u'nontiljoni', u'nontiljonu'),
|
10: ('nontiljons', 'nontiljoni', 'nontiljonu'),
|
||||||
}
|
}
|
||||||
|
|
||||||
CURRENCIES = {
|
GENERIC_DOLLARS = ('dolārs', 'dolāri', 'dolāru')
|
||||||
'LVL': (
|
GENERIC_CENTS = ('cents', 'centi', 'centu')
|
||||||
(u'lats', u'lati', u'latu'), (u'santīms', u'santīmi', u'santīmu')
|
|
||||||
),
|
GENERIC_KRONA = ('krona', 'kronas', 'kronu')
|
||||||
'EUR': (
|
GENERIC_ERA = ('ēre', 'ēras', 'ēru')
|
||||||
(u'eiro', u'eiro', u'eiro'), (u'cents', u'centi', u'centu')
|
|
||||||
),
|
|
||||||
|
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 splitby3(n):
|
def setup(self):
|
||||||
length = len(n)
|
self.negword = "mīnus"
|
||||||
if length > 3:
|
self.pointword = "komats"
|
||||||
start = length % 3
|
|
||||||
if start > 0:
|
def to_cardinal(self, number):
|
||||||
yield int(n[:start])
|
n = str(number).replace(',', '.')
|
||||||
for i in range(start, length, 3):
|
base_str, n = self.parse_minus(n)
|
||||||
yield int(n[i:i+3])
|
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:
|
else:
|
||||||
yield int(n)
|
return "%s%s" % (base_str, self._int2word(int(n)))
|
||||||
|
|
||||||
|
|
||||||
def get_digits(n):
|
|
||||||
return [int(x) for x in reversed(list(('%03d' % n)[-3:]))]
|
|
||||||
|
|
||||||
|
|
||||||
def pluralize(n, forms):
|
|
||||||
# gettext implementation:
|
|
||||||
# (n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2)
|
|
||||||
|
|
||||||
|
def pluralize(self, n, forms):
|
||||||
form = 0 if (n % 10 == 1 and n % 100 != 11) else 1 if n != 0 else 2
|
form = 0 if (n % 10 == 1 and n % 100 != 11) else 1 if n != 0 else 2
|
||||||
|
|
||||||
return forms[form]
|
return forms[form]
|
||||||
|
|
||||||
|
def to_ordinal(self, number):
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
def int2word(n):
|
def _int2word(self, n):
|
||||||
if n == 0:
|
if n == 0:
|
||||||
return ZERO[0]
|
return ZERO[0]
|
||||||
|
|
||||||
words = []
|
words = []
|
||||||
chunks = list(splitby3(str(n)))
|
chunks = list(splitbyx(str(n), 3))
|
||||||
i = len(chunks)
|
i = len(chunks)
|
||||||
for x in chunks:
|
for x in chunks:
|
||||||
i -= 1
|
i -= 1
|
||||||
n1, n2, n3 = get_digits(x)
|
|
||||||
|
|
||||||
# print str(n3) + str(n2) + str(n1)
|
if x == 0:
|
||||||
|
continue
|
||||||
|
|
||||||
|
n1, n2, n3 = get_digits(x)
|
||||||
|
|
||||||
if n3 > 0:
|
if n3 > 0:
|
||||||
if n3 == 1 and n2 == 0 and n1 > 0:
|
if n3 == 1 and n2 == 0 and n1 > 0:
|
||||||
@@ -218,68 +184,6 @@ def int2word(n):
|
|||||||
words.append(ONES[n1][0])
|
words.append(ONES[n1][0])
|
||||||
|
|
||||||
if i > 0:
|
if i > 0:
|
||||||
words.append(pluralize(x, THOUSANDS[i]))
|
words.append(self.pluralize(x, THOUSANDS[i]))
|
||||||
|
|
||||||
return ' '.join(words)
|
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='EUR', cents=True, seperator=','):
|
|
||||||
if type(n) == int:
|
|
||||||
if n < 0:
|
|
||||||
minus = True
|
|
||||||
else:
|
|
||||||
minus = False
|
|
||||||
|
|
||||||
n = abs(n)
|
|
||||||
left = n / 100
|
|
||||||
right = n % 100
|
|
||||||
else:
|
|
||||||
n = str(n).replace(',', '.')
|
|
||||||
if '.' in n:
|
|
||||||
left, right = n.split('.')
|
|
||||||
else:
|
|
||||||
left, right = n, 0
|
|
||||||
left, right = int(left), int(right)
|
|
||||||
minus = False
|
|
||||||
cr1, cr2 = CURRENCIES[currency]
|
|
||||||
|
|
||||||
if minus:
|
|
||||||
minus_str = "mīnus "
|
|
||||||
else:
|
|
||||||
minus_str = ""
|
|
||||||
|
|
||||||
if cents:
|
|
||||||
cents_str = int2word(right)
|
|
||||||
else:
|
|
||||||
cents_str = "%02d" % right
|
|
||||||
|
|
||||||
return u'%s%s %s%s %s %s' % (
|
|
||||||
minus_str,
|
|
||||||
int2word(left),
|
|
||||||
pluralize(left, cr1),
|
|
||||||
seperator,
|
|
||||||
cents_str,
|
|
||||||
pluralize(right, cr2)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class Num2Word_LV(object):
|
|
||||||
def to_cardinal(self, number):
|
|
||||||
return n2w(number)
|
|
||||||
|
|
||||||
def to_ordinal(self, number):
|
|
||||||
raise NotImplementedError()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
import doctest
|
|
||||||
doctest.testmod()
|
|
||||||
|
|||||||
158
num2words/lang_NL.py
Normal file
158
num2words/lang_NL.py
Normal 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
108
num2words/lang_NO.py
Normal 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
260
num2words/lang_PL.py
Normal 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
241
num2words/lang_PT.py
Normal 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
115
num2words/lang_PT_BR.py
Normal 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
173
num2words/lang_RO.py
Normal 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
249
num2words/lang_RU.py
Normal 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
169
num2words/lang_SL.py
Normal 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
219
num2words/lang_SR.py
Normal 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
117
num2words/lang_SV.py
Normal 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
169
num2words/lang_TE.py
Normal 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
149
num2words/lang_TG.py
Normal 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
183
num2words/lang_TH.py
Normal 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
856
num2words/lang_TR.py
Normal 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
852
num2words/lang_UK.py
Normal 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
101
num2words/lang_VI.py
Normal 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
35
num2words/utils.py
Normal 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
7
requirements-test.txt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
tox
|
||||||
|
flake8
|
||||||
|
flake8-copyright
|
||||||
|
isort
|
||||||
|
pep8<1.6
|
||||||
|
coverage
|
||||||
|
delegator.py
|
||||||
72
setup.py
72
setup.py
@@ -1,33 +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.2',
|
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=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
94
tests/test_am.py
Normal 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
113
tests/test_ar.py
Normal 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
65
tests/test_base.py
Normal 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
113
tests/test_cli.py
Normal 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
63
tests/test_currency.py
Normal 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
114
tests/test_cz.py
Normal 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
170
tests/test_de.py
Normal 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
37
tests/test_dk.py
Normal 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")
|
||||||
163
tests/test_en.py
163
tests/test_en.py
@@ -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
27
tests/test_en_in.py
Normal 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
190
tests/test_eo.py
Normal 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
29
tests/test_errors.py
Normal 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
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
60
tests/test_es_co.py
Normal 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
42
tests/test_es_ni.py
Normal 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
59
tests/test_es_ve.py
Normal 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
109
tests/test_fa.py
Normal 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
2762
tests/test_fi.py
Normal file
File diff suppressed because it is too large
Load Diff
205
tests/test_fr.py
Normal file
205
tests/test_fr.py
Normal 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
129
tests/test_fr_be.py
Normal 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
127
tests/test_fr_ch.py
Normal 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
65
tests/test_fr_dz.py
Normal 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
116
tests/test_he.py
Normal 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
213
tests/test_hu.py
Normal 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
62
tests/test_id.py
Normal 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
293
tests/test_it.py
Normal 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
198
tests/test_ja.py
Normal 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
73
tests/test_kn.py
Normal 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
93
tests/test_ko.py
Normal 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
81
tests/test_kz.py
Normal 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
186
tests/test_lt.py
Normal 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
162
tests/test_lv.py
Normal 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
132
tests/test_nl.py
Normal 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
Reference in New Issue
Block a user