n2words 2.0.0 → 3.0.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/CHANGELOG.md +49 -0
- package/README.md +86 -188
- package/dist/languages/am-Latn.js +3 -0
- package/dist/languages/am-Latn.js.map +1 -0
- package/dist/languages/am.js +3 -0
- package/dist/languages/am.js.map +1 -0
- package/dist/languages/ar.js +3 -0
- package/dist/languages/ar.js.map +1 -0
- package/dist/languages/az.js +3 -0
- package/dist/languages/az.js.map +1 -0
- package/dist/languages/bn.js +3 -0
- package/dist/languages/bn.js.map +1 -0
- package/dist/languages/cs.js +3 -0
- package/dist/languages/cs.js.map +1 -0
- package/dist/languages/da.js +3 -0
- package/dist/languages/da.js.map +1 -0
- package/dist/languages/de.js +3 -0
- package/dist/languages/de.js.map +1 -0
- package/dist/languages/el.js +3 -0
- package/dist/languages/el.js.map +1 -0
- package/dist/languages/en.js +3 -0
- package/dist/languages/en.js.map +1 -0
- package/dist/languages/es.js +3 -0
- package/dist/languages/es.js.map +1 -0
- package/dist/languages/fa.js +3 -0
- package/dist/languages/fa.js.map +1 -0
- package/dist/languages/fi.js +3 -0
- package/dist/languages/fi.js.map +1 -0
- package/dist/languages/fil.js +3 -0
- package/dist/languages/fil.js.map +1 -0
- package/dist/languages/fr-BE.js +3 -0
- package/dist/languages/fr-BE.js.map +1 -0
- package/dist/languages/fr.js +3 -0
- package/dist/languages/fr.js.map +1 -0
- package/dist/languages/gu.js +3 -0
- package/dist/languages/gu.js.map +1 -0
- package/dist/languages/ha.js +3 -0
- package/dist/languages/ha.js.map +1 -0
- package/dist/languages/hbo.js +3 -0
- package/dist/languages/hbo.js.map +1 -0
- package/dist/languages/he.js +3 -0
- package/dist/languages/he.js.map +1 -0
- package/dist/languages/hi.js +3 -0
- package/dist/languages/hi.js.map +1 -0
- package/dist/languages/hr.js +3 -0
- package/dist/languages/hr.js.map +1 -0
- package/dist/languages/hu.js +3 -0
- package/dist/languages/hu.js.map +1 -0
- package/dist/languages/id.js +3 -0
- package/dist/languages/id.js.map +1 -0
- package/dist/languages/it.js +3 -0
- package/dist/languages/it.js.map +1 -0
- package/dist/languages/ja.js +3 -0
- package/dist/languages/ja.js.map +1 -0
- package/dist/languages/kn.js +3 -0
- package/dist/languages/kn.js.map +1 -0
- package/dist/languages/ko.js +3 -0
- package/dist/languages/ko.js.map +1 -0
- package/dist/languages/lt.js +3 -0
- package/dist/languages/lt.js.map +1 -0
- package/dist/languages/lv.js +3 -0
- package/dist/languages/lv.js.map +1 -0
- package/dist/languages/mr.js +3 -0
- package/dist/languages/mr.js.map +1 -0
- package/dist/languages/ms.js +3 -0
- package/dist/languages/ms.js.map +1 -0
- package/dist/languages/nb.js +3 -0
- package/dist/languages/nb.js.map +1 -0
- package/dist/languages/nl.js +3 -0
- package/dist/languages/nl.js.map +1 -0
- package/dist/languages/pa.js +3 -0
- package/dist/languages/pa.js.map +1 -0
- package/dist/languages/pl.js +3 -0
- package/dist/languages/pl.js.map +1 -0
- package/dist/languages/pt.js +3 -0
- package/dist/languages/pt.js.map +1 -0
- package/dist/languages/ro.js +3 -0
- package/dist/languages/ro.js.map +1 -0
- package/dist/languages/ru.js +3 -0
- package/dist/languages/ru.js.map +1 -0
- package/dist/languages/sr-Cyrl.js +3 -0
- package/dist/languages/sr-Cyrl.js.map +1 -0
- package/dist/languages/sr-Latn.js +3 -0
- package/dist/languages/sr-Latn.js.map +1 -0
- package/dist/languages/sv.js +3 -0
- package/dist/languages/sv.js.map +1 -0
- package/dist/languages/sw.js +3 -0
- package/dist/languages/sw.js.map +1 -0
- package/dist/languages/ta.js +3 -0
- package/dist/languages/ta.js.map +1 -0
- package/dist/languages/te.js +3 -0
- package/dist/languages/te.js.map +1 -0
- package/dist/languages/th.js +3 -0
- package/dist/languages/th.js.map +1 -0
- package/dist/languages/tr.js +3 -0
- package/dist/languages/tr.js.map +1 -0
- package/dist/languages/uk.js +3 -0
- package/dist/languages/uk.js.map +1 -0
- package/dist/languages/ur.js +3 -0
- package/dist/languages/ur.js.map +1 -0
- package/dist/languages/vi.js +3 -0
- package/dist/languages/vi.js.map +1 -0
- package/dist/languages/zh-Hans.js +3 -0
- package/dist/languages/zh-Hans.js.map +1 -0
- package/dist/languages/zh-Hant.js +3 -0
- package/dist/languages/zh-Hant.js.map +1 -0
- package/dist/n2words.js +2 -2
- package/dist/n2words.js.map +1 -1
- package/lib/languages/am-Latn.d.ts +7 -0
- package/lib/languages/am-Latn.js +164 -0
- package/lib/languages/am.d.ts +7 -0
- package/lib/languages/am.js +164 -0
- package/lib/languages/ar.d.ts +14 -27
- package/lib/languages/ar.js +175 -129
- package/lib/languages/az.d.ts +4 -9
- package/lib/languages/az.js +171 -37
- package/lib/languages/bn.d.ts +4 -8
- package/lib/languages/bn.js +138 -124
- package/lib/languages/cs.d.ts +15 -85
- package/lib/languages/cs.js +310 -114
- package/lib/languages/da.d.ts +11 -12
- package/lib/languages/da.js +276 -101
- package/lib/languages/de.d.ts +14 -11
- package/lib/languages/de.js +317 -86
- package/lib/languages/el.d.ts +11 -11
- package/lib/languages/el.js +231 -78
- package/lib/languages/en.d.ts +14 -13
- package/lib/languages/en.js +242 -72
- package/lib/languages/es.d.ts +18 -12
- package/lib/languages/es.js +317 -103
- package/lib/languages/fa.d.ts +4 -44
- package/lib/languages/fa.js +112 -122
- package/lib/languages/fi.d.ts +14 -0
- package/lib/languages/fi.js +245 -0
- package/lib/languages/fil.d.ts +4 -13
- package/lib/languages/fil.js +207 -106
- package/lib/languages/fr-BE.d.ts +8 -8
- package/lib/languages/fr-BE.js +294 -19
- package/lib/languages/fr.d.ts +18 -12
- package/lib/languages/fr.js +352 -89
- package/lib/languages/gu.d.ts +4 -8
- package/lib/languages/gu.js +130 -125
- package/lib/languages/ha.d.ts +7 -0
- package/lib/languages/ha.js +230 -0
- package/lib/languages/hbo.d.ts +10 -110
- package/lib/languages/hbo.js +263 -214
- package/lib/languages/he.d.ts +10 -77
- package/lib/languages/he.js +242 -172
- package/lib/languages/hi.d.ts +4 -8
- package/lib/languages/hi.js +138 -124
- package/lib/languages/hr.d.ts +8 -77
- package/lib/languages/hr.js +194 -89
- package/lib/languages/hu.d.ts +4 -19
- package/lib/languages/hu.js +198 -119
- package/lib/languages/id.d.ts +4 -34
- package/lib/languages/id.js +171 -129
- package/lib/languages/it.d.ts +16 -34
- package/lib/languages/it.js +339 -94
- package/lib/languages/ja.d.ts +14 -14
- package/lib/languages/ja.js +233 -111
- package/lib/languages/kn.d.ts +4 -8
- package/lib/languages/kn.js +130 -35
- package/lib/languages/ko.d.ts +11 -11
- package/lib/languages/ko.js +257 -49
- package/lib/languages/lt.d.ts +15 -67
- package/lib/languages/lt.js +296 -122
- package/lib/languages/lv.d.ts +15 -67
- package/lib/languages/lv.js +297 -106
- package/lib/languages/mr.d.ts +4 -8
- package/lib/languages/mr.js +130 -125
- package/lib/languages/ms.d.ts +4 -28
- package/lib/languages/ms.js +171 -116
- package/lib/languages/nb.d.ts +11 -9
- package/lib/languages/nb.js +282 -87
- package/lib/languages/nl.d.ts +23 -13
- package/lib/languages/nl.js +317 -133
- package/lib/languages/pa.d.ts +4 -8
- package/lib/languages/pa.js +156 -124
- package/lib/languages/pl.d.ts +19 -77
- package/lib/languages/pl.js +307 -87
- package/lib/languages/pt.d.ts +14 -26
- package/lib/languages/pt.js +286 -92
- package/lib/languages/ro.d.ts +15 -155
- package/lib/languages/ro.js +219 -235
- package/lib/languages/ru.d.ts +8 -82
- package/lib/languages/ru.js +222 -78
- package/lib/languages/sr-Cyrl.d.ts +8 -77
- package/lib/languages/sr-Cyrl.js +191 -89
- package/lib/languages/sr-Latn.d.ts +8 -77
- package/lib/languages/sr-Latn.js +191 -89
- package/lib/languages/sv.d.ts +11 -11
- package/lib/languages/sv.js +288 -74
- package/lib/languages/sw.d.ts +4 -36
- package/lib/languages/sw.js +133 -106
- package/lib/languages/ta.d.ts +4 -17
- package/lib/languages/ta.js +129 -201
- package/lib/languages/te.d.ts +4 -19
- package/lib/languages/te.js +141 -196
- package/lib/languages/th.d.ts +4 -14
- package/lib/languages/th.js +135 -91
- package/lib/languages/tr.d.ts +15 -9
- package/lib/languages/tr.js +256 -49
- package/lib/languages/uk.d.ts +8 -82
- package/lib/languages/uk.js +200 -78
- package/lib/languages/ur.d.ts +4 -8
- package/lib/languages/ur.js +156 -124
- package/lib/languages/vi.d.ts +14 -69
- package/lib/languages/vi.js +294 -125
- package/lib/languages/zh-Hans.d.ts +8 -18
- package/lib/languages/zh-Hans.js +163 -92
- package/lib/languages/zh-Hant.d.ts +8 -18
- package/lib/languages/zh-Hant.js +181 -90
- package/lib/n2words.d.ts +53 -209
- package/lib/n2words.js +111 -530
- package/lib/utils/is-plain-object.d.ts +13 -0
- package/lib/utils/is-plain-object.js +17 -0
- package/lib/utils/parse-numeric.d.ts +17 -0
- package/lib/utils/parse-numeric.js +108 -0
- package/lib/utils/validate-options.d.ts +8 -0
- package/lib/utils/validate-options.js +16 -0
- package/package.json +26 -14
- package/dist/ArabicConverter.js +0 -3
- package/dist/ArabicConverter.js.map +0 -1
- package/dist/AzerbaijaniConverter.js +0 -3
- package/dist/AzerbaijaniConverter.js.map +0 -1
- package/dist/BanglaConverter.js +0 -3
- package/dist/BanglaConverter.js.map +0 -1
- package/dist/BiblicalHebrewConverter.js +0 -3
- package/dist/BiblicalHebrewConverter.js.map +0 -1
- package/dist/CroatianConverter.js +0 -3
- package/dist/CroatianConverter.js.map +0 -1
- package/dist/CzechConverter.js +0 -3
- package/dist/CzechConverter.js.map +0 -1
- package/dist/DanishConverter.js +0 -3
- package/dist/DanishConverter.js.map +0 -1
- package/dist/DutchConverter.js +0 -3
- package/dist/DutchConverter.js.map +0 -1
- package/dist/EnglishConverter.js +0 -3
- package/dist/EnglishConverter.js.map +0 -1
- package/dist/FilipinoConverter.js +0 -3
- package/dist/FilipinoConverter.js.map +0 -1
- package/dist/FrenchBelgiumConverter.js +0 -3
- package/dist/FrenchBelgiumConverter.js.map +0 -1
- package/dist/FrenchConverter.js +0 -3
- package/dist/FrenchConverter.js.map +0 -1
- package/dist/GermanConverter.js +0 -3
- package/dist/GermanConverter.js.map +0 -1
- package/dist/GreekConverter.js +0 -3
- package/dist/GreekConverter.js.map +0 -1
- package/dist/GujaratiConverter.js +0 -3
- package/dist/GujaratiConverter.js.map +0 -1
- package/dist/HebrewConverter.js +0 -3
- package/dist/HebrewConverter.js.map +0 -1
- package/dist/HindiConverter.js +0 -3
- package/dist/HindiConverter.js.map +0 -1
- package/dist/HungarianConverter.js +0 -3
- package/dist/HungarianConverter.js.map +0 -1
- package/dist/IndonesianConverter.js +0 -3
- package/dist/IndonesianConverter.js.map +0 -1
- package/dist/ItalianConverter.js +0 -3
- package/dist/ItalianConverter.js.map +0 -1
- package/dist/JapaneseConverter.js +0 -3
- package/dist/JapaneseConverter.js.map +0 -1
- package/dist/KannadaConverter.js +0 -3
- package/dist/KannadaConverter.js.map +0 -1
- package/dist/KoreanConverter.js +0 -3
- package/dist/KoreanConverter.js.map +0 -1
- package/dist/LatvianConverter.js +0 -3
- package/dist/LatvianConverter.js.map +0 -1
- package/dist/LithuanianConverter.js +0 -3
- package/dist/LithuanianConverter.js.map +0 -1
- package/dist/MalayConverter.js +0 -3
- package/dist/MalayConverter.js.map +0 -1
- package/dist/MarathiConverter.js +0 -3
- package/dist/MarathiConverter.js.map +0 -1
- package/dist/NorwegianBokmalConverter.js +0 -3
- package/dist/NorwegianBokmalConverter.js.map +0 -1
- package/dist/PersianConverter.js +0 -3
- package/dist/PersianConverter.js.map +0 -1
- package/dist/PolishConverter.js +0 -3
- package/dist/PolishConverter.js.map +0 -1
- package/dist/PortugueseConverter.js +0 -3
- package/dist/PortugueseConverter.js.map +0 -1
- package/dist/PunjabiConverter.js +0 -3
- package/dist/PunjabiConverter.js.map +0 -1
- package/dist/RomanianConverter.js +0 -3
- package/dist/RomanianConverter.js.map +0 -1
- package/dist/RussianConverter.js +0 -3
- package/dist/RussianConverter.js.map +0 -1
- package/dist/SerbianCyrillicConverter.js +0 -3
- package/dist/SerbianCyrillicConverter.js.map +0 -1
- package/dist/SerbianLatinConverter.js +0 -3
- package/dist/SerbianLatinConverter.js.map +0 -1
- package/dist/SimplifiedChineseConverter.js +0 -3
- package/dist/SimplifiedChineseConverter.js.map +0 -1
- package/dist/SpanishConverter.js +0 -3
- package/dist/SpanishConverter.js.map +0 -1
- package/dist/SwahiliConverter.js +0 -3
- package/dist/SwahiliConverter.js.map +0 -1
- package/dist/SwedishConverter.js +0 -3
- package/dist/SwedishConverter.js.map +0 -1
- package/dist/TamilConverter.js +0 -3
- package/dist/TamilConverter.js.map +0 -1
- package/dist/TeluguConverter.js +0 -3
- package/dist/TeluguConverter.js.map +0 -1
- package/dist/ThaiConverter.js +0 -3
- package/dist/ThaiConverter.js.map +0 -1
- package/dist/TraditionalChineseConverter.js +0 -3
- package/dist/TraditionalChineseConverter.js.map +0 -1
- package/dist/TurkishConverter.js +0 -3
- package/dist/TurkishConverter.js.map +0 -1
- package/dist/UkrainianConverter.js +0 -3
- package/dist/UkrainianConverter.js.map +0 -1
- package/dist/UrduConverter.js +0 -3
- package/dist/UrduConverter.js.map +0 -1
- package/dist/VietnameseConverter.js +0 -3
- package/dist/VietnameseConverter.js.map +0 -1
- package/lib/classes/abstract-language.d.ts +0 -178
- package/lib/classes/abstract-language.js +0 -268
- package/lib/classes/greedy-scale-language.d.ts +0 -109
- package/lib/classes/greedy-scale-language.js +0 -201
- package/lib/classes/slavic-language.d.ts +0 -148
- package/lib/classes/slavic-language.js +0 -281
- package/lib/classes/south-asian-language.d.ts +0 -70
- package/lib/classes/south-asian-language.js +0 -154
- package/lib/classes/turkic-language.d.ts +0 -26
- package/lib/classes/turkic-language.js +0 -59
package/lib/languages/sr-Cyrl.js
CHANGED
|
@@ -1,113 +1,215 @@
|
|
|
1
|
-
import { SlavicLanguage } from '../classes/slavic-language.js'
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
|
-
* Serbian language converter
|
|
2
|
+
* Serbian Cyrillic language converter - Functional Implementation
|
|
3
|
+
*
|
|
4
|
+
* Self-contained converter using shared Slavic utilities.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
6
|
+
* Key features:
|
|
7
7
|
* - Three-form pluralization (one/few/many)
|
|
8
|
-
* - Gender
|
|
9
|
-
* -
|
|
8
|
+
* - Gender: thousands are feminine, millions+ are masculine
|
|
9
|
+
* - Irregular hundreds
|
|
10
|
+
* - Long scale naming with -ard forms
|
|
11
|
+
* - Cyrillic script
|
|
10
12
|
*/
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
13
|
+
|
|
14
|
+
import { parseNumericValue } from '../utils/parse-numeric.js'
|
|
15
|
+
import { validateOptions } from '../utils/validate-options.js'
|
|
16
|
+
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// Slavic Utilities (inlined for performance)
|
|
19
|
+
// ============================================================================
|
|
20
|
+
|
|
21
|
+
function pluralize (n, forms) {
|
|
22
|
+
const num = typeof n === 'bigint' ? Number(n) : n
|
|
23
|
+
const lastDigit = num % 10
|
|
24
|
+
const lastTwoDigits = num % 100
|
|
25
|
+
|
|
26
|
+
if (lastTwoDigits >= 11 && lastTwoDigits <= 19) {
|
|
27
|
+
return forms[2]
|
|
26
28
|
}
|
|
27
29
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
30
|
+
if (lastDigit === 1) return forms[0]
|
|
31
|
+
if (lastDigit >= 2 && lastDigit <= 4) return forms[1]
|
|
32
|
+
return forms[2]
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function buildAllSegments (onesMasc, onesFem, teens, tens, hundreds) {
|
|
36
|
+
const masc = new Array(1000)
|
|
37
|
+
const fem = new Array(1000)
|
|
38
|
+
|
|
39
|
+
for (let i = 0; i < 1000; i++) {
|
|
40
|
+
masc[i] = buildSegment(i, onesMasc, teens, tens, hundreds)
|
|
41
|
+
fem[i] = buildSegment(i, onesFem, teens, tens, hundreds)
|
|
38
42
|
}
|
|
39
43
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
44
|
+
return { masc, fem }
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function buildSegment (n, ones, teens, tens, hundreds) {
|
|
48
|
+
if (n === 0) return ''
|
|
49
|
+
|
|
50
|
+
const onesDigit = n % 10
|
|
51
|
+
const tensDigit = Math.floor(n / 10) % 10
|
|
52
|
+
const hundredsDigit = Math.floor(n / 100)
|
|
53
|
+
|
|
54
|
+
const parts = []
|
|
55
|
+
|
|
56
|
+
if (hundredsDigit > 0) {
|
|
57
|
+
parts.push(hundreds[hundredsDigit])
|
|
51
58
|
}
|
|
52
59
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
3: 'тридесет',
|
|
56
|
-
4: 'четрдесет',
|
|
57
|
-
5: 'педесет',
|
|
58
|
-
6: 'шездесет',
|
|
59
|
-
7: 'седамдесет',
|
|
60
|
-
8: 'осамдесет',
|
|
61
|
-
9: 'деведесет'
|
|
60
|
+
if (tensDigit > 1) {
|
|
61
|
+
parts.push(tens[tensDigit])
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
4: 'четиристо',
|
|
69
|
-
5: 'петсто',
|
|
70
|
-
6: 'шесто',
|
|
71
|
-
7: 'седамсто',
|
|
72
|
-
8: 'осамсто',
|
|
73
|
-
9: 'девестo'
|
|
64
|
+
if (tensDigit === 1) {
|
|
65
|
+
parts.push(teens[onesDigit])
|
|
66
|
+
} else if (onesDigit > 0) {
|
|
67
|
+
parts.push(ones[onesDigit])
|
|
74
68
|
}
|
|
75
69
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
70
|
+
return parts.join(' ')
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ============================================================================
|
|
74
|
+
// Vocabulary
|
|
75
|
+
// ============================================================================
|
|
76
|
+
|
|
77
|
+
const ONES_MASC = ['', 'један', 'два', 'три', 'четири', 'пет', 'шест', 'седам', 'осам', 'девет']
|
|
78
|
+
const ONES_FEM = ['', 'једна', 'две', 'три', 'четири', 'пет', 'шест', 'седам', 'осам', 'девет']
|
|
79
|
+
const TEENS = ['десет', 'једанаест', 'дванаест', 'тринаест', 'четрнаест', 'петнаест', 'шеснаест', 'седамнаест', 'осамнаест', 'деветнаест']
|
|
80
|
+
const TENS = ['', '', 'двадесет', 'тридесет', 'четрдесет', 'педесет', 'шездесет', 'седамдесет', 'осамдесет', 'деведесет']
|
|
81
|
+
const HUNDREDS = ['', 'сто', 'двеста', 'триста', 'четиристо', 'петсто', 'шесто', 'седамсто', 'осамсто', 'девестo']
|
|
82
|
+
|
|
83
|
+
const ZERO = 'нула'
|
|
84
|
+
const NEGATIVE = 'минус'
|
|
85
|
+
const DECIMAL_SEP = 'запета'
|
|
86
|
+
|
|
87
|
+
// Scale words: [singular, few, many]
|
|
88
|
+
const SCALE_FORMS = [
|
|
89
|
+
['хиљада', 'хиљаде', 'хиљада'],
|
|
90
|
+
['милион', 'милиона', 'милиона'],
|
|
91
|
+
['милијарда', 'милијарде', 'милијарда'],
|
|
92
|
+
['билион', 'билиона', 'билиона'],
|
|
93
|
+
['билијарда', 'билијарде', 'билијарда'],
|
|
94
|
+
['трилион', 'трилиона', 'трилиона'],
|
|
95
|
+
['трилијарда', 'трилијарде', 'трилијарда'],
|
|
96
|
+
['квадрилион', 'квадрилиона', 'квадрилиона'],
|
|
97
|
+
['квадрилијарда', 'квадрилијарде', 'квадрилијарда']
|
|
98
|
+
]
|
|
99
|
+
|
|
100
|
+
// ============================================================================
|
|
101
|
+
// Precomputed Lookup Tables
|
|
102
|
+
// ============================================================================
|
|
103
|
+
|
|
104
|
+
const { masc: SEGMENTS_MASC, fem: SEGMENTS_FEM } = buildAllSegments(ONES_MASC, ONES_FEM, TEENS, TENS, HUNDREDS)
|
|
105
|
+
|
|
106
|
+
// ============================================================================
|
|
107
|
+
// Conversion Functions
|
|
108
|
+
// ============================================================================
|
|
109
|
+
|
|
110
|
+
function integerToWords (n, options = {}) {
|
|
111
|
+
if (n === 0n) return ZERO
|
|
112
|
+
|
|
113
|
+
if (n < 1000n) {
|
|
114
|
+
const segments = options.gender === 'feminine' ? SEGMENTS_FEM : SEGMENTS_MASC
|
|
115
|
+
return segments[Number(n)]
|
|
87
116
|
}
|
|
88
117
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
118
|
+
return buildLargeNumberWords(n, options)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function buildLargeNumberWords (n, options) {
|
|
122
|
+
const numStr = n.toString()
|
|
123
|
+
const len = numStr.length
|
|
124
|
+
|
|
125
|
+
const segments = []
|
|
126
|
+
const segmentSize = 3
|
|
127
|
+
|
|
128
|
+
const remainderLen = len % segmentSize
|
|
129
|
+
let pos = 0
|
|
130
|
+
if (remainderLen > 0) {
|
|
131
|
+
segments.push(Number(numStr.slice(0, remainderLen)))
|
|
132
|
+
pos = remainderLen
|
|
133
|
+
}
|
|
134
|
+
while (pos < len) {
|
|
135
|
+
segments.push(Number(numStr.slice(pos, pos + segmentSize)))
|
|
136
|
+
pos += segmentSize
|
|
96
137
|
}
|
|
97
138
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
const lastDigit = n % 10n
|
|
101
|
-
const lastTwoDigits = n % 100n
|
|
139
|
+
const parts = []
|
|
140
|
+
let scaleIndex = segments.length - 1
|
|
102
141
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
142
|
+
for (let i = 0; i < segments.length; i++) {
|
|
143
|
+
const segment = segments[i]
|
|
106
144
|
|
|
107
|
-
if (
|
|
108
|
-
|
|
145
|
+
if (segment !== 0) {
|
|
146
|
+
if (scaleIndex === 0) {
|
|
147
|
+
const segmentWords = options.gender === 'feminine' ? SEGMENTS_FEM : SEGMENTS_MASC
|
|
148
|
+
parts.push(segmentWords[segment])
|
|
149
|
+
} else {
|
|
150
|
+
const scaleForms = SCALE_FORMS[scaleIndex - 1]
|
|
151
|
+
const scaleWord = pluralize(segment, scaleForms)
|
|
152
|
+
// Thousands (scaleIndex=1) are feminine, others masculine
|
|
153
|
+
const isFeminine = scaleIndex === 1
|
|
154
|
+
const segmentWords = isFeminine ? SEGMENTS_FEM : SEGMENTS_MASC
|
|
155
|
+
parts.push(segmentWords[segment] + ' ' + scaleWord)
|
|
156
|
+
}
|
|
109
157
|
}
|
|
110
158
|
|
|
111
|
-
|
|
159
|
+
scaleIndex--
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return parts.join(' ')
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function decimalPartToWords (decimalPart, options) {
|
|
166
|
+
let result = ''
|
|
167
|
+
let i = 0
|
|
168
|
+
|
|
169
|
+
while (i < decimalPart.length && decimalPart[i] === '0') {
|
|
170
|
+
if (result) result += ' '
|
|
171
|
+
result += ZERO
|
|
172
|
+
i++
|
|
112
173
|
}
|
|
174
|
+
|
|
175
|
+
const remainder = decimalPart.slice(i)
|
|
176
|
+
if (remainder) {
|
|
177
|
+
if (result) result += ' '
|
|
178
|
+
result += integerToWords(BigInt(remainder), options)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return result
|
|
113
182
|
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Converts a numeric value to Serbian (Cyrillic) words.
|
|
186
|
+
*
|
|
187
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
188
|
+
* @param {Object} [options] - Optional configuration
|
|
189
|
+
* @param {('masculine'|'feminine')} [options.gender='masculine'] - Grammatical gender
|
|
190
|
+
* @returns {string} The number in Serbian Cyrillic words
|
|
191
|
+
*/
|
|
192
|
+
function toWords (value, options) {
|
|
193
|
+
options = validateOptions(options)
|
|
194
|
+
const { isNegative, integerPart, decimalPart } = parseNumericValue(value)
|
|
195
|
+
|
|
196
|
+
let result = ''
|
|
197
|
+
|
|
198
|
+
if (isNegative) {
|
|
199
|
+
result = NEGATIVE + ' '
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
result += integerToWords(integerPart, options)
|
|
203
|
+
|
|
204
|
+
if (decimalPart) {
|
|
205
|
+
result += ' ' + DECIMAL_SEP + ' ' + decimalPartToWords(decimalPart, options)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return result
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// ============================================================================
|
|
212
|
+
// Exports
|
|
213
|
+
// ============================================================================
|
|
214
|
+
|
|
215
|
+
export { toWords }
|
|
@@ -1,80 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Serbian Latin
|
|
2
|
+
* Converts a numeric value to Serbian (Latin) words.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
5
|
+
* @param {Object} [options] - Optional configuration
|
|
6
|
+
* @param {('masculine'|'feminine')} [options.gender='masculine'] - Grammatical gender
|
|
7
|
+
* @returns {string} The number in Serbian Latin words
|
|
8
8
|
*/
|
|
9
|
-
export
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
2: string;
|
|
13
|
-
3: string;
|
|
14
|
-
4: string;
|
|
15
|
-
5: string;
|
|
16
|
-
6: string;
|
|
17
|
-
7: string;
|
|
18
|
-
8: string;
|
|
19
|
-
9: string;
|
|
20
|
-
};
|
|
21
|
-
onesFeminineWords: {
|
|
22
|
-
1: string;
|
|
23
|
-
2: string;
|
|
24
|
-
3: string;
|
|
25
|
-
4: string;
|
|
26
|
-
5: string;
|
|
27
|
-
6: string;
|
|
28
|
-
7: string;
|
|
29
|
-
8: string;
|
|
30
|
-
9: string;
|
|
31
|
-
};
|
|
32
|
-
teensWords: {
|
|
33
|
-
0: string;
|
|
34
|
-
1: string;
|
|
35
|
-
2: string;
|
|
36
|
-
3: string;
|
|
37
|
-
4: string;
|
|
38
|
-
5: string;
|
|
39
|
-
6: string;
|
|
40
|
-
7: string;
|
|
41
|
-
8: string;
|
|
42
|
-
9: string;
|
|
43
|
-
};
|
|
44
|
-
twentiesWords: {
|
|
45
|
-
2: string;
|
|
46
|
-
3: string;
|
|
47
|
-
4: string;
|
|
48
|
-
5: string;
|
|
49
|
-
6: string;
|
|
50
|
-
7: string;
|
|
51
|
-
8: string;
|
|
52
|
-
9: string;
|
|
53
|
-
};
|
|
54
|
-
hundredsWords: {
|
|
55
|
-
1: string;
|
|
56
|
-
2: string;
|
|
57
|
-
3: string;
|
|
58
|
-
4: string;
|
|
59
|
-
5: string;
|
|
60
|
-
6: string;
|
|
61
|
-
7: string;
|
|
62
|
-
8: string;
|
|
63
|
-
9: string;
|
|
64
|
-
};
|
|
65
|
-
pluralForms: {
|
|
66
|
-
1: string[];
|
|
67
|
-
2: string[];
|
|
68
|
-
3: string[];
|
|
69
|
-
4: string[];
|
|
70
|
-
5: string[];
|
|
71
|
-
6: string[];
|
|
72
|
-
7: string[];
|
|
73
|
-
8: string[];
|
|
74
|
-
9: string[];
|
|
75
|
-
10: string[];
|
|
76
|
-
};
|
|
77
|
-
/** Selects Serbian plural form: 1 = singular, 2-4 = few, else = many. */
|
|
78
|
-
pluralize(n: any, forms: any): any;
|
|
79
|
-
}
|
|
80
|
-
import { SlavicLanguage } from '../classes/slavic-language.js';
|
|
9
|
+
export function toWords(value: number | string | bigint, options?: {
|
|
10
|
+
gender?: "masculine" | "feminine" | undefined;
|
|
11
|
+
}): string;
|