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/gu.js
CHANGED
|
@@ -1,156 +1,137 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Gujarati language
|
|
2
|
+
* Gujarati language converter - Functional Implementation
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* Numbers: શૂન્ય (0), એક (1), બે (2), ત્રણ (3), ચાર (4), પાંચ (5)...
|
|
4
|
+
* Self-contained converter for South Asian numbering.
|
|
6
5
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
6
|
+
* Key features:
|
|
7
|
+
* - Indian numbering system (હજાર, લાખ, કરોડ)
|
|
8
|
+
* - Gujarati script
|
|
9
|
+
* - 3-2-2 grouping pattern (last 3 digits, then groups of 2)
|
|
10
|
+
* - Complete word forms for 0-99
|
|
11
|
+
* - Per-digit decimal reading
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import
|
|
14
|
+
import { parseNumericValue } from '../utils/parse-numeric.js'
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
'
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
'ઓગણાએંસી',
|
|
108
|
-
'એંસી',
|
|
109
|
-
'એક્યાસી',
|
|
110
|
-
'બ્યાસી',
|
|
111
|
-
'ત્યાસી',
|
|
112
|
-
'ચોર્યાસી',
|
|
113
|
-
'પંચાસી',
|
|
114
|
-
'છ્યાસી',
|
|
115
|
-
'સિત્યાસી',
|
|
116
|
-
'અઠ્યાસી',
|
|
117
|
-
'નેવ્યાસી',
|
|
118
|
-
'નેવું',
|
|
119
|
-
'એકાણું',
|
|
120
|
-
'બાણું',
|
|
121
|
-
'ત્રાણું',
|
|
122
|
-
'ચોરાણું',
|
|
123
|
-
'પંચાણું',
|
|
124
|
-
'છન્નું',
|
|
125
|
-
'સત્તાણું',
|
|
126
|
-
'અઠ્ઠાણું',
|
|
127
|
-
'નવ્વાણું'
|
|
128
|
-
]
|
|
129
|
-
|
|
130
|
-
scaleWords = [
|
|
131
|
-
'',
|
|
132
|
-
'હજાર',
|
|
133
|
-
'લાખ',
|
|
134
|
-
'કરોડ',
|
|
135
|
-
'અબજ',
|
|
136
|
-
'ખરબ',
|
|
137
|
-
'નીલ',
|
|
138
|
-
'પદ્મ',
|
|
139
|
-
'શંખ'
|
|
140
|
-
]
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// Vocabulary
|
|
18
|
+
// ============================================================================
|
|
19
|
+
|
|
20
|
+
const ZERO = 'શૂન્ય'
|
|
21
|
+
const NEGATIVE = 'ઋણ'
|
|
22
|
+
const DECIMAL_SEP = 'દશાંશ'
|
|
23
|
+
const HUNDRED = 'સો'
|
|
24
|
+
|
|
25
|
+
const BELOW_HUNDRED = [
|
|
26
|
+
'શૂન્ય', 'એક', 'બે', 'ત્રણ', 'ચાર', 'પાંચ', 'છ', 'સાત', 'આઠ', 'નવ',
|
|
27
|
+
'દસ', 'અગિયાર', 'બાર', 'તેર', 'ચૌદ', 'પંદર', 'સોળ', 'સત્તર', 'અઢાર', 'ઓગણીસ',
|
|
28
|
+
'વીસ', 'એકવીસ', 'બાવીસ', 'ત્રેવીસ', 'ચોવીસ', 'પચીસ', 'છવ્વીસ', 'સત્તાવીસ', 'અઠ્ઠાવીસ', 'ઓગણત્રીસ',
|
|
29
|
+
'ત્રીસ', 'એકત્રીસ', 'બત્રીસ', 'તેત્રીસ', 'ચોત્રીસ', 'પાંત્રીસ', 'છત્રીસ', 'સાડત્રીસ', 'અડત્રીસ', 'ઓગણચાલીસ',
|
|
30
|
+
'ચાલીસ', 'એકતાલીસ', 'બેતાળીસ', 'ત્રેતાળીસ', 'ચુંમાલીસ', 'પિસ્તાલીસ', 'છેતાળીસ', 'સુડતાળીસ', 'અડતાળીસ', 'ઓગણપચાસ',
|
|
31
|
+
'પચાસ', 'એકાવન', 'બાવન', 'ત્રેપન', 'ચોપન', 'પંચાવન', 'છપ્પન', 'સત્તાવન', 'અઠ્ઠાવન', 'ઓગણસાઠ',
|
|
32
|
+
'સાઠ', 'એકસઠ', 'બાસઠ', 'ત્રેસઠ', 'ચોસઠ', 'પાંસઠ', 'છાસઠ', 'સડસઠ', 'અડસઠ', 'અગણોસિત્તેર',
|
|
33
|
+
'સિત્તેર', 'એકોતેર', 'બોતેર', 'તોતેર', 'ચુમોતેર', 'પંચોતેર', 'છોતેર', 'સિત્યોતેર', 'ઇઠ્યોતેર', 'ઓગણાએંસી',
|
|
34
|
+
'એંસી', 'એક્યાસી', 'બ્યાસી', 'ત્યાસી', 'ચોર્યાસી', 'પંચાસી', 'છ્યાસી', 'સિત્યાસી', 'અઠ્યાસી', 'નેવ્યાસી',
|
|
35
|
+
'નેવું', 'એકાણું', 'બાણું', 'ત્રાણું', 'ચોરાણું', 'પંચાણું', 'છન્નું', 'સત્તાણું', 'અઠ્ઠાણું', 'નવ્વાણું'
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
// Scale words: index 0 = units (empty), 1 = thousand, 2 = lakh, 3 = crore, etc.
|
|
39
|
+
const SCALE_WORDS = ['', 'હજાર', 'લાખ', 'કરોડ', 'અબજ', 'ખરબ', 'નીલ', 'પદ્મ', 'શંખ']
|
|
40
|
+
|
|
41
|
+
// ============================================================================
|
|
42
|
+
// Segment Splitting (inlined for performance)
|
|
43
|
+
// ============================================================================
|
|
44
|
+
|
|
45
|
+
function groupByThreeThenTwos (n) {
|
|
46
|
+
const numStr = n.toString()
|
|
47
|
+
if (numStr.length <= 3) return [Number(numStr)]
|
|
48
|
+
|
|
49
|
+
const segments = []
|
|
50
|
+
segments.unshift(Number(numStr.slice(-3)))
|
|
51
|
+
|
|
52
|
+
let remaining = numStr.slice(0, -3)
|
|
53
|
+
while (remaining.length > 0) {
|
|
54
|
+
segments.unshift(Number(remaining.slice(-2)))
|
|
55
|
+
remaining = remaining.slice(0, -2)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return segments
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function segmentToWords (n) {
|
|
62
|
+
if (n === 0) return ''
|
|
63
|
+
if (n < 100) return BELOW_HUNDRED[n]
|
|
64
|
+
|
|
65
|
+
const hundreds = Math.trunc(n / 100)
|
|
66
|
+
const remainder = n % 100
|
|
67
|
+
|
|
68
|
+
if (remainder === 0) {
|
|
69
|
+
return BELOW_HUNDRED[hundreds] + ' ' + HUNDRED
|
|
70
|
+
}
|
|
71
|
+
return BELOW_HUNDRED[hundreds] + ' ' + HUNDRED + ' ' + BELOW_HUNDRED[remainder]
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// ============================================================================
|
|
75
|
+
// Conversion Functions
|
|
76
|
+
// ============================================================================
|
|
77
|
+
|
|
78
|
+
function integerToWords (n) {
|
|
79
|
+
if (n === 0n) return ZERO
|
|
80
|
+
|
|
81
|
+
const segments = groupByThreeThenTwos(n)
|
|
82
|
+
const segmentCount = segments.length
|
|
83
|
+
const words = []
|
|
84
|
+
|
|
85
|
+
for (let i = 0; i < segmentCount; i++) {
|
|
86
|
+
const segmentValue = segments[i]
|
|
87
|
+
if (segmentValue === 0) continue
|
|
88
|
+
|
|
89
|
+
const scaleIndex = segmentCount - i - 1
|
|
90
|
+
words.push(segmentToWords(segmentValue))
|
|
91
|
+
if (scaleIndex > 0 && SCALE_WORDS[scaleIndex]) {
|
|
92
|
+
words.push(SCALE_WORDS[scaleIndex])
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return words.join(' ').trim()
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function decimalPartToWords (decimalPart) {
|
|
100
|
+
// Per-digit decimal reading
|
|
101
|
+
const digits = []
|
|
102
|
+
for (const char of decimalPart) {
|
|
103
|
+
const d = parseInt(char, 10)
|
|
104
|
+
digits.push(d === 0 ? ZERO : BELOW_HUNDRED[d])
|
|
105
|
+
}
|
|
106
|
+
return digits.join(' ')
|
|
141
107
|
}
|
|
142
108
|
|
|
143
109
|
/**
|
|
144
|
-
*
|
|
110
|
+
* Converts a numeric value to Gujarati words.
|
|
145
111
|
*
|
|
146
|
-
* @param {number|string|bigint} value - The
|
|
147
|
-
* @
|
|
148
|
-
* @returns {string} The Gujarati word representation
|
|
149
|
-
* @example
|
|
150
|
-
* convertToWords(42) // 'બેતાળીસ'
|
|
151
|
-
* convertToWords(1000) // 'એક હજાર'
|
|
152
|
-
* convertToWords(100000) // 'એક લાખ'
|
|
112
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
113
|
+
* @returns {string} The number in Gujarati words
|
|
153
114
|
*/
|
|
154
|
-
|
|
155
|
-
|
|
115
|
+
function toWords (value) {
|
|
116
|
+
const { isNegative, integerPart, decimalPart } = parseNumericValue(value)
|
|
117
|
+
|
|
118
|
+
let result = ''
|
|
119
|
+
|
|
120
|
+
if (isNegative) {
|
|
121
|
+
result = NEGATIVE + ' '
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
result += integerToWords(integerPart)
|
|
125
|
+
|
|
126
|
+
if (decimalPart) {
|
|
127
|
+
result += ' ' + DECIMAL_SEP + ' ' + decimalPartToWords(decimalPart)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return result
|
|
156
131
|
}
|
|
132
|
+
|
|
133
|
+
// ============================================================================
|
|
134
|
+
// Exports
|
|
135
|
+
// ============================================================================
|
|
136
|
+
|
|
137
|
+
export { toWords }
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hausa language converter - Functional Implementation
|
|
3
|
+
*
|
|
4
|
+
* Self-contained converter with precomputed lookup tables.
|
|
5
|
+
*
|
|
6
|
+
* Key features:
|
|
7
|
+
* - Authentic Boko orthography with ɗ (hooked d) and ' (glottal stop)
|
|
8
|
+
* - Teens with "sha" prefix (sha ɗaya = 11)
|
|
9
|
+
* - Compound numbers with "da" connector (ashirin da ɗaya = 21)
|
|
10
|
+
* - Arabic loanwords for tens (ashirin, talatin, arba'in, etc.)
|
|
11
|
+
* - Reversed multiplier order: "biyu ɗari" (200), "biyu dubu" (2000)
|
|
12
|
+
* - Implicit one before ɗari and dubu
|
|
13
|
+
* - Per-digit decimal reading
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { parseNumericValue } from '../utils/parse-numeric.js'
|
|
17
|
+
|
|
18
|
+
// ============================================================================
|
|
19
|
+
// Vocabulary
|
|
20
|
+
// ============================================================================
|
|
21
|
+
|
|
22
|
+
const ONES = ['', 'ɗaya', 'biyu', 'uku', 'huɗu', 'biyar', 'shida', 'bakwai', 'takwas', 'tara']
|
|
23
|
+
const TEENS = ['goma', 'sha ɗaya', 'sha biyu', 'sha uku', 'sha huɗu', 'sha biyar', 'sha shida', 'sha bakwai', 'sha takwas', 'sha tara']
|
|
24
|
+
// Arabic loanwords for tens
|
|
25
|
+
const TENS = ['', '', 'ashirin', 'talatin', "arba'in", 'hamsin', 'sittin', "saba'in", 'tamanin', "tis'in"]
|
|
26
|
+
|
|
27
|
+
const HUNDRED = 'ɗari'
|
|
28
|
+
const THOUSAND = 'dubu'
|
|
29
|
+
|
|
30
|
+
const ZERO = 'sifiri'
|
|
31
|
+
const NEGATIVE = 'babu'
|
|
32
|
+
const DECIMAL_SEP = 'digo'
|
|
33
|
+
|
|
34
|
+
// Short scale
|
|
35
|
+
const SCALE_WORDS = ['', THOUSAND, 'miliyan', 'biliyan']
|
|
36
|
+
|
|
37
|
+
// ============================================================================
|
|
38
|
+
// Precomputed Lookup Table
|
|
39
|
+
// ============================================================================
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Build segment for 0-999 with Hausa patterns.
|
|
43
|
+
* Hausa uses reversed order for hundreds: "biyu ɗari" (200)
|
|
44
|
+
* And "da" connector for ones: "ashirin da ɗaya" (21)
|
|
45
|
+
*/
|
|
46
|
+
function buildSegment (n) {
|
|
47
|
+
if (n === 0) return ''
|
|
48
|
+
|
|
49
|
+
const ones = n % 10
|
|
50
|
+
const tensDigit = Math.floor(n / 10) % 10
|
|
51
|
+
const hundredsDigit = Math.floor(n / 100)
|
|
52
|
+
|
|
53
|
+
const parts = []
|
|
54
|
+
|
|
55
|
+
// Hundreds: implicit one, or "biyu ɗari" (reversed order)
|
|
56
|
+
if (hundredsDigit > 0) {
|
|
57
|
+
if (hundredsDigit === 1) {
|
|
58
|
+
parts.push(HUNDRED)
|
|
59
|
+
} else {
|
|
60
|
+
// Reversed: multiplier + hundredWord
|
|
61
|
+
parts.push(ONES[hundredsDigit] + ' ' + HUNDRED)
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Tens and ones
|
|
66
|
+
const tensOnes = n % 100
|
|
67
|
+
|
|
68
|
+
if (tensOnes === 0) {
|
|
69
|
+
// Just hundreds
|
|
70
|
+
} else if (tensOnes < 10) {
|
|
71
|
+
// Single digit - with "da" connector if after hundreds
|
|
72
|
+
if (hundredsDigit > 0) {
|
|
73
|
+
parts.push('da ' + ONES[ones])
|
|
74
|
+
} else {
|
|
75
|
+
parts.push(ONES[ones])
|
|
76
|
+
}
|
|
77
|
+
} else if (tensOnes < 20) {
|
|
78
|
+
// Teens (10-19): "sha X"
|
|
79
|
+
parts.push(TEENS[ones])
|
|
80
|
+
} else if (ones === 0) {
|
|
81
|
+
// Even tens (20, 30, 40, etc.)
|
|
82
|
+
parts.push(TENS[tensDigit])
|
|
83
|
+
} else {
|
|
84
|
+
// Tens + ones with "da" connector
|
|
85
|
+
parts.push(TENS[tensDigit] + ' da ' + ONES[ones])
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return parts.join(' ')
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const SEGMENTS = new Array(1000)
|
|
92
|
+
for (let i = 0; i < 1000; i++) {
|
|
93
|
+
SEGMENTS[i] = buildSegment(i)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// ============================================================================
|
|
97
|
+
// Conversion Functions
|
|
98
|
+
// ============================================================================
|
|
99
|
+
|
|
100
|
+
function integerToWords (n) {
|
|
101
|
+
if (n === 0n) return ZERO
|
|
102
|
+
|
|
103
|
+
if (n < 1000n) {
|
|
104
|
+
return SEGMENTS[Number(n)]
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return buildLargeNumberWords(n)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Checks if a word is a single digit (1-9).
|
|
112
|
+
*/
|
|
113
|
+
function isSingleDigit (word) {
|
|
114
|
+
return ONES.slice(1).includes(word)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function buildLargeNumberWords (n) {
|
|
118
|
+
const numStr = n.toString()
|
|
119
|
+
const len = numStr.length
|
|
120
|
+
|
|
121
|
+
const segments = []
|
|
122
|
+
const segmentSize = 3
|
|
123
|
+
|
|
124
|
+
const remainderLen = len % segmentSize
|
|
125
|
+
let pos = 0
|
|
126
|
+
if (remainderLen > 0) {
|
|
127
|
+
segments.push(Number(numStr.slice(0, remainderLen)))
|
|
128
|
+
pos = remainderLen
|
|
129
|
+
}
|
|
130
|
+
while (pos < len) {
|
|
131
|
+
segments.push(Number(numStr.slice(pos, pos + segmentSize)))
|
|
132
|
+
pos += segmentSize
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Build raw parts (segment words and scale words)
|
|
136
|
+
const rawParts = []
|
|
137
|
+
let scaleIndex = segments.length - 1
|
|
138
|
+
|
|
139
|
+
for (let i = 0; i < segments.length; i++) {
|
|
140
|
+
const segment = segments[i]
|
|
141
|
+
|
|
142
|
+
if (segment !== 0) {
|
|
143
|
+
const scaleWord = SCALE_WORDS[scaleIndex] || ''
|
|
144
|
+
|
|
145
|
+
if (scaleIndex === 0) {
|
|
146
|
+
rawParts.push(SEGMENTS[segment])
|
|
147
|
+
} else {
|
|
148
|
+
rawParts.push(SEGMENTS[segment])
|
|
149
|
+
rawParts.push(scaleWord)
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
scaleIndex--
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Filter out implicit "ɗaya" before ɗari or dubu
|
|
157
|
+
const filtered = []
|
|
158
|
+
for (let i = 0; i < rawParts.length; i++) {
|
|
159
|
+
const part = rawParts[i]
|
|
160
|
+
const nextPart = rawParts[i + 1]
|
|
161
|
+
|
|
162
|
+
// Skip "ɗaya" before ɗari or dubu (implicit one)
|
|
163
|
+
if (part === 'ɗaya' && nextPart && (nextPart === HUNDRED || nextPart === THOUSAND)) {
|
|
164
|
+
continue
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
filtered.push(part)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Join with correct separators
|
|
171
|
+
const result = []
|
|
172
|
+
for (let i = 0; i < filtered.length; i++) {
|
|
173
|
+
const part = filtered[i]
|
|
174
|
+
const prevPart = i > 0 ? filtered[i - 1] : null
|
|
175
|
+
|
|
176
|
+
// Determine if we need "da" connector
|
|
177
|
+
// Use "da" when current is a single digit following a scale word
|
|
178
|
+
if (prevPart && isSingleDigit(part) &&
|
|
179
|
+
(prevPart === THOUSAND || prevPart === HUNDRED ||
|
|
180
|
+
SCALE_WORDS.includes(prevPart))) {
|
|
181
|
+
result.push(' da ')
|
|
182
|
+
} else if (i > 0) {
|
|
183
|
+
result.push(' ')
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
result.push(part)
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return result.join('')
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function decimalPartToWords (decimalPart) {
|
|
193
|
+
// Per-digit decimal reading
|
|
194
|
+
const digits = []
|
|
195
|
+
for (const char of decimalPart) {
|
|
196
|
+
const d = parseInt(char, 10)
|
|
197
|
+
digits.push(d === 0 ? ZERO : ONES[d])
|
|
198
|
+
}
|
|
199
|
+
return digits.join(' ')
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Converts a numeric value to Hausa words.
|
|
204
|
+
*
|
|
205
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
206
|
+
* @returns {string} The number in Hausa words
|
|
207
|
+
*/
|
|
208
|
+
function toWords (value) {
|
|
209
|
+
const { isNegative, integerPart, decimalPart } = parseNumericValue(value)
|
|
210
|
+
|
|
211
|
+
let result = ''
|
|
212
|
+
|
|
213
|
+
if (isNegative) {
|
|
214
|
+
result = NEGATIVE + ' '
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
result += integerToWords(integerPart)
|
|
218
|
+
|
|
219
|
+
if (decimalPart) {
|
|
220
|
+
result += ' ' + DECIMAL_SEP + ' ' + decimalPartToWords(decimalPart)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return result
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// ============================================================================
|
|
227
|
+
// Exports
|
|
228
|
+
// ============================================================================
|
|
229
|
+
|
|
230
|
+
export { toWords }
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts a numeric value to Biblical 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 Biblical Hebrew words
|
|
9
|
+
*/
|
|
10
|
+
export function toWords(value: number | string | bigint, options?: {
|
|
11
|
+
gender?: "masculine" | "feminine" | undefined;
|
|
12
|
+
andWord?: string | undefined;
|
|
13
|
+
}): string;
|