n2words 5.0.0 → 5.1.1
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 +133 -40
- 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 +33 -24
- 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 +106 -43
- package/src/sr-Latn-RS.d.ts +35 -15
- package/src/sr-Latn-RS.js +106 -43
- 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-KE.js
CHANGED
|
@@ -20,7 +20,9 @@
|
|
|
20
20
|
import { parseCardinalValue } from './utils/parse-cardinal.js'
|
|
21
21
|
import { parseCurrencyValue } from './utils/parse-currency.js'
|
|
22
22
|
import { parseOrdinalValue } from './utils/parse-ordinal.js'
|
|
23
|
-
import {
|
|
23
|
+
import { checkMax } from './utils/check-max.js'
|
|
24
|
+
import { western } from './utils/scale.js'
|
|
25
|
+
import { resolveOptions } from './utils/resolve-options.js'
|
|
24
26
|
|
|
25
27
|
// ============================================================================
|
|
26
28
|
// Vocabulary (module-level constants)
|
|
@@ -35,9 +37,13 @@ const SCALES = [
|
|
|
35
37
|
'quintillion', 'sextillion', 'septillion', 'octillion', 'nonillion',
|
|
36
38
|
'decillion', 'undecillion', 'duodecillion', 'tredecillion', 'quattuordecillion',
|
|
37
39
|
'quindecillion', 'sexdecillion', 'septendecillion', 'octodecillion', 'novemdecillion',
|
|
38
|
-
'vigintillion'
|
|
40
|
+
'vigintillion',
|
|
39
41
|
]
|
|
40
42
|
|
|
43
|
+
export const cardinalMax = western(SCALES.length)
|
|
44
|
+
export const ordinalMax = western(SCALES.length)
|
|
45
|
+
export const currencyMax = western(SCALES.length)
|
|
46
|
+
|
|
41
47
|
const HUNDRED = 'hundred'
|
|
42
48
|
const ZERO = 'zero'
|
|
43
49
|
const NEGATIVE = 'minus'
|
|
@@ -60,7 +66,11 @@ const CENTS = 'cents'
|
|
|
60
66
|
|
|
61
67
|
const segmentResult = { word: '', hasHundred: false }
|
|
62
68
|
|
|
63
|
-
|
|
69
|
+
/**
|
|
70
|
+
* @param {number} n The 0-999 group value to convert
|
|
71
|
+
* @returns {{word: string, hasHundred: boolean}} The segment words and whether it includes a hundreds place
|
|
72
|
+
*/
|
|
73
|
+
function buildSegment(n) {
|
|
64
74
|
if (n === 0) {
|
|
65
75
|
segmentResult.word = ''
|
|
66
76
|
segmentResult.hasHundred = false
|
|
@@ -74,20 +84,24 @@ function buildSegment (n) {
|
|
|
74
84
|
let tensOnes = ''
|
|
75
85
|
if (tens === 1) {
|
|
76
86
|
tensOnes = TEENS[ones]
|
|
77
|
-
}
|
|
87
|
+
}
|
|
88
|
+
else if (tens >= 2) {
|
|
78
89
|
tensOnes = ones > 0 ? TENS[tens] + '-' + ONES[ones] : TENS[tens]
|
|
79
|
-
}
|
|
90
|
+
}
|
|
91
|
+
else if (ones > 0) {
|
|
80
92
|
tensOnes = ONES[ones]
|
|
81
93
|
}
|
|
82
94
|
|
|
83
95
|
if (hundreds > 0) {
|
|
84
96
|
if (tensOnes) {
|
|
85
97
|
segmentResult.word = ONES[hundreds] + ' ' + HUNDRED + ' and ' + tensOnes
|
|
86
|
-
}
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
87
100
|
segmentResult.word = ONES[hundreds] + ' ' + HUNDRED
|
|
88
101
|
}
|
|
89
102
|
segmentResult.hasHundred = true
|
|
90
|
-
}
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
91
105
|
segmentResult.word = tensOnes
|
|
92
106
|
segmentResult.hasHundred = false
|
|
93
107
|
}
|
|
@@ -99,7 +113,11 @@ function buildSegment (n) {
|
|
|
99
113
|
// Conversion Functions
|
|
100
114
|
// ============================================================================
|
|
101
115
|
|
|
102
|
-
|
|
116
|
+
/**
|
|
117
|
+
* @param {bigint} n The non-negative integer to convert
|
|
118
|
+
* @returns {string} The integer in English words
|
|
119
|
+
*/
|
|
120
|
+
function integerToWords(n) {
|
|
103
121
|
if (n === 0n) return ZERO
|
|
104
122
|
|
|
105
123
|
if (n < 1000n) {
|
|
@@ -124,7 +142,11 @@ function integerToWords (n) {
|
|
|
124
142
|
return buildLargeNumberWords(n)
|
|
125
143
|
}
|
|
126
144
|
|
|
127
|
-
|
|
145
|
+
/**
|
|
146
|
+
* @param {bigint} n The integer of one million or greater to convert
|
|
147
|
+
* @returns {string} The integer in English words
|
|
148
|
+
*/
|
|
149
|
+
function buildLargeNumberWords(n) {
|
|
128
150
|
const segments = []
|
|
129
151
|
let temp = n
|
|
130
152
|
while (temp > 0n) {
|
|
@@ -160,7 +182,8 @@ function buildLargeNumberWords (n) {
|
|
|
160
182
|
if (i > 0) {
|
|
161
183
|
result += ' ' + SCALES[i - 1]
|
|
162
184
|
prevWasScale = true
|
|
163
|
-
}
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
164
187
|
prevWasScale = false
|
|
165
188
|
}
|
|
166
189
|
}
|
|
@@ -168,7 +191,11 @@ function buildLargeNumberWords (n) {
|
|
|
168
191
|
return result
|
|
169
192
|
}
|
|
170
193
|
|
|
171
|
-
|
|
194
|
+
/**
|
|
195
|
+
* @param {string} decimalPart The fractional digits as a string
|
|
196
|
+
* @returns {string} The decimal digits in English words
|
|
197
|
+
*/
|
|
198
|
+
function decimalPartToWords(decimalPart) {
|
|
172
199
|
let result = ''
|
|
173
200
|
|
|
174
201
|
let i = 0
|
|
@@ -189,14 +216,16 @@ function decimalPartToWords (decimalPart) {
|
|
|
189
216
|
|
|
190
217
|
/**
|
|
191
218
|
* Converts a numeric value to Kenyan English words.
|
|
192
|
-
*
|
|
193
219
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
194
220
|
* @returns {string} The number in English words
|
|
195
221
|
* @throws {TypeError} If value is not a valid numeric type
|
|
196
222
|
* @throws {Error} If value is not a valid number format
|
|
197
223
|
*/
|
|
198
|
-
function toCardinal
|
|
224
|
+
function toCardinal(value) {
|
|
199
225
|
const { isNegative, integerPart, decimalPart } = parseCardinalValue(value)
|
|
226
|
+
// Both the integer part and the decimal's significant digits are spelled via
|
|
227
|
+
// the scale builder, so both must clear the ceiling.
|
|
228
|
+
checkMax(integerPart, cardinalMax, decimalPart)
|
|
200
229
|
|
|
201
230
|
let result = ''
|
|
202
231
|
|
|
@@ -217,7 +246,11 @@ function toCardinal (value) {
|
|
|
217
246
|
// ORDINAL
|
|
218
247
|
// ============================================================================
|
|
219
248
|
|
|
220
|
-
|
|
249
|
+
/**
|
|
250
|
+
* @param {number} n The 0-999 group value to convert
|
|
251
|
+
* @returns {string} The segment as ordinal English words
|
|
252
|
+
*/
|
|
253
|
+
function buildOrdinalSegment(n) {
|
|
221
254
|
const ones = n % 10
|
|
222
255
|
const tens = Math.trunc(n / 10) % 10
|
|
223
256
|
const hundreds = Math.trunc(n / 100)
|
|
@@ -225,20 +258,24 @@ function buildOrdinalSegment (n) {
|
|
|
225
258
|
let tensOnesOrdinal = ''
|
|
226
259
|
if (tens === 1) {
|
|
227
260
|
tensOnesOrdinal = ORDINAL_TEENS[ones]
|
|
228
|
-
}
|
|
261
|
+
}
|
|
262
|
+
else if (tens >= 2) {
|
|
229
263
|
if (ones > 0) {
|
|
230
264
|
tensOnesOrdinal = TENS[tens] + '-' + ORDINAL_ONES[ones]
|
|
231
|
-
}
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
232
267
|
tensOnesOrdinal = ORDINAL_TENS[tens]
|
|
233
268
|
}
|
|
234
|
-
}
|
|
269
|
+
}
|
|
270
|
+
else if (ones > 0) {
|
|
235
271
|
tensOnesOrdinal = ORDINAL_ONES[ones]
|
|
236
272
|
}
|
|
237
273
|
|
|
238
274
|
if (hundreds > 0) {
|
|
239
275
|
if (tensOnesOrdinal) {
|
|
240
276
|
return ONES[hundreds] + ' ' + HUNDRED + ' ' + tensOnesOrdinal
|
|
241
|
-
}
|
|
277
|
+
}
|
|
278
|
+
else {
|
|
242
279
|
return ONES[hundreds] + ' hundredth'
|
|
243
280
|
}
|
|
244
281
|
}
|
|
@@ -246,7 +283,11 @@ function buildOrdinalSegment (n) {
|
|
|
246
283
|
return tensOnesOrdinal
|
|
247
284
|
}
|
|
248
285
|
|
|
249
|
-
|
|
286
|
+
/**
|
|
287
|
+
* @param {bigint} n The non-negative integer to convert
|
|
288
|
+
* @returns {string} The integer as ordinal English words
|
|
289
|
+
*/
|
|
290
|
+
function integerToOrdinal(n) {
|
|
250
291
|
if (n < 1000n) {
|
|
251
292
|
return buildOrdinalSegment(Number(n))
|
|
252
293
|
}
|
|
@@ -266,7 +307,11 @@ function integerToOrdinal (n) {
|
|
|
266
307
|
return buildLargeOrdinal(n)
|
|
267
308
|
}
|
|
268
309
|
|
|
269
|
-
|
|
310
|
+
/**
|
|
311
|
+
* @param {bigint} n The integer of one million or greater to convert
|
|
312
|
+
* @returns {string} The integer as ordinal English words
|
|
313
|
+
*/
|
|
314
|
+
function buildLargeOrdinal(n) {
|
|
270
315
|
const segments = []
|
|
271
316
|
let temp = n
|
|
272
317
|
while (temp > 0n) {
|
|
@@ -295,10 +340,12 @@ function buildLargeOrdinal (n) {
|
|
|
295
340
|
if (isLowestSegment) {
|
|
296
341
|
if (i === 0) {
|
|
297
342
|
result += buildOrdinalSegment(segment)
|
|
298
|
-
}
|
|
343
|
+
}
|
|
344
|
+
else {
|
|
299
345
|
result += buildSegment(segment).word + ' ' + SCALES[i - 1] + 'th'
|
|
300
346
|
}
|
|
301
|
-
}
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
302
349
|
result += buildSegment(segment).word
|
|
303
350
|
if (i > 0) {
|
|
304
351
|
result += ' ' + SCALES[i - 1]
|
|
@@ -309,8 +356,14 @@ function buildLargeOrdinal (n) {
|
|
|
309
356
|
return result
|
|
310
357
|
}
|
|
311
358
|
|
|
312
|
-
|
|
359
|
+
/**
|
|
360
|
+
* Converts a numeric value to Kenyan English ordinal words.
|
|
361
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
362
|
+
* @returns {string} The ordinal in English words
|
|
363
|
+
*/
|
|
364
|
+
function toOrdinal(value) {
|
|
313
365
|
const integerPart = parseOrdinalValue(value)
|
|
366
|
+
checkMax(integerPart, ordinalMax)
|
|
314
367
|
return integerToOrdinal(integerPart)
|
|
315
368
|
}
|
|
316
369
|
|
|
@@ -318,10 +371,24 @@ function toOrdinal (value) {
|
|
|
318
371
|
// CURRENCY
|
|
319
372
|
// ============================================================================
|
|
320
373
|
|
|
321
|
-
|
|
322
|
-
|
|
374
|
+
/**
|
|
375
|
+
* @typedef {object} CurrencyOptions
|
|
376
|
+
* @property {boolean} [and] - Use "and" between shillings and cents
|
|
377
|
+
*/
|
|
378
|
+
|
|
379
|
+
/** @type {Required<CurrencyOptions>} */
|
|
380
|
+
export const currencyDefaults = { and: true }
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Converts a numeric value to Kenyan English currency words.
|
|
384
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
385
|
+
* @param {CurrencyOptions} [options] - Optional configuration
|
|
386
|
+
* @returns {string} The currency in English words
|
|
387
|
+
*/
|
|
388
|
+
function toCurrency(value, options) {
|
|
323
389
|
const { isNegative, dollars: shillings, cents } = parseCurrencyValue(value)
|
|
324
|
-
|
|
390
|
+
checkMax(shillings, currencyMax)
|
|
391
|
+
const { and: useAnd } = resolveOptions(options, currencyDefaults)
|
|
325
392
|
|
|
326
393
|
let result = ''
|
|
327
394
|
if (isNegative) result = NEGATIVE + ' '
|
package/src/en-MY.d.ts
CHANGED
|
@@ -1,11 +1,34 @@
|
|
|
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 ringgit and sen
|
|
7
|
+
*/
|
|
8
|
+
/** @type {Required<CurrencyOptions>} */
|
|
9
|
+
export const currencyDefaults: Required<CurrencyOptions>;
|
|
10
|
+
export type CurrencyOptions = {
|
|
11
|
+
/**
|
|
12
|
+
* - Use "and" between ringgit and sen
|
|
13
|
+
*/
|
|
14
|
+
and?: boolean | undefined;
|
|
15
|
+
};
|
|
1
16
|
/**
|
|
2
17
|
* Converts a numeric value to Malaysian 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
|
+
* @param {number | string | bigint} value The numeric value to convert.
|
|
26
|
+
* @returns {string} The number as an ordinal in English words.
|
|
27
|
+
*/
|
|
28
|
+
export function toOrdinal(value: number | string | bigint): string;
|
|
29
|
+
/**
|
|
30
|
+
* @param {number | string | bigint} value The numeric value to convert.
|
|
31
|
+
* @param {CurrencyOptions} [options] - Optional configuration
|
|
32
|
+
* @returns {string} The amount in Malaysian ringgit and sen in English words.
|
|
33
|
+
*/
|
|
34
|
+
export function toCurrency(value: number | string | bigint, options?: CurrencyOptions): string;
|
package/src/en-MY.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'
|
|
@@ -61,7 +67,11 @@ const SEN = 'sen'
|
|
|
61
67
|
|
|
62
68
|
const segmentResult = { word: '', hasHundred: false }
|
|
63
69
|
|
|
64
|
-
|
|
70
|
+
/**
|
|
71
|
+
* @param {number} n The 0-999 segment to convert.
|
|
72
|
+
* @returns {{word: string, hasHundred: boolean}} The segment in words and whether it includes a hundreds part.
|
|
73
|
+
*/
|
|
74
|
+
function buildSegment(n) {
|
|
65
75
|
if (n === 0) {
|
|
66
76
|
segmentResult.word = ''
|
|
67
77
|
segmentResult.hasHundred = false
|
|
@@ -75,20 +85,24 @@ function buildSegment (n) {
|
|
|
75
85
|
let tensOnes = ''
|
|
76
86
|
if (tens === 1) {
|
|
77
87
|
tensOnes = TEENS[ones]
|
|
78
|
-
}
|
|
88
|
+
}
|
|
89
|
+
else if (tens >= 2) {
|
|
79
90
|
tensOnes = ones > 0 ? TENS[tens] + '-' + ONES[ones] : TENS[tens]
|
|
80
|
-
}
|
|
91
|
+
}
|
|
92
|
+
else if (ones > 0) {
|
|
81
93
|
tensOnes = ONES[ones]
|
|
82
94
|
}
|
|
83
95
|
|
|
84
96
|
if (hundreds > 0) {
|
|
85
97
|
if (tensOnes) {
|
|
86
98
|
segmentResult.word = ONES[hundreds] + ' ' + HUNDRED + ' and ' + tensOnes
|
|
87
|
-
}
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
88
101
|
segmentResult.word = ONES[hundreds] + ' ' + HUNDRED
|
|
89
102
|
}
|
|
90
103
|
segmentResult.hasHundred = true
|
|
91
|
-
}
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
92
106
|
segmentResult.word = tensOnes
|
|
93
107
|
segmentResult.hasHundred = false
|
|
94
108
|
}
|
|
@@ -100,7 +114,11 @@ function buildSegment (n) {
|
|
|
100
114
|
// Conversion Functions
|
|
101
115
|
// ============================================================================
|
|
102
116
|
|
|
103
|
-
|
|
117
|
+
/**
|
|
118
|
+
* @param {bigint} n The non-negative integer to convert.
|
|
119
|
+
* @returns {string} The integer in English words.
|
|
120
|
+
*/
|
|
121
|
+
function integerToWords(n) {
|
|
104
122
|
if (n === 0n) return ZERO
|
|
105
123
|
|
|
106
124
|
if (n < 1000n) {
|
|
@@ -125,7 +143,11 @@ function integerToWords (n) {
|
|
|
125
143
|
return buildLargeNumberWords(n)
|
|
126
144
|
}
|
|
127
145
|
|
|
128
|
-
|
|
146
|
+
/**
|
|
147
|
+
* @param {bigint} n The integer of one million or greater to convert.
|
|
148
|
+
* @returns {string} The integer in English words.
|
|
149
|
+
*/
|
|
150
|
+
function buildLargeNumberWords(n) {
|
|
129
151
|
const segments = []
|
|
130
152
|
let temp = n
|
|
131
153
|
while (temp > 0n) {
|
|
@@ -161,7 +183,8 @@ function buildLargeNumberWords (n) {
|
|
|
161
183
|
if (i > 0) {
|
|
162
184
|
result += ' ' + SCALES[i - 1]
|
|
163
185
|
prevWasScale = true
|
|
164
|
-
}
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
165
188
|
prevWasScale = false
|
|
166
189
|
}
|
|
167
190
|
}
|
|
@@ -169,7 +192,11 @@ function buildLargeNumberWords (n) {
|
|
|
169
192
|
return result
|
|
170
193
|
}
|
|
171
194
|
|
|
172
|
-
|
|
195
|
+
/**
|
|
196
|
+
* @param {string} decimalPart The fractional digits after the decimal point.
|
|
197
|
+
* @returns {string} The decimal digits in English words.
|
|
198
|
+
*/
|
|
199
|
+
function decimalPartToWords(decimalPart) {
|
|
173
200
|
let result = ''
|
|
174
201
|
|
|
175
202
|
let i = 0
|
|
@@ -190,14 +217,16 @@ function decimalPartToWords (decimalPart) {
|
|
|
190
217
|
|
|
191
218
|
/**
|
|
192
219
|
* Converts a numeric value to Malaysian English words.
|
|
193
|
-
*
|
|
194
220
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
195
221
|
* @returns {string} The number in English words
|
|
196
222
|
* @throws {TypeError} If value is not a valid numeric type
|
|
197
223
|
* @throws {Error} If value is not a valid number format
|
|
198
224
|
*/
|
|
199
|
-
function toCardinal
|
|
225
|
+
function toCardinal(value) {
|
|
200
226
|
const { isNegative, integerPart, decimalPart } = parseCardinalValue(value)
|
|
227
|
+
// Both the integer part and the decimal's significant digits are spelled via
|
|
228
|
+
// the scale builder, so both must clear the ceiling.
|
|
229
|
+
checkMax(integerPart, cardinalMax, decimalPart)
|
|
201
230
|
|
|
202
231
|
let result = ''
|
|
203
232
|
|
|
@@ -218,7 +247,11 @@ function toCardinal (value) {
|
|
|
218
247
|
// ORDINAL
|
|
219
248
|
// ============================================================================
|
|
220
249
|
|
|
221
|
-
|
|
250
|
+
/**
|
|
251
|
+
* @param {number} n The 0-999 segment to convert.
|
|
252
|
+
* @returns {string} The segment as an ordinal in English words.
|
|
253
|
+
*/
|
|
254
|
+
function buildOrdinalSegment(n) {
|
|
222
255
|
const ones = n % 10
|
|
223
256
|
const tens = Math.trunc(n / 10) % 10
|
|
224
257
|
const hundreds = Math.trunc(n / 100)
|
|
@@ -226,20 +259,24 @@ function buildOrdinalSegment (n) {
|
|
|
226
259
|
let tensOnesOrdinal = ''
|
|
227
260
|
if (tens === 1) {
|
|
228
261
|
tensOnesOrdinal = ORDINAL_TEENS[ones]
|
|
229
|
-
}
|
|
262
|
+
}
|
|
263
|
+
else if (tens >= 2) {
|
|
230
264
|
if (ones > 0) {
|
|
231
265
|
tensOnesOrdinal = TENS[tens] + '-' + ORDINAL_ONES[ones]
|
|
232
|
-
}
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
233
268
|
tensOnesOrdinal = ORDINAL_TENS[tens]
|
|
234
269
|
}
|
|
235
|
-
}
|
|
270
|
+
}
|
|
271
|
+
else if (ones > 0) {
|
|
236
272
|
tensOnesOrdinal = ORDINAL_ONES[ones]
|
|
237
273
|
}
|
|
238
274
|
|
|
239
275
|
if (hundreds > 0) {
|
|
240
276
|
if (tensOnesOrdinal) {
|
|
241
277
|
return ONES[hundreds] + ' ' + HUNDRED + ' ' + tensOnesOrdinal
|
|
242
|
-
}
|
|
278
|
+
}
|
|
279
|
+
else {
|
|
243
280
|
return ONES[hundreds] + ' hundredth'
|
|
244
281
|
}
|
|
245
282
|
}
|
|
@@ -247,7 +284,11 @@ function buildOrdinalSegment (n) {
|
|
|
247
284
|
return tensOnesOrdinal
|
|
248
285
|
}
|
|
249
286
|
|
|
250
|
-
|
|
287
|
+
/**
|
|
288
|
+
* @param {bigint} n The non-negative integer to convert.
|
|
289
|
+
* @returns {string} The integer as an ordinal in English words.
|
|
290
|
+
*/
|
|
291
|
+
function integerToOrdinal(n) {
|
|
251
292
|
if (n < 1000n) {
|
|
252
293
|
return buildOrdinalSegment(Number(n))
|
|
253
294
|
}
|
|
@@ -267,7 +308,11 @@ function integerToOrdinal (n) {
|
|
|
267
308
|
return buildLargeOrdinal(n)
|
|
268
309
|
}
|
|
269
310
|
|
|
270
|
-
|
|
311
|
+
/**
|
|
312
|
+
* @param {bigint} n The integer of one million or greater to convert.
|
|
313
|
+
* @returns {string} The integer as an ordinal in English words.
|
|
314
|
+
*/
|
|
315
|
+
function buildLargeOrdinal(n) {
|
|
271
316
|
const segments = []
|
|
272
317
|
let temp = n
|
|
273
318
|
while (temp > 0n) {
|
|
@@ -296,10 +341,12 @@ function buildLargeOrdinal (n) {
|
|
|
296
341
|
if (isLowestSegment) {
|
|
297
342
|
if (i === 0) {
|
|
298
343
|
result += buildOrdinalSegment(segment)
|
|
299
|
-
}
|
|
344
|
+
}
|
|
345
|
+
else {
|
|
300
346
|
result += buildSegment(segment).word + ' ' + SCALES[i - 1] + 'th'
|
|
301
347
|
}
|
|
302
|
-
}
|
|
348
|
+
}
|
|
349
|
+
else {
|
|
303
350
|
result += buildSegment(segment).word
|
|
304
351
|
if (i > 0) {
|
|
305
352
|
result += ' ' + SCALES[i - 1]
|
|
@@ -310,8 +357,13 @@ function buildLargeOrdinal (n) {
|
|
|
310
357
|
return result
|
|
311
358
|
}
|
|
312
359
|
|
|
313
|
-
|
|
360
|
+
/**
|
|
361
|
+
* @param {number | string | bigint} value The numeric value to convert.
|
|
362
|
+
* @returns {string} The number as an ordinal in English words.
|
|
363
|
+
*/
|
|
364
|
+
function toOrdinal(value) {
|
|
314
365
|
const integerPart = parseOrdinalValue(value)
|
|
366
|
+
checkMax(integerPart, ordinalMax)
|
|
315
367
|
return integerToOrdinal(integerPart)
|
|
316
368
|
}
|
|
317
369
|
|
|
@@ -319,10 +371,23 @@ function toOrdinal (value) {
|
|
|
319
371
|
// CURRENCY
|
|
320
372
|
// ============================================================================
|
|
321
373
|
|
|
322
|
-
|
|
323
|
-
|
|
374
|
+
/**
|
|
375
|
+
* @typedef {object} CurrencyOptions
|
|
376
|
+
* @property {boolean} [and] - Use "and" between ringgit and sen
|
|
377
|
+
*/
|
|
378
|
+
|
|
379
|
+
/** @type {Required<CurrencyOptions>} */
|
|
380
|
+
export const currencyDefaults = { and: true }
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* @param {number | string | bigint} value The numeric value to convert.
|
|
384
|
+
* @param {CurrencyOptions} [options] - Optional configuration
|
|
385
|
+
* @returns {string} The amount in Malaysian ringgit and sen in English words.
|
|
386
|
+
*/
|
|
387
|
+
function toCurrency(value, options) {
|
|
324
388
|
const { isNegative, dollars: ringgit, cents: sen } = parseCurrencyValue(value)
|
|
325
|
-
|
|
389
|
+
checkMax(ringgit, currencyMax)
|
|
390
|
+
const { and: useAnd } = resolveOptions(options, currencyDefaults)
|
|
326
391
|
|
|
327
392
|
let result = ''
|
|
328
393
|
if (isNegative) result = NEGATIVE + ' '
|
package/src/en-NG.d.ts
CHANGED
|
@@ -1,14 +1,27 @@
|
|
|
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 naira and kobo (e.g., "one naira and fifty kobo")
|
|
7
|
+
*/
|
|
8
|
+
/** @type {Required<CurrencyOptions>} */
|
|
9
|
+
export const currencyDefaults: Required<CurrencyOptions>;
|
|
10
|
+
export type CurrencyOptions = {
|
|
11
|
+
/**
|
|
12
|
+
* - Use "and" between naira and kobo (e.g., "one naira and fifty kobo")
|
|
13
|
+
*/
|
|
14
|
+
and?: boolean | undefined;
|
|
15
|
+
};
|
|
1
16
|
/**
|
|
2
17
|
* Converts a numeric value to Nigerian English words.
|
|
3
18
|
*
|
|
4
19
|
* This is the main public API. It accepts any valid numeric input
|
|
5
20
|
* (number, string, or bigint) and handles parsing internally.
|
|
6
|
-
*
|
|
7
21
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
8
22
|
* @returns {string} The number in English words
|
|
9
23
|
* @throws {TypeError} If value is not a valid numeric type
|
|
10
24
|
* @throws {Error} If value is not a valid number format
|
|
11
|
-
*
|
|
12
25
|
* @example
|
|
13
26
|
* toCardinal(42) // 'forty-two'
|
|
14
27
|
* toCardinal(-3.14) // 'minus three point fourteen'
|
|
@@ -17,12 +30,10 @@
|
|
|
17
30
|
export function toCardinal(value: number | string | bigint): string;
|
|
18
31
|
/**
|
|
19
32
|
* Converts a numeric value to Nigerian English ordinal words.
|
|
20
|
-
*
|
|
21
33
|
* @param {number | string | bigint} value - The numeric value to convert (must be a positive integer)
|
|
22
34
|
* @returns {string} The number as ordinal words (e.g., "first", "forty-second")
|
|
23
35
|
* @throws {TypeError} If value is not a valid numeric type
|
|
24
36
|
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
25
|
-
*
|
|
26
37
|
* @example
|
|
27
38
|
* toOrdinal(1) // 'first'
|
|
28
39
|
* toOrdinal(2) // 'second'
|
|
@@ -36,14 +47,11 @@ export function toCardinal(value: number | string | bigint): string;
|
|
|
36
47
|
export function toOrdinal(value: number | string | bigint): string;
|
|
37
48
|
/**
|
|
38
49
|
* Converts a numeric value to Nigerian English currency words.
|
|
39
|
-
*
|
|
40
50
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
41
|
-
* @param {
|
|
42
|
-
* @param {boolean} [options.and=true] - Use "and" between naira and kobo (e.g., "one naira and fifty kobo")
|
|
51
|
+
* @param {CurrencyOptions} [options] - Optional configuration
|
|
43
52
|
* @returns {string} The amount in Nigerian English currency words
|
|
44
53
|
* @throws {TypeError} If value is not a valid numeric type
|
|
45
54
|
* @throws {Error} If value is not a valid number format
|
|
46
|
-
*
|
|
47
55
|
* @example
|
|
48
56
|
* toCurrency(42.50) // 'forty-two naira and fifty kobo'
|
|
49
57
|
* toCurrency(1) // 'one naira'
|
|
@@ -51,6 +59,4 @@ export function toOrdinal(value: number | string | bigint): string;
|
|
|
51
59
|
* toCurrency(0.01) // 'one kobo'
|
|
52
60
|
* toCurrency(42.50, { and: false }) // 'forty-two naira fifty kobo'
|
|
53
61
|
*/
|
|
54
|
-
export function toCurrency(value: number | string | bigint, options?:
|
|
55
|
-
and?: boolean | undefined;
|
|
56
|
-
}): string;
|
|
62
|
+
export function toCurrency(value: number | string | bigint, options?: CurrencyOptions): string;
|