n2words 4.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 +53 -0
- package/README.md +14 -12
- 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 -0
- package/dist/pt-BR.umd.js +2 -0
- 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 +53 -36
- 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 +42 -0
- package/src/pt-BR.js +574 -0
- 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/lv-LV.js
CHANGED
|
@@ -14,7 +14,9 @@
|
|
|
14
14
|
import { parseCardinalValue } from './utils/parse-cardinal.js'
|
|
15
15
|
import { parseCurrencyValue } from './utils/parse-currency.js'
|
|
16
16
|
import { parseOrdinalValue } from './utils/parse-ordinal.js'
|
|
17
|
-
import {
|
|
17
|
+
import { checkMax } from './utils/check-max.js'
|
|
18
|
+
import { western } from './utils/scale.js'
|
|
19
|
+
import { resolveOptions } from './utils/resolve-options.js'
|
|
18
20
|
|
|
19
21
|
// ============================================================================
|
|
20
22
|
// Vocabulary (module-level constants)
|
|
@@ -72,9 +74,18 @@ const SCALE_FORMS = [
|
|
|
72
74
|
['kvintiljons', 'kvintiljoni', 'kvintiljonu'],
|
|
73
75
|
['sikstiljons', 'sikstiljoni', 'sikstiljonu'],
|
|
74
76
|
['septiljons', 'septiljoni', 'septiljonu'],
|
|
75
|
-
['oktiljons', 'oktiljoni', 'oktiljonu']
|
|
77
|
+
['oktiljons', 'oktiljoni', 'oktiljonu'],
|
|
76
78
|
]
|
|
77
79
|
|
|
80
|
+
// Supported magnitude ceilings (checked at the public entry points). Both
|
|
81
|
+
// tables are indexed [scaleIndex - 1] (units separate), so the cardinal/
|
|
82
|
+
// currency ceiling is 10^((SCALE_FORMS.length + 1) * 3) = 10^30, and the
|
|
83
|
+
// shorter ORDINAL_SCALES bounds ordinals at 10^((ORDINAL_SCALES.length + 1) *
|
|
84
|
+
// 3) = 10^15.
|
|
85
|
+
export const cardinalMax = western(SCALE_FORMS.length)
|
|
86
|
+
export const ordinalMax = western(ORDINAL_SCALES.length)
|
|
87
|
+
export const currencyMax = western(SCALE_FORMS.length)
|
|
88
|
+
|
|
78
89
|
// ============================================================================
|
|
79
90
|
// Segment Building
|
|
80
91
|
// ============================================================================
|
|
@@ -83,8 +94,10 @@ const SCALE_FORMS = [
|
|
|
83
94
|
* Builds segment word for 0-999 (masculine form).
|
|
84
95
|
* Does NOT include special handling for segment=1 (omitOneBeforeScale).
|
|
85
96
|
* That's handled at join time.
|
|
97
|
+
* @param {number} n - Segment value 0-999
|
|
98
|
+
* @returns {string} The segment in Latvian words
|
|
86
99
|
*/
|
|
87
|
-
function buildSegment
|
|
100
|
+
function buildSegment(n) {
|
|
88
101
|
if (n === 0) return ''
|
|
89
102
|
|
|
90
103
|
const ones = n % 10
|
|
@@ -98,11 +111,13 @@ function buildSegment (n) {
|
|
|
98
111
|
if (hundreds === 1 && tens === 0 && ones > 0) {
|
|
99
112
|
// 101-109: use genitive form "simtu"
|
|
100
113
|
parts.push(HUNDRED_GENITIVE)
|
|
101
|
-
}
|
|
114
|
+
}
|
|
115
|
+
else if (hundreds > 1) {
|
|
102
116
|
// 200-999: use plural "simti"
|
|
103
117
|
parts.push(ONES_MASC[hundreds])
|
|
104
118
|
parts.push(HUNDRED_PLURAL)
|
|
105
|
-
}
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
106
121
|
// 100, 110-199: use singular "simts"
|
|
107
122
|
parts.push(HUNDRED_SINGULAR)
|
|
108
123
|
}
|
|
@@ -116,7 +131,8 @@ function buildSegment (n) {
|
|
|
116
131
|
// Teens or ones
|
|
117
132
|
if (tens === 1) {
|
|
118
133
|
parts.push(TEENS[ones])
|
|
119
|
-
}
|
|
134
|
+
}
|
|
135
|
+
else if (ones > 0) {
|
|
120
136
|
parts.push(ONES_MASC[ones])
|
|
121
137
|
}
|
|
122
138
|
|
|
@@ -125,8 +141,10 @@ function buildSegment (n) {
|
|
|
125
141
|
|
|
126
142
|
/**
|
|
127
143
|
* Builds segment word for 0-999 (feminine form - only differs in ones).
|
|
144
|
+
* @param {number} n - Segment value 0-999
|
|
145
|
+
* @returns {string} The segment in Latvian words
|
|
128
146
|
*/
|
|
129
|
-
function buildSegmentFeminine
|
|
147
|
+
function buildSegmentFeminine(n) {
|
|
130
148
|
if (n === 0) return ''
|
|
131
149
|
|
|
132
150
|
const ones = n % 10
|
|
@@ -139,10 +157,12 @@ function buildSegmentFeminine (n) {
|
|
|
139
157
|
if (hundreds > 0) {
|
|
140
158
|
if (hundreds === 1 && tens === 0 && ones > 0) {
|
|
141
159
|
parts.push(HUNDRED_GENITIVE)
|
|
142
|
-
}
|
|
160
|
+
}
|
|
161
|
+
else if (hundreds > 1) {
|
|
143
162
|
parts.push(ONES_MASC[hundreds])
|
|
144
163
|
parts.push(HUNDRED_PLURAL)
|
|
145
|
-
}
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
146
166
|
parts.push(HUNDRED_SINGULAR)
|
|
147
167
|
}
|
|
148
168
|
}
|
|
@@ -155,7 +175,8 @@ function buildSegmentFeminine (n) {
|
|
|
155
175
|
// Teens or ones - feminine for ones only
|
|
156
176
|
if (tens === 1) {
|
|
157
177
|
parts.push(TEENS[ones])
|
|
158
|
-
}
|
|
178
|
+
}
|
|
179
|
+
else if (ones > 0) {
|
|
159
180
|
parts.push(ONES_FEM[ones])
|
|
160
181
|
}
|
|
161
182
|
|
|
@@ -170,12 +191,11 @@ function buildSegmentFeminine (n) {
|
|
|
170
191
|
* Latvian pluralization - simpler than Slavic.
|
|
171
192
|
* Singular: ends in 1 (except 11)
|
|
172
193
|
* Plural: everything else
|
|
173
|
-
*
|
|
174
194
|
* @param {number} n - The segment value
|
|
175
195
|
* @param {string[]} forms - [singular, plural, genitive]
|
|
176
196
|
* @returns {string} The appropriate form
|
|
177
197
|
*/
|
|
178
|
-
function pluralize
|
|
198
|
+
function pluralize(n, forms) {
|
|
179
199
|
if (n === 0) return forms[2]
|
|
180
200
|
|
|
181
201
|
const lastDigit = n % 10
|
|
@@ -191,12 +211,11 @@ function pluralize (n, forms) {
|
|
|
191
211
|
/**
|
|
192
212
|
* Latvian currency pluralization.
|
|
193
213
|
* Uses genitive for 0, 10-19, and multiples of 10.
|
|
194
|
-
*
|
|
195
214
|
* @param {number} n - The segment value
|
|
196
215
|
* @param {string[]} forms - [singular, plural, genitive]
|
|
197
216
|
* @returns {string} The appropriate form
|
|
198
217
|
*/
|
|
199
|
-
function pluralizeCurrency
|
|
218
|
+
function pluralizeCurrency(n, forms) {
|
|
200
219
|
if (n === 0) return forms[2]
|
|
201
220
|
|
|
202
221
|
const lastDigit = n % 10
|
|
@@ -227,12 +246,11 @@ function pluralizeCurrency (n, forms) {
|
|
|
227
246
|
|
|
228
247
|
/**
|
|
229
248
|
* Converts a non-negative integer to Latvian words.
|
|
230
|
-
*
|
|
231
249
|
* @param {bigint} n - Non-negative integer to convert
|
|
232
|
-
* @param {
|
|
250
|
+
* @param {string} gender - Gender for numbers < 1000
|
|
233
251
|
* @returns {string} Latvian words
|
|
234
252
|
*/
|
|
235
|
-
function integerToWords
|
|
253
|
+
function integerToWords(n, gender) {
|
|
236
254
|
if (n === 0n) return ZERO
|
|
237
255
|
|
|
238
256
|
// Fast path: numbers < 1000
|
|
@@ -243,17 +261,15 @@ function integerToWords (n, gender) {
|
|
|
243
261
|
|
|
244
262
|
// For numbers >= 1000, feminine only applies to final segment if < 1000
|
|
245
263
|
// But we use masculine for all segments when n >= 1000
|
|
246
|
-
return buildLargeNumberWords(n
|
|
264
|
+
return buildLargeNumberWords(n)
|
|
247
265
|
}
|
|
248
266
|
|
|
249
267
|
/**
|
|
250
268
|
* Builds words for numbers >= 1000.
|
|
251
|
-
*
|
|
252
269
|
* @param {bigint} n - Number >= 1000
|
|
253
|
-
* @param {Object} options - Conversion options
|
|
254
270
|
* @returns {string} Latvian words
|
|
255
271
|
*/
|
|
256
|
-
function buildLargeNumberWords
|
|
272
|
+
function buildLargeNumberWords(n) {
|
|
257
273
|
const numStr = n.toString()
|
|
258
274
|
const len = numStr.length
|
|
259
275
|
|
|
@@ -285,7 +301,8 @@ function buildLargeNumberWords (n, gender) {
|
|
|
285
301
|
if (scaleIndex === 0) {
|
|
286
302
|
// Units segment - use masculine (feminine doesn't apply when n >= 1000)
|
|
287
303
|
parts.push(segmentWord)
|
|
288
|
-
}
|
|
304
|
+
}
|
|
305
|
+
else {
|
|
289
306
|
// Segment with scale word
|
|
290
307
|
const scaleForms = SCALE_FORMS[scaleIndex - 1]
|
|
291
308
|
const scaleWord = pluralize(segment, scaleForms)
|
|
@@ -293,7 +310,8 @@ function buildLargeNumberWords (n, gender) {
|
|
|
293
310
|
// Latvian omits "one" before scale words
|
|
294
311
|
if (segment === 1) {
|
|
295
312
|
parts.push(scaleWord)
|
|
296
|
-
}
|
|
313
|
+
}
|
|
314
|
+
else {
|
|
297
315
|
parts.push(segmentWord + ' ' + scaleWord)
|
|
298
316
|
}
|
|
299
317
|
}
|
|
@@ -307,12 +325,11 @@ function buildLargeNumberWords (n, gender) {
|
|
|
307
325
|
|
|
308
326
|
/**
|
|
309
327
|
* Converts decimal digits to Latvian words.
|
|
310
|
-
*
|
|
311
328
|
* @param {string} decimalPart - Decimal digits (without the point)
|
|
312
|
-
* @param {
|
|
329
|
+
* @param {string} gender - Gender for numbers < 1000
|
|
313
330
|
* @returns {string} Latvian words for decimal part
|
|
314
331
|
*/
|
|
315
|
-
function decimalPartToWords
|
|
332
|
+
function decimalPartToWords(decimalPart, gender) {
|
|
316
333
|
let result = ''
|
|
317
334
|
|
|
318
335
|
// Handle leading zeros
|
|
@@ -333,27 +350,37 @@ function decimalPartToWords (decimalPart, gender) {
|
|
|
333
350
|
return result
|
|
334
351
|
}
|
|
335
352
|
|
|
353
|
+
/**
|
|
354
|
+
* @typedef {object} CardinalOptions
|
|
355
|
+
* @property {('masculine'|'feminine')} [gender] - Gender for numbers < 1000
|
|
356
|
+
*/
|
|
357
|
+
|
|
358
|
+
/** @type {Required<CardinalOptions>} */
|
|
359
|
+
export const cardinalDefaults = { gender: 'masculine' }
|
|
360
|
+
|
|
361
|
+
/** @type {{ gender: ReadonlyArray<Required<CardinalOptions>['gender']> }} */
|
|
362
|
+
export const cardinalValues = { gender: ['masculine', 'feminine'] }
|
|
363
|
+
|
|
336
364
|
/**
|
|
337
365
|
* Converts a numeric value to Latvian words.
|
|
338
|
-
*
|
|
339
366
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
340
|
-
* @param {
|
|
341
|
-
* @param {string} [options.gender='masculine'] - Gender for numbers < 1000
|
|
367
|
+
* @param {CardinalOptions} [options] - Conversion options
|
|
342
368
|
* @returns {string} The number in Latvian words
|
|
343
369
|
* @throws {TypeError} If value is not a valid numeric type
|
|
344
370
|
* @throws {Error} If value is not a valid number format
|
|
345
|
-
*
|
|
346
371
|
* @example
|
|
347
372
|
* toCardinal(42) // 'četrdesmit divi'
|
|
348
373
|
* toCardinal(1, { gender: 'feminine' }) // 'viena'
|
|
349
374
|
* toCardinal(1000) // 'tūkstotis'
|
|
350
375
|
*/
|
|
351
|
-
function toCardinal
|
|
352
|
-
options = validateOptions(options)
|
|
376
|
+
function toCardinal(value, options) {
|
|
353
377
|
const { isNegative, integerPart, decimalPart } = parseCardinalValue(value)
|
|
378
|
+
// Both the integer part and the decimal's significant digits are spelled via
|
|
379
|
+
// the scale builder, so both must clear the ceiling.
|
|
380
|
+
checkMax(integerPart, cardinalMax, decimalPart)
|
|
354
381
|
|
|
355
382
|
// Apply option defaults
|
|
356
|
-
const { gender
|
|
383
|
+
const { gender } = resolveOptions(options, cardinalDefaults, cardinalValues)
|
|
357
384
|
|
|
358
385
|
let result = ''
|
|
359
386
|
|
|
@@ -376,11 +403,10 @@ function toCardinal (value, options) {
|
|
|
376
403
|
|
|
377
404
|
/**
|
|
378
405
|
* Builds ordinal for a 0-99 segment when it's the final (ordinal) part.
|
|
379
|
-
*
|
|
380
406
|
* @param {number} n - Number 0-99
|
|
381
407
|
* @returns {string} Ordinal words
|
|
382
408
|
*/
|
|
383
|
-
function buildOrdinalTensOnes
|
|
409
|
+
function buildOrdinalTensOnes(n) {
|
|
384
410
|
if (n === 0) return ''
|
|
385
411
|
|
|
386
412
|
const onesDigit = n % 10
|
|
@@ -403,11 +429,10 @@ function buildOrdinalTensOnes (n) {
|
|
|
403
429
|
|
|
404
430
|
/**
|
|
405
431
|
* Converts a positive integer to Latvian ordinal words (masculine nominative).
|
|
406
|
-
*
|
|
407
432
|
* @param {bigint} n - Positive integer to convert
|
|
408
433
|
* @returns {string} Ordinal Latvian words
|
|
409
434
|
*/
|
|
410
|
-
function integerToOrdinal
|
|
435
|
+
function integerToOrdinal(n) {
|
|
411
436
|
if (n < 100n) {
|
|
412
437
|
return buildOrdinalTensOnes(Number(n))
|
|
413
438
|
}
|
|
@@ -425,7 +450,8 @@ function integerToOrdinal (n) {
|
|
|
425
450
|
let hundredWord
|
|
426
451
|
if (hundredsDigit === 1) {
|
|
427
452
|
hundredWord = HUNDRED_SINGULAR
|
|
428
|
-
}
|
|
453
|
+
}
|
|
454
|
+
else {
|
|
429
455
|
hundredWord = ONES_MASC[hundredsDigit] + ' ' + HUNDRED_PLURAL
|
|
430
456
|
}
|
|
431
457
|
return hundredWord + ' ' + buildOrdinalTensOnes(remainder)
|
|
@@ -454,11 +480,10 @@ function integerToOrdinal (n) {
|
|
|
454
480
|
|
|
455
481
|
/**
|
|
456
482
|
* Builds ordinal words for numbers >= 1,000,000.
|
|
457
|
-
*
|
|
458
483
|
* @param {bigint} n - Number >= 1,000,000
|
|
459
484
|
* @returns {string} Ordinal Latvian words
|
|
460
485
|
*/
|
|
461
|
-
function buildLargeOrdinal
|
|
486
|
+
function buildLargeOrdinal(n) {
|
|
462
487
|
const numStr = n.toString()
|
|
463
488
|
const len = numStr.length
|
|
464
489
|
|
|
@@ -493,25 +518,30 @@ function buildLargeOrdinal (n) {
|
|
|
493
518
|
if (scaleIndex === 0) {
|
|
494
519
|
if (isLastNonZero) {
|
|
495
520
|
parts.push(integerToOrdinal(BigInt(segment)))
|
|
496
|
-
}
|
|
521
|
+
}
|
|
522
|
+
else {
|
|
497
523
|
parts.push(buildSegment(segment))
|
|
498
524
|
}
|
|
499
|
-
}
|
|
525
|
+
}
|
|
526
|
+
else {
|
|
500
527
|
if (isLastNonZero) {
|
|
501
528
|
if (segment === 1) {
|
|
502
529
|
parts.push(ORDINAL_SCALES[scaleIndex - 1])
|
|
503
|
-
}
|
|
530
|
+
}
|
|
531
|
+
else {
|
|
504
532
|
// For 2+, include cardinal scale word before ordinal
|
|
505
533
|
const scaleForms = SCALE_FORMS[scaleIndex - 1]
|
|
506
534
|
const cardinalScaleWord = pluralize(segment, scaleForms)
|
|
507
535
|
parts.push(buildSegment(segment) + ' ' + cardinalScaleWord + ' ' + ORDINAL_SCALES[scaleIndex - 1])
|
|
508
536
|
}
|
|
509
|
-
}
|
|
537
|
+
}
|
|
538
|
+
else {
|
|
510
539
|
const scaleForms = SCALE_FORMS[scaleIndex - 1]
|
|
511
540
|
const scaleWord = pluralize(segment, scaleForms)
|
|
512
541
|
if (segment === 1) {
|
|
513
542
|
parts.push(scaleWord)
|
|
514
|
-
}
|
|
543
|
+
}
|
|
544
|
+
else {
|
|
515
545
|
parts.push(buildSegment(segment) + ' ' + scaleWord)
|
|
516
546
|
}
|
|
517
547
|
}
|
|
@@ -526,12 +556,10 @@ function buildLargeOrdinal (n) {
|
|
|
526
556
|
|
|
527
557
|
/**
|
|
528
558
|
* Converts a numeric value to Latvian ordinal words (masculine nominative).
|
|
529
|
-
*
|
|
530
559
|
* @param {number | string | bigint} value - The numeric value to convert (must be a positive integer)
|
|
531
560
|
* @returns {string} The number as ordinal words
|
|
532
561
|
* @throws {TypeError} If value is not a valid numeric type
|
|
533
562
|
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
534
|
-
*
|
|
535
563
|
* @example
|
|
536
564
|
* toOrdinal(1) // 'pirmais'
|
|
537
565
|
* toOrdinal(2) // 'otrais'
|
|
@@ -539,8 +567,9 @@ function buildLargeOrdinal (n) {
|
|
|
539
567
|
* toOrdinal(100) // 'simtais'
|
|
540
568
|
* toOrdinal(1000) // 'tūkstošais'
|
|
541
569
|
*/
|
|
542
|
-
function toOrdinal
|
|
570
|
+
function toOrdinal(value) {
|
|
543
571
|
const integerPart = parseOrdinalValue(value)
|
|
572
|
+
checkMax(integerPart, ordinalMax)
|
|
544
573
|
return integerToOrdinal(integerPart)
|
|
545
574
|
}
|
|
546
575
|
|
|
@@ -550,20 +579,19 @@ function toOrdinal (value) {
|
|
|
550
579
|
|
|
551
580
|
/**
|
|
552
581
|
* Converts a numeric value to Latvian currency words (Euro).
|
|
553
|
-
*
|
|
554
582
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
555
583
|
* @returns {string} The amount in Latvian currency words
|
|
556
584
|
* @throws {TypeError} If value is not a valid numeric type
|
|
557
585
|
* @throws {Error} If value is not a valid number format
|
|
558
|
-
*
|
|
559
586
|
* @example
|
|
560
587
|
* toCurrency(42) // 'četrdesmit divi eiro'
|
|
561
588
|
* toCurrency(1) // 'viens eiro'
|
|
562
589
|
* toCurrency(1.50) // 'viens eiro piecdesmit centu'
|
|
563
590
|
* toCurrency(-5) // 'mīnus pieci eiro'
|
|
564
591
|
*/
|
|
565
|
-
function toCurrency
|
|
592
|
+
function toCurrency(value) {
|
|
566
593
|
const { isNegative, dollars: euros, cents } = parseCurrencyValue(value)
|
|
594
|
+
checkMax(euros, currencyMax)
|
|
567
595
|
|
|
568
596
|
let result = ''
|
|
569
597
|
if (isNegative) {
|
package/src/mr-IN.d.ts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
+
export const cardinalMax: bigint;
|
|
2
|
+
export const ordinalMax: bigint;
|
|
3
|
+
export const currencyMax: bigint;
|
|
1
4
|
/**
|
|
2
5
|
* Converts a numeric value to Marathi words.
|
|
3
|
-
*
|
|
4
6
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
5
7
|
* @returns {string} The number in Marathi words
|
|
6
8
|
*/
|
|
7
9
|
export function toCardinal(value: number | string | bigint): string;
|
|
8
10
|
/**
|
|
9
11
|
* Converts a numeric value to Marathi 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) // 'पहिला'
|
|
18
18
|
* toOrdinal(2) // 'दुसरा'
|
|
@@ -22,12 +22,10 @@ export function toCardinal(value: number | string | bigint): string;
|
|
|
22
22
|
export function toOrdinal(value: number | string | bigint): string;
|
|
23
23
|
/**
|
|
24
24
|
* Converts a numeric value to Marathi currency words (Indian Rupee).
|
|
25
|
-
*
|
|
26
25
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
27
26
|
* @returns {string} The amount in Marathi currency words
|
|
28
27
|
* @throws {TypeError} If value is not a valid numeric type
|
|
29
28
|
* @throws {Error} If value is not a valid number format
|
|
30
|
-
*
|
|
31
29
|
* @example
|
|
32
30
|
* toCurrency(42.50) // 'बेचाळीस रुपये पन्नास पैसे'
|
|
33
31
|
* toCurrency(1) // 'एक रुपया'
|
package/src/mr-IN.js
CHANGED
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
import { parseCardinalValue } from './utils/parse-cardinal.js'
|
|
15
15
|
import { parseCurrencyValue } from './utils/parse-currency.js'
|
|
16
16
|
import { parseOrdinalValue } from './utils/parse-ordinal.js'
|
|
17
|
+
import { checkMax } from './utils/check-max.js'
|
|
18
|
+
import { indian } from './utils/scale.js'
|
|
17
19
|
|
|
18
20
|
// ============================================================================
|
|
19
21
|
// Vocabulary
|
|
@@ -56,20 +58,29 @@ const BELOW_HUNDRED = [
|
|
|
56
58
|
'साठ', 'एकसष्ठ', 'बासष्ठ', 'त्रेसष्ठ', 'चौसष्ठ', 'पासष्ठ', 'सहासष्ठ', 'सदुसष्ठ', 'अडुसष्ठ', 'एकोणसत्तर',
|
|
57
59
|
'सत्तर', 'एकाहत्तर', 'बाहत्तर', 'त्र्याहत्तर', 'चौऱ्याहत्तर', 'पंच्याहत्तर', 'शहात्तर', 'सत्याहत्तर', 'अठ्ठ्याहत्तर', 'एकोणऐंशी',
|
|
58
60
|
'ऐंशी', 'एक्याऐंशी', 'ब्याऐंशी', 'त्र्याऐंशी', 'चौऱ्याऐंशी', 'पंच्याऐंशी', 'शहाऐंशी', 'सत्याऐंशी', 'अठ्ठ्याऐंशी', 'एकोणनव्वद',
|
|
59
|
-
'नव्वद', 'एक्याण्णव', 'ब्याण्णव', 'त्र्याण्णव', 'चौऱ्याण्णव', 'पंच्याण्णव', 'शहाण्णव', 'सत्याण्णव', 'अठ्ठ्याण्णव', 'नव्याण्णव'
|
|
61
|
+
'नव्वद', 'एक्याण्णव', 'ब्याण्णव', 'त्र्याण्णव', 'चौऱ्याण्णव', 'पंच्याण्णव', 'शहाण्णव', 'सत्याण्णव', 'अठ्ठ्याण्णव', 'नव्याण्णव',
|
|
60
62
|
]
|
|
61
63
|
|
|
62
64
|
// Scale words: index 0 = units (empty), 1 = thousand, 2 = lakh, 3 = crore, etc.
|
|
63
65
|
const SCALE_WORDS = ['', 'हजार', 'लाख', 'कोटी', 'अब्ज', 'खर्व', 'निखर्व', 'महापद्म', 'शंकू']
|
|
64
66
|
|
|
67
|
+
// 3-2-2 Indian grouping: a 3-digit base segment, then 2 digits per scale word
|
|
68
|
+
// (SCALE_WORDS[0] = '' is the units slot). Past the table the scale word is
|
|
69
|
+
// dropped, which collapses the magnitude — so cap there.
|
|
70
|
+
export const cardinalMax = indian(SCALE_WORDS.length)
|
|
71
|
+
export const ordinalMax = indian(SCALE_WORDS.length)
|
|
72
|
+
export const currencyMax = indian(SCALE_WORDS.length)
|
|
73
|
+
|
|
65
74
|
// ============================================================================
|
|
66
75
|
// Segment Building
|
|
67
76
|
// ============================================================================
|
|
68
77
|
|
|
69
78
|
/**
|
|
70
79
|
* Builds words for a 0-999 segment.
|
|
80
|
+
* @param {number} n - Segment value (0-999)
|
|
81
|
+
* @returns {string} Marathi words for the segment
|
|
71
82
|
*/
|
|
72
|
-
function buildSegment
|
|
83
|
+
function buildSegment(n) {
|
|
73
84
|
if (n === 0) return ''
|
|
74
85
|
if (n < 100) return BELOW_HUNDRED[n]
|
|
75
86
|
|
|
@@ -91,11 +102,10 @@ function buildSegment (n) {
|
|
|
91
102
|
*
|
|
92
103
|
* Uses BigInt modulo for segment extraction (faster than string slicing).
|
|
93
104
|
* South Asian 3-2-2 grouping: first 3 digits, then groups of 2.
|
|
94
|
-
*
|
|
95
105
|
* @param {bigint} n - Non-negative integer to convert
|
|
96
106
|
* @returns {string} Marathi words
|
|
97
107
|
*/
|
|
98
|
-
function integerToWords
|
|
108
|
+
function integerToWords(n) {
|
|
99
109
|
if (n === 0n) return ZERO
|
|
100
110
|
|
|
101
111
|
// Fast path: numbers < 1000 (direct lookup)
|
|
@@ -121,7 +131,8 @@ function integerToWords (n) {
|
|
|
121
131
|
|
|
122
132
|
if (i === 0) {
|
|
123
133
|
words.push(buildSegment(segment))
|
|
124
|
-
}
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
125
136
|
words.push(BELOW_HUNDRED[segment])
|
|
126
137
|
}
|
|
127
138
|
|
|
@@ -133,7 +144,12 @@ function integerToWords (n) {
|
|
|
133
144
|
return words.join(' ')
|
|
134
145
|
}
|
|
135
146
|
|
|
136
|
-
|
|
147
|
+
/**
|
|
148
|
+
* Reads the fractional digits per-digit in Marathi.
|
|
149
|
+
* @param {string} decimalPart - Decimal digit string
|
|
150
|
+
* @returns {string} Marathi words for each digit
|
|
151
|
+
*/
|
|
152
|
+
function decimalPartToWords(decimalPart) {
|
|
137
153
|
// Per-digit decimal reading
|
|
138
154
|
const digits = []
|
|
139
155
|
for (const char of decimalPart) {
|
|
@@ -145,12 +161,13 @@ function decimalPartToWords (decimalPart) {
|
|
|
145
161
|
|
|
146
162
|
/**
|
|
147
163
|
* Converts a numeric value to Marathi words.
|
|
148
|
-
*
|
|
149
164
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
150
165
|
* @returns {string} The number in Marathi words
|
|
151
166
|
*/
|
|
152
|
-
function toCardinal
|
|
167
|
+
function toCardinal(value) {
|
|
153
168
|
const { isNegative, integerPart, decimalPart } = parseCardinalValue(value)
|
|
169
|
+
// The fraction is spelled digit by digit, so only the integer part has a ceiling.
|
|
170
|
+
checkMax(integerPart, cardinalMax)
|
|
154
171
|
|
|
155
172
|
let result = ''
|
|
156
173
|
|
|
@@ -175,11 +192,10 @@ function toCardinal (value) {
|
|
|
175
192
|
* Converts a positive integer to Marathi ordinal words.
|
|
176
193
|
*
|
|
177
194
|
* Marathi ordinals: First 6 are irregular, then add -वा suffix.
|
|
178
|
-
*
|
|
179
195
|
* @param {bigint} n - Positive integer to convert
|
|
180
196
|
* @returns {string} Marathi ordinal words
|
|
181
197
|
*/
|
|
182
|
-
function integerToOrdinal
|
|
198
|
+
function integerToOrdinal(n) {
|
|
183
199
|
// Special ordinals for 1-6
|
|
184
200
|
if (n >= 1n && n <= 6n) {
|
|
185
201
|
return ORDINAL_SPECIAL[Number(n)]
|
|
@@ -192,20 +208,20 @@ function integerToOrdinal (n) {
|
|
|
192
208
|
|
|
193
209
|
/**
|
|
194
210
|
* Converts a numeric value to Marathi ordinal words.
|
|
195
|
-
*
|
|
196
211
|
* @param {number | string | bigint} value - The numeric value to convert (positive integer)
|
|
197
212
|
* @returns {string} The number as ordinal words
|
|
198
213
|
* @throws {TypeError} If value is not a valid numeric type
|
|
199
214
|
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
200
|
-
*
|
|
201
215
|
* @example
|
|
202
216
|
* toOrdinal(1) // 'पहिला'
|
|
203
217
|
* toOrdinal(2) // 'दुसरा'
|
|
204
218
|
* toOrdinal(3) // 'तिसरा'
|
|
205
219
|
* toOrdinal(10) // 'दहावा'
|
|
206
220
|
*/
|
|
207
|
-
function toOrdinal
|
|
221
|
+
function toOrdinal(value) {
|
|
208
222
|
const integerPart = parseOrdinalValue(value)
|
|
223
|
+
// Ordinals build on the cardinal speller, so they share its ceiling.
|
|
224
|
+
checkMax(integerPart, ordinalMax)
|
|
209
225
|
return integerToOrdinal(integerPart)
|
|
210
226
|
}
|
|
211
227
|
|
|
@@ -215,19 +231,18 @@ function toOrdinal (value) {
|
|
|
215
231
|
|
|
216
232
|
/**
|
|
217
233
|
* Converts a numeric value to Marathi currency words (Indian Rupee).
|
|
218
|
-
*
|
|
219
234
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
220
235
|
* @returns {string} The amount in Marathi currency words
|
|
221
236
|
* @throws {TypeError} If value is not a valid numeric type
|
|
222
237
|
* @throws {Error} If value is not a valid number format
|
|
223
|
-
*
|
|
224
238
|
* @example
|
|
225
239
|
* toCurrency(42.50) // 'बेचाळीस रुपये पन्नास पैसे'
|
|
226
240
|
* toCurrency(1) // 'एक रुपया'
|
|
227
241
|
* toCurrency(0.01) // 'एक पैसा'
|
|
228
242
|
*/
|
|
229
|
-
function toCurrency
|
|
243
|
+
function toCurrency(value) {
|
|
230
244
|
const { isNegative, dollars: rupees, cents: paise } = parseCurrencyValue(value)
|
|
245
|
+
checkMax(rupees, currencyMax)
|
|
231
246
|
|
|
232
247
|
// Build result
|
|
233
248
|
let result = ''
|
package/src/ms-MY.d.ts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
+
export const cardinalMax: bigint;
|
|
2
|
+
export const ordinalMax: bigint;
|
|
3
|
+
export const currencyMax: bigint;
|
|
1
4
|
/**
|
|
2
5
|
* Converts a numeric value to Malay words.
|
|
3
|
-
*
|
|
4
6
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
5
7
|
* @returns {string} The number in Malay words
|
|
6
8
|
*/
|
|
7
9
|
export function toCardinal(value: number | string | bigint): string;
|
|
8
10
|
/**
|
|
9
11
|
* Converts a numeric value to Malay 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) // 'pertama'
|
|
18
18
|
* toOrdinal(2) // 'kedua'
|
|
@@ -23,12 +23,10 @@ export function toOrdinal(value: number | string | bigint): string;
|
|
|
23
23
|
* Converts a numeric value to Malay currency words (Ringgit).
|
|
24
24
|
*
|
|
25
25
|
* Malaysian Ringgit uses sen as subunit (100 sen = 1 ringgit).
|
|
26
|
-
*
|
|
27
26
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
28
27
|
* @returns {string} The amount in Malay 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) // 'empat puluh dua ringgit'
|
|
34
32
|
* toCurrency(1.50) // 'satu ringgit lima puluh sen'
|