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/yo-NG.d.ts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
+
export const cardinalMax: null;
|
|
2
|
+
export const ordinalMax: null;
|
|
3
|
+
export const currencyMax: null;
|
|
1
4
|
/**
|
|
2
5
|
* Converts a numeric value to Yoruba words.
|
|
3
|
-
*
|
|
4
6
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
5
7
|
* @returns {string} The number in Yoruba words
|
|
6
8
|
*/
|
|
7
9
|
export function toCardinal(value: number | string | bigint): string;
|
|
8
10
|
/**
|
|
9
11
|
* Converts a numeric value to Yoruba ordinal words.
|
|
10
|
-
*
|
|
11
12
|
* @param {number | string | bigint} value - The numeric value to convert (positive integer)
|
|
12
13
|
* @returns {string} The number as ordinal words
|
|
13
14
|
* @throws {TypeError} If value is not a valid numeric type
|
|
14
15
|
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
15
|
-
*
|
|
16
16
|
* @example
|
|
17
17
|
* toOrdinal(1) // 'àkọ́kọ́'
|
|
18
18
|
* toOrdinal(2) // 'ìkejì'
|
|
@@ -23,12 +23,10 @@ export function toOrdinal(value: number | string | bigint): string;
|
|
|
23
23
|
* Converts a numeric value to Yoruba currency words (Nigerian Naira).
|
|
24
24
|
*
|
|
25
25
|
* Uses náírà (naira) and kọ́bọ̀ (kobo).
|
|
26
|
-
*
|
|
27
26
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
28
27
|
* @returns {string} The amount in Yoruba currency words
|
|
29
28
|
* @throws {TypeError} If value is not a valid numeric type
|
|
30
29
|
* @throws {Error} If value is not a valid number format
|
|
31
|
-
*
|
|
32
30
|
* @example
|
|
33
31
|
* toCurrency(42) // 'èjì lé lógójì náírà'
|
|
34
32
|
* toCurrency(1.50) // 'ọ̀kan náírà àti àádọ́ta kọ́bọ̀'
|
package/src/yo-NG.js
CHANGED
|
@@ -19,6 +19,12 @@
|
|
|
19
19
|
import { parseCardinalValue } from './utils/parse-cardinal.js'
|
|
20
20
|
import { parseCurrencyValue } from './utils/parse-currency.js'
|
|
21
21
|
import { parseOrdinalValue } from './utils/parse-ordinal.js'
|
|
22
|
+
import { UNBOUNDED } from './utils/scale.js'
|
|
23
|
+
|
|
24
|
+
// No fixed scale ceiling — the vigesimal speller composes every magnitude.
|
|
25
|
+
export const cardinalMax = UNBOUNDED
|
|
26
|
+
export const ordinalMax = UNBOUNDED
|
|
27
|
+
export const currencyMax = UNBOUNDED
|
|
22
28
|
|
|
23
29
|
// ============================================================================
|
|
24
30
|
// Vocabulary (module-level constants)
|
|
@@ -36,7 +42,7 @@ const ONES = [
|
|
|
36
42
|
'èje', // 7
|
|
37
43
|
'ẹ̀jọ', // 8
|
|
38
44
|
'ẹ̀sán', // 9
|
|
39
|
-
'ẹ̀wá' // 10
|
|
45
|
+
'ẹ̀wá', // 10
|
|
40
46
|
]
|
|
41
47
|
|
|
42
48
|
// Numbers 11-14 (additive: X + 10, using "lá")
|
|
@@ -45,7 +51,7 @@ const TEENS_ADD = [
|
|
|
45
51
|
'ọ̀kànlá', // 11 = 1 + 10
|
|
46
52
|
'èjìlá', // 12 = 2 + 10
|
|
47
53
|
'ẹ̀talá', // 13 = 3 + 10
|
|
48
|
-
'ẹ̀rinlá' // 14 = 4 + 10
|
|
54
|
+
'ẹ̀rinlá', // 14 = 4 + 10
|
|
49
55
|
]
|
|
50
56
|
|
|
51
57
|
// Numbers 15-19 (subtractive: 20 - X, using "dín")
|
|
@@ -54,12 +60,13 @@ const TEENS_SUB = [
|
|
|
54
60
|
'ẹ̀rìndínlógún', // 16 = 20 - 4
|
|
55
61
|
'ẹ̀tadínlógún', // 17 = 20 - 3
|
|
56
62
|
'èjìdínlógún', // 18 = 20 - 2
|
|
57
|
-
'ọ̀kàndínlógún' // 19 = 20 - 1
|
|
63
|
+
'ọ̀kàndínlógún', // 19 = 20 - 1
|
|
58
64
|
]
|
|
59
65
|
|
|
60
66
|
// Decades (base-20 structure)
|
|
61
67
|
// Even decades are multiples of 20
|
|
62
68
|
// Odd decades subtract 10 from next even decade
|
|
69
|
+
/** @type {Record<number, string>} */
|
|
63
70
|
const DECADES = {
|
|
64
71
|
20: 'ogún', // 20 = 20 × 1
|
|
65
72
|
30: 'ọgbọ̀n', // 30 = 20 + 10 (special word)
|
|
@@ -69,10 +76,11 @@ const DECADES = {
|
|
|
69
76
|
70: 'àádọ́rin', // 70 = 80 - 10
|
|
70
77
|
80: 'ogórin', // 80 = 20 × 4
|
|
71
78
|
90: 'àádọ́rùn', // 90 = 100 - 10
|
|
72
|
-
100: 'ọgọ́rùn' // 100 = 20 × 5
|
|
79
|
+
100: 'ọgọ́rùn', // 100 = 20 × 5
|
|
73
80
|
}
|
|
74
81
|
|
|
75
82
|
// Prefixes for adding to decades (lé lógún, lé lọgbọ̀n, etc.)
|
|
83
|
+
/** @type {Record<number, string>} */
|
|
76
84
|
const DECADE_ADD_SUFFIX = {
|
|
77
85
|
20: 'lógún',
|
|
78
86
|
30: 'lọgbọ̀n',
|
|
@@ -82,10 +90,11 @@ const DECADE_ADD_SUFFIX = {
|
|
|
82
90
|
70: 'láàádọ́rin',
|
|
83
91
|
80: 'lógórin',
|
|
84
92
|
90: 'láàádọ́rùn',
|
|
85
|
-
100: 'lọ́gọ́rùn'
|
|
93
|
+
100: 'lọ́gọ́rùn',
|
|
86
94
|
}
|
|
87
95
|
|
|
88
96
|
// Prefixes for subtracting from decades (dín lógójì, etc.)
|
|
97
|
+
/** @type {Record<number, string>} */
|
|
89
98
|
const DECADE_SUB_SUFFIX = {
|
|
90
99
|
20: 'dínlógún',
|
|
91
100
|
30: 'dínlọgbọ̀n',
|
|
@@ -95,7 +104,7 @@ const DECADE_SUB_SUFFIX = {
|
|
|
95
104
|
70: 'dínláàádọ́rin',
|
|
96
105
|
80: 'dínlógórin',
|
|
97
106
|
90: 'dínláàádọ́rùn',
|
|
98
|
-
100: 'dínlọ́gọ́rùn'
|
|
107
|
+
100: 'dínlọ́gọ́rùn',
|
|
99
108
|
}
|
|
100
109
|
|
|
101
110
|
// Scale words
|
|
@@ -135,8 +144,10 @@ const KOBO = 'kọ́bọ̀'
|
|
|
135
144
|
|
|
136
145
|
/**
|
|
137
146
|
* Builds word for numbers 0-99
|
|
147
|
+
* @param {number} n - Integer in the range 0-99
|
|
148
|
+
* @returns {string} Yoruba words for the number
|
|
138
149
|
*/
|
|
139
|
-
function buildUnder100
|
|
150
|
+
function buildUnder100(n) {
|
|
140
151
|
if (n === 0) return ''
|
|
141
152
|
if (n <= 10) return ONES[n]
|
|
142
153
|
|
|
@@ -169,8 +180,10 @@ function buildUnder100 (n) {
|
|
|
169
180
|
|
|
170
181
|
/**
|
|
171
182
|
* Converts hundreds (100-999)
|
|
183
|
+
* @param {number} n - Integer in the range 0-999
|
|
184
|
+
* @returns {string} Yoruba words for the number
|
|
172
185
|
*/
|
|
173
|
-
function convertHundreds
|
|
186
|
+
function convertHundreds(n) {
|
|
174
187
|
if (n < 100) return buildUnder100(n)
|
|
175
188
|
|
|
176
189
|
const hundreds = Math.trunc(n / 100)
|
|
@@ -189,11 +202,14 @@ function convertHundreds (n) {
|
|
|
189
202
|
// Build hundreds
|
|
190
203
|
if (hundreds === 1) {
|
|
191
204
|
result = HUNDRED
|
|
192
|
-
}
|
|
205
|
+
}
|
|
206
|
+
else if (hundreds === 2) {
|
|
193
207
|
result = TWO_HUNDRED
|
|
194
|
-
}
|
|
208
|
+
}
|
|
209
|
+
else if (hundreds === 4) {
|
|
195
210
|
result = FOUR_HUNDRED
|
|
196
|
-
}
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
197
213
|
// Other hundreds: X ọgọ́rùn
|
|
198
214
|
result = ONES[hundreds] + ' ' + HUNDRED
|
|
199
215
|
}
|
|
@@ -207,11 +223,10 @@ function convertHundreds (n) {
|
|
|
207
223
|
|
|
208
224
|
/**
|
|
209
225
|
* Converts a non-negative integer to Yoruba words.
|
|
210
|
-
*
|
|
211
226
|
* @param {bigint} n - Non-negative integer to convert
|
|
212
227
|
* @returns {string} Yoruba words
|
|
213
228
|
*/
|
|
214
|
-
function integerToWords
|
|
229
|
+
function integerToWords(n) {
|
|
215
230
|
if (n === 0n) return ZERO
|
|
216
231
|
|
|
217
232
|
// Fast path: numbers < 100
|
|
@@ -234,7 +249,8 @@ function integerToWords (n) {
|
|
|
234
249
|
remaining = remaining % 1_000_000n
|
|
235
250
|
if (millions === 1n) {
|
|
236
251
|
parts.push(MILLION + ' kan')
|
|
237
|
-
}
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
238
254
|
parts.push(MILLION + ' ' + integerToWords(millions))
|
|
239
255
|
}
|
|
240
256
|
}
|
|
@@ -246,13 +262,17 @@ function integerToWords (n) {
|
|
|
246
262
|
|
|
247
263
|
if (thousands === 1n) {
|
|
248
264
|
parts.push(THOUSAND + ' kan')
|
|
249
|
-
}
|
|
265
|
+
}
|
|
266
|
+
else if (thousands === 10n) {
|
|
250
267
|
parts.push(TEN_THOUSAND)
|
|
251
|
-
}
|
|
268
|
+
}
|
|
269
|
+
else if (thousands === 20n) {
|
|
252
270
|
parts.push(TWENTY_THOUSAND)
|
|
253
|
-
}
|
|
271
|
+
}
|
|
272
|
+
else if (thousands < 100n) {
|
|
254
273
|
parts.push(THOUSAND + ' ' + buildUnder100(Number(thousands)))
|
|
255
|
-
}
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
256
276
|
parts.push(THOUSAND + ' ' + convertHundreds(Number(thousands)))
|
|
257
277
|
}
|
|
258
278
|
}
|
|
@@ -262,13 +282,16 @@ function integerToWords (n) {
|
|
|
262
282
|
if (remaining < 100n) {
|
|
263
283
|
if (parts.length > 0) {
|
|
264
284
|
parts.push(AND + ' ' + buildUnder100(Number(remaining)))
|
|
265
|
-
}
|
|
285
|
+
}
|
|
286
|
+
else {
|
|
266
287
|
parts.push(buildUnder100(Number(remaining)))
|
|
267
288
|
}
|
|
268
|
-
}
|
|
289
|
+
}
|
|
290
|
+
else {
|
|
269
291
|
if (parts.length > 0) {
|
|
270
292
|
parts.push(AND + ' ' + convertHundreds(Number(remaining)))
|
|
271
|
-
}
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
272
295
|
parts.push(convertHundreds(Number(remaining)))
|
|
273
296
|
}
|
|
274
297
|
}
|
|
@@ -279,11 +302,10 @@ function integerToWords (n) {
|
|
|
279
302
|
|
|
280
303
|
/**
|
|
281
304
|
* Converts decimal digits to Yoruba words.
|
|
282
|
-
*
|
|
283
305
|
* @param {string} decimalPart - Decimal digits
|
|
284
306
|
* @returns {string} Yoruba words for decimal
|
|
285
307
|
*/
|
|
286
|
-
function decimalPartToWords
|
|
308
|
+
function decimalPartToWords(decimalPart) {
|
|
287
309
|
const parts = []
|
|
288
310
|
|
|
289
311
|
for (const digit of decimalPart) {
|
|
@@ -296,11 +318,10 @@ function decimalPartToWords (decimalPart) {
|
|
|
296
318
|
|
|
297
319
|
/**
|
|
298
320
|
* Converts a numeric value to Yoruba words.
|
|
299
|
-
*
|
|
300
321
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
301
322
|
* @returns {string} The number in Yoruba words
|
|
302
323
|
*/
|
|
303
|
-
function toCardinal
|
|
324
|
+
function toCardinal(value) {
|
|
304
325
|
const { isNegative, integerPart, decimalPart } = parseCardinalValue(value)
|
|
305
326
|
|
|
306
327
|
let result = ''
|
|
@@ -326,11 +347,10 @@ function toCardinal (value) {
|
|
|
326
347
|
* Converts a non-negative integer to Yoruba ordinal words.
|
|
327
348
|
*
|
|
328
349
|
* Yoruba ordinals: àkọ́kọ́ (1st), ìkejì (2nd), ìkẹta (3rd), ìkẹrin (4th), etc.
|
|
329
|
-
*
|
|
330
350
|
* @param {bigint} n - Positive integer to convert
|
|
331
351
|
* @returns {string} Yoruba ordinal words
|
|
332
352
|
*/
|
|
333
|
-
function integerToOrdinal
|
|
353
|
+
function integerToOrdinal(n) {
|
|
334
354
|
// Special forms
|
|
335
355
|
if (n === 1n) return ORDINAL_FIRST
|
|
336
356
|
if (n === 2n) return ORDINAL_SECOND
|
|
@@ -341,18 +361,16 @@ function integerToOrdinal (n) {
|
|
|
341
361
|
|
|
342
362
|
/**
|
|
343
363
|
* Converts a numeric value to Yoruba ordinal words.
|
|
344
|
-
*
|
|
345
364
|
* @param {number | string | bigint} value - The numeric value to convert (positive integer)
|
|
346
365
|
* @returns {string} The number as ordinal words
|
|
347
366
|
* @throws {TypeError} If value is not a valid numeric type
|
|
348
367
|
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
349
|
-
*
|
|
350
368
|
* @example
|
|
351
369
|
* toOrdinal(1) // 'àkọ́kọ́'
|
|
352
370
|
* toOrdinal(2) // 'ìkejì'
|
|
353
371
|
* toOrdinal(3) // 'ìkẹẹ̀ta'
|
|
354
372
|
*/
|
|
355
|
-
function toOrdinal
|
|
373
|
+
function toOrdinal(value) {
|
|
356
374
|
const integerPart = parseOrdinalValue(value)
|
|
357
375
|
return integerToOrdinal(integerPart)
|
|
358
376
|
}
|
|
@@ -365,18 +383,16 @@ function toOrdinal (value) {
|
|
|
365
383
|
* Converts a numeric value to Yoruba currency words (Nigerian Naira).
|
|
366
384
|
*
|
|
367
385
|
* Uses náírà (naira) and kọ́bọ̀ (kobo).
|
|
368
|
-
*
|
|
369
386
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
370
387
|
* @returns {string} The amount in Yoruba currency words
|
|
371
388
|
* @throws {TypeError} If value is not a valid numeric type
|
|
372
389
|
* @throws {Error} If value is not a valid number format
|
|
373
|
-
*
|
|
374
390
|
* @example
|
|
375
391
|
* toCurrency(42) // 'èjì lé lógójì náírà'
|
|
376
392
|
* toCurrency(1.50) // 'ọ̀kan náírà àti àádọ́ta kọ́bọ̀'
|
|
377
393
|
* toCurrency(-5) // 'àìní àrùn náírà'
|
|
378
394
|
*/
|
|
379
|
-
function toCurrency
|
|
395
|
+
function toCurrency(value) {
|
|
380
396
|
const { isNegative, dollars: naira, cents: kobo } = parseCurrencyValue(value)
|
|
381
397
|
|
|
382
398
|
let result = ''
|
package/src/zh-Hans-CN.d.ts
CHANGED
|
@@ -1,48 +1,73 @@
|
|
|
1
|
+
export const cardinalMax: bigint;
|
|
2
|
+
export const ordinalMax: bigint;
|
|
3
|
+
export const currencyMax: bigint;
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {object} CardinalOptions
|
|
6
|
+
* @property {boolean} [formal] - Use formal/financial numerals
|
|
7
|
+
*/
|
|
8
|
+
/** @type {Required<CardinalOptions>} */
|
|
9
|
+
export const cardinalDefaults: Required<CardinalOptions>;
|
|
10
|
+
/**
|
|
11
|
+
* @typedef {object} OrdinalOptions
|
|
12
|
+
* @property {boolean} [formal] - Use formal/financial numerals
|
|
13
|
+
*/
|
|
14
|
+
/** @type {Required<OrdinalOptions>} */
|
|
15
|
+
export const ordinalDefaults: Required<OrdinalOptions>;
|
|
16
|
+
/**
|
|
17
|
+
* @typedef {object} CurrencyOptions
|
|
18
|
+
* @property {boolean} [formal] - Use formal/financial numerals
|
|
19
|
+
*/
|
|
20
|
+
/** @type {Required<CurrencyOptions>} */
|
|
21
|
+
export const currencyDefaults: Required<CurrencyOptions>;
|
|
22
|
+
export type CardinalOptions = {
|
|
23
|
+
/**
|
|
24
|
+
* - Use formal/financial numerals
|
|
25
|
+
*/
|
|
26
|
+
formal?: boolean | undefined;
|
|
27
|
+
};
|
|
28
|
+
export type OrdinalOptions = {
|
|
29
|
+
/**
|
|
30
|
+
* - Use formal/financial numerals
|
|
31
|
+
*/
|
|
32
|
+
formal?: boolean | undefined;
|
|
33
|
+
};
|
|
34
|
+
export type CurrencyOptions = {
|
|
35
|
+
/**
|
|
36
|
+
* - Use formal/financial numerals
|
|
37
|
+
*/
|
|
38
|
+
formal?: boolean | undefined;
|
|
39
|
+
};
|
|
1
40
|
/**
|
|
2
41
|
* Converts a numeric value to Simplified Chinese words.
|
|
3
|
-
*
|
|
4
42
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
5
|
-
* @param {
|
|
6
|
-
* @param {boolean} [options.formal=true] - Use formal/financial numerals
|
|
43
|
+
* @param {CardinalOptions} [options] - Optional configuration
|
|
7
44
|
* @returns {string} The number in Simplified Chinese words
|
|
8
45
|
*/
|
|
9
|
-
export function toCardinal(value: number | string | bigint, options?:
|
|
10
|
-
formal?: boolean | undefined;
|
|
11
|
-
}): string;
|
|
46
|
+
export function toCardinal(value: number | string | bigint, options?: CardinalOptions): string;
|
|
12
47
|
/**
|
|
13
48
|
* Converts a numeric value to Simplified Chinese ordinal words.
|
|
14
|
-
*
|
|
15
49
|
* @param {number | string | bigint} value - The numeric value to convert (positive integer)
|
|
16
|
-
* @param {
|
|
17
|
-
* @param {boolean} [options.formal=true] - Use formal/financial numerals
|
|
50
|
+
* @param {OrdinalOptions} [options] - Optional configuration
|
|
18
51
|
* @returns {string} The number as ordinal words
|
|
19
52
|
* @throws {TypeError} If value is not a valid numeric type
|
|
20
53
|
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
21
|
-
*
|
|
22
54
|
* @example
|
|
23
55
|
* toOrdinal(1) // '第壹'
|
|
24
56
|
* toOrdinal(1, { formal: false }) // '第一'
|
|
25
57
|
* toOrdinal(10) // '第壹拾'
|
|
26
58
|
*/
|
|
27
|
-
export function toOrdinal(value: number | string | bigint, options?:
|
|
28
|
-
formal?: boolean | undefined;
|
|
29
|
-
}): string;
|
|
59
|
+
export function toOrdinal(value: number | string | bigint, options?: OrdinalOptions): string;
|
|
30
60
|
/**
|
|
31
61
|
* Converts a numeric value to Simplified Chinese currency words (Yuan/Renminbi).
|
|
32
|
-
*
|
|
33
62
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
34
|
-
* @param {
|
|
35
|
-
* @param {boolean} [options.formal=true] - Use formal/financial numerals
|
|
63
|
+
* @param {CurrencyOptions} [options] - Optional configuration
|
|
36
64
|
* @returns {string} The amount in Simplified Chinese currency words
|
|
37
65
|
* @throws {TypeError} If value is not a valid numeric type
|
|
38
66
|
* @throws {Error} If value is not a valid number format
|
|
39
|
-
*
|
|
40
67
|
* @example
|
|
41
68
|
* toCurrency(42.50) // '肆拾贰圆伍角整'
|
|
42
69
|
* toCurrency(1) // '壹圆整'
|
|
43
70
|
* toCurrency(0.05) // '伍分'
|
|
44
71
|
* toCurrency(42.50, { formal: false }) // '四十二元五角整'
|
|
45
72
|
*/
|
|
46
|
-
export function toCurrency(value: number | string | bigint, options?:
|
|
47
|
-
formal?: boolean | undefined;
|
|
48
|
-
}): string;
|
|
73
|
+
export function toCurrency(value: number | string | bigint, options?: CurrencyOptions): string;
|
package/src/zh-Hans-CN.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 { bounded } from './utils/scale.js'
|
|
18
|
+
import { resolveOptions } from './utils/resolve-options.js'
|
|
17
19
|
|
|
18
20
|
// ============================================================================
|
|
19
21
|
// Vocabulary
|
|
@@ -35,6 +37,17 @@ const THOUSAND_FORMAL = '仟'
|
|
|
35
37
|
const WAN_WORD = '万' // 10,000
|
|
36
38
|
const YI_WORD = '亿' // 100,000,000
|
|
37
39
|
|
|
40
|
+
// Supported magnitude ceiling (checked at the public entry points). Numbers
|
|
41
|
+
// >= 亿 (10^8) split into n / 10^8, which is then spelled by convertBelowYi —
|
|
42
|
+
// itself only valid below 亿. So the ceiling is 亿² = 10^16. Ordinal (第 +
|
|
43
|
+
// cardinal) and currency build on the cardinal, so they share it. Decimals are
|
|
44
|
+
// spelled digit-by-digit, so they have no ceiling.
|
|
45
|
+
// No scale table — bounded by the convertBelowYi recursion (亿² = 10^16),
|
|
46
|
+
// declared via the escape hatch and verified by the gate. The three forms share it.
|
|
47
|
+
export const cardinalMax = bounded(16)
|
|
48
|
+
export const ordinalMax = bounded(16)
|
|
49
|
+
export const currencyMax = bounded(16)
|
|
50
|
+
|
|
38
51
|
const ZERO = '零'
|
|
39
52
|
const NEGATIVE = '负'
|
|
40
53
|
const DECIMAL_SEP = '点'
|
|
@@ -69,8 +82,14 @@ const ZHENG = '整'
|
|
|
69
82
|
|
|
70
83
|
/**
|
|
71
84
|
* Convert number below 万 (10,000) to words using direct string concatenation.
|
|
85
|
+
* @param {bigint} value The integer (0-9999) to convert
|
|
86
|
+
* @param {string[]} ones Digit words for 0-9
|
|
87
|
+
* @param {string} ten Word for the tens place
|
|
88
|
+
* @param {string} hundred Word for the hundreds place
|
|
89
|
+
* @param {string} thousand Word for the thousands place
|
|
90
|
+
* @returns {string} The number in words
|
|
72
91
|
*/
|
|
73
|
-
function convertBelowWan
|
|
92
|
+
function convertBelowWan(value, ones, ten, hundred, thousand) {
|
|
74
93
|
if (value === 0n) return ''
|
|
75
94
|
|
|
76
95
|
let result = ''
|
|
@@ -91,7 +110,8 @@ function convertBelowWan (value, ones, ten, hundred, thousand) {
|
|
|
91
110
|
if (needsZero) result += ZERO
|
|
92
111
|
result += ones[Number(hundredsVal)] + hundred
|
|
93
112
|
needsZero = hundredsRemainder > 0n && hundredsRemainder < 10n
|
|
94
|
-
}
|
|
113
|
+
}
|
|
114
|
+
else if (thousandsVal > 0n && hundredsRemainder > 0n) {
|
|
95
115
|
needsZero = true
|
|
96
116
|
}
|
|
97
117
|
|
|
@@ -102,7 +122,8 @@ function convertBelowWan (value, ones, ten, hundred, thousand) {
|
|
|
102
122
|
if (needsZero) result += ZERO
|
|
103
123
|
result += ones[Number(tensVal)] + ten
|
|
104
124
|
needsZero = false
|
|
105
|
-
}
|
|
125
|
+
}
|
|
126
|
+
else if ((hundredsVal > 0n || thousandsVal > 0n) && onesVal > 0n) {
|
|
106
127
|
needsZero = true
|
|
107
128
|
}
|
|
108
129
|
|
|
@@ -117,8 +138,14 @@ function convertBelowWan (value, ones, ten, hundred, thousand) {
|
|
|
117
138
|
|
|
118
139
|
/**
|
|
119
140
|
* Convert number below 亿 (100 million) to words.
|
|
141
|
+
* @param {bigint} value The integer to convert
|
|
142
|
+
* @param {string[]} ones Digit words for 0-9
|
|
143
|
+
* @param {string} ten Word for the tens place
|
|
144
|
+
* @param {string} hundred Word for the hundreds place
|
|
145
|
+
* @param {string} thousand Word for the thousands place
|
|
146
|
+
* @returns {string} The number in words
|
|
120
147
|
*/
|
|
121
|
-
function convertBelowYi
|
|
148
|
+
function convertBelowYi(value, ones, ten, hundred, thousand) {
|
|
122
149
|
if (value === 0n) return ''
|
|
123
150
|
|
|
124
151
|
if (value >= 10_000n) {
|
|
@@ -139,7 +166,13 @@ function convertBelowYi (value, ones, ten, hundred, thousand) {
|
|
|
139
166
|
return convertBelowWan(value, ones, ten, hundred, thousand)
|
|
140
167
|
}
|
|
141
168
|
|
|
142
|
-
|
|
169
|
+
/**
|
|
170
|
+
* Convert an integer to Simplified Chinese words.
|
|
171
|
+
* @param {bigint} n The integer to convert
|
|
172
|
+
* @param {boolean} [formal] Use formal/financial numerals
|
|
173
|
+
* @returns {string} The integer in Simplified Chinese words
|
|
174
|
+
*/
|
|
175
|
+
function integerToWords(n, formal = true) {
|
|
143
176
|
if (n === 0n) return ZERO
|
|
144
177
|
|
|
145
178
|
const ones = formal ? ONES_FORMAL : ONES_COMMON
|
|
@@ -167,8 +200,11 @@ function integerToWords (n, formal = true) {
|
|
|
167
200
|
|
|
168
201
|
/**
|
|
169
202
|
* Convert decimal digits to words using direct concatenation.
|
|
203
|
+
* @param {string} decimalString The decimal digits to convert
|
|
204
|
+
* @param {string[]} ones Digit words for 0-9
|
|
205
|
+
* @returns {string} The decimal digits in words
|
|
170
206
|
*/
|
|
171
|
-
function decimalDigitsToWords
|
|
207
|
+
function decimalDigitsToWords(decimalString, ones) {
|
|
172
208
|
let result = ''
|
|
173
209
|
for (let i = 0; i < decimalString.length; i++) {
|
|
174
210
|
result += ones[Number(decimalString[i])]
|
|
@@ -176,20 +212,26 @@ function decimalDigitsToWords (decimalString, ones) {
|
|
|
176
212
|
return result
|
|
177
213
|
}
|
|
178
214
|
|
|
215
|
+
/**
|
|
216
|
+
* @typedef {object} CardinalOptions
|
|
217
|
+
* @property {boolean} [formal] - Use formal/financial numerals
|
|
218
|
+
*/
|
|
219
|
+
|
|
220
|
+
/** @type {Required<CardinalOptions>} */
|
|
221
|
+
export const cardinalDefaults = { formal: true }
|
|
222
|
+
|
|
179
223
|
/**
|
|
180
224
|
* Converts a numeric value to Simplified Chinese words.
|
|
181
|
-
*
|
|
182
225
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
183
|
-
* @param {
|
|
184
|
-
* @param {boolean} [options.formal=true] - Use formal/financial numerals
|
|
226
|
+
* @param {CardinalOptions} [options] - Optional configuration
|
|
185
227
|
* @returns {string} The number in Simplified Chinese words
|
|
186
228
|
*/
|
|
187
|
-
function toCardinal
|
|
188
|
-
options = validateOptions(options)
|
|
229
|
+
function toCardinal(value, options) {
|
|
189
230
|
const { isNegative, integerPart, decimalPart } = parseCardinalValue(value)
|
|
231
|
+
checkMax(integerPart, cardinalMax)
|
|
190
232
|
|
|
191
233
|
// Apply option defaults
|
|
192
|
-
const { formal
|
|
234
|
+
const { formal } = resolveOptions(options, cardinalDefaults)
|
|
193
235
|
|
|
194
236
|
let result = isNegative ? NEGATIVE : ''
|
|
195
237
|
|
|
@@ -211,34 +253,38 @@ function toCardinal (value, options) {
|
|
|
211
253
|
* Converts a positive integer to Simplified Chinese ordinal words.
|
|
212
254
|
*
|
|
213
255
|
* Chinese ordinals: 第 prefix + cardinal number.
|
|
214
|
-
*
|
|
215
256
|
* @param {bigint} n - Positive integer to convert
|
|
216
257
|
* @param {boolean} formal - Use formal numerals
|
|
217
258
|
* @returns {string} Simplified Chinese ordinal words
|
|
218
259
|
*/
|
|
219
|
-
function integerToOrdinal
|
|
260
|
+
function integerToOrdinal(n, formal) {
|
|
220
261
|
return ORDINAL_PREFIX + integerToWords(n, formal)
|
|
221
262
|
}
|
|
222
263
|
|
|
264
|
+
/**
|
|
265
|
+
* @typedef {object} OrdinalOptions
|
|
266
|
+
* @property {boolean} [formal] - Use formal/financial numerals
|
|
267
|
+
*/
|
|
268
|
+
|
|
269
|
+
/** @type {Required<OrdinalOptions>} */
|
|
270
|
+
export const ordinalDefaults = { formal: true }
|
|
271
|
+
|
|
223
272
|
/**
|
|
224
273
|
* Converts a numeric value to Simplified Chinese ordinal words.
|
|
225
|
-
*
|
|
226
274
|
* @param {number | string | bigint} value - The numeric value to convert (positive integer)
|
|
227
|
-
* @param {
|
|
228
|
-
* @param {boolean} [options.formal=true] - Use formal/financial numerals
|
|
275
|
+
* @param {OrdinalOptions} [options] - Optional configuration
|
|
229
276
|
* @returns {string} The number as ordinal words
|
|
230
277
|
* @throws {TypeError} If value is not a valid numeric type
|
|
231
278
|
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
232
|
-
*
|
|
233
279
|
* @example
|
|
234
280
|
* toOrdinal(1) // '第壹'
|
|
235
281
|
* toOrdinal(1, { formal: false }) // '第一'
|
|
236
282
|
* toOrdinal(10) // '第壹拾'
|
|
237
283
|
*/
|
|
238
|
-
function toOrdinal
|
|
239
|
-
options = validateOptions(options)
|
|
284
|
+
function toOrdinal(value, options) {
|
|
240
285
|
const integerPart = parseOrdinalValue(value)
|
|
241
|
-
|
|
286
|
+
checkMax(integerPart, ordinalMax)
|
|
287
|
+
const { formal } = resolveOptions(options, ordinalDefaults)
|
|
242
288
|
return integerToOrdinal(integerPart, formal)
|
|
243
289
|
}
|
|
244
290
|
|
|
@@ -246,26 +292,31 @@ function toOrdinal (value, options) {
|
|
|
246
292
|
// CURRENCY: toCurrency(value, options?)
|
|
247
293
|
// ============================================================================
|
|
248
294
|
|
|
295
|
+
/**
|
|
296
|
+
* @typedef {object} CurrencyOptions
|
|
297
|
+
* @property {boolean} [formal] - Use formal/financial numerals
|
|
298
|
+
*/
|
|
299
|
+
|
|
300
|
+
/** @type {Required<CurrencyOptions>} */
|
|
301
|
+
export const currencyDefaults = { formal: true }
|
|
302
|
+
|
|
249
303
|
/**
|
|
250
304
|
* Converts a numeric value to Simplified Chinese currency words (Yuan/Renminbi).
|
|
251
|
-
*
|
|
252
305
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
253
|
-
* @param {
|
|
254
|
-
* @param {boolean} [options.formal=true] - Use formal/financial numerals
|
|
306
|
+
* @param {CurrencyOptions} [options] - Optional configuration
|
|
255
307
|
* @returns {string} The amount in Simplified Chinese currency words
|
|
256
308
|
* @throws {TypeError} If value is not a valid numeric type
|
|
257
309
|
* @throws {Error} If value is not a valid number format
|
|
258
|
-
*
|
|
259
310
|
* @example
|
|
260
311
|
* toCurrency(42.50) // '肆拾贰圆伍角整'
|
|
261
312
|
* toCurrency(1) // '壹圆整'
|
|
262
313
|
* toCurrency(0.05) // '伍分'
|
|
263
314
|
* toCurrency(42.50, { formal: false }) // '四十二元五角整'
|
|
264
315
|
*/
|
|
265
|
-
function toCurrency
|
|
266
|
-
options = validateOptions(options)
|
|
316
|
+
function toCurrency(value, options) {
|
|
267
317
|
const { isNegative, dollars: yuan, cents } = parseCurrencyValue(value)
|
|
268
|
-
|
|
318
|
+
checkMax(yuan, currencyMax)
|
|
319
|
+
const { formal } = resolveOptions(options, currencyDefaults)
|
|
269
320
|
|
|
270
321
|
const ones = formal ? ONES_FORMAL : ONES_COMMON
|
|
271
322
|
const yuanWord = formal ? YUAN_FORMAL : YUAN_COMMON
|
|
@@ -286,7 +337,8 @@ function toCurrency (value, options) {
|
|
|
286
337
|
// Jiao part (1/10)
|
|
287
338
|
if (jiao > 0n) {
|
|
288
339
|
result += ones[Number(jiao)] + JIAO
|
|
289
|
-
}
|
|
340
|
+
}
|
|
341
|
+
else if (yuan > 0n && fen > 0n) {
|
|
290
342
|
// Need zero placeholder between yuan and fen
|
|
291
343
|
result += ZERO
|
|
292
344
|
}
|
|
@@ -294,7 +346,8 @@ function toCurrency (value, options) {
|
|
|
294
346
|
// Fen part (1/100)
|
|
295
347
|
if (fen > 0n) {
|
|
296
348
|
result += ones[Number(fen)] + FEN
|
|
297
|
-
}
|
|
349
|
+
}
|
|
350
|
+
else if (yuan > 0n || jiao > 0n) {
|
|
298
351
|
// Add 整 (zheng) to indicate whole amount
|
|
299
352
|
result += ZHENG
|
|
300
353
|
}
|