n2words 5.0.0 → 5.1.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 +128 -42
- package/README.md +6 -4
- package/dist/am-ET.js +2 -2
- package/dist/am-ET.umd.js +2 -2
- package/dist/am-Latn-ET.js +2 -2
- package/dist/am-Latn-ET.umd.js +2 -2
- package/dist/ar-SA.js +2 -2
- package/dist/ar-SA.umd.js +2 -2
- package/dist/az-AZ.js +2 -2
- package/dist/az-AZ.umd.js +2 -2
- package/dist/bn-BD.js +2 -2
- package/dist/bn-BD.umd.js +2 -2
- package/dist/cs-CZ.js +2 -2
- package/dist/cs-CZ.umd.js +2 -2
- package/dist/da-DK.js +2 -2
- package/dist/da-DK.umd.js +2 -2
- package/dist/de-DE.js +2 -2
- package/dist/de-DE.umd.js +2 -2
- package/dist/el-GR.js +2 -2
- package/dist/el-GR.umd.js +2 -2
- package/dist/en-AU.js +2 -2
- package/dist/en-AU.umd.js +2 -2
- package/dist/en-BD.js +2 -2
- package/dist/en-BD.umd.js +2 -2
- package/dist/en-CA.js +2 -2
- package/dist/en-CA.umd.js +2 -2
- package/dist/en-GB.js +2 -2
- package/dist/en-GB.umd.js +2 -2
- package/dist/en-GH.js +2 -2
- package/dist/en-GH.umd.js +2 -2
- package/dist/en-IE.js +2 -2
- package/dist/en-IE.umd.js +2 -2
- package/dist/en-IN.js +2 -2
- package/dist/en-IN.umd.js +2 -2
- package/dist/en-KE.js +2 -2
- package/dist/en-KE.umd.js +2 -2
- package/dist/en-MY.js +2 -2
- package/dist/en-MY.umd.js +2 -2
- package/dist/en-NG.js +2 -2
- package/dist/en-NG.umd.js +2 -2
- package/dist/en-NZ.js +2 -2
- package/dist/en-NZ.umd.js +2 -2
- package/dist/en-PH.js +2 -2
- package/dist/en-PH.umd.js +2 -2
- package/dist/en-PK.js +2 -2
- package/dist/en-PK.umd.js +2 -2
- package/dist/en-SG.js +2 -2
- package/dist/en-SG.umd.js +2 -2
- package/dist/en-US.js +2 -2
- package/dist/en-US.umd.js +2 -2
- package/dist/en-ZA.js +2 -2
- package/dist/en-ZA.umd.js +2 -2
- package/dist/es-ES.js +2 -2
- package/dist/es-ES.umd.js +2 -2
- package/dist/es-MX.js +2 -2
- package/dist/es-MX.umd.js +2 -2
- package/dist/es-US.js +2 -2
- package/dist/es-US.umd.js +2 -2
- package/dist/fa-IR.js +2 -2
- package/dist/fa-IR.umd.js +2 -2
- package/dist/fi-FI.js +2 -2
- package/dist/fi-FI.umd.js +2 -2
- package/dist/fil-PH.js +2 -2
- package/dist/fil-PH.umd.js +2 -2
- package/dist/fr-BE.js +2 -2
- package/dist/fr-BE.umd.js +2 -2
- package/dist/fr-FR.js +2 -2
- package/dist/fr-FR.umd.js +2 -2
- package/dist/gu-IN.js +2 -2
- package/dist/gu-IN.umd.js +2 -2
- package/dist/ha-NG.js +2 -2
- package/dist/ha-NG.umd.js +2 -2
- package/dist/hbo-IL.js +2 -2
- package/dist/hbo-IL.umd.js +2 -2
- package/dist/he-IL.js +2 -2
- package/dist/he-IL.umd.js +2 -2
- package/dist/hi-IN.js +2 -2
- package/dist/hi-IN.umd.js +2 -2
- package/dist/hr-HR.js +2 -2
- package/dist/hr-HR.umd.js +2 -2
- package/dist/hu-HU.js +2 -2
- package/dist/hu-HU.umd.js +2 -2
- package/dist/id-ID.js +2 -2
- package/dist/id-ID.umd.js +2 -2
- package/dist/it-IT.js +2 -2
- package/dist/it-IT.umd.js +2 -2
- package/dist/ja-JP.js +2 -2
- package/dist/ja-JP.umd.js +2 -2
- package/dist/ka-GE.js +2 -2
- package/dist/ka-GE.umd.js +2 -2
- package/dist/kn-IN.js +2 -2
- package/dist/kn-IN.umd.js +2 -2
- package/dist/ko-KR.js +2 -2
- package/dist/ko-KR.umd.js +2 -2
- package/dist/lt-LT.js +2 -2
- package/dist/lt-LT.umd.js +2 -2
- package/dist/lv-LV.js +2 -2
- package/dist/lv-LV.umd.js +2 -2
- package/dist/mr-IN.js +2 -2
- package/dist/mr-IN.umd.js +2 -2
- package/dist/ms-MY.js +2 -2
- package/dist/ms-MY.umd.js +2 -2
- package/dist/nb-NO.js +2 -2
- package/dist/nb-NO.umd.js +2 -2
- package/dist/nl-NL.js +2 -2
- package/dist/nl-NL.umd.js +2 -2
- package/dist/pa-IN.js +2 -2
- package/dist/pa-IN.umd.js +2 -2
- package/dist/pl-PL.js +2 -2
- package/dist/pl-PL.umd.js +2 -2
- package/dist/pt-BR.js +2 -2
- package/dist/pt-BR.umd.js +2 -2
- package/dist/pt-PT.js +2 -2
- package/dist/pt-PT.umd.js +2 -2
- package/dist/ro-RO.js +2 -2
- package/dist/ro-RO.umd.js +2 -2
- package/dist/ru-RU.js +2 -2
- package/dist/ru-RU.umd.js +2 -2
- package/dist/sr-Cyrl-RS.js +2 -2
- package/dist/sr-Cyrl-RS.umd.js +2 -2
- package/dist/sr-Latn-RS.js +2 -2
- package/dist/sr-Latn-RS.umd.js +2 -2
- package/dist/sv-SE.js +2 -2
- package/dist/sv-SE.umd.js +2 -2
- package/dist/sw-KE.js +2 -2
- package/dist/sw-KE.umd.js +2 -2
- package/dist/ta-IN.js +2 -2
- package/dist/ta-IN.umd.js +2 -2
- package/dist/te-IN.js +2 -2
- package/dist/te-IN.umd.js +2 -2
- package/dist/th-TH.js +2 -2
- package/dist/th-TH.umd.js +2 -2
- package/dist/tr-TR.js +2 -2
- package/dist/tr-TR.umd.js +2 -2
- package/dist/uk-UA.js +2 -2
- package/dist/uk-UA.umd.js +2 -2
- package/dist/ur-PK.js +2 -2
- package/dist/ur-PK.umd.js +2 -2
- package/dist/vi-VN.js +2 -2
- package/dist/vi-VN.umd.js +2 -2
- package/dist/yo-NG.js +2 -2
- package/dist/yo-NG.umd.js +2 -2
- package/dist/zh-Hans-CN.js +2 -2
- package/dist/zh-Hans-CN.umd.js +2 -2
- package/dist/zh-Hant-TW.js +2 -2
- package/dist/zh-Hant-TW.umd.js +2 -2
- package/package.json +31 -22
- package/src/am-ET.d.ts +3 -5
- package/src/am-ET.js +41 -16
- package/src/am-Latn-ET.d.ts +3 -5
- package/src/am-Latn-ET.js +45 -16
- package/src/ar-SA.d.ts +44 -18
- package/src/ar-SA.js +93 -40
- package/src/az-AZ.d.ts +3 -5
- package/src/az-AZ.js +58 -20
- package/src/bn-BD.d.ts +3 -5
- package/src/bn-BD.js +32 -16
- package/src/cs-CZ.d.ts +3 -6
- package/src/cs-CZ.js +66 -42
- package/src/da-DK.d.ts +3 -6
- package/src/da-DK.js +53 -48
- package/src/de-DE.d.ts +17 -11
- package/src/de-DE.js +88 -57
- package/src/el-GR.d.ts +3 -6
- package/src/el-GR.js +45 -32
- package/src/en-AU.d.ts +17 -11
- package/src/en-AU.js +56 -41
- package/src/en-BD.d.ts +17 -11
- package/src/en-BD.js +60 -41
- package/src/en-CA.d.ts +36 -18
- package/src/en-CA.js +67 -46
- package/src/en-GB.d.ts +17 -11
- package/src/en-GB.js +56 -41
- package/src/en-GH.d.ts +32 -3
- package/src/en-GH.js +104 -26
- package/src/en-IE.d.ts +17 -11
- package/src/en-IE.js +56 -41
- package/src/en-IN.d.ts +17 -11
- package/src/en-IN.js +60 -41
- package/src/en-KE.d.ts +28 -3
- package/src/en-KE.js +93 -26
- package/src/en-MY.d.ts +26 -3
- package/src/en-MY.js +91 -26
- package/src/en-NG.d.ts +17 -11
- package/src/en-NG.js +56 -41
- package/src/en-NZ.d.ts +32 -3
- package/src/en-NZ.js +85 -31
- package/src/en-PH.d.ts +32 -3
- package/src/en-PH.js +97 -26
- package/src/en-PK.d.ts +17 -11
- package/src/en-PK.js +60 -41
- package/src/en-SG.d.ts +28 -3
- package/src/en-SG.js +93 -26
- package/src/en-US.d.ts +36 -18
- package/src/en-US.js +70 -47
- package/src/en-ZA.d.ts +17 -11
- package/src/en-ZA.js +56 -41
- package/src/es-ES.d.ts +53 -21
- package/src/es-ES.js +104 -56
- package/src/es-MX.d.ts +53 -21
- package/src/es-MX.js +104 -56
- package/src/es-US.d.ts +53 -21
- package/src/es-US.js +92 -51
- package/src/fa-IR.d.ts +3 -5
- package/src/fa-IR.js +28 -13
- package/src/fi-FI.d.ts +3 -6
- package/src/fi-FI.js +47 -29
- package/src/fil-PH.d.ts +3 -5
- package/src/fil-PH.js +61 -28
- package/src/fr-BE.d.ts +31 -15
- package/src/fr-BE.js +128 -57
- package/src/fr-FR.d.ts +31 -16
- package/src/fr-FR.js +97 -60
- package/src/gu-IN.d.ts +3 -5
- package/src/gu-IN.js +31 -16
- package/src/ha-NG.d.ts +3 -5
- package/src/ha-NG.js +55 -27
- package/src/hbo-IL.d.ts +26 -12
- package/src/hbo-IL.js +92 -51
- package/src/he-IL.d.ts +17 -10
- package/src/he-IL.js +92 -50
- package/src/hi-IN.d.ts +3 -5
- package/src/hi-IN.js +30 -17
- package/src/hr-HR.d.ts +21 -10
- package/src/hr-HR.js +89 -33
- package/src/hu-HU.d.ts +3 -5
- package/src/hu-HU.js +57 -23
- package/src/id-ID.d.ts +3 -5
- package/src/id-ID.js +56 -23
- package/src/it-IT.d.ts +17 -11
- package/src/it-IT.js +74 -43
- package/src/ja-JP.d.ts +3 -6
- package/src/ja-JP.js +39 -26
- package/src/ka-GE.d.ts +3 -6
- package/src/ka-GE.js +38 -26
- package/src/kn-IN.d.ts +3 -5
- package/src/kn-IN.js +31 -16
- package/src/ko-KR.d.ts +3 -6
- package/src/ko-KR.js +34 -26
- package/src/lt-LT.d.ts +21 -11
- package/src/lt-LT.js +64 -42
- package/src/lv-LV.d.ts +21 -11
- package/src/lv-LV.js +79 -51
- package/src/mr-IN.d.ts +3 -5
- package/src/mr-IN.js +31 -16
- package/src/ms-MY.d.ts +3 -5
- package/src/ms-MY.js +58 -24
- package/src/nb-NO.d.ts +3 -6
- package/src/nb-NO.js +54 -34
- package/src/nl-NL.d.ts +41 -20
- package/src/nl-NL.js +111 -69
- package/src/pa-IN.d.ts +3 -5
- package/src/pa-IN.js +32 -16
- package/src/pl-PL.d.ts +21 -11
- package/src/pl-PL.js +69 -45
- package/src/pt-BR.d.ts +22 -11
- package/src/pt-BR.js +93 -53
- package/src/pt-PT.d.ts +17 -11
- package/src/pt-PT.js +80 -48
- package/src/ro-RO.d.ts +21 -11
- package/src/ro-RO.js +77 -39
- package/src/ru-RU.d.ts +35 -15
- package/src/ru-RU.js +100 -38
- package/src/sr-Cyrl-RS.d.ts +35 -15
- package/src/sr-Cyrl-RS.js +100 -38
- package/src/sr-Latn-RS.d.ts +35 -15
- package/src/sr-Latn-RS.js +100 -38
- package/src/sv-SE.d.ts +3 -6
- package/src/sv-SE.js +53 -34
- package/src/sw-KE.d.ts +3 -5
- package/src/sw-KE.js +50 -20
- package/src/ta-IN.d.ts +3 -5
- package/src/ta-IN.js +29 -17
- package/src/te-IN.d.ts +3 -5
- package/src/te-IN.js +31 -16
- package/src/th-TH.d.ts +3 -5
- package/src/th-TH.js +42 -19
- package/src/tr-TR.d.ts +17 -11
- package/src/tr-TR.js +63 -37
- package/src/uk-UA.d.ts +21 -10
- package/src/uk-UA.js +89 -33
- package/src/ur-PK.d.ts +3 -5
- package/src/ur-PK.js +32 -16
- package/src/utils/check-max.d.ts +26 -0
- package/src/utils/check-max.js +33 -0
- package/src/utils/expand-scientific.d.ts +0 -4
- package/src/utils/expand-scientific.js +7 -9
- package/src/utils/is-plain-object.d.ts +3 -4
- package/src/utils/is-plain-object.js +3 -4
- package/src/utils/parse-cardinal.d.ts +1 -2
- package/src/utils/parse-cardinal.js +12 -9
- package/src/utils/parse-currency.d.ts +1 -2
- package/src/utils/parse-currency.js +9 -11
- package/src/utils/parse-ordinal.d.ts +0 -1
- package/src/utils/parse-ordinal.js +9 -10
- package/src/utils/resolve-options.d.ts +17 -0
- package/src/utils/resolve-options.js +56 -0
- package/src/utils/scale.d.ts +49 -0
- package/src/utils/scale.js +65 -0
- package/src/vi-VN.d.ts +3 -6
- package/src/vi-VN.js +41 -28
- package/src/yo-NG.d.ts +3 -5
- package/src/yo-NG.js +49 -33
- package/src/zh-Hans-CN.d.ts +45 -20
- package/src/zh-Hans-CN.js +84 -31
- package/src/zh-Hant-TW.d.ts +45 -20
- package/src/zh-Hant-TW.js +85 -34
- package/src/utils/validate-options.d.ts +0 -8
- package/src/utils/validate-options.js +0 -16
package/src/en-IE.js
CHANGED
|
@@ -23,7 +23,9 @@
|
|
|
23
23
|
import { parseCardinalValue } from './utils/parse-cardinal.js'
|
|
24
24
|
import { parseCurrencyValue } from './utils/parse-currency.js'
|
|
25
25
|
import { parseOrdinalValue } from './utils/parse-ordinal.js'
|
|
26
|
-
import {
|
|
26
|
+
import { checkMax } from './utils/check-max.js'
|
|
27
|
+
import { western } from './utils/scale.js'
|
|
28
|
+
import { resolveOptions } from './utils/resolve-options.js'
|
|
27
29
|
|
|
28
30
|
// ============================================================================
|
|
29
31
|
// Vocabulary (module-level constants)
|
|
@@ -38,9 +40,13 @@ const SCALES = [
|
|
|
38
40
|
'quintillion', 'sextillion', 'septillion', 'octillion', 'nonillion',
|
|
39
41
|
'decillion', 'undecillion', 'duodecillion', 'tredecillion', 'quattuordecillion',
|
|
40
42
|
'quindecillion', 'sexdecillion', 'septendecillion', 'octodecillion', 'novemdecillion',
|
|
41
|
-
'vigintillion'
|
|
43
|
+
'vigintillion',
|
|
42
44
|
]
|
|
43
45
|
|
|
46
|
+
export const cardinalMax = western(SCALES.length)
|
|
47
|
+
export const ordinalMax = western(SCALES.length)
|
|
48
|
+
export const currencyMax = western(SCALES.length)
|
|
49
|
+
|
|
44
50
|
const HUNDRED = 'hundred'
|
|
45
51
|
const ZERO = 'zero'
|
|
46
52
|
const NEGATIVE = 'minus'
|
|
@@ -65,11 +71,10 @@ const segmentResult = { word: '', hasHundred: false }
|
|
|
65
71
|
|
|
66
72
|
/**
|
|
67
73
|
* Builds words for a 0-999 segment.
|
|
68
|
-
*
|
|
69
74
|
* @param {number} n - Number 0-999
|
|
70
|
-
* @returns {{ word: string, hasHundred: boolean }}
|
|
75
|
+
* @returns {{ word: string, hasHundred: boolean }} The segment words and whether a hundreds part is present.
|
|
71
76
|
*/
|
|
72
|
-
function buildSegment
|
|
77
|
+
function buildSegment(n) {
|
|
73
78
|
if (n === 0) {
|
|
74
79
|
segmentResult.word = ''
|
|
75
80
|
segmentResult.hasHundred = false
|
|
@@ -84,9 +89,11 @@ function buildSegment (n) {
|
|
|
84
89
|
let tensOnes = ''
|
|
85
90
|
if (tens === 1) {
|
|
86
91
|
tensOnes = TEENS[ones]
|
|
87
|
-
}
|
|
92
|
+
}
|
|
93
|
+
else if (tens >= 2) {
|
|
88
94
|
tensOnes = ones > 0 ? TENS[tens] + '-' + ONES[ones] : TENS[tens]
|
|
89
|
-
}
|
|
95
|
+
}
|
|
96
|
+
else if (ones > 0) {
|
|
90
97
|
tensOnes = ONES[ones]
|
|
91
98
|
}
|
|
92
99
|
|
|
@@ -94,11 +101,13 @@ function buildSegment (n) {
|
|
|
94
101
|
if (hundreds > 0) {
|
|
95
102
|
if (tensOnes) {
|
|
96
103
|
segmentResult.word = ONES[hundreds] + ' ' + HUNDRED + ' and ' + tensOnes
|
|
97
|
-
}
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
98
106
|
segmentResult.word = ONES[hundreds] + ' ' + HUNDRED
|
|
99
107
|
}
|
|
100
108
|
segmentResult.hasHundred = true
|
|
101
|
-
}
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
102
111
|
segmentResult.word = tensOnes
|
|
103
112
|
segmentResult.hasHundred = false
|
|
104
113
|
}
|
|
@@ -112,11 +121,10 @@ function buildSegment (n) {
|
|
|
112
121
|
|
|
113
122
|
/**
|
|
114
123
|
* Converts a non-negative integer to English words.
|
|
115
|
-
*
|
|
116
124
|
* @param {bigint} n - Non-negative integer to convert
|
|
117
125
|
* @returns {string} English words
|
|
118
126
|
*/
|
|
119
|
-
function integerToWords
|
|
127
|
+
function integerToWords(n) {
|
|
120
128
|
if (n === 0n) return ZERO
|
|
121
129
|
|
|
122
130
|
// Fast path: numbers < 1000
|
|
@@ -147,11 +155,10 @@ function integerToWords (n) {
|
|
|
147
155
|
/**
|
|
148
156
|
* Builds words for numbers >= 1,000,000.
|
|
149
157
|
* Uses BigInt division for faster segment extraction.
|
|
150
|
-
*
|
|
151
158
|
* @param {bigint} n - Number >= 1,000,000
|
|
152
159
|
* @returns {string} English words
|
|
153
160
|
*/
|
|
154
|
-
function buildLargeNumberWords
|
|
161
|
+
function buildLargeNumberWords(n) {
|
|
155
162
|
// Extract segments using BigInt division
|
|
156
163
|
// Segments are stored least-significant first (index 0 = ones, 1 = thousands, etc.)
|
|
157
164
|
const segments = []
|
|
@@ -194,7 +201,8 @@ function buildLargeNumberWords (n) {
|
|
|
194
201
|
if (i > 0) {
|
|
195
202
|
result += ' ' + SCALES[i - 1]
|
|
196
203
|
prevWasScale = true
|
|
197
|
-
}
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
198
206
|
prevWasScale = false
|
|
199
207
|
}
|
|
200
208
|
}
|
|
@@ -204,11 +212,10 @@ function buildLargeNumberWords (n) {
|
|
|
204
212
|
|
|
205
213
|
/**
|
|
206
214
|
* Converts decimal digits to English words.
|
|
207
|
-
*
|
|
208
215
|
* @param {string} decimalPart - Decimal digits (without the point)
|
|
209
216
|
* @returns {string} English words for decimal part
|
|
210
217
|
*/
|
|
211
|
-
function decimalPartToWords
|
|
218
|
+
function decimalPartToWords(decimalPart) {
|
|
212
219
|
let result = ''
|
|
213
220
|
|
|
214
221
|
// Handle leading zeros
|
|
@@ -234,19 +241,20 @@ function decimalPartToWords (decimalPart) {
|
|
|
234
241
|
*
|
|
235
242
|
* This is the main public API. It accepts any valid numeric input
|
|
236
243
|
* (number, string, or bigint) and handles parsing internally.
|
|
237
|
-
*
|
|
238
244
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
239
245
|
* @returns {string} The number in English words
|
|
240
246
|
* @throws {TypeError} If value is not a valid numeric type
|
|
241
247
|
* @throws {Error} If value is not a valid number format
|
|
242
|
-
*
|
|
243
248
|
* @example
|
|
244
249
|
* toCardinal(42) // 'forty-two'
|
|
245
250
|
* toCardinal(-3.14) // 'minus three point fourteen'
|
|
246
251
|
* toCardinal('1000000') // 'one million'
|
|
247
252
|
*/
|
|
248
|
-
function toCardinal
|
|
253
|
+
function toCardinal(value) {
|
|
249
254
|
const { isNegative, integerPart, decimalPart } = parseCardinalValue(value)
|
|
255
|
+
// Both the integer part and the decimal's significant digits are spelled via
|
|
256
|
+
// the scale builder, so both must clear the ceiling.
|
|
257
|
+
checkMax(integerPart, cardinalMax, decimalPart)
|
|
250
258
|
|
|
251
259
|
let result = ''
|
|
252
260
|
|
|
@@ -270,11 +278,10 @@ function toCardinal (value) {
|
|
|
270
278
|
/**
|
|
271
279
|
* Builds ordinal words for a 0-999 segment (final segment only).
|
|
272
280
|
* Returns ordinal form: "first", "twenty-third", "one hundred forty-fifth"
|
|
273
|
-
*
|
|
274
281
|
* @param {number} n - Number 0-999
|
|
275
282
|
* @returns {string} Ordinal words for this segment
|
|
276
283
|
*/
|
|
277
|
-
function buildOrdinalSegment
|
|
284
|
+
function buildOrdinalSegment(n) {
|
|
278
285
|
const ones = n % 10
|
|
279
286
|
const tens = Math.trunc(n / 10) % 10
|
|
280
287
|
const hundreds = Math.trunc(n / 100)
|
|
@@ -284,15 +291,18 @@ function buildOrdinalSegment (n) {
|
|
|
284
291
|
if (tens === 1) {
|
|
285
292
|
// Teens: 10-19 → "tenth" through "nineteenth"
|
|
286
293
|
tensOnesOrdinal = ORDINAL_TEENS[ones]
|
|
287
|
-
}
|
|
294
|
+
}
|
|
295
|
+
else if (tens >= 2) {
|
|
288
296
|
if (ones > 0) {
|
|
289
297
|
// Compound: "twenty-first", "thirty-second", etc.
|
|
290
298
|
tensOnesOrdinal = TENS[tens] + '-' + ORDINAL_ONES[ones]
|
|
291
|
-
}
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
292
301
|
// Round tens: "twentieth", "thirtieth", etc.
|
|
293
302
|
tensOnesOrdinal = ORDINAL_TENS[tens]
|
|
294
303
|
}
|
|
295
|
-
}
|
|
304
|
+
}
|
|
305
|
+
else if (ones > 0) {
|
|
296
306
|
// Single digit: "first", "second", etc.
|
|
297
307
|
tensOnesOrdinal = ORDINAL_ONES[ones]
|
|
298
308
|
}
|
|
@@ -302,7 +312,8 @@ function buildOrdinalSegment (n) {
|
|
|
302
312
|
if (tensOnesOrdinal) {
|
|
303
313
|
// "one hundred twenty-first"
|
|
304
314
|
return ONES[hundreds] + ' ' + HUNDRED + ' ' + tensOnesOrdinal
|
|
305
|
-
}
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
306
317
|
// "one hundredth", "two hundredth", etc.
|
|
307
318
|
return ONES[hundreds] + ' hundredth'
|
|
308
319
|
}
|
|
@@ -314,11 +325,10 @@ function buildOrdinalSegment (n) {
|
|
|
314
325
|
/**
|
|
315
326
|
* Converts a positive integer to ordinal words.
|
|
316
327
|
* Generates ordinals directly without string manipulation.
|
|
317
|
-
*
|
|
318
328
|
* @param {bigint} n - Positive integer to convert
|
|
319
329
|
* @returns {string} Ordinal English words
|
|
320
330
|
*/
|
|
321
|
-
function integerToOrdinal
|
|
331
|
+
function integerToOrdinal(n) {
|
|
322
332
|
// Fast path: numbers < 1000
|
|
323
333
|
if (n < 1000n) {
|
|
324
334
|
return buildOrdinalSegment(Number(n))
|
|
@@ -346,11 +356,10 @@ function integerToOrdinal (n) {
|
|
|
346
356
|
/**
|
|
347
357
|
* Builds ordinal words for numbers >= 1,000,000.
|
|
348
358
|
* All segments except the final one are cardinal; final segment is ordinal.
|
|
349
|
-
*
|
|
350
359
|
* @param {bigint} n - Number >= 1,000,000
|
|
351
360
|
* @returns {string} Ordinal English words
|
|
352
361
|
*/
|
|
353
|
-
function buildLargeOrdinal
|
|
362
|
+
function buildLargeOrdinal(n) {
|
|
354
363
|
// Extract segments (least-significant first)
|
|
355
364
|
const segments = []
|
|
356
365
|
let temp = n
|
|
@@ -384,11 +393,13 @@ function buildLargeOrdinal (n) {
|
|
|
384
393
|
if (i === 0) {
|
|
385
394
|
// Units position: use ordinal segment
|
|
386
395
|
result += buildOrdinalSegment(segment)
|
|
387
|
-
}
|
|
396
|
+
}
|
|
397
|
+
else {
|
|
388
398
|
// Scale position with no remainder below: "one millionth"
|
|
389
399
|
result += buildSegment(segment).word + ' ' + SCALES[i - 1] + 'th'
|
|
390
400
|
}
|
|
391
|
-
}
|
|
401
|
+
}
|
|
402
|
+
else {
|
|
392
403
|
// Non-final segments are cardinal
|
|
393
404
|
result += buildSegment(segment).word
|
|
394
405
|
if (i > 0) {
|
|
@@ -402,12 +413,10 @@ function buildLargeOrdinal (n) {
|
|
|
402
413
|
|
|
403
414
|
/**
|
|
404
415
|
* Converts a numeric value to Irish English ordinal words.
|
|
405
|
-
*
|
|
406
416
|
* @param {number | string | bigint} value - The numeric value to convert (must be a positive integer)
|
|
407
417
|
* @returns {string} The number as ordinal words (e.g., "first", "forty-second")
|
|
408
418
|
* @throws {TypeError} If value is not a valid numeric type
|
|
409
419
|
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
410
|
-
*
|
|
411
420
|
* @example
|
|
412
421
|
* toOrdinal(1) // 'first'
|
|
413
422
|
* toOrdinal(2) // 'second'
|
|
@@ -418,8 +427,9 @@ function buildLargeOrdinal (n) {
|
|
|
418
427
|
* toOrdinal(101) // 'one hundred first'
|
|
419
428
|
* toOrdinal(1000) // 'one thousandth'
|
|
420
429
|
*/
|
|
421
|
-
function toOrdinal
|
|
430
|
+
function toOrdinal(value) {
|
|
422
431
|
const integerPart = parseOrdinalValue(value)
|
|
432
|
+
checkMax(integerPart, ordinalMax)
|
|
423
433
|
return integerToOrdinal(integerPart)
|
|
424
434
|
}
|
|
425
435
|
|
|
@@ -427,16 +437,21 @@ function toOrdinal (value) {
|
|
|
427
437
|
// CURRENCY: toCurrency(value, options?)
|
|
428
438
|
// ============================================================================
|
|
429
439
|
|
|
440
|
+
/**
|
|
441
|
+
* @typedef {object} CurrencyOptions
|
|
442
|
+
* @property {boolean} [and] - Use "and" between euro and cent (e.g., "one euro and fifty cents")
|
|
443
|
+
*/
|
|
444
|
+
|
|
445
|
+
/** @type {Required<CurrencyOptions>} */
|
|
446
|
+
export const currencyDefaults = { and: true }
|
|
447
|
+
|
|
430
448
|
/**
|
|
431
449
|
* Converts a numeric value to Irish English currency words.
|
|
432
|
-
*
|
|
433
450
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
434
|
-
* @param {
|
|
435
|
-
* @param {boolean} [options.and=true] - Use "and" between euro and cent (e.g., "one euro and fifty cents")
|
|
451
|
+
* @param {CurrencyOptions} [options] - Optional configuration
|
|
436
452
|
* @returns {string} The amount in Irish English currency words
|
|
437
453
|
* @throws {TypeError} If value is not a valid numeric type
|
|
438
454
|
* @throws {Error} If value is not a valid number format
|
|
439
|
-
*
|
|
440
455
|
* @example
|
|
441
456
|
* toCurrency(42.50) // 'forty-two euro and fifty cents'
|
|
442
457
|
* toCurrency(1) // 'one euro'
|
|
@@ -444,10 +459,10 @@ function toOrdinal (value) {
|
|
|
444
459
|
* toCurrency(0.01) // 'one cent'
|
|
445
460
|
* toCurrency(42.50, { and: false }) // 'forty-two euro fifty cents'
|
|
446
461
|
*/
|
|
447
|
-
function toCurrency
|
|
448
|
-
options = validateOptions(options)
|
|
462
|
+
function toCurrency(value, options) {
|
|
449
463
|
const { isNegative, dollars: euros, cents } = parseCurrencyValue(value)
|
|
450
|
-
|
|
464
|
+
checkMax(euros, currencyMax)
|
|
465
|
+
const { and: useAnd } = resolveOptions(options, currencyDefaults)
|
|
451
466
|
|
|
452
467
|
// Build result
|
|
453
468
|
let result = ''
|
package/src/en-IN.d.ts
CHANGED
|
@@ -1,11 +1,24 @@
|
|
|
1
|
+
export const cardinalMax: bigint;
|
|
2
|
+
export const ordinalMax: bigint;
|
|
3
|
+
export const currencyMax: bigint;
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {object} CurrencyOptions
|
|
6
|
+
* @property {boolean} [and] - Use "and" between rupees and paise
|
|
7
|
+
*/
|
|
8
|
+
/** @type {Required<CurrencyOptions>} */
|
|
9
|
+
export const currencyDefaults: Required<CurrencyOptions>;
|
|
10
|
+
export type CurrencyOptions = {
|
|
11
|
+
/**
|
|
12
|
+
* - Use "and" between rupees and paise
|
|
13
|
+
*/
|
|
14
|
+
and?: boolean | undefined;
|
|
15
|
+
};
|
|
1
16
|
/**
|
|
2
17
|
* Converts a numeric value to English words using Indian numbering.
|
|
3
|
-
*
|
|
4
18
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
5
19
|
* @returns {string} The number in English words
|
|
6
20
|
* @throws {TypeError} If value is not a valid numeric type
|
|
7
21
|
* @throws {Error} If value is not a valid number format
|
|
8
|
-
*
|
|
9
22
|
* @example
|
|
10
23
|
* toCardinal(42) // 'forty-two'
|
|
11
24
|
* toCardinal(100000) // 'one lakh'
|
|
@@ -15,12 +28,10 @@
|
|
|
15
28
|
export function toCardinal(value: number | string | bigint): string;
|
|
16
29
|
/**
|
|
17
30
|
* Converts a numeric value to English ordinal words using Indian numbering.
|
|
18
|
-
*
|
|
19
31
|
* @param {number | string | bigint} value - The numeric value to convert (must be a positive integer)
|
|
20
32
|
* @returns {string} The number as ordinal words
|
|
21
33
|
* @throws {TypeError} If value is not a valid numeric type
|
|
22
34
|
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
23
|
-
*
|
|
24
35
|
* @example
|
|
25
36
|
* toOrdinal(1) // 'first'
|
|
26
37
|
* toOrdinal(100000) // 'one lakhth'
|
|
@@ -29,14 +40,11 @@ export function toCardinal(value: number | string | bigint): string;
|
|
|
29
40
|
export function toOrdinal(value: number | string | bigint): string;
|
|
30
41
|
/**
|
|
31
42
|
* Converts a numeric value to Indian English currency words.
|
|
32
|
-
*
|
|
33
43
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
34
|
-
* @param {
|
|
35
|
-
* @param {boolean} [options.and=true] - Use "and" between rupees and paise
|
|
44
|
+
* @param {CurrencyOptions} [options] - Optional configuration
|
|
36
45
|
* @returns {string} The amount in Indian English currency words
|
|
37
46
|
* @throws {TypeError} If value is not a valid numeric type
|
|
38
47
|
* @throws {Error} If value is not a valid number format
|
|
39
|
-
*
|
|
40
48
|
* @example
|
|
41
49
|
* toCurrency(42.50) // 'forty-two rupees and fifty paise'
|
|
42
50
|
* toCurrency(100000) // 'one lakh rupees'
|
|
@@ -44,6 +52,4 @@ export function toOrdinal(value: number | string | bigint): string;
|
|
|
44
52
|
* toCurrency(0.50) // 'fifty paise'
|
|
45
53
|
* toCurrency(42.50, { and: false }) // 'forty-two rupees fifty paise'
|
|
46
54
|
*/
|
|
47
|
-
export function toCurrency(value: number | string | bigint, options?:
|
|
48
|
-
and?: boolean | undefined;
|
|
49
|
-
}): string;
|
|
55
|
+
export function toCurrency(value: number | string | bigint, options?: CurrencyOptions): string;
|
package/src/en-IN.js
CHANGED
|
@@ -13,7 +13,9 @@
|
|
|
13
13
|
import { parseCardinalValue } from './utils/parse-cardinal.js'
|
|
14
14
|
import { parseCurrencyValue } from './utils/parse-currency.js'
|
|
15
15
|
import { parseOrdinalValue } from './utils/parse-ordinal.js'
|
|
16
|
-
import {
|
|
16
|
+
import { checkMax } from './utils/check-max.js'
|
|
17
|
+
import { indian } from './utils/scale.js'
|
|
18
|
+
import { resolveOptions } from './utils/resolve-options.js'
|
|
17
19
|
|
|
18
20
|
// ============================================================================
|
|
19
21
|
// Vocabulary (module-level constants)
|
|
@@ -26,6 +28,11 @@ const TENS = ['', '', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy',
|
|
|
26
28
|
// Indian numbering scales: 10^3, 10^5, 10^7, 10^9, 10^11, 10^13, 10^15, 10^17
|
|
27
29
|
const SCALES = ['thousand', 'lakh', 'crore', 'arab', 'kharab', 'neel', 'padma', 'shankh']
|
|
28
30
|
|
|
31
|
+
// 3-2-2 grouping: a 3-digit base segment then 2 digits per Indian scale word.
|
|
32
|
+
export const cardinalMax = indian(SCALES.length + 1)
|
|
33
|
+
export const ordinalMax = indian(SCALES.length + 1)
|
|
34
|
+
export const currencyMax = indian(SCALES.length + 1)
|
|
35
|
+
|
|
29
36
|
const HUNDRED = 'hundred'
|
|
30
37
|
const ZERO = 'zero'
|
|
31
38
|
const NEGATIVE = 'minus'
|
|
@@ -51,11 +58,10 @@ const segmentResult = { word: '', hasHundred: false }
|
|
|
51
58
|
|
|
52
59
|
/**
|
|
53
60
|
* Builds words for a 0-999 segment (British-style with "and" after hundreds).
|
|
54
|
-
*
|
|
55
61
|
* @param {number} n - Number 0-999
|
|
56
|
-
* @returns {{ word: string, hasHundred: boolean }}
|
|
62
|
+
* @returns {{ word: string, hasHundred: boolean }} The segment words and whether a hundred was included
|
|
57
63
|
*/
|
|
58
|
-
function buildSegment
|
|
64
|
+
function buildSegment(n) {
|
|
59
65
|
if (n === 0) {
|
|
60
66
|
segmentResult.word = ''
|
|
61
67
|
segmentResult.hasHundred = false
|
|
@@ -70,9 +76,11 @@ function buildSegment (n) {
|
|
|
70
76
|
let tensOnes = ''
|
|
71
77
|
if (tens === 1) {
|
|
72
78
|
tensOnes = TEENS[ones]
|
|
73
|
-
}
|
|
79
|
+
}
|
|
80
|
+
else if (tens >= 2) {
|
|
74
81
|
tensOnes = ones > 0 ? TENS[tens] + '-' + ONES[ones] : TENS[tens]
|
|
75
|
-
}
|
|
82
|
+
}
|
|
83
|
+
else if (ones > 0) {
|
|
76
84
|
tensOnes = ONES[ones]
|
|
77
85
|
}
|
|
78
86
|
|
|
@@ -80,11 +88,13 @@ function buildSegment (n) {
|
|
|
80
88
|
if (hundreds > 0) {
|
|
81
89
|
if (tensOnes) {
|
|
82
90
|
segmentResult.word = ONES[hundreds] + ' ' + HUNDRED + ' and ' + tensOnes
|
|
83
|
-
}
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
84
93
|
segmentResult.word = ONES[hundreds] + ' ' + HUNDRED
|
|
85
94
|
}
|
|
86
95
|
segmentResult.hasHundred = true
|
|
87
|
-
}
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
88
98
|
segmentResult.word = tensOnes
|
|
89
99
|
segmentResult.hasHundred = false
|
|
90
100
|
}
|
|
@@ -94,11 +104,10 @@ function buildSegment (n) {
|
|
|
94
104
|
|
|
95
105
|
/**
|
|
96
106
|
* Builds words for a 0-99 segment (no hundreds).
|
|
97
|
-
*
|
|
98
107
|
* @param {number} n - Number 0-99
|
|
99
|
-
* @returns {string}
|
|
108
|
+
* @returns {string} The segment in words
|
|
100
109
|
*/
|
|
101
|
-
function buildSmallSegment
|
|
110
|
+
function buildSmallSegment(n) {
|
|
102
111
|
if (n === 0) return ''
|
|
103
112
|
|
|
104
113
|
const ones = n % 10
|
|
@@ -106,7 +115,8 @@ function buildSmallSegment (n) {
|
|
|
106
115
|
|
|
107
116
|
if (tens === 1) {
|
|
108
117
|
return TEENS[ones]
|
|
109
|
-
}
|
|
118
|
+
}
|
|
119
|
+
else if (tens >= 2) {
|
|
110
120
|
return ones > 0 ? TENS[tens] + '-' + ONES[ones] : TENS[tens]
|
|
111
121
|
}
|
|
112
122
|
return ONES[ones]
|
|
@@ -121,11 +131,10 @@ function buildSmallSegment (n) {
|
|
|
121
131
|
*
|
|
122
132
|
* Uses BigInt modulo for segment extraction.
|
|
123
133
|
* South Asian 3-2-2 grouping: first 3 digits, then groups of 2.
|
|
124
|
-
*
|
|
125
134
|
* @param {bigint} n - Non-negative integer to convert
|
|
126
135
|
* @returns {string} English words
|
|
127
136
|
*/
|
|
128
|
-
function integerToWords
|
|
137
|
+
function integerToWords(n) {
|
|
129
138
|
if (n === 0n) return ZERO
|
|
130
139
|
|
|
131
140
|
// Fast path: numbers < 1000
|
|
@@ -162,7 +171,8 @@ function integerToWords (n) {
|
|
|
162
171
|
words.push('and')
|
|
163
172
|
}
|
|
164
173
|
words.push(word)
|
|
165
|
-
}
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
166
176
|
// Other segments are 0-99
|
|
167
177
|
words.push(buildSmallSegment(segment))
|
|
168
178
|
// Add scale word
|
|
@@ -177,11 +187,10 @@ function integerToWords (n) {
|
|
|
177
187
|
|
|
178
188
|
/**
|
|
179
189
|
* Converts decimal digits to English words.
|
|
180
|
-
*
|
|
181
190
|
* @param {string} decimalPart - Decimal digits (without the point)
|
|
182
191
|
* @returns {string} English words for decimal part
|
|
183
192
|
*/
|
|
184
|
-
function decimalPartToWords
|
|
193
|
+
function decimalPartToWords(decimalPart) {
|
|
185
194
|
let result = ''
|
|
186
195
|
|
|
187
196
|
// Handle leading zeros
|
|
@@ -204,20 +213,21 @@ function decimalPartToWords (decimalPart) {
|
|
|
204
213
|
|
|
205
214
|
/**
|
|
206
215
|
* Converts a numeric value to English words using Indian numbering.
|
|
207
|
-
*
|
|
208
216
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
209
217
|
* @returns {string} The number in English words
|
|
210
218
|
* @throws {TypeError} If value is not a valid numeric type
|
|
211
219
|
* @throws {Error} If value is not a valid number format
|
|
212
|
-
*
|
|
213
220
|
* @example
|
|
214
221
|
* toCardinal(42) // 'forty-two'
|
|
215
222
|
* toCardinal(100000) // 'one lakh'
|
|
216
223
|
* toCardinal(10000000) // 'one crore'
|
|
217
224
|
* toCardinal(1234567) // 'twelve lakh thirty-four thousand five hundred and sixty-seven'
|
|
218
225
|
*/
|
|
219
|
-
function toCardinal
|
|
226
|
+
function toCardinal(value) {
|
|
220
227
|
const { isNegative, integerPart, decimalPart } = parseCardinalValue(value)
|
|
228
|
+
// Both the integer part and the decimal's significant digits are spelled via
|
|
229
|
+
// the scale builder, so both must clear the ceiling.
|
|
230
|
+
checkMax(integerPart, cardinalMax, decimalPart)
|
|
221
231
|
|
|
222
232
|
let result = ''
|
|
223
233
|
|
|
@@ -240,11 +250,10 @@ function toCardinal (value) {
|
|
|
240
250
|
|
|
241
251
|
/**
|
|
242
252
|
* Builds ordinal words for a 0-999 segment (final segment only).
|
|
243
|
-
*
|
|
244
253
|
* @param {number} n - Number 0-999
|
|
245
254
|
* @returns {string} Ordinal words for this segment
|
|
246
255
|
*/
|
|
247
|
-
function buildOrdinalSegment
|
|
256
|
+
function buildOrdinalSegment(n) {
|
|
248
257
|
const ones = n % 10
|
|
249
258
|
const tens = Math.trunc(n / 10) % 10
|
|
250
259
|
const hundreds = Math.trunc(n / 100)
|
|
@@ -253,13 +262,16 @@ function buildOrdinalSegment (n) {
|
|
|
253
262
|
let tensOnesOrdinal = ''
|
|
254
263
|
if (tens === 1) {
|
|
255
264
|
tensOnesOrdinal = ORDINAL_TEENS[ones]
|
|
256
|
-
}
|
|
265
|
+
}
|
|
266
|
+
else if (tens >= 2) {
|
|
257
267
|
if (ones > 0) {
|
|
258
268
|
tensOnesOrdinal = TENS[tens] + '-' + ORDINAL_ONES[ones]
|
|
259
|
-
}
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
260
271
|
tensOnesOrdinal = ORDINAL_TENS[tens]
|
|
261
272
|
}
|
|
262
|
-
}
|
|
273
|
+
}
|
|
274
|
+
else if (ones > 0) {
|
|
263
275
|
tensOnesOrdinal = ORDINAL_ONES[ones]
|
|
264
276
|
}
|
|
265
277
|
|
|
@@ -267,7 +279,8 @@ function buildOrdinalSegment (n) {
|
|
|
267
279
|
if (hundreds > 0) {
|
|
268
280
|
if (tensOnesOrdinal) {
|
|
269
281
|
return ONES[hundreds] + ' ' + HUNDRED + ' ' + tensOnesOrdinal
|
|
270
|
-
}
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
271
284
|
return ONES[hundreds] + ' hundredth'
|
|
272
285
|
}
|
|
273
286
|
}
|
|
@@ -277,11 +290,10 @@ function buildOrdinalSegment (n) {
|
|
|
277
290
|
|
|
278
291
|
/**
|
|
279
292
|
* Converts a positive integer to ordinal words using Indian numbering.
|
|
280
|
-
*
|
|
281
293
|
* @param {bigint} n - Positive integer to convert
|
|
282
294
|
* @returns {string} Ordinal English words
|
|
283
295
|
*/
|
|
284
|
-
function integerToOrdinal
|
|
296
|
+
function integerToOrdinal(n) {
|
|
285
297
|
// Fast path: numbers < 1000
|
|
286
298
|
if (n < 1000n) {
|
|
287
299
|
return buildOrdinalSegment(Number(n))
|
|
@@ -323,16 +335,19 @@ function integerToOrdinal (n) {
|
|
|
323
335
|
if (i === 0) {
|
|
324
336
|
// Units position: use ordinal segment
|
|
325
337
|
words.push(buildOrdinalSegment(segment))
|
|
326
|
-
}
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
327
340
|
// Scale position with no remainder below: "one lakhth"
|
|
328
341
|
words.push(buildSmallSegment(segment))
|
|
329
342
|
words.push(SCALES[i - 1] + 'th')
|
|
330
343
|
}
|
|
331
|
-
}
|
|
344
|
+
}
|
|
345
|
+
else {
|
|
332
346
|
// Non-final segments are cardinal
|
|
333
347
|
if (i === 0) {
|
|
334
348
|
words.push(buildSegment(segment).word)
|
|
335
|
-
}
|
|
349
|
+
}
|
|
350
|
+
else {
|
|
336
351
|
words.push(buildSmallSegment(segment))
|
|
337
352
|
words.push(SCALES[i - 1])
|
|
338
353
|
}
|
|
@@ -344,19 +359,18 @@ function integerToOrdinal (n) {
|
|
|
344
359
|
|
|
345
360
|
/**
|
|
346
361
|
* Converts a numeric value to English ordinal words using Indian numbering.
|
|
347
|
-
*
|
|
348
362
|
* @param {number | string | bigint} value - The numeric value to convert (must be a positive integer)
|
|
349
363
|
* @returns {string} The number as ordinal words
|
|
350
364
|
* @throws {TypeError} If value is not a valid numeric type
|
|
351
365
|
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
352
|
-
*
|
|
353
366
|
* @example
|
|
354
367
|
* toOrdinal(1) // 'first'
|
|
355
368
|
* toOrdinal(100000) // 'one lakhth'
|
|
356
369
|
* toOrdinal(100001) // 'one lakh first'
|
|
357
370
|
*/
|
|
358
|
-
function toOrdinal
|
|
371
|
+
function toOrdinal(value) {
|
|
359
372
|
const integerPart = parseOrdinalValue(value)
|
|
373
|
+
checkMax(integerPart, ordinalMax)
|
|
360
374
|
return integerToOrdinal(integerPart)
|
|
361
375
|
}
|
|
362
376
|
|
|
@@ -364,16 +378,21 @@ function toOrdinal (value) {
|
|
|
364
378
|
// CURRENCY: toCurrency(value, options?)
|
|
365
379
|
// ============================================================================
|
|
366
380
|
|
|
381
|
+
/**
|
|
382
|
+
* @typedef {object} CurrencyOptions
|
|
383
|
+
* @property {boolean} [and] - Use "and" between rupees and paise
|
|
384
|
+
*/
|
|
385
|
+
|
|
386
|
+
/** @type {Required<CurrencyOptions>} */
|
|
387
|
+
export const currencyDefaults = { and: true }
|
|
388
|
+
|
|
367
389
|
/**
|
|
368
390
|
* Converts a numeric value to Indian English currency words.
|
|
369
|
-
*
|
|
370
391
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
371
|
-
* @param {
|
|
372
|
-
* @param {boolean} [options.and=true] - Use "and" between rupees and paise
|
|
392
|
+
* @param {CurrencyOptions} [options] - Optional configuration
|
|
373
393
|
* @returns {string} The amount in Indian English currency words
|
|
374
394
|
* @throws {TypeError} If value is not a valid numeric type
|
|
375
395
|
* @throws {Error} If value is not a valid number format
|
|
376
|
-
*
|
|
377
396
|
* @example
|
|
378
397
|
* toCurrency(42.50) // 'forty-two rupees and fifty paise'
|
|
379
398
|
* toCurrency(100000) // 'one lakh rupees'
|
|
@@ -381,10 +400,10 @@ function toOrdinal (value) {
|
|
|
381
400
|
* toCurrency(0.50) // 'fifty paise'
|
|
382
401
|
* toCurrency(42.50, { and: false }) // 'forty-two rupees fifty paise'
|
|
383
402
|
*/
|
|
384
|
-
function toCurrency
|
|
385
|
-
options = validateOptions(options)
|
|
403
|
+
function toCurrency(value, options) {
|
|
386
404
|
const { isNegative, dollars: rupees, cents: paise } = parseCurrencyValue(value)
|
|
387
|
-
|
|
405
|
+
checkMax(rupees, currencyMax)
|
|
406
|
+
const { and: useAnd } = resolveOptions(options, currencyDefaults)
|
|
388
407
|
|
|
389
408
|
// Build result
|
|
390
409
|
let result = ''
|
package/src/en-KE.d.ts
CHANGED
|
@@ -1,11 +1,36 @@
|
|
|
1
|
+
export const cardinalMax: bigint;
|
|
2
|
+
export const ordinalMax: bigint;
|
|
3
|
+
export const currencyMax: bigint;
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {object} CurrencyOptions
|
|
6
|
+
* @property {boolean} [and] - Use "and" between shillings and cents
|
|
7
|
+
*/
|
|
8
|
+
/** @type {Required<CurrencyOptions>} */
|
|
9
|
+
export const currencyDefaults: Required<CurrencyOptions>;
|
|
10
|
+
export type CurrencyOptions = {
|
|
11
|
+
/**
|
|
12
|
+
* - Use "and" between shillings and cents
|
|
13
|
+
*/
|
|
14
|
+
and?: boolean | undefined;
|
|
15
|
+
};
|
|
1
16
|
/**
|
|
2
17
|
* Converts a numeric value to Kenyan English words.
|
|
3
|
-
*
|
|
4
18
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
5
19
|
* @returns {string} The number in English words
|
|
6
20
|
* @throws {TypeError} If value is not a valid numeric type
|
|
7
21
|
* @throws {Error} If value is not a valid number format
|
|
8
22
|
*/
|
|
9
23
|
export function toCardinal(value: number | string | bigint): string;
|
|
10
|
-
|
|
11
|
-
|
|
24
|
+
/**
|
|
25
|
+
* Converts a numeric value to Kenyan English ordinal words.
|
|
26
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
27
|
+
* @returns {string} The ordinal in English words
|
|
28
|
+
*/
|
|
29
|
+
export function toOrdinal(value: number | string | bigint): string;
|
|
30
|
+
/**
|
|
31
|
+
* Converts a numeric value to Kenyan English currency words.
|
|
32
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
33
|
+
* @param {CurrencyOptions} [options] - Optional configuration
|
|
34
|
+
* @returns {string} The currency in English words
|
|
35
|
+
*/
|
|
36
|
+
export function toCurrency(value: number | string | bigint, options?: CurrencyOptions): string;
|