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/fr-BE.js
CHANGED
|
@@ -13,7 +13,9 @@
|
|
|
13
13
|
import { parseCardinalValue } from './utils/parse-cardinal.js'
|
|
14
14
|
import { parseCurrencyValue } from './utils/parse-currency.js'
|
|
15
15
|
import { parseOrdinalValue } from './utils/parse-ordinal.js'
|
|
16
|
-
import {
|
|
16
|
+
import { checkMax } from './utils/check-max.js'
|
|
17
|
+
import { longScale } from './utils/scale.js'
|
|
18
|
+
import { resolveOptions } from './utils/resolve-options.js'
|
|
17
19
|
|
|
18
20
|
// ============================================================================
|
|
19
21
|
// Vocabulary
|
|
@@ -27,6 +29,15 @@ const TENS = ['', '', 'vingt', 'trente', 'quarante', 'cinquante', 'soixante', 's
|
|
|
27
29
|
const SCALES = ['million', 'billion', 'trillion', 'quadrillion']
|
|
28
30
|
const SCALES_ARD = ['milliard', 'billiard', 'trilliard', 'quadrilliard']
|
|
29
31
|
|
|
32
|
+
// Supported magnitude ceiling (checked at the public entry points). Long scale:
|
|
33
|
+
// each SCALES entry has a base and an "-ard" form spanning two segment groups,
|
|
34
|
+
// so with the units group that's 2 * SCALES.length + 2 groups of 3 digits.
|
|
35
|
+
// Cardinals must stay below 10^30; ordinals and currency build on the cardinal,
|
|
36
|
+
// so they share the same ceiling.
|
|
37
|
+
export const cardinalMax = longScale(SCALES.length)
|
|
38
|
+
export const ordinalMax = longScale(SCALES.length)
|
|
39
|
+
export const currencyMax = longScale(SCALES.length)
|
|
40
|
+
|
|
30
41
|
const THOUSAND = 'mille'
|
|
31
42
|
const HUNDRED = 'cent'
|
|
32
43
|
const ZERO = 'zéro'
|
|
@@ -56,7 +67,12 @@ const CENTIMES = 'centimes'
|
|
|
56
67
|
// Segment Building
|
|
57
68
|
// ============================================================================
|
|
58
69
|
|
|
59
|
-
|
|
70
|
+
/**
|
|
71
|
+
* Builds the words for a 0-999 segment.
|
|
72
|
+
* @param {number} n - Segment value (0-999)
|
|
73
|
+
* @returns {{word: string, endsWithCents: boolean, endsWithVingts: boolean}} Segment words and flags
|
|
74
|
+
*/
|
|
75
|
+
function buildSegment(n) {
|
|
60
76
|
if (n === 0) return { word: '', endsWithCents: false, endsWithVingts: false }
|
|
61
77
|
|
|
62
78
|
const tensOnes = n % 100
|
|
@@ -70,11 +86,13 @@ function buildSegment (n) {
|
|
|
70
86
|
if (hundreds > 0) {
|
|
71
87
|
if (hundreds === 1) {
|
|
72
88
|
parts.push(HUNDRED)
|
|
73
|
-
}
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
74
91
|
if (tensOnes === 0) {
|
|
75
92
|
parts.push(ONES[hundreds] + ' ' + HUNDRED + 's')
|
|
76
93
|
endsWithCents = true
|
|
77
|
-
}
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
78
96
|
parts.push(ONES[hundreds] + ' ' + HUNDRED)
|
|
79
97
|
}
|
|
80
98
|
}
|
|
@@ -83,49 +101,63 @@ function buildSegment (n) {
|
|
|
83
101
|
// Tens and ones - Belgian pattern
|
|
84
102
|
if (tensOnes === 0) {
|
|
85
103
|
// Just hundreds
|
|
86
|
-
}
|
|
104
|
+
}
|
|
105
|
+
else if (tensOnes < 10) {
|
|
87
106
|
parts.push(ONES[tensOnes])
|
|
88
|
-
}
|
|
107
|
+
}
|
|
108
|
+
else if (tensOnes < 17) {
|
|
89
109
|
parts.push(TEENS[tensOnes - 10])
|
|
90
|
-
}
|
|
110
|
+
}
|
|
111
|
+
else if (tensOnes < 20) {
|
|
91
112
|
parts.push(TEENS[tensOnes - 10])
|
|
92
|
-
}
|
|
113
|
+
}
|
|
114
|
+
else if (tensOnes < 70) {
|
|
93
115
|
// 20-69: standard pattern
|
|
94
116
|
const t = Math.trunc(tensOnes / 10)
|
|
95
117
|
const o = tensOnes % 10
|
|
96
118
|
if (o === 0) {
|
|
97
119
|
parts.push(TENS[t])
|
|
98
|
-
}
|
|
120
|
+
}
|
|
121
|
+
else if (o === 1) {
|
|
99
122
|
parts.push(TENS[t] + ' et ' + ONES[1])
|
|
100
|
-
}
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
101
125
|
parts.push(TENS[t] + '-' + ONES[o])
|
|
102
126
|
}
|
|
103
|
-
}
|
|
127
|
+
}
|
|
128
|
+
else if (tensOnes < 80) {
|
|
104
129
|
// 70-79: septante pattern (Belgian)
|
|
105
130
|
const o = tensOnes % 10
|
|
106
131
|
if (o === 0) {
|
|
107
132
|
parts.push('septante')
|
|
108
|
-
}
|
|
133
|
+
}
|
|
134
|
+
else if (o === 1) {
|
|
109
135
|
parts.push('septante et ' + ONES[1])
|
|
110
|
-
}
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
111
138
|
parts.push('septante-' + ONES[o])
|
|
112
139
|
}
|
|
113
|
-
}
|
|
140
|
+
}
|
|
141
|
+
else if (tensOnes === 80) {
|
|
114
142
|
// 80: quatre-vingts (same as standard)
|
|
115
143
|
parts.push('quatre-vingts')
|
|
116
144
|
endsWithVingts = true
|
|
117
|
-
}
|
|
145
|
+
}
|
|
146
|
+
else if (tensOnes < 90) {
|
|
118
147
|
// 81-89: quatre-vingt-X (same as standard)
|
|
119
148
|
const remainder = tensOnes - 80
|
|
120
149
|
parts.push('quatre-vingt-' + ONES[remainder])
|
|
121
|
-
}
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
122
152
|
// 90-99: nonante pattern (Belgian)
|
|
123
153
|
const o = tensOnes % 10
|
|
124
154
|
if (o === 0) {
|
|
125
155
|
parts.push('nonante')
|
|
126
|
-
}
|
|
156
|
+
}
|
|
157
|
+
else if (o === 1) {
|
|
127
158
|
parts.push('nonante et ' + ONES[1])
|
|
128
|
-
}
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
129
161
|
parts.push('nonante-' + ONES[o])
|
|
130
162
|
}
|
|
131
163
|
}
|
|
@@ -137,7 +169,13 @@ function buildSegment (n) {
|
|
|
137
169
|
// Helper Functions
|
|
138
170
|
// ============================================================================
|
|
139
171
|
|
|
140
|
-
|
|
172
|
+
/**
|
|
173
|
+
* Returns the scale word (mille, million, milliard, ...) for a scale index.
|
|
174
|
+
* @param {number} scaleIndex - Scale group index
|
|
175
|
+
* @param {bigint} segment - Segment value used to decide pluralization
|
|
176
|
+
* @returns {string} The scale word
|
|
177
|
+
*/
|
|
178
|
+
function getScaleWord(scaleIndex, segment) {
|
|
141
179
|
if (scaleIndex === 1) return THOUSAND
|
|
142
180
|
|
|
143
181
|
if (scaleIndex % 2 === 0) {
|
|
@@ -145,7 +183,8 @@ function getScaleWord (scaleIndex, segment) {
|
|
|
145
183
|
const baseWord = SCALES[arrayIndex]
|
|
146
184
|
if (!baseWord) return ''
|
|
147
185
|
return segment > 1n ? baseWord + 's' : baseWord
|
|
148
|
-
}
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
149
188
|
const arrayIndex = ((scaleIndex - 1) / 2) - 1
|
|
150
189
|
const ardWord = SCALES_ARD[arrayIndex]
|
|
151
190
|
if (!ardWord) return THOUSAND
|
|
@@ -157,7 +196,13 @@ function getScaleWord (scaleIndex, segment) {
|
|
|
157
196
|
// Conversion Functions
|
|
158
197
|
// ============================================================================
|
|
159
198
|
|
|
160
|
-
|
|
199
|
+
/**
|
|
200
|
+
* Converts a non-negative integer to Belgian French cardinal words.
|
|
201
|
+
* @param {bigint} n - Non-negative integer
|
|
202
|
+
* @param {boolean} [withHyphen] - Use hyphens between words
|
|
203
|
+
* @returns {string} The integer in Belgian French words
|
|
204
|
+
*/
|
|
205
|
+
function integerToWords(n, withHyphen = false) {
|
|
161
206
|
if (n === 0n) return ZERO
|
|
162
207
|
|
|
163
208
|
if (n < 1000n) {
|
|
@@ -172,7 +217,8 @@ function integerToWords (n, withHyphen = false) {
|
|
|
172
217
|
let result
|
|
173
218
|
if (thousands === 1) {
|
|
174
219
|
result = THOUSAND
|
|
175
|
-
}
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
176
222
|
const { word: thousandsWord, endsWithCents, endsWithVingts } = buildSegment(thousands)
|
|
177
223
|
let adjustedWord = thousandsWord
|
|
178
224
|
if (endsWithCents || endsWithVingts) {
|
|
@@ -196,7 +242,13 @@ function integerToWords (n, withHyphen = false) {
|
|
|
196
242
|
return buildLargeNumberWords(n, withHyphen)
|
|
197
243
|
}
|
|
198
244
|
|
|
199
|
-
|
|
245
|
+
/**
|
|
246
|
+
* Builds words for large integers (>= 1,000,000) using scale groups.
|
|
247
|
+
* @param {bigint} n - Integer value (>= 1,000,000)
|
|
248
|
+
* @param {boolean} withHyphen - Use hyphens between words
|
|
249
|
+
* @returns {string} The integer in Belgian French words
|
|
250
|
+
*/
|
|
251
|
+
function buildLargeNumberWords(n, withHyphen) {
|
|
200
252
|
const numStr = n.toString()
|
|
201
253
|
const len = numStr.length
|
|
202
254
|
|
|
@@ -226,10 +278,12 @@ function buildLargeNumberWords (n, withHyphen) {
|
|
|
226
278
|
|
|
227
279
|
if (scaleIndex === 0) {
|
|
228
280
|
parts.push(segWords)
|
|
229
|
-
}
|
|
281
|
+
}
|
|
282
|
+
else if (scaleIndex === 1) {
|
|
230
283
|
if (segment === 1) {
|
|
231
284
|
parts.push(THOUSAND)
|
|
232
|
-
}
|
|
285
|
+
}
|
|
286
|
+
else {
|
|
233
287
|
let adjustedWord = segWords
|
|
234
288
|
if (endsWithCents || endsWithVingts) {
|
|
235
289
|
adjustedWord = segWords.slice(0, -1)
|
|
@@ -237,7 +291,8 @@ function buildLargeNumberWords (n, withHyphen) {
|
|
|
237
291
|
parts.push(adjustedWord)
|
|
238
292
|
parts.push(scaleWord)
|
|
239
293
|
}
|
|
240
|
-
}
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
241
296
|
parts.push(segWords)
|
|
242
297
|
parts.push(scaleWord)
|
|
243
298
|
}
|
|
@@ -256,7 +311,13 @@ function buildLargeNumberWords (n, withHyphen) {
|
|
|
256
311
|
return result
|
|
257
312
|
}
|
|
258
313
|
|
|
259
|
-
|
|
314
|
+
/**
|
|
315
|
+
* Converts the decimal part digits to words (leading zeros spoken as zéro).
|
|
316
|
+
* @param {string} decimalPart - Decimal digits as a string
|
|
317
|
+
* @param {boolean} withHyphen - Use hyphens between words
|
|
318
|
+
* @returns {string} The decimal part in Belgian French words
|
|
319
|
+
*/
|
|
320
|
+
function decimalPartToWords(decimalPart, withHyphen) {
|
|
260
321
|
let result = ''
|
|
261
322
|
const sep = withHyphen ? '-' : ' '
|
|
262
323
|
|
|
@@ -276,20 +337,28 @@ function decimalPartToWords (decimalPart, withHyphen) {
|
|
|
276
337
|
return result
|
|
277
338
|
}
|
|
278
339
|
|
|
340
|
+
/**
|
|
341
|
+
* @typedef {object} CardinalOptions
|
|
342
|
+
* @property {boolean} [withHyphenSeparator] - Use hyphens between words
|
|
343
|
+
*/
|
|
344
|
+
|
|
345
|
+
/** @type {Required<CardinalOptions>} */
|
|
346
|
+
export const cardinalDefaults = { withHyphenSeparator: false }
|
|
347
|
+
|
|
279
348
|
/**
|
|
280
349
|
* Converts a numeric value to Belgian French words.
|
|
281
|
-
*
|
|
282
350
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
283
|
-
* @param {
|
|
284
|
-
* @param {boolean} [options.withHyphenSeparator=false] - Use hyphens between words
|
|
351
|
+
* @param {CardinalOptions} [options] - Optional configuration
|
|
285
352
|
* @returns {string} The number in Belgian French words
|
|
286
353
|
*/
|
|
287
|
-
function toCardinal
|
|
288
|
-
options = validateOptions(options)
|
|
354
|
+
function toCardinal(value, options) {
|
|
289
355
|
const { isNegative, integerPart, decimalPart } = parseCardinalValue(value)
|
|
356
|
+
// Both the integer part and the decimal's significant digits are spelled via
|
|
357
|
+
// the scale builder, so both must clear the ceiling.
|
|
358
|
+
checkMax(integerPart, cardinalMax, decimalPart)
|
|
290
359
|
|
|
291
360
|
// Apply option defaults
|
|
292
|
-
const { withHyphenSeparator
|
|
361
|
+
const { withHyphenSeparator } = resolveOptions(options, cardinalDefaults)
|
|
293
362
|
|
|
294
363
|
let result = ''
|
|
295
364
|
const sep = withHyphenSeparator ? '-' : ' '
|
|
@@ -318,11 +387,10 @@ function toCardinal (value, options) {
|
|
|
318
387
|
* - Drop final -e before adding -ième (quatre → quatrième)
|
|
319
388
|
* - cinq → cinquième (add -u- before -ième)
|
|
320
389
|
* - neuf → neuvième (f → v before -ième)
|
|
321
|
-
*
|
|
322
390
|
* @param {string} cardinalWord - Cardinal word to convert
|
|
323
391
|
* @returns {string} Ordinal form
|
|
324
392
|
*/
|
|
325
|
-
function cardinalToOrdinal
|
|
393
|
+
function cardinalToOrdinal(cardinalWord) {
|
|
326
394
|
// Handle special endings
|
|
327
395
|
if (cardinalWord.endsWith('cinq')) {
|
|
328
396
|
// cinq → cinquième (add 'u')
|
|
@@ -336,16 +404,16 @@ function cardinalToOrdinal (cardinalWord) {
|
|
|
336
404
|
|
|
337
405
|
// Drop plural -s from cents/vingts/millions/etc. (quatre-vingts → quatre-vingtième)
|
|
338
406
|
// Note: "trois", "six" also end in s but that's not a plural
|
|
339
|
-
if (cardinalWord.endsWith('cents')
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
407
|
+
if (cardinalWord.endsWith('cents')
|
|
408
|
+
|| cardinalWord.endsWith('vingts')
|
|
409
|
+
|| cardinalWord.endsWith('millions')
|
|
410
|
+
|| cardinalWord.endsWith('milliards')
|
|
411
|
+
|| cardinalWord.endsWith('billions')
|
|
412
|
+
|| cardinalWord.endsWith('billiards')
|
|
413
|
+
|| cardinalWord.endsWith('trillions')
|
|
414
|
+
|| cardinalWord.endsWith('trilliards')
|
|
415
|
+
|| cardinalWord.endsWith('quadrillions')
|
|
416
|
+
|| cardinalWord.endsWith('quadrilliards')) {
|
|
349
417
|
return cardinalWord.slice(0, -1) + ORDINAL_SUFFIX
|
|
350
418
|
}
|
|
351
419
|
|
|
@@ -360,11 +428,10 @@ function cardinalToOrdinal (cardinalWord) {
|
|
|
360
428
|
|
|
361
429
|
/**
|
|
362
430
|
* Converts a positive integer to Belgian French ordinal words.
|
|
363
|
-
*
|
|
364
431
|
* @param {bigint} n - Positive integer
|
|
365
432
|
* @returns {string} Belgian French ordinal words
|
|
366
433
|
*/
|
|
367
|
-
function integerToOrdinal
|
|
434
|
+
function integerToOrdinal(n) {
|
|
368
435
|
// Special case: 1 → premier
|
|
369
436
|
if (n === 1n) {
|
|
370
437
|
return PREMIER
|
|
@@ -380,20 +447,19 @@ function integerToOrdinal (n) {
|
|
|
380
447
|
*
|
|
381
448
|
* Belgian French ordinals: premier (1st), then cardinal + ième.
|
|
382
449
|
* Special rules: quatre→quatrième, cinq→cinquième, neuf→neuvième.
|
|
383
|
-
*
|
|
384
450
|
* @param {number | string | bigint} value - The numeric value to convert (positive integer)
|
|
385
451
|
* @returns {string} The number as ordinal words
|
|
386
452
|
* @throws {TypeError} If value is not a valid numeric type
|
|
387
453
|
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
388
|
-
*
|
|
389
454
|
* @example
|
|
390
455
|
* toOrdinal(1) // 'premier'
|
|
391
456
|
* toOrdinal(2) // 'deuxième'
|
|
392
457
|
* toOrdinal(70) // 'septantième'
|
|
393
458
|
* toOrdinal(90) // 'nonantième'
|
|
394
459
|
*/
|
|
395
|
-
function toOrdinal
|
|
460
|
+
function toOrdinal(value) {
|
|
396
461
|
const integerPart = parseOrdinalValue(value)
|
|
462
|
+
checkMax(integerPart, ordinalMax)
|
|
397
463
|
return integerToOrdinal(integerPart)
|
|
398
464
|
}
|
|
399
465
|
|
|
@@ -401,16 +467,21 @@ function toOrdinal (value) {
|
|
|
401
467
|
// CURRENCY: toCurrency(value, options?)
|
|
402
468
|
// ============================================================================
|
|
403
469
|
|
|
470
|
+
/**
|
|
471
|
+
* @typedef {object} CurrencyOptions
|
|
472
|
+
* @property {boolean} [and] - Use "et" between euros and centimes
|
|
473
|
+
*/
|
|
474
|
+
|
|
475
|
+
/** @type {Required<CurrencyOptions>} */
|
|
476
|
+
export const currencyDefaults = { and: true }
|
|
477
|
+
|
|
404
478
|
/**
|
|
405
479
|
* Converts a numeric value to Belgian French currency words (Euro).
|
|
406
|
-
*
|
|
407
480
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
408
|
-
* @param {
|
|
409
|
-
* @param {boolean} [options.and=true] - Use "et" between euros and centimes
|
|
481
|
+
* @param {CurrencyOptions} [options] - Optional configuration
|
|
410
482
|
* @returns {string} The amount in Belgian French currency words
|
|
411
483
|
* @throws {TypeError} If value is not a valid numeric type
|
|
412
484
|
* @throws {Error} If value is not a valid number format
|
|
413
|
-
*
|
|
414
485
|
* @example
|
|
415
486
|
* toCurrency(42.50) // 'quarante-deux euros et cinquante centimes'
|
|
416
487
|
* toCurrency(1) // 'un euro'
|
|
@@ -418,10 +489,10 @@ function toOrdinal (value) {
|
|
|
418
489
|
* toCurrency(0.01) // 'un centime'
|
|
419
490
|
* toCurrency(42.50, { and: false }) // 'quarante-deux euros cinquante centimes'
|
|
420
491
|
*/
|
|
421
|
-
function toCurrency
|
|
422
|
-
options = validateOptions(options)
|
|
492
|
+
function toCurrency(value, options) {
|
|
423
493
|
const { isNegative, dollars: euros, cents: centimes } = parseCurrencyValue(value)
|
|
424
|
-
|
|
494
|
+
checkMax(euros, currencyMax)
|
|
495
|
+
const { and: useAnd } = resolveOptions(options, currencyDefaults)
|
|
425
496
|
|
|
426
497
|
// Build result
|
|
427
498
|
let result = ''
|
package/src/fr-FR.d.ts
CHANGED
|
@@ -1,35 +1,55 @@
|
|
|
1
|
+
export const cardinalMax: bigint;
|
|
2
|
+
export const ordinalMax: bigint;
|
|
3
|
+
export const currencyMax: bigint;
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {object} CardinalOptions
|
|
6
|
+
* @property {boolean} [withHyphenSeparator] - Use hyphens between all words
|
|
7
|
+
*/
|
|
8
|
+
/** @type {Required<CardinalOptions>} */
|
|
9
|
+
export const cardinalDefaults: Required<CardinalOptions>;
|
|
10
|
+
/**
|
|
11
|
+
* @typedef {object} CurrencyOptions
|
|
12
|
+
* @property {boolean} [and] - Use "et" between euros and centimes
|
|
13
|
+
*/
|
|
14
|
+
/** @type {Required<CurrencyOptions>} */
|
|
15
|
+
export const currencyDefaults: Required<CurrencyOptions>;
|
|
16
|
+
export type CardinalOptions = {
|
|
17
|
+
/**
|
|
18
|
+
* - Use hyphens between all words
|
|
19
|
+
*/
|
|
20
|
+
withHyphenSeparator?: boolean | undefined;
|
|
21
|
+
};
|
|
22
|
+
export type CurrencyOptions = {
|
|
23
|
+
/**
|
|
24
|
+
* - Use "et" between euros and centimes
|
|
25
|
+
*/
|
|
26
|
+
and?: boolean | undefined;
|
|
27
|
+
};
|
|
1
28
|
/**
|
|
2
29
|
* Converts a numeric value to French words.
|
|
3
30
|
*
|
|
4
31
|
* This is the main public API. It accepts any valid numeric input
|
|
5
32
|
* (number, string, or bigint) and handles parsing internally.
|
|
6
|
-
*
|
|
7
33
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
8
|
-
* @param {
|
|
9
|
-
* @param {boolean} [options.withHyphenSeparator=false] - Use hyphens between all words
|
|
34
|
+
* @param {CardinalOptions} [options] - Optional configuration
|
|
10
35
|
* @returns {string} The number in French words
|
|
11
36
|
* @throws {TypeError} If value is not a valid numeric type
|
|
12
37
|
* @throws {Error} If value is not a valid number format
|
|
13
|
-
*
|
|
14
38
|
* @example
|
|
15
39
|
* toCardinal(21) // 'vingt et un'
|
|
16
40
|
* toCardinal(80) // 'quatre-vingts'
|
|
17
41
|
* toCardinal(1000000) // 'un million'
|
|
18
42
|
*/
|
|
19
|
-
export function toCardinal(value: number | string | bigint, options?:
|
|
20
|
-
withHyphenSeparator?: boolean | undefined;
|
|
21
|
-
}): string;
|
|
43
|
+
export function toCardinal(value: number | string | bigint, options?: CardinalOptions): string;
|
|
22
44
|
/**
|
|
23
45
|
* Converts a numeric value to French ordinal words.
|
|
24
46
|
*
|
|
25
47
|
* French ordinals: premier (1st), then cardinal + ième.
|
|
26
48
|
* Special rules: quatre→quatrième, cinq→cinquième, neuf→neuvième.
|
|
27
|
-
*
|
|
28
49
|
* @param {number | string | bigint} value - The numeric value to convert (positive integer)
|
|
29
50
|
* @returns {string} The number as ordinal words
|
|
30
51
|
* @throws {TypeError} If value is not a valid numeric type
|
|
31
52
|
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
32
|
-
*
|
|
33
53
|
* @example
|
|
34
54
|
* toOrdinal(1) // 'premier'
|
|
35
55
|
* toOrdinal(2) // 'deuxième'
|
|
@@ -43,14 +63,11 @@ export function toCardinal(value: number | string | bigint, options?: {
|
|
|
43
63
|
export function toOrdinal(value: number | string | bigint): string;
|
|
44
64
|
/**
|
|
45
65
|
* Converts a numeric value to French currency words (Euro).
|
|
46
|
-
*
|
|
47
66
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
48
|
-
* @param {
|
|
49
|
-
* @param {boolean} [options.and=true] - Use "et" between euros and centimes
|
|
67
|
+
* @param {CurrencyOptions} [options] - Optional configuration
|
|
50
68
|
* @returns {string} The amount in French currency words
|
|
51
69
|
* @throws {TypeError} If value is not a valid numeric type
|
|
52
70
|
* @throws {Error} If value is not a valid number format
|
|
53
|
-
*
|
|
54
71
|
* @example
|
|
55
72
|
* toCurrency(42.50) // 'quarante-deux euros et cinquante centimes'
|
|
56
73
|
* toCurrency(1) // 'un euro'
|
|
@@ -58,6 +75,4 @@ export function toOrdinal(value: number | string | bigint): string;
|
|
|
58
75
|
* toCurrency(0.01) // 'un centime'
|
|
59
76
|
* toCurrency(42.50, { and: false }) // 'quarante-deux euros cinquante centimes'
|
|
60
77
|
*/
|
|
61
|
-
export function toCurrency(value: number | string | bigint, options?:
|
|
62
|
-
and?: boolean | undefined;
|
|
63
|
-
}): string;
|
|
78
|
+
export function toCurrency(value: number | string | bigint, options?: CurrencyOptions): string;
|