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
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Biblical Hebrew language converter - Functional Implementation
|
|
3
|
+
*
|
|
4
|
+
* Self-contained converter with segment-based decomposition.
|
|
5
|
+
*
|
|
6
|
+
* Key features:
|
|
7
|
+
* - Gender agreement (masculine default, feminine via option)
|
|
8
|
+
* - Dual forms for 2, 200, 2000
|
|
9
|
+
* - Special 1-9 thousands construct state
|
|
10
|
+
* - "ו" (ve) conjunction rules vary by position
|
|
11
|
+
* - Per-digit decimal reading
|
|
12
|
+
*
|
|
13
|
+
* Optimization: Precomputed segment lookup tables for both genders.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { parseNumericValue } from '../utils/parse-numeric.js'
|
|
17
|
+
import { validateOptions } from '../utils/validate-options.js'
|
|
18
|
+
|
|
19
|
+
// ============================================================================
|
|
20
|
+
// Vocabulary (arrays for indexed access - faster than object property lookup)
|
|
21
|
+
// ============================================================================
|
|
22
|
+
|
|
23
|
+
// Masculine forms (default in Biblical Hebrew) - index 0 unused
|
|
24
|
+
const ONES_MASC = ['', 'אחד', 'שניים', 'שלשה', 'ארבעה', 'חמשה', 'ששה', 'שבעה', 'שמונה', 'תשעה']
|
|
25
|
+
const TEENS_MASC = ['עשרה', 'אחד עשר', 'שנים עשר', 'שלשה עשר', 'ארבעה עשר', 'חמשה עשר', 'ששה עשר', 'שבעה עשר', 'שמונה עשר', 'תשעה עשר']
|
|
26
|
+
const THOUSANDS_MASC = ['', 'אלף', 'אלפיים', 'שלשה אלפים', 'ארבעה אלפים', 'חמשה אלפים', 'ששה אלפים', 'שבעה אלפים', 'שמונה אלפים', 'תשעה אלפים']
|
|
27
|
+
|
|
28
|
+
// Feminine forms - index 0 unused
|
|
29
|
+
const ONES_FEM = ['', 'אחת', 'שתים', 'שלש', 'ארבע', 'חמש', 'שש', 'שבע', 'שמונה', 'תשע']
|
|
30
|
+
const TEENS_FEM = ['עשר', 'אחת עשרה', 'שתים עשרה', 'שלש עשרה', 'ארבע עשרה', 'חמש עשרה', 'שש עשרה', 'שבע עשרה', 'שמונה עשרה', 'תשע עשרה']
|
|
31
|
+
const THOUSANDS_FEM = ['', 'אלף', 'אלפיים', 'שלשת אלפים', 'ארבעת אלפים', 'חמשת אלפים', 'ששת אלפים', 'שבעת אלפים', 'שמונת אלפים', 'תשעת אלפים']
|
|
32
|
+
|
|
33
|
+
// Shared vocabulary
|
|
34
|
+
const TENS = ['', '', 'עשרים', 'שלשים', 'ארבעים', 'חמישים', 'ששים', 'שבעים', 'שמונים', 'תשעים']
|
|
35
|
+
const HUNDREDS = ['', 'מאה', 'מאתיים', 'שלשה מאות', 'ארבעה מאות', 'חמשה מאות', 'ששה מאות', 'שבעה מאות', 'שמונה מאות', 'תשעה מאות']
|
|
36
|
+
const HUNDREDS_FEM = ['', 'מאה', 'מאתיים', 'שלש מאות', 'ארבע מאות', 'חמש מאות', 'שש מאות', 'שבע מאות', 'שמונה מאות', 'תשע מאות']
|
|
37
|
+
|
|
38
|
+
// Scale words (index 1 = thousands, 2 = millions, etc.)
|
|
39
|
+
const SCALE = ['', 'אלף', 'מיליון', 'מיליארד', 'טריליון', 'קוודרליון', 'קווינטיליון']
|
|
40
|
+
const SCALE_PLURAL = ['', 'אלפים', 'מיליונים', 'מיליארדים', 'טריליונים', 'קוודרליונים', 'קווינטיליונים']
|
|
41
|
+
|
|
42
|
+
const ZERO = 'אפס'
|
|
43
|
+
const NEGATIVE = 'מינוס'
|
|
44
|
+
const DECIMAL_SEP = 'נקודה'
|
|
45
|
+
|
|
46
|
+
// ============================================================================
|
|
47
|
+
// Precomputed Lookup Tables (built once at module load)
|
|
48
|
+
// ============================================================================
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Builds segment word for scale segments (thousands, millions, etc.).
|
|
52
|
+
* "ו" is added before tens and ones when following hundreds.
|
|
53
|
+
*/
|
|
54
|
+
function buildScaleSegment (n, andWord, ONES, TEENS, HUNDREDS_ARR) {
|
|
55
|
+
if (n === 0) return ''
|
|
56
|
+
|
|
57
|
+
const ones = n % 10
|
|
58
|
+
const tens = Math.floor(n / 10) % 10
|
|
59
|
+
const hundreds = Math.floor(n / 100)
|
|
60
|
+
|
|
61
|
+
let result = ''
|
|
62
|
+
|
|
63
|
+
// Hundreds
|
|
64
|
+
if (hundreds > 0) {
|
|
65
|
+
result = HUNDREDS_ARR[hundreds]
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Tens and ones
|
|
69
|
+
if (tens === 1) {
|
|
70
|
+
// Teens (10-19)
|
|
71
|
+
const teenWord = TEENS[ones]
|
|
72
|
+
if (result) {
|
|
73
|
+
result += ' ' + andWord + teenWord
|
|
74
|
+
} else {
|
|
75
|
+
result = teenWord
|
|
76
|
+
}
|
|
77
|
+
} else {
|
|
78
|
+
// Tens (20-90)
|
|
79
|
+
if (tens >= 2) {
|
|
80
|
+
if (result) {
|
|
81
|
+
result += ' ' + andWord + TENS[tens]
|
|
82
|
+
} else {
|
|
83
|
+
result = TENS[tens]
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Ones
|
|
88
|
+
if (ones > 0) {
|
|
89
|
+
if (result) {
|
|
90
|
+
result += ' ' + andWord + ONES[ones]
|
|
91
|
+
} else {
|
|
92
|
+
result = ONES[ones]
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return result
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Builds segment word for units segment (no scale word).
|
|
102
|
+
* "ו" is only added before the final ones digit.
|
|
103
|
+
*/
|
|
104
|
+
function buildUnitsSegment (n, andWord, ONES, TEENS, HUNDREDS_ARR) {
|
|
105
|
+
if (n === 0) return ''
|
|
106
|
+
|
|
107
|
+
const ones = n % 10
|
|
108
|
+
const tens = Math.floor(n / 10) % 10
|
|
109
|
+
const hundreds = Math.floor(n / 100)
|
|
110
|
+
|
|
111
|
+
let result = ''
|
|
112
|
+
|
|
113
|
+
// Hundreds
|
|
114
|
+
if (hundreds > 0) {
|
|
115
|
+
result = HUNDREDS_ARR[hundreds]
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Tens (no conjunction)
|
|
119
|
+
if (tens === 1) {
|
|
120
|
+
// Teens (10-19)
|
|
121
|
+
if (result) {
|
|
122
|
+
result += ' ' + TEENS[ones]
|
|
123
|
+
} else {
|
|
124
|
+
result = TEENS[ones]
|
|
125
|
+
}
|
|
126
|
+
} else {
|
|
127
|
+
if (tens >= 2) {
|
|
128
|
+
if (result) {
|
|
129
|
+
result += ' ' + TENS[tens]
|
|
130
|
+
} else {
|
|
131
|
+
result = TENS[tens]
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Ones - conjunction only here
|
|
136
|
+
if (ones > 0) {
|
|
137
|
+
if (result) {
|
|
138
|
+
result += ' ' + andWord + ONES[ones]
|
|
139
|
+
} else {
|
|
140
|
+
result = ONES[ones]
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return result
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Precompute all 1000 segment words for masculine (default) with default conjunction
|
|
149
|
+
const SCALE_SEGMENTS_MASC = new Array(1000)
|
|
150
|
+
const UNITS_SEGMENTS_MASC = new Array(1000)
|
|
151
|
+
const SCALE_SEGMENTS_FEM = new Array(1000)
|
|
152
|
+
const UNITS_SEGMENTS_FEM = new Array(1000)
|
|
153
|
+
|
|
154
|
+
for (let i = 0; i < 1000; i++) {
|
|
155
|
+
SCALE_SEGMENTS_MASC[i] = buildScaleSegment(i, 'ו', ONES_MASC, TEENS_MASC, HUNDREDS)
|
|
156
|
+
UNITS_SEGMENTS_MASC[i] = buildUnitsSegment(i, 'ו', ONES_MASC, TEENS_MASC, HUNDREDS)
|
|
157
|
+
SCALE_SEGMENTS_FEM[i] = buildScaleSegment(i, 'ו', ONES_FEM, TEENS_FEM, HUNDREDS_FEM)
|
|
158
|
+
UNITS_SEGMENTS_FEM[i] = buildUnitsSegment(i, 'ו', ONES_FEM, TEENS_FEM, HUNDREDS_FEM)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// ============================================================================
|
|
162
|
+
// Conversion Functions
|
|
163
|
+
// ============================================================================
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Converts a non-negative integer to Biblical Hebrew words.
|
|
167
|
+
*
|
|
168
|
+
* @param {bigint} n - Non-negative integer to convert
|
|
169
|
+
* @param {Object} options - Conversion options
|
|
170
|
+
* @returns {string} Biblical Hebrew words
|
|
171
|
+
*/
|
|
172
|
+
function integerToWords (n, options) {
|
|
173
|
+
if (n === 0n) return ZERO
|
|
174
|
+
|
|
175
|
+
const andWord = options.andWord ?? 'ו'
|
|
176
|
+
const gender = options.gender || 'masculine'
|
|
177
|
+
const isFeminine = gender === 'feminine'
|
|
178
|
+
const usePrecomputed = andWord === 'ו'
|
|
179
|
+
|
|
180
|
+
// Select vocabulary based on gender
|
|
181
|
+
const ONES = isFeminine ? ONES_FEM : ONES_MASC
|
|
182
|
+
const TEENS = isFeminine ? TEENS_FEM : TEENS_MASC
|
|
183
|
+
const THOUSANDS_SPECIAL = isFeminine ? THOUSANDS_FEM : THOUSANDS_MASC
|
|
184
|
+
const HUNDREDS_ARR = isFeminine ? HUNDREDS_FEM : HUNDREDS
|
|
185
|
+
const SCALE_SEGS = isFeminine ? SCALE_SEGMENTS_FEM : SCALE_SEGMENTS_MASC
|
|
186
|
+
const UNITS_SEGS = isFeminine ? UNITS_SEGMENTS_FEM : UNITS_SEGMENTS_MASC
|
|
187
|
+
|
|
188
|
+
// Fast path: numbers < 1000 (direct lookup)
|
|
189
|
+
if (n < 1000n) {
|
|
190
|
+
return usePrecomputed ? UNITS_SEGS[Number(n)] : buildUnitsSegment(Number(n), andWord, ONES, TEENS, HUNDREDS_ARR)
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Extract segments using BigInt modulo
|
|
194
|
+
const segments = []
|
|
195
|
+
let temp = n
|
|
196
|
+
while (temp > 0n) {
|
|
197
|
+
segments.push(Number(temp % 1000n))
|
|
198
|
+
temp = temp / 1000n
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Build result string directly
|
|
202
|
+
let result = ''
|
|
203
|
+
|
|
204
|
+
for (let i = segments.length - 1; i >= 0; i--) {
|
|
205
|
+
const segment = segments[i]
|
|
206
|
+
if (segment === 0) continue
|
|
207
|
+
|
|
208
|
+
if (i === 0) {
|
|
209
|
+
// Units segment (no scale word)
|
|
210
|
+
const segmentWord = usePrecomputed ? UNITS_SEGS[segment] : buildUnitsSegment(segment, andWord, ONES, TEENS, HUNDREDS_ARR)
|
|
211
|
+
if (result) {
|
|
212
|
+
// Add "ו" before single-digit units when following scale words
|
|
213
|
+
if (segment <= 9) {
|
|
214
|
+
result += ' ' + andWord + segmentWord
|
|
215
|
+
} else {
|
|
216
|
+
result += ' ' + segmentWord
|
|
217
|
+
}
|
|
218
|
+
} else {
|
|
219
|
+
result = segmentWord
|
|
220
|
+
}
|
|
221
|
+
} else if (i === 1) {
|
|
222
|
+
// Thousands - special handling for 1-9
|
|
223
|
+
if (segment <= 9) {
|
|
224
|
+
if (result) result += ' '
|
|
225
|
+
result += THOUSANDS_SPECIAL[segment]
|
|
226
|
+
} else {
|
|
227
|
+
const segmentWord = usePrecomputed ? SCALE_SEGS[segment] : buildScaleSegment(segment, andWord, ONES, TEENS, HUNDREDS_ARR)
|
|
228
|
+
if (result) result += ' '
|
|
229
|
+
result += segmentWord + ' ' + SCALE[1]
|
|
230
|
+
}
|
|
231
|
+
} else {
|
|
232
|
+
// Millions and above
|
|
233
|
+
if (segment === 1) {
|
|
234
|
+
if (result) result += ' '
|
|
235
|
+
result += SCALE[i]
|
|
236
|
+
} else {
|
|
237
|
+
const segmentWord = usePrecomputed ? SCALE_SEGS[segment] : buildScaleSegment(segment, andWord, ONES, TEENS, HUNDREDS_ARR)
|
|
238
|
+
if (result) result += ' '
|
|
239
|
+
result += segmentWord + ' ' + SCALE_PLURAL[i]
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return result
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Converts decimal digits to Biblical Hebrew words (digit by digit).
|
|
249
|
+
*
|
|
250
|
+
* @param {string} decimalPart - Decimal digits (without the point)
|
|
251
|
+
* @param {Object} options - Conversion options
|
|
252
|
+
* @returns {string} Biblical Hebrew words for decimal part
|
|
253
|
+
*/
|
|
254
|
+
function decimalPartToWords (decimalPart, options) {
|
|
255
|
+
const gender = options.gender || 'masculine'
|
|
256
|
+
const ONES = gender === 'feminine' ? ONES_FEM : ONES_MASC
|
|
257
|
+
|
|
258
|
+
let result = ''
|
|
259
|
+
for (let i = 0; i < decimalPart.length; i++) {
|
|
260
|
+
const d = parseInt(decimalPart[i], 10)
|
|
261
|
+
if (result) result += ' '
|
|
262
|
+
result += d === 0 ? ZERO : ONES[d]
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
return result
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Converts a numeric value to Biblical Hebrew words.
|
|
270
|
+
*
|
|
271
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
272
|
+
* @param {Object} [options] - Optional configuration
|
|
273
|
+
* @param {('masculine'|'feminine')} [options.gender='masculine'] - Grammatical gender
|
|
274
|
+
* @param {string} [options.andWord] - Custom conjunction word
|
|
275
|
+
* @returns {string} The number in Biblical Hebrew words
|
|
276
|
+
*/
|
|
277
|
+
function toWords (value, options) {
|
|
278
|
+
options = validateOptions(options)
|
|
279
|
+
const { isNegative, integerPart, decimalPart } = parseNumericValue(value)
|
|
280
|
+
|
|
281
|
+
let result = ''
|
|
282
|
+
|
|
283
|
+
if (isNegative) {
|
|
284
|
+
result = NEGATIVE + ' '
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
result += integerToWords(integerPart, options)
|
|
288
|
+
|
|
289
|
+
if (decimalPart) {
|
|
290
|
+
result += ' ' + DECIMAL_SEP + ' ' + decimalPartToWords(decimalPart, options)
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
return result
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// ============================================================================
|
|
297
|
+
// Exports
|
|
298
|
+
// ============================================================================
|
|
299
|
+
|
|
300
|
+
export { toWords }
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts a numeric value to Modern Hebrew words.
|
|
3
|
+
*
|
|
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
|
+
* @param {string} [options.andWord] - Custom conjunction word
|
|
8
|
+
* @returns {string} The number in Modern Hebrew words
|
|
9
|
+
*/
|
|
10
|
+
export function toWords(value: number | string | bigint, options?: {
|
|
11
|
+
gender?: "masculine" | "feminine" | undefined;
|
|
12
|
+
andWord?: string | undefined;
|
|
13
|
+
}): string;
|