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/nl-NL.js
CHANGED
|
@@ -16,7 +16,9 @@
|
|
|
16
16
|
import { parseCardinalValue } from './utils/parse-cardinal.js'
|
|
17
17
|
import { parseCurrencyValue } from './utils/parse-currency.js'
|
|
18
18
|
import { parseOrdinalValue } from './utils/parse-ordinal.js'
|
|
19
|
-
import {
|
|
19
|
+
import { checkMax } from './utils/check-max.js'
|
|
20
|
+
import { western } from './utils/scale.js'
|
|
21
|
+
import { resolveOptions } from './utils/resolve-options.js'
|
|
20
22
|
|
|
21
23
|
// ============================================================================
|
|
22
24
|
// Vocabulary (module-level constants)
|
|
@@ -31,6 +33,19 @@ const HUNDRED = 'honderd'
|
|
|
31
33
|
// Scale words (long scale with -ard forms)
|
|
32
34
|
const SCALES = ['duizend', 'miljoen', 'miljard', 'biljoen', 'biljard', 'triljoen', 'triljard', 'quadriljoen', 'quadriljard']
|
|
33
35
|
|
|
36
|
+
// Scale ordinal words. Module-scope so its length can derive the ordinal
|
|
37
|
+
// ceiling and so it isn't rebuilt on every call.
|
|
38
|
+
const SCALE_ORDINAL = ['', 'duizendste', 'miljoenste', 'miljardste', 'biljoenste', 'biljardste', 'triljoenste']
|
|
39
|
+
|
|
40
|
+
// Supported magnitude ceilings (checked at the public entry points). SCALES is
|
|
41
|
+
// indexed [scaleIndex - 1] from 'duizend' (10^3), so cardinals/currency reach
|
|
42
|
+
// 10^((SCALES.length + 1) * 3) = 10^30. The ordinal of a number whose lowest
|
|
43
|
+
// non-zero group is a scale group uses the shorter SCALE_ORDINAL, so ordinals
|
|
44
|
+
// are bounded at 10^(SCALE_ORDINAL.length * 3) = 10^21.
|
|
45
|
+
export const cardinalMax = western(SCALES.length)
|
|
46
|
+
export const ordinalMax = western(SCALE_ORDINAL.length - 1)
|
|
47
|
+
export const currencyMax = western(SCALES.length)
|
|
48
|
+
|
|
34
49
|
const ZERO = 'nul'
|
|
35
50
|
const NEGATIVE = 'min'
|
|
36
51
|
const DECIMAL_SEP = 'komma'
|
|
@@ -51,7 +66,7 @@ const CENTEN = 'cent' // Cent doesn't pluralize in written currency
|
|
|
51
66
|
* @param {boolean} withAnd - Include "en" for values < 13 after hundreds
|
|
52
67
|
* @returns {string} Dutch word (compound, no spaces)
|
|
53
68
|
*/
|
|
54
|
-
function buildSegment
|
|
69
|
+
function buildSegment(n, withAnd) {
|
|
55
70
|
if (n === 0) return ''
|
|
56
71
|
|
|
57
72
|
const ones = n % 10
|
|
@@ -65,7 +80,8 @@ function buildSegment (n, withAnd) {
|
|
|
65
80
|
if (hundreds > 0) {
|
|
66
81
|
if (hundreds === 1) {
|
|
67
82
|
result = HUNDRED
|
|
68
|
-
}
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
69
85
|
result = ONES[hundreds] + HUNDRED
|
|
70
86
|
}
|
|
71
87
|
}
|
|
@@ -73,25 +89,31 @@ function buildSegment (n, withAnd) {
|
|
|
73
89
|
// Tens and ones
|
|
74
90
|
if (tensOnes === 0) {
|
|
75
91
|
// Just hundreds
|
|
76
|
-
}
|
|
92
|
+
}
|
|
93
|
+
else if (tensOnes < 10) {
|
|
77
94
|
// Single digit - add "en" if withAnd and after hundreds
|
|
78
95
|
if (hundreds > 0 && withAnd) {
|
|
79
96
|
result += 'en' + ONES[tensOnes]
|
|
80
|
-
}
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
81
99
|
result += ONES[tensOnes]
|
|
82
100
|
}
|
|
83
|
-
}
|
|
101
|
+
}
|
|
102
|
+
else if (tensOnes < 20) {
|
|
84
103
|
// Teens - add "en" if withAnd and after hundreds and < 13
|
|
85
104
|
if (hundreds > 0 && withAnd && tensOnes < 13) {
|
|
86
105
|
result += 'en' + TEENS[ones]
|
|
87
|
-
}
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
88
108
|
result += TEENS[ones]
|
|
89
109
|
}
|
|
90
|
-
}
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
91
112
|
// 20-99: Dutch inverts with connector
|
|
92
113
|
if (ones === 0) {
|
|
93
114
|
result += TENS[tens]
|
|
94
|
-
}
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
95
117
|
// "ën" if ones ends in 'e' (twee, drie)
|
|
96
118
|
const onesWord = ONES[ones]
|
|
97
119
|
const connector = onesWord.endsWith('e') ? 'ën' : 'en'
|
|
@@ -108,17 +130,20 @@ function buildSegment (n, withAnd) {
|
|
|
108
130
|
|
|
109
131
|
/**
|
|
110
132
|
* Converts a non-negative integer to Dutch words.
|
|
111
|
-
*
|
|
112
133
|
* @param {bigint} n - Non-negative integer to convert
|
|
113
|
-
* @param {
|
|
134
|
+
* @param {{accentOne: boolean, includeOptionalAnd: boolean, noHundredPairing: boolean}} options - Conversion options
|
|
114
135
|
* @returns {string} Dutch words
|
|
115
136
|
*/
|
|
116
|
-
function integerToWords
|
|
137
|
+
function integerToWords(n, options) {
|
|
117
138
|
if (n === 0n) return ZERO
|
|
118
139
|
|
|
119
140
|
const { accentOne, includeOptionalAnd, noHundredPairing } = options
|
|
120
141
|
|
|
121
142
|
// Apply één/een replacement
|
|
143
|
+
/**
|
|
144
|
+
* @param {string} word The word to apply accent replacement to
|
|
145
|
+
* @returns {string} The word with "een" replaced by "één" when accentOne is set
|
|
146
|
+
*/
|
|
122
147
|
const applyAccent = (word) => {
|
|
123
148
|
if (accentOne) {
|
|
124
149
|
return word.replace(/\been\b/g, 'één')
|
|
@@ -143,7 +168,8 @@ function integerToWords (n, options) {
|
|
|
143
168
|
const lowWord = buildSegment(low, includeOptionalAnd)
|
|
144
169
|
if (includeOptionalAnd && low < 13) {
|
|
145
170
|
result += ' en ' + lowWord
|
|
146
|
-
}
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
147
173
|
result += ' ' + lowWord
|
|
148
174
|
}
|
|
149
175
|
}
|
|
@@ -160,7 +186,8 @@ function integerToWords (n, options) {
|
|
|
160
186
|
if (thousands === 1) {
|
|
161
187
|
// "duizend" not "eenduizend"
|
|
162
188
|
result = SCALES[0]
|
|
163
|
-
}
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
164
191
|
// Compound: "vijfduizend"
|
|
165
192
|
result = buildSegment(thousands, includeOptionalAnd) + SCALES[0]
|
|
166
193
|
}
|
|
@@ -169,7 +196,8 @@ function integerToWords (n, options) {
|
|
|
169
196
|
const remainderWord = buildSegment(remainder, includeOptionalAnd)
|
|
170
197
|
if (includeOptionalAnd && remainder < 13) {
|
|
171
198
|
result += ' en ' + remainderWord
|
|
172
|
-
}
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
173
201
|
result += ' ' + remainderWord
|
|
174
202
|
}
|
|
175
203
|
}
|
|
@@ -184,12 +212,11 @@ function integerToWords (n, options) {
|
|
|
184
212
|
/**
|
|
185
213
|
* Builds words for numbers >= 1,000,000.
|
|
186
214
|
* Uses BigInt division for faster segment extraction (4x faster than string slicing).
|
|
187
|
-
*
|
|
188
215
|
* @param {bigint} n - Number >= 1,000,000
|
|
189
|
-
* @param {
|
|
216
|
+
* @param {{accentOne: boolean, includeOptionalAnd: boolean, noHundredPairing: boolean}} options - Conversion options
|
|
190
217
|
* @returns {string} Dutch words
|
|
191
218
|
*/
|
|
192
|
-
function buildLargeNumberWords
|
|
219
|
+
function buildLargeNumberWords(n, options) {
|
|
193
220
|
const { includeOptionalAnd } = options
|
|
194
221
|
|
|
195
222
|
// Extract segments using BigInt division (faster than string slicing)
|
|
@@ -215,29 +242,35 @@ function buildLargeNumberWords (n, options) {
|
|
|
215
242
|
if (result) {
|
|
216
243
|
if (prevWasScale && includeOptionalAnd && segment < 13) {
|
|
217
244
|
result += ' en ' + word
|
|
218
|
-
}
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
219
247
|
result += ' ' + word
|
|
220
248
|
}
|
|
221
|
-
}
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
222
251
|
result = word
|
|
223
252
|
}
|
|
224
253
|
prevWasScale = false
|
|
225
|
-
}
|
|
254
|
+
}
|
|
255
|
+
else if (i === 1) {
|
|
226
256
|
// Thousands - compound
|
|
227
257
|
if (result) result += ' '
|
|
228
258
|
if (segment === 1) {
|
|
229
259
|
result += SCALES[0]
|
|
230
|
-
}
|
|
260
|
+
}
|
|
261
|
+
else {
|
|
231
262
|
result += buildSegment(segment, includeOptionalAnd) + SCALES[0]
|
|
232
263
|
}
|
|
233
264
|
prevWasScale = true
|
|
234
|
-
}
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
235
267
|
// Million and above - space around scale
|
|
236
268
|
const scaleWord = SCALES[i - 1]
|
|
237
269
|
if (result) result += ' '
|
|
238
270
|
if (segment === 1) {
|
|
239
271
|
result += 'een ' + scaleWord
|
|
240
|
-
}
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
241
274
|
result += buildSegment(segment, includeOptionalAnd) + ' ' + scaleWord
|
|
242
275
|
}
|
|
243
276
|
prevWasScale = true
|
|
@@ -249,12 +282,11 @@ function buildLargeNumberWords (n, options) {
|
|
|
249
282
|
|
|
250
283
|
/**
|
|
251
284
|
* Converts decimal digits to Dutch words.
|
|
252
|
-
*
|
|
253
285
|
* @param {string} decimalPart - Decimal digits (without the point)
|
|
254
|
-
* @param {
|
|
286
|
+
* @param {{accentOne: boolean, includeOptionalAnd: boolean, noHundredPairing: boolean}} options - Conversion options
|
|
255
287
|
* @returns {string} Dutch words for decimal part
|
|
256
288
|
*/
|
|
257
|
-
function decimalPartToWords
|
|
289
|
+
function decimalPartToWords(decimalPart, options) {
|
|
258
290
|
let result = ''
|
|
259
291
|
|
|
260
292
|
// Handle leading zeros
|
|
@@ -276,37 +308,40 @@ function decimalPartToWords (decimalPart, options) {
|
|
|
276
308
|
return result
|
|
277
309
|
}
|
|
278
310
|
|
|
311
|
+
/**
|
|
312
|
+
* @typedef {object} CardinalOptions
|
|
313
|
+
* @property {boolean} [accentOne] - Use "één" instead of "een"
|
|
314
|
+
* @property {boolean} [includeOptionalAnd] - Include "en" before small numbers
|
|
315
|
+
* @property {boolean} [noHundredPairing] - Disable hundred pairing (1104→duizend honderdvier)
|
|
316
|
+
*/
|
|
317
|
+
|
|
318
|
+
/** @type {Required<CardinalOptions>} */
|
|
319
|
+
export const cardinalDefaults = { accentOne: true, includeOptionalAnd: false, noHundredPairing: false }
|
|
320
|
+
|
|
279
321
|
/**
|
|
280
322
|
* Converts a numeric value to Dutch words.
|
|
281
323
|
*
|
|
282
324
|
* This is the main public API. It accepts any valid numeric input
|
|
283
325
|
* (number, string, or bigint) and handles parsing internally.
|
|
284
|
-
*
|
|
285
326
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
286
|
-
* @param {
|
|
287
|
-
* @param {boolean} [options.accentOne=true] - Use "één" instead of "een"
|
|
288
|
-
* @param {boolean} [options.includeOptionalAnd=false] - Include "en" before small numbers
|
|
289
|
-
* @param {boolean} [options.noHundredPairing=false] - Disable hundred pairing (1104→duizend honderdvier)
|
|
327
|
+
* @param {CardinalOptions} [options] - Optional configuration
|
|
290
328
|
* @returns {string} The number in Dutch words
|
|
291
329
|
* @throws {TypeError} If value is not a valid numeric type
|
|
292
330
|
* @throws {Error} If value is not a valid number format
|
|
293
|
-
*
|
|
294
331
|
* @example
|
|
295
332
|
* toCardinal(21) // 'eenentwintig'
|
|
296
333
|
* toCardinal(1) // 'één'
|
|
297
334
|
* toCardinal(1, {accentOne: false}) // 'een'
|
|
298
335
|
* toCardinal(1104) // 'elfhonderd vier'
|
|
299
336
|
*/
|
|
300
|
-
function toCardinal
|
|
301
|
-
options = validateOptions(options)
|
|
337
|
+
function toCardinal(value, options) {
|
|
302
338
|
const { isNegative, integerPart, decimalPart } = parseCardinalValue(value)
|
|
339
|
+
// Both the integer part and the decimal's significant digits are spelled via
|
|
340
|
+
// the scale builder, so both must clear the ceiling.
|
|
341
|
+
checkMax(integerPart, cardinalMax, decimalPart)
|
|
303
342
|
|
|
304
343
|
// Apply option defaults
|
|
305
|
-
const {
|
|
306
|
-
accentOne = true,
|
|
307
|
-
includeOptionalAnd = false,
|
|
308
|
-
noHundredPairing = false
|
|
309
|
-
} = options
|
|
344
|
+
const { accentOne, includeOptionalAnd, noHundredPairing } = resolveOptions(options, cardinalDefaults)
|
|
310
345
|
|
|
311
346
|
const opts = { accentOne, includeOptionalAnd, noHundredPairing }
|
|
312
347
|
|
|
@@ -335,12 +370,11 @@ const ORDINAL_ONES = ['', 'eerste', 'tweede', 'derde', 'vierde', 'vijfde', 'zesd
|
|
|
335
370
|
/**
|
|
336
371
|
* Converts a small cardinal to ordinal.
|
|
337
372
|
* Rules: 1-19 add -de (except eerste, derde, achtste), 20+ add -ste
|
|
338
|
-
*
|
|
339
373
|
* @param {string} cardinalWord - Cardinal word
|
|
340
374
|
* @param {number} n - The number value (0-99)
|
|
341
375
|
* @returns {string} Ordinal word
|
|
342
376
|
*/
|
|
343
|
-
function smallCardinalToOrdinal
|
|
377
|
+
function smallCardinalToOrdinal(cardinalWord, n) {
|
|
344
378
|
// Special cases for 1-9
|
|
345
379
|
if (n >= 1 && n <= 9) return ORDINAL_ONES[n]
|
|
346
380
|
|
|
@@ -358,11 +392,10 @@ function smallCardinalToOrdinal (cardinalWord, n) {
|
|
|
358
392
|
|
|
359
393
|
/**
|
|
360
394
|
* Builds ordinal words for 0-999.
|
|
361
|
-
*
|
|
362
395
|
* @param {number} n - Number 0-999
|
|
363
396
|
* @returns {string} Dutch ordinal words
|
|
364
397
|
*/
|
|
365
|
-
function buildOrdinalSegment
|
|
398
|
+
function buildOrdinalSegment(n) {
|
|
366
399
|
if (n === 0) return ''
|
|
367
400
|
|
|
368
401
|
const hundreds = Math.trunc(n / 100)
|
|
@@ -375,10 +408,11 @@ function buildOrdinalSegment (n) {
|
|
|
375
408
|
}
|
|
376
409
|
|
|
377
410
|
// Hundreds: need to build prefix + ordinal suffix
|
|
378
|
-
let prefix
|
|
411
|
+
let prefix
|
|
379
412
|
if (hundreds === 1) {
|
|
380
413
|
prefix = HUNDRED
|
|
381
|
-
}
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
382
416
|
prefix = ONES[hundreds] + HUNDRED
|
|
383
417
|
}
|
|
384
418
|
|
|
@@ -395,17 +429,16 @@ function buildOrdinalSegment (n) {
|
|
|
395
429
|
|
|
396
430
|
/**
|
|
397
431
|
* Converts a number to Dutch ordinal words.
|
|
398
|
-
*
|
|
399
432
|
* @param {number | string | bigint} value - The number to convert
|
|
400
433
|
* @returns {string} Dutch ordinal words
|
|
401
|
-
*
|
|
402
434
|
* @example
|
|
403
435
|
* toOrdinal(1) // 'eerste'
|
|
404
436
|
* toOrdinal(21) // 'eenentwintigste'
|
|
405
437
|
* toOrdinal(100) // 'honderdste'
|
|
406
438
|
*/
|
|
407
|
-
function toOrdinal
|
|
439
|
+
function toOrdinal(value) {
|
|
408
440
|
const n = parseOrdinalValue(value)
|
|
441
|
+
checkMax(n, ordinalMax)
|
|
409
442
|
|
|
410
443
|
// Fast path: 1-9
|
|
411
444
|
if (n < 10n) return ORDINAL_ONES[Number(n)]
|
|
@@ -427,11 +460,10 @@ function toOrdinal (value) {
|
|
|
427
460
|
|
|
428
461
|
/**
|
|
429
462
|
* Builds ordinal words for large numbers.
|
|
430
|
-
*
|
|
431
463
|
* @param {bigint} n - Non-negative integer >= 1000
|
|
432
464
|
* @returns {string} Dutch ordinal words
|
|
433
465
|
*/
|
|
434
|
-
function buildLargeOrdinal
|
|
466
|
+
function buildLargeOrdinal(n) {
|
|
435
467
|
// Extract segments
|
|
436
468
|
const segments = []
|
|
437
469
|
let temp = n
|
|
@@ -449,9 +481,6 @@ function buildLargeOrdinal (n) {
|
|
|
449
481
|
}
|
|
450
482
|
}
|
|
451
483
|
|
|
452
|
-
// Scale ordinal words
|
|
453
|
-
const SCALE_ORDINAL = ['', 'duizendste', 'miljoenste', 'miljardste', 'biljoenste', 'biljardste', 'triljoenste']
|
|
454
|
-
|
|
455
484
|
let result = ''
|
|
456
485
|
|
|
457
486
|
for (let i = segments.length - 1; i >= 0; i--) {
|
|
@@ -465,34 +494,42 @@ function buildLargeOrdinal (n) {
|
|
|
465
494
|
if (i === 0) {
|
|
466
495
|
// Units segment: use ordinal segment builder
|
|
467
496
|
result += buildOrdinalSegment(segment)
|
|
468
|
-
}
|
|
497
|
+
}
|
|
498
|
+
else if (segment === 1 && i > 0) {
|
|
469
499
|
// Exact scale: duizendste, miljoenste, etc.
|
|
470
500
|
if (i === 1) {
|
|
471
501
|
result += SCALE_ORDINAL[i]
|
|
472
|
-
}
|
|
502
|
+
}
|
|
503
|
+
else {
|
|
473
504
|
result += 'een ' + SCALE_ORDINAL[i]
|
|
474
505
|
}
|
|
475
|
-
}
|
|
506
|
+
}
|
|
507
|
+
else {
|
|
476
508
|
// Segment + scale ordinal
|
|
477
509
|
if (i === 1) {
|
|
478
510
|
result += buildSegment(segment, false) + SCALE_ORDINAL[i]
|
|
479
|
-
}
|
|
511
|
+
}
|
|
512
|
+
else {
|
|
480
513
|
result += buildSegment(segment, false) + ' ' + SCALE_ORDINAL[i]
|
|
481
514
|
}
|
|
482
515
|
}
|
|
483
|
-
}
|
|
516
|
+
}
|
|
517
|
+
else {
|
|
484
518
|
// Higher segments use cardinal form
|
|
485
519
|
if (i === 1) {
|
|
486
520
|
if (segment === 1) {
|
|
487
521
|
result += SCALES[0]
|
|
488
|
-
}
|
|
522
|
+
}
|
|
523
|
+
else {
|
|
489
524
|
result += buildSegment(segment, false) + SCALES[0]
|
|
490
525
|
}
|
|
491
|
-
}
|
|
526
|
+
}
|
|
527
|
+
else {
|
|
492
528
|
const scaleWord = SCALES[i - 1]
|
|
493
529
|
if (segment === 1) {
|
|
494
530
|
result += 'een ' + scaleWord
|
|
495
|
-
}
|
|
531
|
+
}
|
|
532
|
+
else {
|
|
496
533
|
result += buildSegment(segment, false) + ' ' + scaleWord
|
|
497
534
|
}
|
|
498
535
|
}
|
|
@@ -506,23 +543,28 @@ function buildLargeOrdinal (n) {
|
|
|
506
543
|
// Currency Functions
|
|
507
544
|
// ============================================================================
|
|
508
545
|
|
|
546
|
+
/**
|
|
547
|
+
* @typedef {object} CurrencyOptions
|
|
548
|
+
* @property {boolean} [and] - Include "en" between euros and cents
|
|
549
|
+
*/
|
|
550
|
+
|
|
551
|
+
/** @type {Required<CurrencyOptions>} */
|
|
552
|
+
export const currencyDefaults = { and: true }
|
|
553
|
+
|
|
509
554
|
/**
|
|
510
555
|
* Converts a number to Dutch currency words (Euro).
|
|
511
|
-
*
|
|
512
556
|
* @param {number | string | bigint} value - The amount to convert
|
|
513
|
-
* @param {
|
|
514
|
-
* @param {boolean} [options.and=true] - Include "en" between euros and cents
|
|
557
|
+
* @param {CurrencyOptions} [options] Optional configuration
|
|
515
558
|
* @returns {string} Dutch currency words
|
|
516
|
-
*
|
|
517
559
|
* @example
|
|
518
560
|
* toCurrency(42.50) // 'tweeënveertig euro en vijftig cent'
|
|
519
561
|
* toCurrency(1) // 'één euro'
|
|
520
562
|
* toCurrency(0.01) // 'één cent'
|
|
521
563
|
*/
|
|
522
|
-
function toCurrency
|
|
523
|
-
options = validateOptions(options)
|
|
564
|
+
function toCurrency(value, options) {
|
|
524
565
|
const { isNegative, dollars: euros, cents } = parseCurrencyValue(value)
|
|
525
|
-
|
|
566
|
+
checkMax(euros, currencyMax)
|
|
567
|
+
const { and } = resolveOptions(options, currencyDefaults)
|
|
526
568
|
|
|
527
569
|
let result = ''
|
|
528
570
|
|
package/src/pa-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 Punjabi words.
|
|
3
|
-
*
|
|
4
6
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
5
7
|
* @returns {string} The number in Punjabi words
|
|
6
8
|
*/
|
|
7
9
|
export function toCardinal(value: number | string | bigint): string;
|
|
8
10
|
/**
|
|
9
11
|
* Converts a numeric value to Punjabi 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 Punjabi currency words (Indian Rupee).
|
|
25
|
-
*
|
|
26
25
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
27
26
|
* @returns {string} The amount in Punjabi 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/pa-IN.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 { indian } from './utils/scale.js'
|
|
16
18
|
|
|
17
19
|
// ============================================================================
|
|
18
20
|
// Vocabulary
|
|
@@ -55,20 +57,29 @@ const BELOW_HUNDRED = [
|
|
|
55
57
|
'ਸੱਠ', 'ਇਕਾਹਠ', 'ਬਾਹਠ', 'ਤਰਸਠ', 'ਚੌਂਸਠ', 'ਪੈਂਸਠ', 'ਛਿਆਸਠ', 'ਸੜਸਠ', 'ਅੜਸਠ', 'ਉਣਹੱਤਰ',
|
|
56
58
|
'ਸਤੱਰ', 'ਇਕਹੱਤਰ', 'ਬਹੱਤਰ', 'ਤਹੱਤਰ', 'ਚੌਹੱਤਰ', 'ਪੰਝਹੱਤਰ', 'ਛਿਹੱਤਰ', 'ਸਤੱਤਰ', 'ਅਠੱਤਰ', 'ਉਨਾਸੀ',
|
|
57
59
|
'ਅੱਸੀ', 'ਇਕਿਆਸੀ', 'ਬਿਆਸੀ', 'ਤਰਿਆਸੀ', 'ਚੌਰਿਆਸੀ', 'ਪਚਾਸੀ', 'ਛਿਆਸੀ', 'ਸੱਤਾਸੀ', 'ਅਠਾਸੀ', 'ਨਵਾਸੀ',
|
|
58
|
-
'ਨੱਬੇ', 'ਇਕਾਨਵੇਂ', 'ਬਾਨਵੇਂ', 'ਤਰਾਨਵੇਂ', 'ਚੁਰਾਨਵੇਂ', 'ਪੰਚਾਨਵੇਂ', 'ਛਿਆਨਵੇਂ', 'ਸਤਾਨਵੇਂ', 'ਅਠਾਨਵੇਂ', 'ਨਿਨਾਨਵੇਂ'
|
|
60
|
+
'ਨੱਬੇ', 'ਇਕਾਨਵੇਂ', 'ਬਾਨਵੇਂ', 'ਤਰਾਨਵੇਂ', 'ਚੁਰਾਨਵੇਂ', 'ਪੰਚਾਨਵੇਂ', 'ਛਿਆਨਵੇਂ', 'ਸਤਾਨਵੇਂ', 'ਅਠਾਨਵੇਂ', 'ਨਿਨਾਨਵੇਂ',
|
|
59
61
|
]
|
|
60
62
|
|
|
61
63
|
// Scale words: index 0 = units (empty), 1 = thousand, 2 = lakh, 3 = crore, etc.
|
|
62
64
|
const SCALE_WORDS = ['', 'ਹਜ਼ਾਰ', 'ਲੱਖ', 'ਕਰੋੜ', 'ਅਰਬ', 'ਖਰਬ', 'ਨੀਲ', 'ਪਦਮ', 'ਸ਼ੰਖ']
|
|
63
65
|
|
|
66
|
+
// 3-2-2 Indian grouping: a 3-digit base segment, then 2 digits per scale word
|
|
67
|
+
// (SCALE_WORDS[0] = '' is the units slot). Past the table the scale word is
|
|
68
|
+
// dropped, which collapses the magnitude — so cap there.
|
|
69
|
+
export const cardinalMax = indian(SCALE_WORDS.length)
|
|
70
|
+
export const ordinalMax = indian(SCALE_WORDS.length)
|
|
71
|
+
export const currencyMax = indian(SCALE_WORDS.length)
|
|
72
|
+
|
|
64
73
|
// ============================================================================
|
|
65
74
|
// Segment Building
|
|
66
75
|
// ============================================================================
|
|
67
76
|
|
|
68
77
|
/**
|
|
69
78
|
* Builds words for a 0-999 segment.
|
|
79
|
+
* @param {number} n - Segment value (0-999)
|
|
80
|
+
* @returns {string} Punjabi words for the segment
|
|
70
81
|
*/
|
|
71
|
-
function buildSegment
|
|
82
|
+
function buildSegment(n) {
|
|
72
83
|
if (n === 0) return ''
|
|
73
84
|
if (n < 100) return BELOW_HUNDRED[n]
|
|
74
85
|
|
|
@@ -90,11 +101,10 @@ function buildSegment (n) {
|
|
|
90
101
|
*
|
|
91
102
|
* Uses BigInt modulo for segment extraction (faster than string slicing).
|
|
92
103
|
* South Asian 3-2-2 grouping: first 3 digits, then groups of 2.
|
|
93
|
-
*
|
|
94
104
|
* @param {bigint} n - Non-negative integer to convert
|
|
95
105
|
* @returns {string} Punjabi words
|
|
96
106
|
*/
|
|
97
|
-
function integerToWords
|
|
107
|
+
function integerToWords(n) {
|
|
98
108
|
if (n === 0n) return ZERO
|
|
99
109
|
|
|
100
110
|
// Fast path: numbers < 1000 (direct lookup)
|
|
@@ -120,7 +130,8 @@ function integerToWords (n) {
|
|
|
120
130
|
|
|
121
131
|
if (i === 0) {
|
|
122
132
|
words.push(buildSegment(segment))
|
|
123
|
-
}
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
124
135
|
words.push(BELOW_HUNDRED[segment])
|
|
125
136
|
}
|
|
126
137
|
|
|
@@ -132,7 +143,12 @@ function integerToWords (n) {
|
|
|
132
143
|
return words.join(' ')
|
|
133
144
|
}
|
|
134
145
|
|
|
135
|
-
|
|
146
|
+
/**
|
|
147
|
+
* Converts the fractional digit string to Punjabi words.
|
|
148
|
+
* @param {string} decimalPart - Digits after the decimal point
|
|
149
|
+
* @returns {string} Punjabi words for the decimal part
|
|
150
|
+
*/
|
|
151
|
+
function decimalPartToWords(decimalPart) {
|
|
136
152
|
let result = ''
|
|
137
153
|
let i = 0
|
|
138
154
|
|
|
@@ -153,12 +169,14 @@ function decimalPartToWords (decimalPart) {
|
|
|
153
169
|
|
|
154
170
|
/**
|
|
155
171
|
* Converts a numeric value to Punjabi words.
|
|
156
|
-
*
|
|
157
172
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
158
173
|
* @returns {string} The number in Punjabi words
|
|
159
174
|
*/
|
|
160
|
-
function toCardinal
|
|
175
|
+
function toCardinal(value) {
|
|
161
176
|
const { isNegative, integerPart, decimalPart } = parseCardinalValue(value)
|
|
177
|
+
// Both the integer part and the decimal's significant digits are spelled via
|
|
178
|
+
// the scale builder, so both must clear the ceiling.
|
|
179
|
+
checkMax(integerPart, cardinalMax, decimalPart)
|
|
162
180
|
|
|
163
181
|
let result = ''
|
|
164
182
|
|
|
@@ -183,11 +201,10 @@ function toCardinal (value) {
|
|
|
183
201
|
* Converts a positive integer to Punjabi ordinal words.
|
|
184
202
|
*
|
|
185
203
|
* Punjabi ordinals: First 6 are irregular, then add -ਵਾਂ suffix.
|
|
186
|
-
*
|
|
187
204
|
* @param {bigint} n - Positive integer to convert
|
|
188
205
|
* @returns {string} Punjabi ordinal words
|
|
189
206
|
*/
|
|
190
|
-
function integerToOrdinal
|
|
207
|
+
function integerToOrdinal(n) {
|
|
191
208
|
// Special ordinals for 1-6
|
|
192
209
|
if (n >= 1n && n <= 6n) {
|
|
193
210
|
return ORDINAL_SPECIAL[Number(n)]
|
|
@@ -200,20 +217,20 @@ function integerToOrdinal (n) {
|
|
|
200
217
|
|
|
201
218
|
/**
|
|
202
219
|
* Converts a numeric value to Punjabi ordinal words.
|
|
203
|
-
*
|
|
204
220
|
* @param {number | string | bigint} value - The numeric value to convert (positive integer)
|
|
205
221
|
* @returns {string} The number as ordinal words
|
|
206
222
|
* @throws {TypeError} If value is not a valid numeric type
|
|
207
223
|
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
208
|
-
*
|
|
209
224
|
* @example
|
|
210
225
|
* toOrdinal(1) // 'ਪਹਿਲਾ'
|
|
211
226
|
* toOrdinal(2) // 'ਦੂਜਾ'
|
|
212
227
|
* toOrdinal(3) // 'ਤੀਜਾ'
|
|
213
228
|
* toOrdinal(10) // 'ਦੱਸਵਾਂ'
|
|
214
229
|
*/
|
|
215
|
-
function toOrdinal
|
|
230
|
+
function toOrdinal(value) {
|
|
216
231
|
const integerPart = parseOrdinalValue(value)
|
|
232
|
+
// Ordinals build on the cardinal speller, so they share its ceiling.
|
|
233
|
+
checkMax(integerPart, ordinalMax)
|
|
217
234
|
return integerToOrdinal(integerPart)
|
|
218
235
|
}
|
|
219
236
|
|
|
@@ -223,19 +240,18 @@ function toOrdinal (value) {
|
|
|
223
240
|
|
|
224
241
|
/**
|
|
225
242
|
* Converts a numeric value to Punjabi currency words (Indian Rupee).
|
|
226
|
-
*
|
|
227
243
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
228
244
|
* @returns {string} The amount in Punjabi currency words
|
|
229
245
|
* @throws {TypeError} If value is not a valid numeric type
|
|
230
246
|
* @throws {Error} If value is not a valid number format
|
|
231
|
-
*
|
|
232
247
|
* @example
|
|
233
248
|
* toCurrency(42.50) // 'ਬਿਆਲੀ ਰੁਪਏ ਪੰਜਾਹ ਪੈਸੇ'
|
|
234
249
|
* toCurrency(1) // 'ਇੱਕ ਰੁਪਇਆ'
|
|
235
250
|
* toCurrency(0.01) // 'ਇੱਕ ਪੈਸਾ'
|
|
236
251
|
*/
|
|
237
|
-
function toCurrency
|
|
252
|
+
function toCurrency(value) {
|
|
238
253
|
const { isNegative, dollars: rupees, cents: paise } = parseCurrencyValue(value)
|
|
254
|
+
checkMax(rupees, currencyMax)
|
|
239
255
|
|
|
240
256
|
// Build result
|
|
241
257
|
let result = ''
|
package/src/pl-PL.d.ts
CHANGED
|
@@ -1,33 +1,45 @@
|
|
|
1
|
+
export const cardinalMax: bigint;
|
|
2
|
+
export const ordinalMax: bigint;
|
|
3
|
+
export const currencyMax: bigint;
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {object} CardinalOptions
|
|
6
|
+
* @property {('masculine'|'feminine')} [gender] - Gender for numbers < 1000
|
|
7
|
+
*/
|
|
8
|
+
/** @type {Required<CardinalOptions>} */
|
|
9
|
+
export const cardinalDefaults: Required<CardinalOptions>;
|
|
10
|
+
/** @type {{ gender: ReadonlyArray<Required<CardinalOptions>['gender']> }} */
|
|
11
|
+
export const cardinalValues: {
|
|
12
|
+
gender: ReadonlyArray<Required<CardinalOptions>["gender"]>;
|
|
13
|
+
};
|
|
14
|
+
export type CardinalOptions = {
|
|
15
|
+
/**
|
|
16
|
+
* - Gender for numbers < 1000
|
|
17
|
+
*/
|
|
18
|
+
gender?: "feminine" | "masculine" | undefined;
|
|
19
|
+
};
|
|
1
20
|
/**
|
|
2
21
|
* Converts a numeric value to Polish words.
|
|
3
22
|
*
|
|
4
23
|
* This is the main public API. It accepts any valid numeric input
|
|
5
24
|
* (number, string, or bigint) and handles parsing internally.
|
|
6
|
-
*
|
|
7
25
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
8
|
-
* @param {
|
|
9
|
-
* @param {string} [options.gender='masculine'] - Gender for numbers < 1000
|
|
26
|
+
* @param {CardinalOptions} [options] - Conversion options
|
|
10
27
|
* @returns {string} The number in Polish words
|
|
11
28
|
* @throws {TypeError} If value is not a valid numeric type
|
|
12
29
|
* @throws {Error} If value is not a valid number format
|
|
13
|
-
*
|
|
14
30
|
* @example
|
|
15
31
|
* toCardinal(1) // 'jeden'
|
|
16
32
|
* toCardinal(1, { gender: 'feminine' }) // 'jedna'
|
|
17
33
|
* toCardinal(1000) // 'tysiąc'
|
|
18
34
|
* toCardinal(2000) // 'dwa tysiące'
|
|
19
35
|
*/
|
|
20
|
-
export function toCardinal(value: number | string | bigint, options?:
|
|
21
|
-
gender?: string | undefined;
|
|
22
|
-
}): string;
|
|
36
|
+
export function toCardinal(value: number | string | bigint, options?: CardinalOptions): string;
|
|
23
37
|
/**
|
|
24
38
|
* Converts a numeric value to Polish ordinal words (masculine nominative).
|
|
25
|
-
*
|
|
26
39
|
* @param {number | string | bigint} value - The numeric value to convert (must be a positive integer)
|
|
27
40
|
* @returns {string} The number as ordinal words (e.g., "pierwszy", "czterdziesty drugi")
|
|
28
41
|
* @throws {TypeError} If value is not a valid numeric type
|
|
29
42
|
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
30
|
-
*
|
|
31
43
|
* @example
|
|
32
44
|
* toOrdinal(1) // 'pierwszy'
|
|
33
45
|
* toOrdinal(2) // 'drugi'
|
|
@@ -40,12 +52,10 @@ export function toCardinal(value: number | string | bigint, options?: {
|
|
|
40
52
|
export function toOrdinal(value: number | string | bigint): string;
|
|
41
53
|
/**
|
|
42
54
|
* Converts a numeric value to Polish currency words (Polish Złoty).
|
|
43
|
-
*
|
|
44
55
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
45
56
|
* @returns {string} The amount in Polish currency words
|
|
46
57
|
* @throws {TypeError} If value is not a valid numeric type
|
|
47
58
|
* @throws {Error} If value is not a valid number format
|
|
48
|
-
*
|
|
49
59
|
* @example
|
|
50
60
|
* toCurrency(42) // 'czterdzieści dwa złote'
|
|
51
61
|
* toCurrency(1) // 'jeden złoty'
|