n2words 1.24.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 +183 -156
- 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 -2
- package/dist/languages/ar.js.map +1 -1
- package/dist/languages/az.js +3 -2
- package/dist/languages/az.js.map +1 -1
- package/dist/languages/bn.js +3 -2
- package/dist/languages/bn.js.map +1 -1
- package/dist/languages/cs.js +3 -2
- package/dist/languages/cs.js.map +1 -1
- package/dist/languages/da.js +3 -2
- package/dist/languages/da.js.map +1 -1
- package/dist/languages/de.js +3 -2
- package/dist/languages/de.js.map +1 -1
- package/dist/languages/el.js +3 -2
- package/dist/languages/el.js.map +1 -1
- package/dist/languages/en.js +3 -2
- package/dist/languages/en.js.map +1 -1
- package/dist/languages/es.js +3 -2
- package/dist/languages/es.js.map +1 -1
- package/dist/languages/fa.js +3 -2
- package/dist/languages/fa.js.map +1 -1
- package/dist/languages/fi.js +3 -0
- package/dist/languages/fi.js.map +1 -0
- package/dist/languages/fil.js +3 -2
- package/dist/languages/fil.js.map +1 -1
- package/dist/languages/fr-BE.js +3 -2
- package/dist/languages/fr-BE.js.map +1 -1
- package/dist/languages/fr.js +3 -2
- package/dist/languages/fr.js.map +1 -1
- package/dist/languages/gu.js +3 -2
- package/dist/languages/gu.js.map +1 -1
- 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 -2
- package/dist/languages/he.js.map +1 -1
- package/dist/languages/hi.js +3 -2
- package/dist/languages/hi.js.map +1 -1
- package/dist/languages/hr.js +3 -2
- package/dist/languages/hr.js.map +1 -1
- package/dist/languages/hu.js +3 -2
- package/dist/languages/hu.js.map +1 -1
- package/dist/languages/id.js +3 -2
- package/dist/languages/id.js.map +1 -1
- package/dist/languages/it.js +3 -2
- package/dist/languages/it.js.map +1 -1
- package/dist/languages/ja.js +3 -2
- package/dist/languages/ja.js.map +1 -1
- package/dist/languages/kn.js +3 -2
- package/dist/languages/kn.js.map +1 -1
- package/dist/languages/ko.js +3 -2
- package/dist/languages/ko.js.map +1 -1
- package/dist/languages/lt.js +3 -2
- package/dist/languages/lt.js.map +1 -1
- package/dist/languages/lv.js +3 -2
- package/dist/languages/lv.js.map +1 -1
- package/dist/languages/mr.js +3 -2
- package/dist/languages/mr.js.map +1 -1
- package/dist/languages/ms.js +3 -2
- package/dist/languages/ms.js.map +1 -1
- package/dist/languages/nb.js +3 -2
- package/dist/languages/nb.js.map +1 -1
- package/dist/languages/nl.js +3 -2
- package/dist/languages/nl.js.map +1 -1
- package/dist/languages/pa.js +3 -0
- package/dist/languages/pa.js.map +1 -0
- package/dist/languages/pl.js +3 -2
- package/dist/languages/pl.js.map +1 -1
- package/dist/languages/pt.js +3 -2
- package/dist/languages/pt.js.map +1 -1
- package/dist/languages/ro.js +3 -2
- package/dist/languages/ro.js.map +1 -1
- package/dist/languages/ru.js +3 -2
- package/dist/languages/ru.js.map +1 -1
- package/dist/languages/sr-Cyrl.js +3 -0
- package/dist/languages/sr-Cyrl.js.map +1 -0
- package/dist/languages/sr-Latn.js +3 -2
- package/dist/languages/sr-Latn.js.map +1 -1
- package/dist/languages/sv.js +3 -2
- package/dist/languages/sv.js.map +1 -1
- package/dist/languages/sw.js +3 -2
- package/dist/languages/sw.js.map +1 -1
- package/dist/languages/ta.js +3 -2
- package/dist/languages/ta.js.map +1 -1
- package/dist/languages/te.js +3 -2
- package/dist/languages/te.js.map +1 -1
- package/dist/languages/th.js +3 -2
- package/dist/languages/th.js.map +1 -1
- package/dist/languages/tr.js +3 -2
- package/dist/languages/tr.js.map +1 -1
- package/dist/languages/uk.js +3 -2
- package/dist/languages/uk.js.map +1 -1
- package/dist/languages/ur.js +3 -2
- package/dist/languages/ur.js.map +1 -1
- package/dist/languages/vi.js +3 -2
- package/dist/languages/vi.js.map +1 -1
- package/dist/languages/zh-Hans.js +3 -2
- package/dist/languages/zh-Hans.js.map +1 -1
- package/dist/languages/zh-Hant.js +3 -0
- package/dist/languages/zh-Hant.js.map +1 -0
- package/dist/n2words.js +3 -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 +17 -0
- package/lib/languages/ar.js +171 -209
- package/lib/languages/az.d.ts +7 -0
- package/lib/languages/az.js +167 -49
- package/lib/languages/bn.d.ts +7 -0
- package/lib/languages/bn.js +142 -123
- package/lib/languages/cs.d.ts +18 -0
- package/lib/languages/cs.js +303 -176
- package/lib/languages/da.d.ts +14 -0
- package/lib/languages/da.js +267 -139
- package/lib/languages/de.d.ts +17 -0
- package/lib/languages/de.js +310 -113
- package/lib/languages/el.d.ts +14 -0
- package/lib/languages/el.js +225 -98
- package/lib/languages/en.d.ts +17 -0
- package/lib/languages/en.js +235 -102
- package/lib/languages/es.d.ts +21 -0
- package/lib/languages/es.js +307 -125
- package/lib/languages/fa.d.ts +7 -0
- package/lib/languages/fa.js +115 -108
- package/lib/languages/fi.d.ts +14 -0
- package/lib/languages/fi.js +245 -0
- package/lib/languages/fil.d.ts +7 -0
- package/lib/languages/fil.js +199 -139
- package/lib/languages/fr-BE.d.ts +11 -0
- package/lib/languages/fr-BE.js +287 -48
- package/lib/languages/fr.d.ts +21 -0
- package/lib/languages/fr.js +343 -119
- package/lib/languages/gu.d.ts +7 -0
- package/lib/languages/gu.js +125 -144
- package/lib/languages/ha.d.ts +7 -0
- package/lib/languages/ha.js +230 -0
- package/lib/languages/hbo.d.ts +13 -0
- package/lib/languages/hbo.js +300 -0
- package/lib/languages/he.d.ts +13 -0
- package/lib/languages/he.js +230 -283
- package/lib/languages/hi.d.ts +7 -0
- package/lib/languages/hi.js +142 -123
- package/lib/languages/hr.d.ts +11 -0
- package/lib/languages/hr.js +190 -129
- package/lib/languages/hu.d.ts +7 -0
- package/lib/languages/hu.js +194 -133
- package/lib/languages/id.d.ts +7 -0
- package/lib/languages/id.js +167 -140
- package/lib/languages/it.d.ts +19 -0
- package/lib/languages/it.js +337 -108
- package/lib/languages/ja.d.ts +17 -0
- package/lib/languages/ja.js +224 -155
- package/lib/languages/kn.d.ts +7 -0
- package/lib/languages/kn.js +128 -62
- package/lib/languages/ko.d.ts +14 -0
- package/lib/languages/ko.js +250 -70
- package/lib/languages/lt.d.ts +18 -0
- package/lib/languages/lt.js +287 -148
- package/lib/languages/lv.d.ts +18 -0
- package/lib/languages/lv.js +291 -123
- package/lib/languages/mr.d.ts +7 -0
- package/lib/languages/mr.js +125 -144
- package/lib/languages/ms.d.ts +7 -0
- package/lib/languages/ms.js +171 -112
- package/lib/languages/nb.d.ts +14 -0
- package/lib/languages/nb.js +275 -100
- package/lib/languages/nl.d.ts +26 -0
- package/lib/languages/nl.js +307 -174
- package/lib/languages/pa.d.ts +7 -0
- package/lib/languages/pa.js +163 -0
- package/lib/languages/pl.d.ts +22 -0
- package/lib/languages/pl.js +299 -158
- package/lib/languages/pt.d.ts +17 -0
- package/lib/languages/pt.js +279 -120
- package/lib/languages/ro.d.ts +18 -0
- package/lib/languages/ro.js +214 -337
- package/lib/languages/ru.d.ts +11 -0
- package/lib/languages/ru.js +219 -95
- package/lib/languages/sr-Cyrl.d.ts +11 -0
- package/lib/languages/sr-Cyrl.js +215 -0
- package/lib/languages/sr-Latn.d.ts +11 -0
- package/lib/languages/sr-Latn.js +190 -132
- package/lib/languages/sv.d.ts +14 -0
- package/lib/languages/sv.js +280 -103
- package/lib/languages/sw.d.ts +7 -0
- package/lib/languages/sw.js +135 -103
- package/lib/languages/ta.d.ts +7 -0
- package/lib/languages/ta.js +133 -205
- package/lib/languages/te.d.ts +7 -0
- package/lib/languages/te.js +148 -213
- package/lib/languages/th.d.ts +7 -0
- package/lib/languages/th.js +139 -101
- package/lib/languages/tr.d.ts +18 -0
- package/lib/languages/tr.js +246 -66
- package/lib/languages/uk.d.ts +11 -0
- package/lib/languages/uk.js +197 -101
- package/lib/languages/ur.d.ts +7 -0
- package/lib/languages/ur.js +160 -123
- package/lib/languages/vi.d.ts +17 -0
- package/lib/languages/vi.js +287 -164
- package/lib/languages/zh-Hans.d.ts +11 -0
- package/lib/languages/zh-Hans.js +159 -142
- package/lib/languages/zh-Hant.d.ts +11 -0
- package/lib/languages/zh-Hant.js +202 -0
- package/lib/n2words.d.ts +53 -0
- package/lib/n2words.js +91 -227
- 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 +118 -67
- package/dist/languages/pa-Guru.js +0 -2
- package/dist/languages/pa-Guru.js.map +0 -1
- package/lib/classes/abstract-language.js +0 -261
- package/lib/classes/greedy-scale-language.js +0 -195
- package/lib/classes/slavic-language.js +0 -251
- package/lib/classes/south-asian-language.js +0 -161
- package/lib/classes/turkic-language.js +0 -63
- package/lib/languages/pa-Guru.js +0 -126
- package/typings/classes/abstract-language.d.ts +0 -144
- package/typings/classes/greedy-scale-language.d.ts +0 -148
- package/typings/classes/slavic-language.d.ts +0 -145
- package/typings/classes/south-asian-language.d.ts +0 -101
- package/typings/classes/turkic-language.d.ts +0 -42
- package/typings/languages/ar.d.ts +0 -93
- package/typings/languages/az.d.ts +0 -25
- package/typings/languages/bn.d.ts +0 -1
- package/typings/languages/cs.d.ts +0 -120
- package/typings/languages/da.d.ts +0 -53
- package/typings/languages/de.d.ts +0 -26
- package/typings/languages/el.d.ts +0 -11
- package/typings/languages/en.d.ts +0 -30
- package/typings/languages/es.d.ts +0 -43
- package/typings/languages/fa.d.ts +0 -81
- package/typings/languages/fil.d.ts +0 -12
- package/typings/languages/fr-BE.d.ts +0 -41
- package/typings/languages/fr.d.ts +0 -43
- package/typings/languages/gu.d.ts +0 -12
- package/typings/languages/he.d.ts +0 -197
- package/typings/languages/hi.d.ts +0 -1
- package/typings/languages/hr.d.ts +0 -110
- package/typings/languages/hu.d.ts +0 -37
- package/typings/languages/id.d.ts +0 -69
- package/typings/languages/it.d.ts +0 -51
- package/typings/languages/ja.d.ts +0 -58
- package/typings/languages/kn.d.ts +0 -11
- package/typings/languages/ko.d.ts +0 -25
- package/typings/languages/lt.d.ts +0 -110
- package/typings/languages/lv.d.ts +0 -99
- package/typings/languages/mr.d.ts +0 -12
- package/typings/languages/ms.d.ts +0 -37
- package/typings/languages/nb.d.ts +0 -27
- package/typings/languages/nl.d.ts +0 -65
- package/typings/languages/pa-Guru.d.ts +0 -1
- package/typings/languages/pl.d.ts +0 -116
- package/typings/languages/pt.d.ts +0 -39
- package/typings/languages/ro.d.ts +0 -229
- package/typings/languages/ru.d.ts +0 -108
- package/typings/languages/sr-Latn.d.ts +0 -98
- package/typings/languages/sv.d.ts +0 -30
- package/typings/languages/sw.d.ts +0 -1
- package/typings/languages/ta.d.ts +0 -1
- package/typings/languages/te.d.ts +0 -1
- package/typings/languages/th.d.ts +0 -1
- package/typings/languages/tr.d.ts +0 -46
- package/typings/languages/uk.d.ts +0 -117
- package/typings/languages/ur.d.ts +0 -1
- package/typings/languages/vi.d.ts +0 -116
- package/typings/languages/zh-Hans.d.ts +0 -57
- package/typings/n2words.d.ts +0 -177
package/lib/languages/fil.js
CHANGED
|
@@ -1,162 +1,222 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Filipino
|
|
2
|
+
* Filipino language converter - Functional Implementation
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* Filipino numbers follow patterns like: sampu (10), labinisa (11), dalawampu (20)
|
|
4
|
+
* Self-contained converter with precomputed lookup tables.
|
|
6
5
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
6
|
+
* Key features:
|
|
7
|
+
* - Linker "ng" after vowels: "isang daang" (100)
|
|
8
|
+
* - Linker " na " after consonants: "siyam na daang" (900)
|
|
9
|
+
* - Special tens with linker: "limampung anim" (56)
|
|
10
|
+
* - Per-digit decimal reading
|
|
12
11
|
*/
|
|
13
12
|
|
|
14
|
-
import
|
|
13
|
+
import { parseNumericValue } from '../utils/parse-numeric.js'
|
|
14
|
+
|
|
15
|
+
// ============================================================================
|
|
16
|
+
// Vocabulary
|
|
17
|
+
// ============================================================================
|
|
18
|
+
|
|
19
|
+
const ONES = ['', 'isa', 'dalawa', 'tatlo', 'apat', 'lima', 'anim', 'pito', 'walo', 'siyam']
|
|
20
|
+
const TEENS = ['sampu', 'labinisa', 'labindalawa', 'labintatlo', 'labinapat', 'labinlima', 'labinanum', 'labimpito', 'labingwalo', 'labinsiyam']
|
|
21
|
+
const TENS = ['', '', 'dalawampu', 'tatlumpu', 'apatnapu', 'limampu', 'animnapu', 'pitumpu', 'walumpu', 'siyamnapu']
|
|
22
|
+
|
|
23
|
+
// Scale words include linker (end with "ng")
|
|
24
|
+
const HUNDRED = 'daang'
|
|
25
|
+
const THOUSAND = 'libong'
|
|
26
|
+
|
|
27
|
+
const ZERO = 'zero'
|
|
28
|
+
const NEGATIVE = 'negatibo'
|
|
29
|
+
const DECIMAL_SEP = 'punto'
|
|
30
|
+
|
|
31
|
+
// Short scale with linker
|
|
32
|
+
const SCALE_WORDS = ['', THOUSAND, 'milyong', 'bilyong', 'trilyong']
|
|
33
|
+
|
|
34
|
+
// ============================================================================
|
|
35
|
+
// Helper Functions
|
|
36
|
+
// ============================================================================
|
|
37
|
+
|
|
38
|
+
const VOWELS = ['a', 'e', 'i', 'o', 'u']
|
|
39
|
+
|
|
40
|
+
function addLinker (word) {
|
|
41
|
+
const lastChar = word[word.length - 1]
|
|
42
|
+
if (VOWELS.includes(lastChar)) {
|
|
43
|
+
return word + 'ng'
|
|
44
|
+
}
|
|
45
|
+
return word + ' na'
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// ============================================================================
|
|
49
|
+
// Precomputed Lookup Table
|
|
50
|
+
// ============================================================================
|
|
51
|
+
|
|
52
|
+
function buildSegment (n) {
|
|
53
|
+
if (n === 0) return ''
|
|
54
|
+
|
|
55
|
+
const ones = n % 10
|
|
56
|
+
const tensDigit = Math.floor(n / 10) % 10
|
|
57
|
+
const hundredsDigit = Math.floor(n / 100)
|
|
58
|
+
|
|
59
|
+
const parts = []
|
|
60
|
+
|
|
61
|
+
// Hundreds: "isang daan", "dalawang daan", "siyam na daan"
|
|
62
|
+
if (hundredsDigit > 0) {
|
|
63
|
+
const hundredPrefix = addLinker(ONES[hundredsDigit])
|
|
64
|
+
parts.push(hundredPrefix + ' ' + HUNDRED)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Tens and ones
|
|
68
|
+
const tensOnes = n % 100
|
|
69
|
+
|
|
70
|
+
if (tensOnes === 0) {
|
|
71
|
+
// Just hundreds
|
|
72
|
+
} else if (tensOnes < 10) {
|
|
73
|
+
// Single digit
|
|
74
|
+
parts.push(ONES[ones])
|
|
75
|
+
} else if (tensOnes < 20) {
|
|
76
|
+
// Teens (10-19)
|
|
77
|
+
parts.push(TEENS[ones])
|
|
78
|
+
} else if (ones === 0) {
|
|
79
|
+
// Even tens (20, 30, 40, etc.)
|
|
80
|
+
parts.push(TENS[tensDigit])
|
|
81
|
+
} else {
|
|
82
|
+
// Tens + ones
|
|
83
|
+
// limampu (50) gets special linker: "limampung anim" (56)
|
|
84
|
+
if (tensDigit === 5) {
|
|
85
|
+
parts.push(TENS[tensDigit] + 'ng ' + ONES[ones])
|
|
86
|
+
} else {
|
|
87
|
+
parts.push(TENS[tensDigit] + ' ' + ONES[ones])
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return parts.join(' ')
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const SEGMENTS = new Array(1000)
|
|
95
|
+
for (let i = 0; i < 1000; i++) {
|
|
96
|
+
SEGMENTS[i] = buildSegment(i)
|
|
97
|
+
}
|
|
15
98
|
|
|
16
99
|
/**
|
|
17
|
-
*
|
|
18
|
-
* Extends GreedyScaleLanguage with scale-based number conversion
|
|
100
|
+
* Builds segment with linker added to last word (for use before scale words).
|
|
19
101
|
*/
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
[
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
[100n, 'daang'],
|
|
32
|
-
|
|
33
|
-
// Tens
|
|
34
|
-
[90n, 'siyamnapu'],
|
|
35
|
-
[80n, 'walumpu'],
|
|
36
|
-
[70n, 'pitumpu'],
|
|
37
|
-
[60n, 'animnapu'],
|
|
38
|
-
[50n, 'limampu'],
|
|
39
|
-
[40n, 'apatnapu'],
|
|
40
|
-
[30n, 'tatlumpu'],
|
|
41
|
-
[20n, 'dalawampu'],
|
|
42
|
-
|
|
43
|
-
// Teens (must come before 10 to be matched first)
|
|
44
|
-
[19n, 'labinsiyam'],
|
|
45
|
-
[18n, 'labingwalo'],
|
|
46
|
-
[17n, 'labimpito'],
|
|
47
|
-
[16n, 'labinanum'],
|
|
48
|
-
[15n, 'labinlima'],
|
|
49
|
-
[14n, 'labinapat'],
|
|
50
|
-
[13n, 'labintatlo'],
|
|
51
|
-
[12n, 'labindalawa'],
|
|
52
|
-
[11n, 'labinisa'],
|
|
53
|
-
[10n, 'sampu'],
|
|
54
|
-
|
|
55
|
-
// Ones
|
|
56
|
-
[9n, 'siyam'],
|
|
57
|
-
[8n, 'walo'],
|
|
58
|
-
[7n, 'pito'],
|
|
59
|
-
[6n, 'anim'],
|
|
60
|
-
[5n, 'lima'],
|
|
61
|
-
[4n, 'apat'],
|
|
62
|
-
[3n, 'tatlo'],
|
|
63
|
-
[2n, 'dalawa'],
|
|
64
|
-
[1n, 'isa'],
|
|
65
|
-
[0n, 'zero']
|
|
66
|
-
]
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Convert a whole number to Filipino words.
|
|
70
|
-
* Overrides parent to handle zero explicitly.
|
|
71
|
-
*
|
|
72
|
-
* @param {bigint} wholeNumber The whole number to convert.
|
|
73
|
-
* @returns {string} The Filipino representation.
|
|
74
|
-
*/
|
|
75
|
-
convertWholePart (wholeNumber) {
|
|
76
|
-
// Handle zero explicitly
|
|
77
|
-
if (wholeNumber === 0n) {
|
|
78
|
-
return this.zeroWord
|
|
102
|
+
function buildSegmentWithLinker (n) {
|
|
103
|
+
const segmentWord = SEGMENTS[n]
|
|
104
|
+
if (!segmentWord) return ''
|
|
105
|
+
|
|
106
|
+
// Find the last space to get the last word
|
|
107
|
+
const lastSpaceIdx = segmentWord.lastIndexOf(' ')
|
|
108
|
+
if (lastSpaceIdx === -1) {
|
|
109
|
+
// Single word
|
|
110
|
+
const lastChar = segmentWord[segmentWord.length - 1]
|
|
111
|
+
if (lastChar === 'g' && segmentWord.endsWith('ng')) {
|
|
112
|
+
return segmentWord // Already has linker
|
|
79
113
|
}
|
|
80
|
-
return
|
|
114
|
+
return addLinker(segmentWord)
|
|
81
115
|
}
|
|
82
116
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
* Features Filipino-specific rules:
|
|
87
|
-
* - "ng" connector between words
|
|
88
|
-
* - Consonant-ending words use "na" instead of "ng"
|
|
89
|
-
* - Implicit "one" omission ("isang daan" → "daan")
|
|
90
|
-
*
|
|
91
|
-
* @param {Object} leftWordSet Left word-set as `{ word: BigInt }`.
|
|
92
|
-
* @param {Object} rightWordSet Right word-set as `{ word: BigInt }`.
|
|
93
|
-
* @returns {Object} Merged word-set with combined text and value.
|
|
94
|
-
*/
|
|
95
|
-
mergeScales (leftWordSet, rightWordSet) {
|
|
96
|
-
const leftWord = Object.keys(leftWordSet)[0]
|
|
97
|
-
const rightWord = Object.keys(rightWordSet)[0]
|
|
98
|
-
const leftValue = Object.values(leftWordSet)[0]
|
|
99
|
-
const rightValue = Object.values(rightWordSet)[0]
|
|
100
|
-
|
|
101
|
-
// Don't merge zero with anything - just return the non-zero value
|
|
102
|
-
if (leftValue === 0n) {
|
|
103
|
-
return rightWordSet
|
|
104
|
-
}
|
|
105
|
-
if (rightValue === 0n) {
|
|
106
|
-
return leftWordSet
|
|
107
|
-
}
|
|
117
|
+
// Multi-word: add linker to last word
|
|
118
|
+
const prefix = segmentWord.slice(0, lastSpaceIdx + 1)
|
|
119
|
+
const lastWord = segmentWord.slice(lastSpaceIdx + 1)
|
|
108
120
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
121
|
+
if (lastWord.endsWith('ng')) {
|
|
122
|
+
return segmentWord // Already has linker
|
|
123
|
+
}
|
|
124
|
+
return prefix + addLinker(lastWord)
|
|
125
|
+
}
|
|
113
126
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
const lastChar = leftWord[leftWord.length - 1]
|
|
120
|
-
if (!vowels.includes(lastChar)) {
|
|
121
|
-
return {
|
|
122
|
-
[`${leftWord} na ${rightWord}`]: leftValue * rightValue
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
// Vowel-ending words add "ng"
|
|
126
|
-
return {
|
|
127
|
-
[`${leftWord}ng ${rightWord}`]: leftValue * rightValue
|
|
128
|
-
}
|
|
129
|
-
}
|
|
127
|
+
// Precompute segments with linker for scale word usage
|
|
128
|
+
const SEGMENTS_WITH_LINKER = new Array(1000)
|
|
129
|
+
for (let i = 0; i < 1000; i++) {
|
|
130
|
+
SEGMENTS_WITH_LINKER[i] = buildSegmentWithLinker(i)
|
|
131
|
+
}
|
|
130
132
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
133
|
+
// ============================================================================
|
|
134
|
+
// Conversion Functions
|
|
135
|
+
// ============================================================================
|
|
136
|
+
|
|
137
|
+
function integerToWords (n) {
|
|
138
|
+
if (n === 0n) return ZERO
|
|
139
|
+
|
|
140
|
+
if (n < 1000n) {
|
|
141
|
+
return SEGMENTS[Number(n)]
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return buildLargeNumberWords(n)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Builds words for large numbers using BigInt division.
|
|
149
|
+
* @param {bigint} n - Number >= 1000
|
|
150
|
+
* @returns {string} Filipino words
|
|
151
|
+
*/
|
|
152
|
+
function buildLargeNumberWords (n) {
|
|
153
|
+
// Extract segments using BigInt division (faster than string slicing)
|
|
154
|
+
const segmentValues = []
|
|
155
|
+
let temp = n
|
|
156
|
+
while (temp > 0n) {
|
|
157
|
+
segmentValues.push(Number(temp % 1000n))
|
|
158
|
+
temp = temp / 1000n
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Build result string directly
|
|
162
|
+
let result = ''
|
|
163
|
+
|
|
164
|
+
for (let i = segmentValues.length - 1; i >= 0; i--) {
|
|
165
|
+
const segment = segmentValues[i]
|
|
166
|
+
if (segment === 0) continue
|
|
167
|
+
|
|
168
|
+
const scaleWord = SCALE_WORDS[i] || ''
|
|
141
169
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
170
|
+
if (result) result += ' '
|
|
171
|
+
|
|
172
|
+
if (i === 0) {
|
|
173
|
+
result += SEGMENTS[segment]
|
|
174
|
+
} else {
|
|
175
|
+
// Add linker to segment before scale word
|
|
176
|
+
const segmentWord = SEGMENTS_WITH_LINKER[segment]
|
|
177
|
+
result += segmentWord + ' ' + scaleWord
|
|
145
178
|
}
|
|
146
179
|
}
|
|
180
|
+
|
|
181
|
+
return result
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function decimalPartToWords (decimalPart) {
|
|
185
|
+
// Per-digit decimal reading
|
|
186
|
+
const digits = []
|
|
187
|
+
for (const char of decimalPart) {
|
|
188
|
+
const d = parseInt(char, 10)
|
|
189
|
+
digits.push(d === 0 ? ZERO : ONES[d])
|
|
190
|
+
}
|
|
191
|
+
return digits.join(' ')
|
|
147
192
|
}
|
|
148
193
|
|
|
149
194
|
/**
|
|
150
|
-
*
|
|
195
|
+
* Converts a numeric value to Filipino words.
|
|
151
196
|
*
|
|
152
|
-
* @param {number|string|bigint} value - The
|
|
153
|
-
* @
|
|
154
|
-
* @returns {string} The Filipino word representation
|
|
155
|
-
* @example
|
|
156
|
-
* convertToWords(42) // 'apatnapu dalawa'
|
|
157
|
-
* convertToWords(1000) // 'isang libo'
|
|
158
|
-
* convertToWords(123456) // 'isang daang dalawampung tatlong libong apat na daang limampung anim'
|
|
197
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
198
|
+
* @returns {string} The number in Filipino words
|
|
159
199
|
*/
|
|
160
|
-
|
|
161
|
-
|
|
200
|
+
function toWords (value) {
|
|
201
|
+
const { isNegative, integerPart, decimalPart } = parseNumericValue(value)
|
|
202
|
+
|
|
203
|
+
let result = ''
|
|
204
|
+
|
|
205
|
+
if (isNegative) {
|
|
206
|
+
result = NEGATIVE + ' '
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
result += integerToWords(integerPart)
|
|
210
|
+
|
|
211
|
+
if (decimalPart) {
|
|
212
|
+
result += ' ' + DECIMAL_SEP + ' ' + decimalPartToWords(decimalPart)
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return result
|
|
162
216
|
}
|
|
217
|
+
|
|
218
|
+
// ============================================================================
|
|
219
|
+
// Exports
|
|
220
|
+
// ============================================================================
|
|
221
|
+
|
|
222
|
+
export { toWords }
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts a numeric value to Belgian French words.
|
|
3
|
+
*
|
|
4
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
5
|
+
* @param {Object} [options] - Optional configuration
|
|
6
|
+
* @param {boolean} [options.withHyphenSeparator=false] - Use hyphens between words
|
|
7
|
+
* @returns {string} The number in Belgian French words
|
|
8
|
+
*/
|
|
9
|
+
export function toWords(value: number | string | bigint, options?: {
|
|
10
|
+
withHyphenSeparator?: boolean | undefined;
|
|
11
|
+
}): string;
|