n2words 1.23.0 → 1.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +182 -53
- package/dist/languages/ar.js +2 -0
- package/dist/languages/ar.js.map +1 -0
- package/dist/languages/az.js +2 -0
- package/dist/languages/az.js.map +1 -0
- package/dist/languages/bn.js +2 -0
- package/dist/languages/bn.js.map +1 -0
- package/dist/languages/cs.js +2 -0
- package/dist/languages/cs.js.map +1 -0
- package/dist/languages/da.js +2 -0
- package/dist/languages/da.js.map +1 -0
- package/dist/languages/de.js +2 -0
- package/dist/languages/de.js.map +1 -0
- package/dist/languages/el.js +2 -0
- package/dist/languages/el.js.map +1 -0
- package/dist/languages/en.js +2 -0
- package/dist/languages/en.js.map +1 -0
- package/dist/languages/es.js +2 -0
- package/dist/languages/es.js.map +1 -0
- package/dist/languages/fa.js +2 -0
- package/dist/languages/fa.js.map +1 -0
- package/dist/languages/fil.js +2 -0
- package/dist/languages/fil.js.map +1 -0
- package/dist/languages/fr-BE.js +2 -0
- package/dist/languages/fr-BE.js.map +1 -0
- package/dist/languages/fr.js +2 -0
- package/dist/languages/fr.js.map +1 -0
- package/dist/languages/gu.js +2 -0
- package/dist/languages/gu.js.map +1 -0
- package/dist/languages/he.js +2 -0
- package/dist/languages/he.js.map +1 -0
- package/dist/languages/hi.js +2 -0
- package/dist/languages/hi.js.map +1 -0
- package/dist/languages/hr.js +2 -0
- package/dist/languages/hr.js.map +1 -0
- package/dist/languages/hu.js +2 -0
- package/dist/languages/hu.js.map +1 -0
- package/dist/languages/id.js +2 -0
- package/dist/languages/id.js.map +1 -0
- package/dist/languages/it.js +2 -0
- package/dist/languages/it.js.map +1 -0
- package/dist/languages/ja.js +2 -0
- package/dist/languages/ja.js.map +1 -0
- package/dist/languages/kn.js +2 -0
- package/dist/languages/kn.js.map +1 -0
- package/dist/languages/ko.js +2 -0
- package/dist/languages/ko.js.map +1 -0
- package/dist/languages/lt.js +2 -0
- package/dist/languages/lt.js.map +1 -0
- package/dist/languages/lv.js +2 -0
- package/dist/languages/lv.js.map +1 -0
- package/dist/languages/mr.js +2 -0
- package/dist/languages/mr.js.map +1 -0
- package/dist/languages/ms.js +2 -0
- package/dist/languages/ms.js.map +1 -0
- package/dist/languages/nb.js +2 -0
- package/dist/languages/nb.js.map +1 -0
- package/dist/languages/nl.js +2 -0
- package/dist/languages/nl.js.map +1 -0
- package/dist/languages/pa-Guru.js +2 -0
- package/dist/languages/pa-Guru.js.map +1 -0
- package/dist/languages/pl.js +2 -0
- package/dist/languages/pl.js.map +1 -0
- package/dist/languages/pt.js +2 -0
- package/dist/languages/pt.js.map +1 -0
- package/dist/languages/ro.js +2 -0
- package/dist/languages/ro.js.map +1 -0
- package/dist/languages/ru.js +2 -0
- package/dist/languages/ru.js.map +1 -0
- package/dist/languages/sr-Latn.js +2 -0
- package/dist/languages/sr-Latn.js.map +1 -0
- package/dist/languages/sv.js +2 -0
- package/dist/languages/sv.js.map +1 -0
- package/dist/languages/sw.js +2 -0
- package/dist/languages/sw.js.map +1 -0
- package/dist/languages/ta.js +2 -0
- package/dist/languages/ta.js.map +1 -0
- package/dist/languages/te.js +2 -0
- package/dist/languages/te.js.map +1 -0
- package/dist/languages/th.js +2 -0
- package/dist/languages/th.js.map +1 -0
- package/dist/languages/tr.js +2 -0
- package/dist/languages/tr.js.map +1 -0
- package/dist/languages/uk.js +2 -0
- package/dist/languages/uk.js.map +1 -0
- package/dist/languages/ur.js +2 -0
- package/dist/languages/ur.js.map +1 -0
- package/dist/languages/vi.js +2 -0
- package/dist/languages/vi.js.map +1 -0
- package/dist/languages/zh-Hans.js +2 -0
- package/dist/languages/zh-Hans.js.map +1 -0
- package/dist/n2words.js +1 -1
- package/dist/n2words.js.map +1 -1
- package/lib/classes/abstract-language.js +211 -110
- package/lib/classes/greedy-scale-language.js +195 -0
- package/lib/classes/slavic-language.js +251 -0
- package/lib/classes/south-asian-language.js +161 -0
- package/lib/classes/turkic-language.js +63 -0
- package/lib/languages/ar.js +243 -0
- package/lib/languages/az.js +58 -0
- package/lib/languages/bn.js +126 -0
- package/lib/languages/cs.js +212 -0
- package/lib/languages/da.js +167 -0
- package/lib/languages/de.js +135 -0
- package/lib/languages/el.js +116 -0
- package/lib/languages/en.js +123 -0
- package/lib/languages/es.js +153 -0
- package/lib/languages/fa.js +127 -0
- package/lib/languages/fil.js +162 -0
- package/lib/languages/fr-BE.js +61 -0
- package/lib/languages/fr.js +145 -0
- package/lib/languages/gu.js +156 -0
- package/lib/languages/he.js +329 -0
- package/lib/languages/hi.js +126 -0
- package/lib/languages/hr.js +157 -0
- package/lib/languages/hu.js +155 -0
- package/lib/languages/id.js +174 -0
- package/lib/languages/it.js +148 -0
- package/lib/languages/ja.js +190 -0
- package/lib/languages/kn.js +71 -0
- package/lib/languages/ko.js +83 -0
- package/lib/languages/lt.js +171 -0
- package/lib/languages/lv.js +153 -0
- package/lib/languages/mr.js +156 -0
- package/lib/languages/ms.js +146 -0
- package/lib/languages/nb.js +120 -0
- package/lib/languages/nl.js +206 -0
- package/lib/languages/pa-Guru.js +126 -0
- package/lib/languages/pl.js +189 -0
- package/lib/languages/pt.js +147 -0
- package/lib/languages/ro.js +380 -0
- package/lib/languages/ru.js +116 -0
- package/lib/languages/sr-Latn.js +157 -0
- package/lib/languages/sv.js +127 -0
- package/lib/languages/sw.js +121 -0
- package/lib/languages/ta.js +226 -0
- package/lib/languages/te.js +229 -0
- package/lib/languages/th.js +123 -0
- package/lib/languages/tr.js +83 -0
- package/lib/{i18n → languages}/uk.js +50 -23
- package/lib/languages/ur.js +126 -0
- package/lib/languages/vi.js +193 -0
- package/lib/languages/zh-Hans.js +165 -0
- package/lib/n2words.js +246 -75
- package/package.json +80 -72
- package/typings/classes/abstract-language.d.ts +144 -0
- package/typings/classes/greedy-scale-language.d.ts +148 -0
- package/typings/classes/slavic-language.d.ts +145 -0
- package/typings/classes/south-asian-language.d.ts +101 -0
- package/typings/classes/turkic-language.d.ts +42 -0
- package/typings/languages/ar.d.ts +93 -0
- package/typings/languages/az.d.ts +25 -0
- package/typings/languages/bn.d.ts +1 -0
- package/typings/languages/cs.d.ts +120 -0
- package/typings/languages/da.d.ts +53 -0
- package/typings/languages/de.d.ts +26 -0
- package/typings/languages/el.d.ts +11 -0
- package/typings/languages/en.d.ts +30 -0
- package/typings/languages/es.d.ts +43 -0
- package/typings/languages/fa.d.ts +81 -0
- package/typings/languages/fil.d.ts +12 -0
- package/typings/languages/fr-BE.d.ts +41 -0
- package/typings/languages/fr.d.ts +43 -0
- package/typings/languages/gu.d.ts +12 -0
- package/typings/languages/he.d.ts +197 -0
- package/typings/languages/hi.d.ts +1 -0
- package/typings/languages/hr.d.ts +110 -0
- package/typings/languages/hu.d.ts +37 -0
- package/typings/languages/id.d.ts +69 -0
- package/typings/languages/it.d.ts +51 -0
- package/typings/languages/ja.d.ts +58 -0
- package/typings/languages/kn.d.ts +11 -0
- package/typings/languages/ko.d.ts +25 -0
- package/typings/languages/lt.d.ts +110 -0
- package/typings/languages/lv.d.ts +99 -0
- package/typings/languages/mr.d.ts +12 -0
- package/typings/languages/ms.d.ts +37 -0
- package/typings/languages/nb.d.ts +27 -0
- package/typings/languages/nl.d.ts +65 -0
- package/typings/languages/pa-Guru.d.ts +1 -0
- package/typings/languages/pl.d.ts +116 -0
- package/typings/languages/pt.d.ts +39 -0
- package/typings/languages/ro.d.ts +229 -0
- package/typings/languages/ru.d.ts +108 -0
- package/typings/languages/sr-Latn.d.ts +98 -0
- package/typings/languages/sv.d.ts +30 -0
- package/typings/languages/sw.d.ts +1 -0
- package/typings/languages/ta.d.ts +1 -0
- package/typings/languages/te.d.ts +1 -0
- package/typings/languages/th.d.ts +1 -0
- package/typings/languages/tr.d.ts +46 -0
- package/typings/languages/uk.d.ts +117 -0
- package/typings/languages/ur.d.ts +1 -0
- package/typings/languages/vi.d.ts +116 -0
- package/typings/languages/zh-Hans.d.ts +57 -0
- package/typings/n2words.d.ts +177 -0
- package/dist/ar.js +0 -2
- package/dist/ar.js.map +0 -1
- package/dist/az.js +0 -2
- package/dist/az.js.map +0 -1
- package/dist/cz.js +0 -2
- package/dist/cz.js.map +0 -1
- package/dist/de.js +0 -2
- package/dist/de.js.map +0 -1
- package/dist/dk.js +0 -2
- package/dist/dk.js.map +0 -1
- package/dist/en.js +0 -2
- package/dist/en.js.map +0 -1
- package/dist/es.js +0 -2
- package/dist/es.js.map +0 -1
- package/dist/fa.js +0 -2
- package/dist/fa.js.map +0 -1
- package/dist/fr-BE.js +0 -2
- package/dist/fr-BE.js.map +0 -1
- package/dist/fr.js +0 -2
- package/dist/fr.js.map +0 -1
- package/dist/he.js +0 -2
- package/dist/he.js.map +0 -1
- package/dist/hr.js +0 -2
- package/dist/hr.js.map +0 -1
- package/dist/hu.js +0 -2
- package/dist/hu.js.map +0 -1
- package/dist/id.js +0 -2
- package/dist/id.js.map +0 -1
- package/dist/it.js +0 -2
- package/dist/it.js.map +0 -1
- package/dist/ko.js +0 -2
- package/dist/ko.js.map +0 -1
- package/dist/lt.js +0 -2
- package/dist/lt.js.map +0 -1
- package/dist/lv.js +0 -2
- package/dist/lv.js.map +0 -1
- package/dist/n2words.d.ts +0 -2
- package/dist/nl.js +0 -2
- package/dist/nl.js.map +0 -1
- package/dist/no.js +0 -2
- package/dist/no.js.map +0 -1
- package/dist/pl.js +0 -2
- package/dist/pl.js.map +0 -1
- package/dist/pt.js +0 -2
- package/dist/pt.js.map +0 -1
- package/dist/ro.js +0 -2
- package/dist/ro.js.map +0 -1
- package/dist/ru.js +0 -2
- package/dist/ru.js.map +0 -1
- package/dist/sr.js +0 -2
- package/dist/sr.js.map +0 -1
- package/dist/tr.js +0 -2
- package/dist/tr.js.map +0 -1
- package/dist/uk.js +0 -2
- package/dist/uk.js.map +0 -1
- package/dist/vi.js +0 -2
- package/dist/vi.js.map +0 -1
- package/dist/zh.js +0 -2
- package/dist/zh.js.map +0 -1
- package/lib/classes/abstract-language.d.ts +0 -54
- package/lib/classes/base-language.d.ts +0 -58
- package/lib/classes/base-language.js +0 -172
- package/lib/i18n/ar.d.ts +0 -41
- package/lib/i18n/ar.js +0 -209
- package/lib/i18n/az.d.ts +0 -15
- package/lib/i18n/az.js +0 -66
- package/lib/i18n/cz.d.ts +0 -68
- package/lib/i18n/cz.js +0 -135
- package/lib/i18n/de.d.ts +0 -17
- package/lib/i18n/de.js +0 -103
- package/lib/i18n/dk.d.ts +0 -14
- package/lib/i18n/dk.js +0 -110
- package/lib/i18n/en.d.ts +0 -22
- package/lib/i18n/en.js +0 -86
- package/lib/i18n/es.d.ts +0 -16
- package/lib/i18n/es.js +0 -110
- package/lib/i18n/fa.d.ts +0 -54
- package/lib/i18n/fa.js +0 -106
- package/lib/i18n/fr-BE.d.ts +0 -11
- package/lib/i18n/fr-BE.js +0 -20
- package/lib/i18n/fr.d.ts +0 -15
- package/lib/i18n/fr.js +0 -99
- package/lib/i18n/he.d.ts +0 -61
- package/lib/i18n/he.js +0 -132
- package/lib/i18n/hr.d.ts +0 -68
- package/lib/i18n/hr.js +0 -129
- package/lib/i18n/hu.d.ts +0 -17
- package/lib/i18n/hu.js +0 -135
- package/lib/i18n/id.d.ts +0 -43
- package/lib/i18n/id.js +0 -156
- package/lib/i18n/it.d.ts +0 -29
- package/lib/i18n/it.js +0 -137
- package/lib/i18n/ko.d.ts +0 -15
- package/lib/i18n/ko.js +0 -56
- package/lib/i18n/lt.d.ts +0 -68
- package/lib/i18n/lt.js +0 -138
- package/lib/i18n/lv.d.ts +0 -57
- package/lib/i18n/lv.js +0 -120
- package/lib/i18n/nl.d.ts +0 -20
- package/lib/i18n/nl.js +0 -125
- package/lib/i18n/no.d.ts +0 -15
- package/lib/i18n/no.js +0 -77
- package/lib/i18n/pl.d.ts +0 -67
- package/lib/i18n/pl.js +0 -126
- package/lib/i18n/pt.d.ts +0 -26
- package/lib/i18n/pt.js +0 -118
- package/lib/i18n/ro.d.ts +0 -109
- package/lib/i18n/ro.js +0 -360
- package/lib/i18n/ru.d.ts +0 -30
- package/lib/i18n/ru.js +0 -198
- package/lib/i18n/sr.d.ts +0 -56
- package/lib/i18n/sr.js +0 -127
- package/lib/i18n/tr.d.ts +0 -15
- package/lib/i18n/tr.js +0 -64
- package/lib/i18n/uk.d.ts +0 -78
- package/lib/i18n/vi.d.ts +0 -70
- package/lib/i18n/vi.js +0 -151
- package/lib/i18n/zh.d.ts +0 -18
- package/lib/i18n/zh.js +0 -78
- package/lib/n2words.d.ts +0 -9
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import SlavicLanguage from '../classes/slavic-language.js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {Object} SlavicOptions
|
|
5
|
+
* @property {boolean} [feminine=false] Use feminine forms for numbers.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Polish language converter.
|
|
10
|
+
*
|
|
11
|
+
* Implements Polish number words using the Slavic language pattern:
|
|
12
|
+
* - Polish number words (jeden, dwa, trzy, cztery, pięć...)
|
|
13
|
+
* - Complex Slavic three-form pluralization (tysiąc/tysiące/tysięcy)
|
|
14
|
+
* - Polish-specific declension patterns
|
|
15
|
+
* - Distinctive Polish phonology and orthography
|
|
16
|
+
*
|
|
17
|
+
* Key Features:
|
|
18
|
+
* - Three-form pluralization system shared across Slavic languages
|
|
19
|
+
* * Form 1 (singular): 1 (e.g., "tysiąc")
|
|
20
|
+
* * Form 2 (few): 2-4, 22-24, 32-34... excluding teens (e.g., "tysiące")
|
|
21
|
+
* * Form 3 (many): all other numbers (e.g., "tysięcy")
|
|
22
|
+
* - Chunk-based decomposition (splits into groups of 3 digits: ones, thousands, millions, etc.)
|
|
23
|
+
* - Large number handling via thousands[] array with indexed [singular, few, many] forms
|
|
24
|
+
*
|
|
25
|
+
* Features:
|
|
26
|
+
* - Polish diacritical marks (ą, ć, ę, ł, ń, ś, ź, ż)
|
|
27
|
+
* - Gender and case agreement
|
|
28
|
+
* - Polish-specific number word endings
|
|
29
|
+
*
|
|
30
|
+
* Inherits from SlavicLanguage for complex pluralization algorithms.
|
|
31
|
+
*/
|
|
32
|
+
export class Polish extends SlavicLanguage {
|
|
33
|
+
negativeWord = 'minus'
|
|
34
|
+
decimalSeparatorWord = 'przecinek'
|
|
35
|
+
zeroWord = 'zero'
|
|
36
|
+
ones = {
|
|
37
|
+
1: 'jeden',
|
|
38
|
+
2: 'dwa',
|
|
39
|
+
3: 'trzy',
|
|
40
|
+
4: 'cztery',
|
|
41
|
+
5: 'pięć',
|
|
42
|
+
6: 'sześć',
|
|
43
|
+
7: 'siedem',
|
|
44
|
+
8: 'osiem',
|
|
45
|
+
9: 'dziewięć'
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
tens = {
|
|
49
|
+
0: 'dziesięć',
|
|
50
|
+
1: 'jedenaście',
|
|
51
|
+
2: 'dwanaście',
|
|
52
|
+
3: 'trzynaście',
|
|
53
|
+
4: 'czternaście',
|
|
54
|
+
5: 'piętnaście',
|
|
55
|
+
6: 'szesnaście',
|
|
56
|
+
7: 'siedemnaście',
|
|
57
|
+
8: 'osiemnaście',
|
|
58
|
+
9: 'dziewiętnaście'
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
twenties = {
|
|
62
|
+
2: 'dwadzieścia',
|
|
63
|
+
3: 'trzydzieści',
|
|
64
|
+
4: 'czterdzieści',
|
|
65
|
+
5: 'pięćdziesiąt',
|
|
66
|
+
6: 'sześćdziesiąt',
|
|
67
|
+
7: 'siedemdziesiąt',
|
|
68
|
+
8: 'osiemdziesiąt',
|
|
69
|
+
9: 'dziewięćdziesiąt'
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
hundreds = {
|
|
73
|
+
1: 'sto',
|
|
74
|
+
2: 'dwieście',
|
|
75
|
+
3: 'trzysta',
|
|
76
|
+
4: 'czterysta',
|
|
77
|
+
5: 'pięćset',
|
|
78
|
+
6: 'sześćset',
|
|
79
|
+
7: 'siedemset',
|
|
80
|
+
8: 'osiemset',
|
|
81
|
+
9: 'dziewięćset'
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
thousands = {
|
|
85
|
+
1: ['tysiąc', 'tysiące', 'tysięcy'], // 10^ 3
|
|
86
|
+
2: ['milion', 'miliony', 'milionów'], // 10^ 6
|
|
87
|
+
3: ['miliard', 'miliardy', 'miliardów'], // 10^ 9
|
|
88
|
+
4: ['bilion', 'biliony', 'bilionów'], // 10^ 12
|
|
89
|
+
5: ['biliard', 'biliardy', 'biliardów'], // 10^ 15
|
|
90
|
+
6: ['trylion', 'tryliony', 'trylionów'], // 10^ 18
|
|
91
|
+
7: ['tryliard', 'tryliardy', 'tryliardów'], // 10^ 21
|
|
92
|
+
8: ['kwadrylion', 'kwadryliony', 'kwadrylionów'], // 10^ 24
|
|
93
|
+
9: ['kwaryliard', 'kwadryliardy', 'kwadryliardów'], // 10^ 27
|
|
94
|
+
10: ['kwintylion', 'kwintyliony', 'kwintylionów'] // 10^ 30
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Implements Polish-specific three-form pluralization rules.
|
|
99
|
+
*
|
|
100
|
+
* Polish three-form system:
|
|
101
|
+
* - Form 1 (singular): exactly n=1 (e.g., "tysiąc")
|
|
102
|
+
* - Form 2 (few): n ends in 2-4, excluding teens (22-24, 32-34...) (e.g., "tysiące")
|
|
103
|
+
* - Form 3 (many): all other numbers (e.g., "tysięcy")
|
|
104
|
+
*
|
|
105
|
+
* @param {bigint} n The number to classify.
|
|
106
|
+
* @param {Array<string>} forms Array of [singular, few, many] word forms.
|
|
107
|
+
* @returns {string} The appropriate form for the number n.
|
|
108
|
+
*/
|
|
109
|
+
pluralize (n, forms) {
|
|
110
|
+
if (n === 1n) {
|
|
111
|
+
return forms[0]
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const lastDigit = n % 10n
|
|
115
|
+
const lastTwoDigits = n % 100n
|
|
116
|
+
|
|
117
|
+
if (lastDigit < 5n && lastDigit > 1n && (lastTwoDigits < 10n || lastTwoDigits > 20n)) {
|
|
118
|
+
return forms[1]
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return forms[2]
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Converts a whole number to Polish cardinal form.
|
|
126
|
+
*
|
|
127
|
+
* Algorithm (chunk-based decomposition):
|
|
128
|
+
* 1. Split number into chunks of 3 digits (right-to-left): ones, thousands, millions, etc.
|
|
129
|
+
* 2. For each non-zero chunk:
|
|
130
|
+
* a. Extract hundreds digit (n3), tens digit (n2), ones digit (n1)
|
|
131
|
+
* b. Add hundreds word (e.g., "sto", "dwieście")
|
|
132
|
+
* c. Add tens/ones (handles teens 10-19 separately from compound tens)
|
|
133
|
+
* d. Add pluralized magnitude word (e.g., "tysiące", "miliony")
|
|
134
|
+
* 3. Join all words with spaces
|
|
135
|
+
*
|
|
136
|
+
* Example: 1234 → chunks [1, 234] → "jeden tysiąc dwieście trzydzieści cztery"
|
|
137
|
+
* - Chunk 1 (index=1, thousands): "jeden" + "tysiąc"
|
|
138
|
+
* - Chunk 234 (index=0): "dwieście" + "trzydzieści" + "cztery"
|
|
139
|
+
*
|
|
140
|
+
* Special case: When chunk=1 at thousands+ levels, omit the ones word to avoid
|
|
141
|
+
* redundancy with the pluralized magnitude (e.g., just "tysiąc" not "jeden tysiąc").
|
|
142
|
+
*
|
|
143
|
+
* @param {bigint} number The whole number to convert.
|
|
144
|
+
* @returns {string} The number expressed in Polish words.
|
|
145
|
+
*/
|
|
146
|
+
convertWholePart (number) {
|
|
147
|
+
if (number === 0n) {
|
|
148
|
+
return this.zeroWord
|
|
149
|
+
}
|
|
150
|
+
const words = []
|
|
151
|
+
const chunks = this.splitByX(number.toString(), 3)
|
|
152
|
+
let index = chunks.length
|
|
153
|
+
for (const x of chunks) {
|
|
154
|
+
index = index - 1
|
|
155
|
+
if (x === 0n) {
|
|
156
|
+
continue
|
|
157
|
+
}
|
|
158
|
+
const [n1, n2, n3] = this.getDigits(x)
|
|
159
|
+
if (n3 > 0n) {
|
|
160
|
+
words.push(this.hundreds[n3])
|
|
161
|
+
}
|
|
162
|
+
if (n2 > 1n) {
|
|
163
|
+
words.push(this.twenties[n2])
|
|
164
|
+
}
|
|
165
|
+
if (n2 === 1n) {
|
|
166
|
+
words.push(this.tens[n1])
|
|
167
|
+
} else if (n1 > 0n && !(index > 0 && x === 1n)) {
|
|
168
|
+
words.push(this.ones[n1])
|
|
169
|
+
}
|
|
170
|
+
if (index > 0) {
|
|
171
|
+
words.push(this.pluralize(x, this.thousands[index]))
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return words.join(' ')
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Converts a number to Polish cardinal (written) form.
|
|
180
|
+
*
|
|
181
|
+
* @param {number|string|bigint} value The number to convert.
|
|
182
|
+
* @param {SlavicOptions} [options={}] Configuration options.
|
|
183
|
+
* @returns {string} The number expressed in Polish words.
|
|
184
|
+
* @throws {TypeError} If value is NaN or invalid type.
|
|
185
|
+
* @throws {Error} If value is an invalid number string.
|
|
186
|
+
*/
|
|
187
|
+
export default function convertToWords (value, options = {}) {
|
|
188
|
+
return new Polish(options).convertToWords(value)
|
|
189
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import GreedyScaleLanguage from '../classes/greedy-scale-language.js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* (European) Portuguese language converter.
|
|
5
|
+
*
|
|
6
|
+
* Features:
|
|
7
|
+
* - Gender-aware hundreds (hundredos, duzentos, etc.)
|
|
8
|
+
* - Million/Billion pluralization
|
|
9
|
+
* - "e" (and) conjunction for number combinations
|
|
10
|
+
* - Post-processing to normalize word flow
|
|
11
|
+
*/
|
|
12
|
+
export class Portuguese extends GreedyScaleLanguage {
|
|
13
|
+
negativeWord = 'menos'
|
|
14
|
+
decimalSeparatorWord = 'vírgula'
|
|
15
|
+
zeroWord = 'zero'
|
|
16
|
+
scaleWordPairs = [
|
|
17
|
+
[1_000_000_000_000_000_000_000_000n, 'quatrilião'],
|
|
18
|
+
[1_000_000_000_000_000_000n, 'trilião'],
|
|
19
|
+
[1_000_000_000_000n, 'bilião'],
|
|
20
|
+
[1_000_000n, 'milião'],
|
|
21
|
+
[1000n, 'mil'],
|
|
22
|
+
[100n, 'cem'],
|
|
23
|
+
[90n, 'noventa'],
|
|
24
|
+
[80n, 'oitenta'],
|
|
25
|
+
[70n, 'setenta'],
|
|
26
|
+
[60n, 'sessenta'],
|
|
27
|
+
[50n, 'cinquenta'],
|
|
28
|
+
[40n, 'quarenta'],
|
|
29
|
+
[30n, 'trinta'],
|
|
30
|
+
[20n, 'vinte'],
|
|
31
|
+
[19n, 'dezanove'],
|
|
32
|
+
[18n, 'dezoito'],
|
|
33
|
+
[17n, 'dezassete'],
|
|
34
|
+
[16n, 'dezasseis'],
|
|
35
|
+
[15n, 'quinze'],
|
|
36
|
+
[14n, 'catorze'],
|
|
37
|
+
[13n, 'treze'],
|
|
38
|
+
[12n, 'doze'],
|
|
39
|
+
[11n, 'onze'],
|
|
40
|
+
[10n, 'dez'],
|
|
41
|
+
[9n, 'nove'],
|
|
42
|
+
[8n, 'oito'],
|
|
43
|
+
[7n, 'sete'],
|
|
44
|
+
[6n, 'seis'],
|
|
45
|
+
[5n, 'cinco'],
|
|
46
|
+
[4n, 'quatro'],
|
|
47
|
+
[3n, 'três'],
|
|
48
|
+
[2n, 'dois'],
|
|
49
|
+
[1n, 'um'],
|
|
50
|
+
[0n, 'zero']
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
hundreds = {
|
|
54
|
+
1: 'cento',
|
|
55
|
+
2: 'duzentos',
|
|
56
|
+
3: 'trezentos',
|
|
57
|
+
4: 'quatrocentos',
|
|
58
|
+
5: 'quinhentos',
|
|
59
|
+
6: 'seiscentos',
|
|
60
|
+
7: 'setecentos',
|
|
61
|
+
8: 'oitocentos',
|
|
62
|
+
9: 'novecentos'
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Pre-compiled regex patterns for postClean - avoid recompilation
|
|
66
|
+
static POSTCLEAN_REGEX = / e (.*entos?) (?=.*e)/g
|
|
67
|
+
|
|
68
|
+
finalizeWords (words) {
|
|
69
|
+
return words.replaceAll(Portuguese.POSTCLEAN_REGEX, ' $1 ')
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Merges two adjacent word-number pairs according to Portuguese grammar rules.
|
|
74
|
+
*
|
|
75
|
+
* Portuguese-specific rules:
|
|
76
|
+
* - Implicit "um": `mergeScales({ 'um': 1n }, { 'mil': 1000n })` → `{ 'mil': 1000n }`
|
|
77
|
+
* - "e" (and) between most combinations: `mergeScales({ 'vinte': 20n }, { 'três': 3n })` → `{ 'vinte e três': 23n }`
|
|
78
|
+
* - Special handling: "cem" (100) becomes "cento" when followed by non-thousands
|
|
79
|
+
* - Gender-aware hundreds: "duzentos", "trezentos", etc.
|
|
80
|
+
* - Million pluralization: "milhões" instead of "milhão" when coefficient > 1
|
|
81
|
+
* - Post-processing with postClean() to normalize word flow
|
|
82
|
+
*
|
|
83
|
+
* @param {Object} current The left operand as `{ word: BigInt }`.
|
|
84
|
+
* @param {Object} next The right operand as `{ word: BigInt }`.
|
|
85
|
+
* @returns {Object} Merged pair with combined word and resulting numeric value.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* mergeScales({ 'um': 1n }, { 'mil': 1000n }); // { 'mil': 1000n }
|
|
89
|
+
* mergeScales({ 'vinte': 20n }, { 'dois': 2n }); // { 'vinte e dois': 22n }
|
|
90
|
+
*/
|
|
91
|
+
mergeScales (current, next) {
|
|
92
|
+
// Extract words and numeric values
|
|
93
|
+
let cText = Object.keys(current)[0]
|
|
94
|
+
let nText = Object.keys(next)[0]
|
|
95
|
+
const cNumber = Object.values(current)[0] // BigInt
|
|
96
|
+
const nNumber = Object.values(next)[0] // BigInt
|
|
97
|
+
|
|
98
|
+
// Implicit "um": omit before millions ("um milhão" → "milhão")
|
|
99
|
+
if (cNumber === 1n) {
|
|
100
|
+
if (nNumber < 1_000_000n) return { [nText]: nNumber }
|
|
101
|
+
cText = 'um'
|
|
102
|
+
} else if (cNumber === 100n && nNumber % 1000n !== 0n) {
|
|
103
|
+
// Special handling: "cem" (100) becomes "cento" when followed by non-thousands
|
|
104
|
+
cText = 'cento'
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (nNumber < cNumber) {
|
|
108
|
+
return { [`${cText} e ${nText}`]: cNumber + nNumber }
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Handle "milião" -> "milhão" conversion
|
|
112
|
+
if (nText === 'milião') nText = 'milhão'
|
|
113
|
+
|
|
114
|
+
// Pluralization logic for large numbers
|
|
115
|
+
if (cNumber > 1n) {
|
|
116
|
+
if (nNumber % 1_000_000_000n === 0n) {
|
|
117
|
+
nText = nText.replace('bilião', 'biliões')
|
|
118
|
+
} else if (nNumber % 1_000_000n === 0n) {
|
|
119
|
+
nText = nText.replace('milhão', 'milhões')
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (nNumber === 100n) {
|
|
124
|
+
cText = this.hundreds[cNumber]
|
|
125
|
+
return { [`${cText}`]: cNumber * nNumber }
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return { [`${cText} ${nText}`]: cNumber * nNumber }
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Converts a number to Portuguese cardinal (written) form.
|
|
134
|
+
*
|
|
135
|
+
* @param {number|string|bigint} value The number to convert.
|
|
136
|
+
* @param {Object} [options] Conversion options (see Portuguese class options).
|
|
137
|
+
* @returns {string} The number expressed in Portuguese words.
|
|
138
|
+
* @throws {TypeError} If value is NaN or invalid type.
|
|
139
|
+
* @throws {Error} If value is an invalid number string.
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* convertToWords(42); // 'quarenta e dois'
|
|
143
|
+
* convertToWords('100.5'); // 'cem vírgula cinco'
|
|
144
|
+
*/
|
|
145
|
+
export default function convertToWords (value, options = {}) {
|
|
146
|
+
return new Portuguese(options).convertToWords(value)
|
|
147
|
+
}
|