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/id-ID.js
CHANGED
|
@@ -13,6 +13,8 @@
|
|
|
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 { checkMax } from './utils/check-max.js'
|
|
17
|
+
import { western } from './utils/scale.js'
|
|
16
18
|
|
|
17
19
|
// ============================================================================
|
|
18
20
|
// Vocabulary
|
|
@@ -26,6 +28,11 @@ const HUNDRED_WORD = 'ratus'
|
|
|
26
28
|
const THOUSAND_WORD = 'ribu'
|
|
27
29
|
const SCALE_WORDS = ['juta', 'miliar', 'triliun', 'kuadriliun', 'kuantiliun', 'sekstiliun', 'septiliun', 'oktiliun', 'noniliun', 'desiliun']
|
|
28
30
|
|
|
31
|
+
// Supported magnitude ceiling (checked at the public entry points), derived from the scale table.
|
|
32
|
+
export const cardinalMax = western(SCALE_WORDS.length + 1)
|
|
33
|
+
export const ordinalMax = western(SCALE_WORDS.length + 1)
|
|
34
|
+
export const currencyMax = western(SCALE_WORDS.length + 1)
|
|
35
|
+
|
|
29
36
|
const ZERO = 'nol'
|
|
30
37
|
const NEGATIVE = 'min'
|
|
31
38
|
const DECIMAL_SEP = 'koma'
|
|
@@ -48,7 +55,12 @@ const RUPIAH = 'rupiah'
|
|
|
48
55
|
// Segment Building
|
|
49
56
|
// ============================================================================
|
|
50
57
|
|
|
51
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Builds the Indonesian words for a 1-3 digit segment (0-999).
|
|
60
|
+
* @param {number} n - The segment value (0-999)
|
|
61
|
+
* @returns {string} The segment in Indonesian words
|
|
62
|
+
*/
|
|
63
|
+
function buildSegment(n) {
|
|
52
64
|
if (n === 0) return ''
|
|
53
65
|
|
|
54
66
|
const onesDigit = n % 10
|
|
@@ -61,7 +73,8 @@ function buildSegment (n) {
|
|
|
61
73
|
if (hundredsDigit > 0) {
|
|
62
74
|
if (hundredsDigit === 1) {
|
|
63
75
|
parts.push('se' + HUNDRED_WORD)
|
|
64
|
-
}
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
65
78
|
parts.push(ONES[hundredsDigit] + ' ' + HUNDRED_WORD)
|
|
66
79
|
}
|
|
67
80
|
}
|
|
@@ -71,13 +84,17 @@ function buildSegment (n) {
|
|
|
71
84
|
|
|
72
85
|
if (tensOnes === 0) {
|
|
73
86
|
// Just hundreds
|
|
74
|
-
}
|
|
87
|
+
}
|
|
88
|
+
else if (tensOnes < 10) {
|
|
75
89
|
parts.push(ONES[tensOnes])
|
|
76
|
-
}
|
|
90
|
+
}
|
|
91
|
+
else if (tensOnes < 20) {
|
|
77
92
|
parts.push(TEENS[tensOnes - 10])
|
|
78
|
-
}
|
|
93
|
+
}
|
|
94
|
+
else if (onesDigit === 0) {
|
|
79
95
|
parts.push(TENS[tensDigit])
|
|
80
|
-
}
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
81
98
|
parts.push(TENS[tensDigit] + ' ' + ONES[onesDigit])
|
|
82
99
|
}
|
|
83
100
|
|
|
@@ -88,7 +105,12 @@ function buildSegment (n) {
|
|
|
88
105
|
// Conversion Functions
|
|
89
106
|
// ============================================================================
|
|
90
107
|
|
|
91
|
-
|
|
108
|
+
/**
|
|
109
|
+
* Converts a non-negative integer to Indonesian words.
|
|
110
|
+
* @param {bigint} n - The integer value to convert
|
|
111
|
+
* @returns {string} The integer in Indonesian words
|
|
112
|
+
*/
|
|
113
|
+
function integerToWords(n) {
|
|
92
114
|
if (n === 0n) return ZERO
|
|
93
115
|
|
|
94
116
|
if (n < 1000n) {
|
|
@@ -102,7 +124,8 @@ function integerToWords (n) {
|
|
|
102
124
|
let result
|
|
103
125
|
if (thousands === 1) {
|
|
104
126
|
result = 'se' + THOUSAND_WORD
|
|
105
|
-
}
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
106
129
|
result = buildSegment(thousands) + ' ' + THOUSAND_WORD
|
|
107
130
|
}
|
|
108
131
|
|
|
@@ -116,7 +139,12 @@ function integerToWords (n) {
|
|
|
116
139
|
return buildLargeNumberWords(n)
|
|
117
140
|
}
|
|
118
141
|
|
|
119
|
-
|
|
142
|
+
/**
|
|
143
|
+
* Builds Indonesian words for large numbers (1,000,000 and above).
|
|
144
|
+
* @param {bigint} n - The integer value to convert
|
|
145
|
+
* @returns {string} The number in Indonesian words
|
|
146
|
+
*/
|
|
147
|
+
function buildLargeNumberWords(n) {
|
|
120
148
|
const numStr = n.toString()
|
|
121
149
|
const len = numStr.length
|
|
122
150
|
|
|
@@ -143,13 +171,16 @@ function buildLargeNumberWords (n) {
|
|
|
143
171
|
if (segment !== 0) {
|
|
144
172
|
if (scaleIndex === 0) {
|
|
145
173
|
parts.push(buildSegment(segment))
|
|
146
|
-
}
|
|
174
|
+
}
|
|
175
|
+
else if (scaleIndex === 1) {
|
|
147
176
|
if (segment === 1) {
|
|
148
177
|
parts.push('se' + THOUSAND_WORD)
|
|
149
|
-
}
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
150
180
|
parts.push(buildSegment(segment) + ' ' + THOUSAND_WORD)
|
|
151
181
|
}
|
|
152
|
-
}
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
153
184
|
// Indonesian: "satu juta" not "sejuta"
|
|
154
185
|
const scaleWord = SCALE_WORDS[scaleIndex - 2]
|
|
155
186
|
parts.push(buildSegment(segment) + ' ' + scaleWord)
|
|
@@ -162,7 +193,12 @@ function buildLargeNumberWords (n) {
|
|
|
162
193
|
return parts.join(' ')
|
|
163
194
|
}
|
|
164
195
|
|
|
165
|
-
|
|
196
|
+
/**
|
|
197
|
+
* Converts the decimal-part digit string to Indonesian words.
|
|
198
|
+
* @param {string} decimalPart - The decimal digits as a string
|
|
199
|
+
* @returns {string} The decimal part in Indonesian words
|
|
200
|
+
*/
|
|
201
|
+
function decimalPartToWords(decimalPart) {
|
|
166
202
|
let result = ''
|
|
167
203
|
|
|
168
204
|
let i = 0
|
|
@@ -183,12 +219,12 @@ function decimalPartToWords (decimalPart) {
|
|
|
183
219
|
|
|
184
220
|
/**
|
|
185
221
|
* Converts a numeric value to Indonesian words.
|
|
186
|
-
*
|
|
187
222
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
188
223
|
* @returns {string} The number in Indonesian words
|
|
189
224
|
*/
|
|
190
|
-
function toCardinal
|
|
225
|
+
function toCardinal(value) {
|
|
191
226
|
const { isNegative, integerPart, decimalPart } = parseCardinalValue(value)
|
|
227
|
+
checkMax(integerPart, cardinalMax, decimalPart)
|
|
192
228
|
|
|
193
229
|
let result = ''
|
|
194
230
|
|
|
@@ -214,11 +250,10 @@ function toCardinal (value) {
|
|
|
214
250
|
*
|
|
215
251
|
* Indonesian ordinals use "ke-" prefix + cardinal number.
|
|
216
252
|
* Special case: "pertama" for 1st (not "kesatu").
|
|
217
|
-
*
|
|
218
253
|
* @param {bigint} n - Positive integer to convert
|
|
219
254
|
* @returns {string} Indonesian ordinal words
|
|
220
255
|
*/
|
|
221
|
-
function integerToOrdinal
|
|
256
|
+
function integerToOrdinal(n) {
|
|
222
257
|
// Special case: 1st is "pertama"
|
|
223
258
|
if (n === 1n) {
|
|
224
259
|
return ORDINAL_FIRST
|
|
@@ -230,19 +265,18 @@ function integerToOrdinal (n) {
|
|
|
230
265
|
|
|
231
266
|
/**
|
|
232
267
|
* Converts a numeric value to Indonesian ordinal words.
|
|
233
|
-
*
|
|
234
268
|
* @param {number | string | bigint} value - The numeric value to convert (positive integer)
|
|
235
269
|
* @returns {string} The number as ordinal words
|
|
236
270
|
* @throws {TypeError} If value is not a valid numeric type
|
|
237
271
|
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
238
|
-
*
|
|
239
272
|
* @example
|
|
240
273
|
* toOrdinal(1) // 'pertama'
|
|
241
274
|
* toOrdinal(2) // 'kedua'
|
|
242
275
|
* toOrdinal(10) // 'kesepuluh'
|
|
243
276
|
*/
|
|
244
|
-
function toOrdinal
|
|
277
|
+
function toOrdinal(value) {
|
|
245
278
|
const integerPart = parseOrdinalValue(value)
|
|
279
|
+
checkMax(integerPart, ordinalMax)
|
|
246
280
|
return integerToOrdinal(integerPart)
|
|
247
281
|
}
|
|
248
282
|
|
|
@@ -255,19 +289,18 @@ function toOrdinal (value) {
|
|
|
255
289
|
*
|
|
256
290
|
* Indonesian Rupiah has no subunit in modern usage (sen are historical).
|
|
257
291
|
* Amounts are rounded to whole rupiah.
|
|
258
|
-
*
|
|
259
292
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
260
293
|
* @returns {string} The amount in Indonesian currency words
|
|
261
294
|
* @throws {TypeError} If value is not a valid numeric type
|
|
262
295
|
* @throws {Error} If value is not a valid number format
|
|
263
|
-
*
|
|
264
296
|
* @example
|
|
265
297
|
* toCurrency(42) // 'empat puluh dua rupiah'
|
|
266
298
|
* toCurrency(1000) // 'seribu rupiah'
|
|
267
299
|
* toCurrency(-5) // 'min lima rupiah'
|
|
268
300
|
*/
|
|
269
|
-
function toCurrency
|
|
301
|
+
function toCurrency(value) {
|
|
270
302
|
const { isNegative, dollars: rupiah } = parseCurrencyValue(value)
|
|
303
|
+
checkMax(rupiah, currencyMax)
|
|
271
304
|
|
|
272
305
|
let result = ''
|
|
273
306
|
if (isNegative) {
|
package/src/it-IT.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 "e" between euros and centesimi
|
|
7
|
+
*/
|
|
8
|
+
/** @type {Required<CurrencyOptions>} */
|
|
9
|
+
export const currencyDefaults: Required<CurrencyOptions>;
|
|
10
|
+
export type CurrencyOptions = {
|
|
11
|
+
/**
|
|
12
|
+
* - Use "e" between euros and centesimi
|
|
13
|
+
*/
|
|
14
|
+
and?: boolean | undefined;
|
|
15
|
+
};
|
|
1
16
|
/**
|
|
2
17
|
* Converts a numeric value to Italian 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 Italian 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(28) // 'ventotto'
|
|
14
27
|
* toCardinal(23) // 'ventitré'
|
|
@@ -22,12 +35,10 @@ export function toCardinal(value: number | string | bigint): string;
|
|
|
22
35
|
*
|
|
23
36
|
* Italian ordinals: primo, secondo, terzo... (1-10 irregular)
|
|
24
37
|
* For 11+: cardinal word (drop final vowel) + -esimo
|
|
25
|
-
*
|
|
26
38
|
* @param {number | string | bigint} value - The numeric value to convert (positive integer)
|
|
27
39
|
* @returns {string} The number as ordinal words (masculine form)
|
|
28
40
|
* @throws {TypeError} If value is not a valid numeric type
|
|
29
41
|
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
30
|
-
*
|
|
31
42
|
* @example
|
|
32
43
|
* toOrdinal(1) // 'primo'
|
|
33
44
|
* toOrdinal(2) // 'secondo'
|
|
@@ -39,14 +50,11 @@ export function toCardinal(value: number | string | bigint): string;
|
|
|
39
50
|
export function toOrdinal(value: number | string | bigint): string;
|
|
40
51
|
/**
|
|
41
52
|
* Converts a numeric value to Italian currency words (Euro).
|
|
42
|
-
*
|
|
43
53
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
44
|
-
* @param {
|
|
45
|
-
* @param {boolean} [options.and=true] - Use "e" between euros and centesimi
|
|
54
|
+
* @param {CurrencyOptions} [options] - Optional configuration
|
|
46
55
|
* @returns {string} The amount in Italian currency words
|
|
47
56
|
* @throws {TypeError} If value is not a valid numeric type
|
|
48
57
|
* @throws {Error} If value is not a valid number format
|
|
49
|
-
*
|
|
50
58
|
* @example
|
|
51
59
|
* toCurrency(42.50) // 'quarantadue euro e cinquanta centesimi'
|
|
52
60
|
* toCurrency(1) // 'un euro'
|
|
@@ -54,6 +62,4 @@ export function toOrdinal(value: number | string | bigint): string;
|
|
|
54
62
|
* toCurrency(0.01) // 'un centesimo'
|
|
55
63
|
* toCurrency(42.50, { and: false }) // 'quarantadue euro cinquanta centesimi'
|
|
56
64
|
*/
|
|
57
|
-
export function toCurrency(value: number | string | bigint, options?:
|
|
58
|
-
and?: boolean | undefined;
|
|
59
|
-
}): string;
|
|
65
|
+
export function toCurrency(value: number | string | bigint, options?: CurrencyOptions): string;
|
package/src/it-IT.js
CHANGED
|
@@ -15,7 +15,9 @@
|
|
|
15
15
|
import { parseCardinalValue } from './utils/parse-cardinal.js'
|
|
16
16
|
import { parseCurrencyValue } from './utils/parse-currency.js'
|
|
17
17
|
import { parseOrdinalValue } from './utils/parse-ordinal.js'
|
|
18
|
-
import {
|
|
18
|
+
import { checkMax } from './utils/check-max.js'
|
|
19
|
+
import { longScale } from './utils/scale.js'
|
|
20
|
+
import { resolveOptions } from './utils/resolve-options.js'
|
|
19
21
|
|
|
20
22
|
// ============================================================================
|
|
21
23
|
// Vocabulary (module-level constants)
|
|
@@ -42,6 +44,15 @@ const THOUSAND_PLURAL_SUFFIX = 'mila'
|
|
|
42
44
|
// Scale word generation
|
|
43
45
|
const SCALE_PREFIXES = ['m', 'b', 'tr', 'quadr', 'quint', 'sest', 'sett', 'ott', 'nov', 'dec']
|
|
44
46
|
|
|
47
|
+
// Long scale: each prefix yields an -ilione (10^6k) and an -iliardo (10^6k+3),
|
|
48
|
+
// so the table spans 6 powers of ten per prefix; past it the scale word is empty.
|
|
49
|
+
// Each form's maximum supported value (a bigint), derived from the prefix table
|
|
50
|
+
// so it can't drift. Exported per form so they split cleanly and the gate/docs
|
|
51
|
+
// read each as a fact. it-IT shares one ceiling across all three forms.
|
|
52
|
+
export const cardinalMax = longScale(SCALE_PREFIXES.length)
|
|
53
|
+
export const ordinalMax = longScale(SCALE_PREFIXES.length)
|
|
54
|
+
export const currencyMax = longScale(SCALE_PREFIXES.length)
|
|
55
|
+
|
|
45
56
|
// ============================================================================
|
|
46
57
|
// Ordinal Vocabulary
|
|
47
58
|
// ============================================================================
|
|
@@ -72,8 +83,10 @@ const CENTESIMI = 'centesimi'
|
|
|
72
83
|
* - Tens ending in vowel + uno/otto → drop tens vowel: ventuno, ventotto
|
|
73
84
|
* - Hundreds cento + otto/ottanta → centotto, centottanta (drop 'o')
|
|
74
85
|
* - Final 'tre' in compounds becomes 'tré': ventitré, trentatré
|
|
86
|
+
* @param {number} n - Number 0-999 to convert
|
|
87
|
+
* @returns {string} Segment word
|
|
75
88
|
*/
|
|
76
|
-
function buildSegment
|
|
89
|
+
function buildSegment(n) {
|
|
77
90
|
if (n === 0) return ''
|
|
78
91
|
|
|
79
92
|
const ones = n % 10
|
|
@@ -89,7 +102,8 @@ function buildSegment (n) {
|
|
|
89
102
|
if (tens === 8 || (tens === 0 && ones === 8)) {
|
|
90
103
|
// Remove final 'o' from hundreds: cento→cent, duecento→duecent, etc.
|
|
91
104
|
result = HUNDREDS[hundreds].slice(0, -1)
|
|
92
|
-
}
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
93
107
|
result = HUNDREDS[hundreds]
|
|
94
108
|
}
|
|
95
109
|
}
|
|
@@ -97,28 +111,35 @@ function buildSegment (n) {
|
|
|
97
111
|
// Tens and ones
|
|
98
112
|
if (tens === 0 && ones === 0) {
|
|
99
113
|
// Nothing more (just hundreds)
|
|
100
|
-
}
|
|
114
|
+
}
|
|
115
|
+
else if (tens === 1) {
|
|
101
116
|
// Teens: 10-19
|
|
102
117
|
result += TEENS[ones]
|
|
103
|
-
}
|
|
118
|
+
}
|
|
119
|
+
else if (tens >= 2) {
|
|
104
120
|
// 20-99: handle elision for uno (1) and otto (8)
|
|
105
121
|
if (ones === 1 || ones === 8) {
|
|
106
122
|
// Use stem form: vent + uno = ventuno, vent + otto = ventotto
|
|
107
123
|
result += TENS_STEM[tens] + ONES[ones]
|
|
108
|
-
}
|
|
124
|
+
}
|
|
125
|
+
else if (ones === 3) {
|
|
109
126
|
// Final tre becomes tré
|
|
110
127
|
result += TENS[tens] + 'tré'
|
|
111
|
-
}
|
|
128
|
+
}
|
|
129
|
+
else if (ones > 0) {
|
|
112
130
|
result += TENS[tens] + ONES[ones]
|
|
113
|
-
}
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
114
133
|
result += TENS[tens]
|
|
115
134
|
}
|
|
116
|
-
}
|
|
135
|
+
}
|
|
136
|
+
else if (ones > 0) {
|
|
117
137
|
// 1-9 (tens === 0)
|
|
118
138
|
if (ones === 3 && hundreds > 0) {
|
|
119
139
|
// centotré, duecentotré, etc.
|
|
120
140
|
result += 'tré'
|
|
121
|
-
}
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
122
143
|
result += ONES[ones]
|
|
123
144
|
}
|
|
124
145
|
}
|
|
@@ -129,8 +150,10 @@ function buildSegment (n) {
|
|
|
129
150
|
/**
|
|
130
151
|
* Builds segment word with "un" for scale context (millions, billions).
|
|
131
152
|
* Same as buildSegment but returns "un" for 1 instead of "uno".
|
|
153
|
+
* @param {number} n - Number 0-999 to convert
|
|
154
|
+
* @returns {string} Segment word
|
|
132
155
|
*/
|
|
133
|
-
function buildSegmentForScale
|
|
156
|
+
function buildSegmentForScale(n) {
|
|
134
157
|
if (n === 0) return ''
|
|
135
158
|
if (n === 1) return 'un' // "un milione" not "uno milione"
|
|
136
159
|
return buildSegment(n)
|
|
@@ -139,8 +162,10 @@ function buildSegmentForScale (n) {
|
|
|
139
162
|
/**
|
|
140
163
|
* Builds thousands word for 1-999 thousand.
|
|
141
164
|
* Handles elision: tre + mila = tremila (no accent), otto + mila = ottomila
|
|
165
|
+
* @param {number} n - Number of thousands 1-999
|
|
166
|
+
* @returns {string} Thousands word
|
|
142
167
|
*/
|
|
143
|
-
function buildThousands
|
|
168
|
+
function buildThousands(n) {
|
|
144
169
|
if (n === 0) return ''
|
|
145
170
|
if (n === 1) return THOUSAND_SINGULAR // "mille"
|
|
146
171
|
|
|
@@ -157,8 +182,9 @@ function buildThousands (n) {
|
|
|
157
182
|
/**
|
|
158
183
|
* Gets singular scale word for index.
|
|
159
184
|
* @param {number} scaleIndex - 2=million, 3=billion, etc.
|
|
185
|
+
* @returns {string} Singular scale word
|
|
160
186
|
*/
|
|
161
|
-
function getScaleWordSingular
|
|
187
|
+
function getScaleWordSingular(scaleIndex) {
|
|
162
188
|
if (scaleIndex < 2) return ''
|
|
163
189
|
const prefixIndex = Math.trunc((scaleIndex - 2) / 2)
|
|
164
190
|
const isIardo = (scaleIndex - 2) % 2 === 1
|
|
@@ -170,8 +196,9 @@ function getScaleWordSingular (scaleIndex) {
|
|
|
170
196
|
/**
|
|
171
197
|
* Gets plural scale word for index.
|
|
172
198
|
* @param {number} scaleIndex - 2=million, 3=billion, etc.
|
|
199
|
+
* @returns {string} Plural scale word
|
|
173
200
|
*/
|
|
174
|
-
function getScaleWordPlural
|
|
201
|
+
function getScaleWordPlural(scaleIndex) {
|
|
175
202
|
if (scaleIndex < 2) return ''
|
|
176
203
|
const prefixIndex = Math.trunc((scaleIndex - 2) / 2)
|
|
177
204
|
const isIardo = (scaleIndex - 2) % 2 === 1
|
|
@@ -186,11 +213,10 @@ function getScaleWordPlural (scaleIndex) {
|
|
|
186
213
|
|
|
187
214
|
/**
|
|
188
215
|
* Converts a non-negative integer to Italian words.
|
|
189
|
-
*
|
|
190
216
|
* @param {bigint} n - Non-negative integer to convert
|
|
191
217
|
* @returns {string} Italian words
|
|
192
218
|
*/
|
|
193
|
-
function integerToWords
|
|
219
|
+
function integerToWords(n) {
|
|
194
220
|
if (n === 0n) return ZERO
|
|
195
221
|
|
|
196
222
|
// Fast path: numbers < 1000
|
|
@@ -217,11 +243,10 @@ function integerToWords (n) {
|
|
|
217
243
|
|
|
218
244
|
/**
|
|
219
245
|
* Builds words for numbers >= 1,000,000.
|
|
220
|
-
*
|
|
221
246
|
* @param {bigint} n - Number >= 1,000,000
|
|
222
247
|
* @returns {string} Italian words
|
|
223
248
|
*/
|
|
224
|
-
function buildLargeNumberWords
|
|
249
|
+
function buildLargeNumberWords(n) {
|
|
225
250
|
const parts = []
|
|
226
251
|
let remaining = n
|
|
227
252
|
|
|
@@ -250,10 +275,12 @@ function buildLargeNumberWords (n) {
|
|
|
250
275
|
? getScaleWordSingular(scaleIndex)
|
|
251
276
|
: getScaleWordPlural(scaleIndex)
|
|
252
277
|
parts.push(segmentWords + ' ' + scaleWord)
|
|
253
|
-
}
|
|
278
|
+
}
|
|
279
|
+
else if (scaleIndex === 1) {
|
|
254
280
|
// Thousands
|
|
255
281
|
parts.push(buildThousands(segNum))
|
|
256
|
-
}
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
257
284
|
// Units (scaleIndex === 0): just the segment
|
|
258
285
|
parts.push(buildSegment(segNum))
|
|
259
286
|
}
|
|
@@ -265,11 +292,10 @@ function buildLargeNumberWords (n) {
|
|
|
265
292
|
/**
|
|
266
293
|
* Joins parts with Italian connector rules.
|
|
267
294
|
* Uses "e" before simple (non-compound) final segment.
|
|
268
|
-
*
|
|
269
295
|
* @param {string[]} parts - Parts to join
|
|
270
296
|
* @returns {string} Joined string
|
|
271
297
|
*/
|
|
272
|
-
function joinPartsWithConnector
|
|
298
|
+
function joinPartsWithConnector(parts) {
|
|
273
299
|
const len = parts.length
|
|
274
300
|
if (len === 0) return ''
|
|
275
301
|
if (len === 1) return parts[0]
|
|
@@ -295,11 +321,10 @@ function joinPartsWithConnector (parts) {
|
|
|
295
321
|
|
|
296
322
|
/**
|
|
297
323
|
* Converts decimal digits to Italian words.
|
|
298
|
-
*
|
|
299
324
|
* @param {string} decimalPart - Decimal digits (without the point)
|
|
300
325
|
* @returns {string} Italian words for decimal part
|
|
301
326
|
*/
|
|
302
|
-
function decimalPartToWords
|
|
327
|
+
function decimalPartToWords(decimalPart) {
|
|
303
328
|
let result = ''
|
|
304
329
|
|
|
305
330
|
// Handle leading zeros
|
|
@@ -325,12 +350,10 @@ function decimalPartToWords (decimalPart) {
|
|
|
325
350
|
*
|
|
326
351
|
* This is the main public API. It accepts any valid numeric input
|
|
327
352
|
* (number, string, or bigint) and handles parsing internally.
|
|
328
|
-
*
|
|
329
353
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
330
354
|
* @returns {string} The number in Italian words
|
|
331
355
|
* @throws {TypeError} If value is not a valid numeric type
|
|
332
356
|
* @throws {Error} If value is not a valid number format
|
|
333
|
-
*
|
|
334
357
|
* @example
|
|
335
358
|
* toCardinal(28) // 'ventotto'
|
|
336
359
|
* toCardinal(23) // 'ventitré'
|
|
@@ -338,8 +361,11 @@ function decimalPartToWords (decimalPart) {
|
|
|
338
361
|
* toCardinal(2000) // 'duemila'
|
|
339
362
|
* toCardinal(1000000) // 'un milione'
|
|
340
363
|
*/
|
|
341
|
-
function toCardinal
|
|
364
|
+
function toCardinal(value) {
|
|
342
365
|
const { isNegative, integerPart, decimalPart } = parseCardinalValue(value)
|
|
366
|
+
// Both the integer part and the decimal's significant digits are spelled via
|
|
367
|
+
// the scale builder, so both must clear the ceiling.
|
|
368
|
+
checkMax(integerPart, cardinalMax, decimalPart)
|
|
343
369
|
|
|
344
370
|
let result = ''
|
|
345
371
|
|
|
@@ -362,11 +388,10 @@ function toCardinal (value) {
|
|
|
362
388
|
|
|
363
389
|
/**
|
|
364
390
|
* Converts a cardinal word to ordinal form by dropping final vowel and adding -esimo.
|
|
365
|
-
*
|
|
366
391
|
* @param {string} cardinalWord - Cardinal word to convert
|
|
367
392
|
* @returns {string} Ordinal form
|
|
368
393
|
*/
|
|
369
|
-
function cardinalToOrdinal
|
|
394
|
+
function cardinalToOrdinal(cardinalWord) {
|
|
370
395
|
// Handle accented 'é' at end (tré → tre + esimo = treesimo)
|
|
371
396
|
if (cardinalWord.endsWith('é')) {
|
|
372
397
|
return cardinalWord.slice(0, -1) + 'e' + ORDINAL_SUFFIX
|
|
@@ -401,11 +426,10 @@ function cardinalToOrdinal (cardinalWord) {
|
|
|
401
426
|
|
|
402
427
|
/**
|
|
403
428
|
* Converts a positive integer to Italian ordinal words.
|
|
404
|
-
*
|
|
405
429
|
* @param {bigint} n - Positive integer
|
|
406
430
|
* @returns {string} Italian ordinal words (masculine form)
|
|
407
431
|
*/
|
|
408
|
-
function integerToOrdinal
|
|
432
|
+
function integerToOrdinal(n) {
|
|
409
433
|
// Special cases: 1-10 have irregular forms
|
|
410
434
|
if (n <= 10n) {
|
|
411
435
|
return ORDINAL_ONES[Number(n)]
|
|
@@ -421,12 +445,10 @@ function integerToOrdinal (n) {
|
|
|
421
445
|
*
|
|
422
446
|
* Italian ordinals: primo, secondo, terzo... (1-10 irregular)
|
|
423
447
|
* For 11+: cardinal word (drop final vowel) + -esimo
|
|
424
|
-
*
|
|
425
448
|
* @param {number | string | bigint} value - The numeric value to convert (positive integer)
|
|
426
449
|
* @returns {string} The number as ordinal words (masculine form)
|
|
427
450
|
* @throws {TypeError} If value is not a valid numeric type
|
|
428
451
|
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
429
|
-
*
|
|
430
452
|
* @example
|
|
431
453
|
* toOrdinal(1) // 'primo'
|
|
432
454
|
* toOrdinal(2) // 'secondo'
|
|
@@ -435,8 +457,10 @@ function integerToOrdinal (n) {
|
|
|
435
457
|
* toOrdinal(100) // 'centesimo'
|
|
436
458
|
* toOrdinal(1000) // 'millesimo'
|
|
437
459
|
*/
|
|
438
|
-
function toOrdinal
|
|
460
|
+
function toOrdinal(value) {
|
|
439
461
|
const integerPart = parseOrdinalValue(value)
|
|
462
|
+
// Ordinals are derived from the cardinal speller, so they share its ceiling.
|
|
463
|
+
checkMax(integerPart, ordinalMax)
|
|
440
464
|
return integerToOrdinal(integerPart)
|
|
441
465
|
}
|
|
442
466
|
|
|
@@ -444,16 +468,21 @@ function toOrdinal (value) {
|
|
|
444
468
|
// CURRENCY: toCurrency(value, options?)
|
|
445
469
|
// ============================================================================
|
|
446
470
|
|
|
471
|
+
/**
|
|
472
|
+
* @typedef {object} CurrencyOptions
|
|
473
|
+
* @property {boolean} [and] - Use "e" between euros and centesimi
|
|
474
|
+
*/
|
|
475
|
+
|
|
476
|
+
/** @type {Required<CurrencyOptions>} */
|
|
477
|
+
export const currencyDefaults = { and: true }
|
|
478
|
+
|
|
447
479
|
/**
|
|
448
480
|
* Converts a numeric value to Italian currency words (Euro).
|
|
449
|
-
*
|
|
450
481
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
451
|
-
* @param {
|
|
452
|
-
* @param {boolean} [options.and=true] - Use "e" between euros and centesimi
|
|
482
|
+
* @param {CurrencyOptions} [options] - Optional configuration
|
|
453
483
|
* @returns {string} The amount in Italian currency words
|
|
454
484
|
* @throws {TypeError} If value is not a valid numeric type
|
|
455
485
|
* @throws {Error} If value is not a valid number format
|
|
456
|
-
*
|
|
457
486
|
* @example
|
|
458
487
|
* toCurrency(42.50) // 'quarantadue euro e cinquanta centesimi'
|
|
459
488
|
* toCurrency(1) // 'un euro'
|
|
@@ -461,10 +490,10 @@ function toOrdinal (value) {
|
|
|
461
490
|
* toCurrency(0.01) // 'un centesimo'
|
|
462
491
|
* toCurrency(42.50, { and: false }) // 'quarantadue euro cinquanta centesimi'
|
|
463
492
|
*/
|
|
464
|
-
function toCurrency
|
|
465
|
-
options = validateOptions(options)
|
|
493
|
+
function toCurrency(value, options) {
|
|
466
494
|
const { isNegative, dollars: euros, cents: centesimi } = parseCurrencyValue(value)
|
|
467
|
-
|
|
495
|
+
checkMax(euros, currencyMax)
|
|
496
|
+
const { and: useAnd } = resolveOptions(options, currencyDefaults)
|
|
468
497
|
|
|
469
498
|
// Build result
|
|
470
499
|
let result = ''
|
|
@@ -475,7 +504,8 @@ function toCurrency (value, options) {
|
|
|
475
504
|
// Use "un" for 1 euro instead of "uno"
|
|
476
505
|
if (euros === 1n) {
|
|
477
506
|
result += 'un'
|
|
478
|
-
}
|
|
507
|
+
}
|
|
508
|
+
else {
|
|
479
509
|
result += integerToWords(euros)
|
|
480
510
|
}
|
|
481
511
|
// Euro is invariable (doesn't change for plural in Italian)
|
|
@@ -490,7 +520,8 @@ function toCurrency (value, options) {
|
|
|
490
520
|
// Use "un" for 1 centesimo instead of "uno"
|
|
491
521
|
if (centesimi === 1n) {
|
|
492
522
|
result += 'un'
|
|
493
|
-
}
|
|
523
|
+
}
|
|
524
|
+
else {
|
|
494
525
|
result += integerToWords(centesimi)
|
|
495
526
|
}
|
|
496
527
|
result += ' ' + (centesimi === 1n ? CENTESIMO : CENTESIMI)
|
package/src/ja-JP.d.ts
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
|
+
export const cardinalMax: bigint;
|
|
2
|
+
export const ordinalMax: bigint;
|
|
3
|
+
export const currencyMax: bigint;
|
|
1
4
|
/**
|
|
2
5
|
* Converts a numeric value to Japanese words.
|
|
3
6
|
*
|
|
4
7
|
* This is the main public API. It accepts any valid numeric input
|
|
5
8
|
* (number, string, or bigint) and handles parsing internally.
|
|
6
|
-
*
|
|
7
9
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
8
10
|
* @returns {string} The number in Japanese kanji words
|
|
9
11
|
* @throws {TypeError} If value is not a valid numeric type
|
|
10
12
|
* @throws {Error} If value is not a valid number format
|
|
11
|
-
*
|
|
12
13
|
* @example
|
|
13
14
|
* toCardinal(42) // '四十二'
|
|
14
15
|
* toCardinal(10000) // '一万'
|
|
@@ -17,12 +18,10 @@
|
|
|
17
18
|
export function toCardinal(value: number | string | bigint): string;
|
|
18
19
|
/**
|
|
19
20
|
* Converts a numeric value to Japanese ordinal words.
|
|
20
|
-
*
|
|
21
21
|
* @param {number | string | bigint} value - The numeric value to convert (positive integer)
|
|
22
22
|
* @returns {string} The number as ordinal words
|
|
23
23
|
* @throws {TypeError} If value is not a valid numeric type
|
|
24
24
|
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
25
|
-
*
|
|
26
25
|
* @example
|
|
27
26
|
* toOrdinal(1) // '第一'
|
|
28
27
|
* toOrdinal(10) // '第十'
|
|
@@ -34,12 +33,10 @@ export function toOrdinal(value: number | string | bigint): string;
|
|
|
34
33
|
*
|
|
35
34
|
* Note: Sen (銭, 1/100 yen) is included for completeness but is rarely used
|
|
36
35
|
* in modern Japan. Most transactions are in whole yen.
|
|
37
|
-
*
|
|
38
36
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
39
37
|
* @returns {string} The amount in Japanese currency words
|
|
40
38
|
* @throws {TypeError} If value is not a valid numeric type
|
|
41
39
|
* @throws {Error} If value is not a valid number format
|
|
42
|
-
*
|
|
43
40
|
* @example
|
|
44
41
|
* toCurrency(42) // '四十二円'
|
|
45
42
|
* toCurrency(1) // '一円'
|