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/bn-BD.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
|
|
@@ -53,20 +55,29 @@ const BELOW_HUNDRED = [
|
|
|
53
55
|
'ষাট', 'একষট্টি', 'বাষট্টি', 'তেষট্টি', 'চৌষট্টি', 'পঁয়ষট্টি', 'ছেষট্টি', 'সাতষট্টি', 'আটষট্টি', 'ঊনসত্তর',
|
|
54
56
|
'সত্তর', 'একাত্তর', 'বাহাত্তর', 'তেহাত্তর', 'চুয়াত্তর', 'পঁচাত্তর', 'ছিয়াত্তর', 'সাতাত্তর', 'আটাত্তর', 'উনআশি',
|
|
55
57
|
'আশি', 'একাশি', 'বিরাশি', 'তিরাশি', 'চুরাশি', 'পঁচাশি', 'ছিয়াশি', 'সাতাশি', 'আটাশি', 'উননব্বই',
|
|
56
|
-
'নব্বই', 'একানব্বই', 'বিরানব্বই', 'তিরানব্বই', 'চুরানব্বই', 'পঁচানব্বই', 'ছিয়ানব্বই', 'সাতানব্বই', 'আটানব্বই', 'নিরানব্বই'
|
|
58
|
+
'নব্বই', 'একানব্বই', 'বিরানব্বই', 'তিরানব্বই', 'চুরানব্বই', 'পঁচানব্বই', 'ছিয়ানব্বই', 'সাতানব্বই', 'আটানব্বই', 'নিরানব্বই',
|
|
57
59
|
]
|
|
58
60
|
|
|
59
61
|
// Scale words: index 0 = units (empty), 1 = thousand, 2 = lakh, 3 = crore, etc.
|
|
60
62
|
const SCALE_WORDS = ['', 'হাজার', 'লাখ', 'কোটি', 'আরব', 'খরব', 'নীল', 'পদ্ম', 'শঙ্খ']
|
|
61
63
|
|
|
64
|
+
// 3-2-2 Indian grouping: a 3-digit base segment, then 2 digits per scale word
|
|
65
|
+
// (SCALE_WORDS[0] = '' is the units slot). Past the table the scale word is
|
|
66
|
+
// dropped, which collapses the magnitude — so cap there.
|
|
67
|
+
export const cardinalMax = indian(SCALE_WORDS.length)
|
|
68
|
+
export const ordinalMax = indian(SCALE_WORDS.length)
|
|
69
|
+
export const currencyMax = indian(SCALE_WORDS.length)
|
|
70
|
+
|
|
62
71
|
// ============================================================================
|
|
63
72
|
// Segment Building
|
|
64
73
|
// ============================================================================
|
|
65
74
|
|
|
66
75
|
/**
|
|
67
76
|
* Builds words for a 0-999 segment.
|
|
77
|
+
* @param {number} n - Segment value in the range 0-999
|
|
78
|
+
* @returns {string} Bengali words for the segment
|
|
68
79
|
*/
|
|
69
|
-
function buildSegment
|
|
80
|
+
function buildSegment(n) {
|
|
70
81
|
if (n === 0) return ''
|
|
71
82
|
if (n < 100) return BELOW_HUNDRED[n]
|
|
72
83
|
|
|
@@ -88,11 +99,10 @@ function buildSegment (n) {
|
|
|
88
99
|
*
|
|
89
100
|
* Uses BigInt modulo for segment extraction (faster than string slicing).
|
|
90
101
|
* South Asian 3-2-2 grouping: first 3 digits, then groups of 2.
|
|
91
|
-
*
|
|
92
102
|
* @param {bigint} n - Non-negative integer to convert
|
|
93
103
|
* @returns {string} Bengali words
|
|
94
104
|
*/
|
|
95
|
-
function integerToWords
|
|
105
|
+
function integerToWords(n) {
|
|
96
106
|
if (n === 0n) return ZERO
|
|
97
107
|
|
|
98
108
|
// Fast path: numbers < 1000 (direct lookup)
|
|
@@ -124,7 +134,8 @@ function integerToWords (n) {
|
|
|
124
134
|
if (i === 0) {
|
|
125
135
|
// First segment (units place) can be 0-999
|
|
126
136
|
words.push(buildSegment(segment))
|
|
127
|
-
}
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
128
139
|
// Other segments are 0-99
|
|
129
140
|
words.push(BELOW_HUNDRED[segment])
|
|
130
141
|
}
|
|
@@ -138,7 +149,12 @@ function integerToWords (n) {
|
|
|
138
149
|
return words.join(' ')
|
|
139
150
|
}
|
|
140
151
|
|
|
141
|
-
|
|
152
|
+
/**
|
|
153
|
+
* Converts the fractional digits string to Bengali words.
|
|
154
|
+
* @param {string} decimalPart - The fractional digits (e.g. '05')
|
|
155
|
+
* @returns {string} Bengali words for the decimal part
|
|
156
|
+
*/
|
|
157
|
+
function decimalPartToWords(decimalPart) {
|
|
142
158
|
let result = ''
|
|
143
159
|
let i = 0
|
|
144
160
|
|
|
@@ -159,12 +175,14 @@ function decimalPartToWords (decimalPart) {
|
|
|
159
175
|
|
|
160
176
|
/**
|
|
161
177
|
* Converts a numeric value to Bengali words.
|
|
162
|
-
*
|
|
163
178
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
164
179
|
* @returns {string} The number in Bengali words
|
|
165
180
|
*/
|
|
166
|
-
function toCardinal
|
|
181
|
+
function toCardinal(value) {
|
|
167
182
|
const { isNegative, integerPart, decimalPart } = parseCardinalValue(value)
|
|
183
|
+
// Both the integer part and the decimal's significant digits are spelled via
|
|
184
|
+
// the scale builder, so both must clear the ceiling.
|
|
185
|
+
checkMax(integerPart, cardinalMax, decimalPart)
|
|
168
186
|
|
|
169
187
|
let result = ''
|
|
170
188
|
|
|
@@ -189,11 +207,10 @@ function toCardinal (value) {
|
|
|
189
207
|
* Converts a positive integer to Bengali ordinal words.
|
|
190
208
|
*
|
|
191
209
|
* Bengali ordinals: First 6 are irregular, then add -তম suffix.
|
|
192
|
-
*
|
|
193
210
|
* @param {bigint} n - Positive integer to convert
|
|
194
211
|
* @returns {string} Bengali ordinal words
|
|
195
212
|
*/
|
|
196
|
-
function integerToOrdinal
|
|
213
|
+
function integerToOrdinal(n) {
|
|
197
214
|
// Special ordinals for 1-6
|
|
198
215
|
if (n >= 1n && n <= 6n) {
|
|
199
216
|
return ORDINAL_SPECIAL[Number(n)]
|
|
@@ -206,20 +223,20 @@ function integerToOrdinal (n) {
|
|
|
206
223
|
|
|
207
224
|
/**
|
|
208
225
|
* Converts a numeric value to Bengali ordinal words.
|
|
209
|
-
*
|
|
210
226
|
* @param {number | string | bigint} value - The numeric value to convert (positive integer)
|
|
211
227
|
* @returns {string} The number as ordinal words
|
|
212
228
|
* @throws {TypeError} If value is not a valid numeric type
|
|
213
229
|
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
214
|
-
*
|
|
215
230
|
* @example
|
|
216
231
|
* toOrdinal(1) // 'প্রথম'
|
|
217
232
|
* toOrdinal(2) // 'দ্বিতীয়'
|
|
218
233
|
* toOrdinal(3) // 'তৃতীয়'
|
|
219
234
|
* toOrdinal(10) // 'দশতম'
|
|
220
235
|
*/
|
|
221
|
-
function toOrdinal
|
|
236
|
+
function toOrdinal(value) {
|
|
222
237
|
const integerPart = parseOrdinalValue(value)
|
|
238
|
+
// Ordinals build on the cardinal speller, so they share its ceiling.
|
|
239
|
+
checkMax(integerPart, ordinalMax)
|
|
223
240
|
return integerToOrdinal(integerPart)
|
|
224
241
|
}
|
|
225
242
|
|
|
@@ -229,19 +246,18 @@ function toOrdinal (value) {
|
|
|
229
246
|
|
|
230
247
|
/**
|
|
231
248
|
* Converts a numeric value to Bengali currency words (Bangladeshi Taka).
|
|
232
|
-
*
|
|
233
249
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
234
250
|
* @returns {string} The amount in Bengali currency words
|
|
235
251
|
* @throws {TypeError} If value is not a valid numeric type
|
|
236
252
|
* @throws {Error} If value is not a valid number format
|
|
237
|
-
*
|
|
238
253
|
* @example
|
|
239
254
|
* toCurrency(42.50) // 'বেয়াল্লিশ টাকা পঞ্চাশ পয়সা'
|
|
240
255
|
* toCurrency(1) // 'এক টাকা'
|
|
241
256
|
* toCurrency(0.01) // 'এক পয়সা'
|
|
242
257
|
*/
|
|
243
|
-
function toCurrency
|
|
258
|
+
function toCurrency(value) {
|
|
244
259
|
const { isNegative, dollars: taka, cents: paisa } = parseCurrencyValue(value)
|
|
260
|
+
checkMax(taka, currencyMax)
|
|
245
261
|
|
|
246
262
|
// Build result
|
|
247
263
|
let result = ''
|
package/src/cs-CZ.d.ts
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
|
+
export const cardinalMax: bigint;
|
|
2
|
+
export const ordinalMax: bigint;
|
|
3
|
+
export const currencyMax: bigint;
|
|
1
4
|
/**
|
|
2
5
|
* Converts a numeric value to Czech words.
|
|
3
6
|
*
|
|
4
7
|
* This is the main public API. It accepts any valid numeric input
|
|
5
8
|
* (number, string, or bigint) and handles parsing internally.
|
|
6
|
-
*
|
|
7
9
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
8
10
|
* @returns {string} The number in Czech words
|
|
9
11
|
* @throws {TypeError} If value is not a valid numeric type
|
|
10
12
|
* @throws {Error} If value is not a valid number format
|
|
11
|
-
*
|
|
12
13
|
* @example
|
|
13
14
|
* toCardinal(21) // 'dvacet jedna'
|
|
14
15
|
* toCardinal(1000) // 'tisíc'
|
|
@@ -18,12 +19,10 @@
|
|
|
18
19
|
export function toCardinal(value: number | string | bigint): string;
|
|
19
20
|
/**
|
|
20
21
|
* Converts a numeric value to Czech ordinal words (masculine nominative).
|
|
21
|
-
*
|
|
22
22
|
* @param {number | string | bigint} value - The numeric value to convert (must be a positive integer)
|
|
23
23
|
* @returns {string} The number as ordinal words
|
|
24
24
|
* @throws {TypeError} If value is not a valid numeric type
|
|
25
25
|
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
26
|
-
*
|
|
27
26
|
* @example
|
|
28
27
|
* toOrdinal(1) // 'první'
|
|
29
28
|
* toOrdinal(2) // 'druhý'
|
|
@@ -34,12 +33,10 @@ export function toCardinal(value: number | string | bigint): string;
|
|
|
34
33
|
export function toOrdinal(value: number | string | bigint): string;
|
|
35
34
|
/**
|
|
36
35
|
* Converts a numeric value to Czech currency words (Koruna).
|
|
37
|
-
*
|
|
38
36
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
39
37
|
* @returns {string} The amount in Czech currency words
|
|
40
38
|
* @throws {TypeError} If value is not a valid numeric type
|
|
41
39
|
* @throws {Error} If value is not a valid number format
|
|
42
|
-
*
|
|
43
40
|
* @example
|
|
44
41
|
* toCurrency(42) // 'čtyřicet dva koruny'
|
|
45
42
|
* toCurrency(1) // 'jedna koruna'
|
package/src/cs-CZ.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 { western } from './utils/scale.js'
|
|
17
19
|
|
|
18
20
|
// ============================================================================
|
|
19
21
|
// Vocabulary (module-level constants)
|
|
@@ -32,6 +34,7 @@ const TENS = ['', '', 'dvacet', 'třicet', 'čtyřicet', 'padesát', 'šedesát'
|
|
|
32
34
|
const HUNDREDS = ['', 'sto', 'dvě stě', 'tři sta', 'čtyři sta', 'pět set', 'šest set', 'sedm set', 'osm set', 'devět set']
|
|
33
35
|
|
|
34
36
|
// Scale plural forms [singular, few (2-4), many (5+)]
|
|
37
|
+
/** @type {Record<number, string[]>} */
|
|
35
38
|
const PLURAL_FORMS = {
|
|
36
39
|
1: ['tisíc', 'tisíce', 'tisíc'], // 10^3
|
|
37
40
|
2: ['milion', 'miliony', 'milionů'], // 10^6
|
|
@@ -41,9 +44,16 @@ const PLURAL_FORMS = {
|
|
|
41
44
|
6: ['trilion', 'triliony', 'trilionů'], // 10^18
|
|
42
45
|
7: ['triliarda', 'triliardy', 'triliard'], // 10^21
|
|
43
46
|
8: ['kvadrilion', 'kvadriliony', 'kvadrilionů'], // 10^24
|
|
44
|
-
9: ['kvadriliarda', 'kvadriliardy', 'kvadriliard'] // 10^27
|
|
47
|
+
9: ['kvadriliarda', 'kvadriliardy', 'kvadriliard'], // 10^27
|
|
45
48
|
}
|
|
46
49
|
|
|
50
|
+
// PLURAL_FORMS is keyed by 1000-power; past its largest key the builder drops the
|
|
51
|
+
// scale word (cardinal) or dereferences undefined (ordinal), so cap there.
|
|
52
|
+
const MAX_SCALE_KEY = Math.max(...Object.keys(PLURAL_FORMS).map(Number))
|
|
53
|
+
export const cardinalMax = western(MAX_SCALE_KEY)
|
|
54
|
+
export const ordinalMax = western(MAX_SCALE_KEY)
|
|
55
|
+
export const currencyMax = western(MAX_SCALE_KEY)
|
|
56
|
+
|
|
47
57
|
const ZERO = 'nula'
|
|
48
58
|
const NEGATIVE = 'mínus'
|
|
49
59
|
|
|
@@ -81,8 +91,10 @@ const HALER_FORMS = ['haléř', 'haléře', 'haléřů']
|
|
|
81
91
|
|
|
82
92
|
/**
|
|
83
93
|
* Builds segment word for 0-999 (masculine, default form).
|
|
94
|
+
* @param {number} n - Number 0-999
|
|
95
|
+
* @returns {string} Czech words
|
|
84
96
|
*/
|
|
85
|
-
function buildSegment
|
|
97
|
+
function buildSegment(n) {
|
|
86
98
|
if (n === 0) return ''
|
|
87
99
|
|
|
88
100
|
const ones = n % 10
|
|
@@ -100,12 +112,14 @@ function buildSegment (n) {
|
|
|
100
112
|
if (tens === 1) {
|
|
101
113
|
// Teens
|
|
102
114
|
parts.push(TEENS[ones])
|
|
103
|
-
}
|
|
115
|
+
}
|
|
116
|
+
else if (tens >= 2) {
|
|
104
117
|
parts.push(TENS[tens])
|
|
105
118
|
if (ones > 0) {
|
|
106
119
|
parts.push(ONES[ones])
|
|
107
120
|
}
|
|
108
|
-
}
|
|
121
|
+
}
|
|
122
|
+
else if (ones > 0) {
|
|
109
123
|
parts.push(ONES[ones])
|
|
110
124
|
}
|
|
111
125
|
|
|
@@ -115,8 +129,10 @@ function buildSegment (n) {
|
|
|
115
129
|
/**
|
|
116
130
|
* Builds segment word for 0-999 with feminine hundreds.
|
|
117
131
|
* Hundreds use irregular forms (dvě stě, tři sta) but ones remain masculine.
|
|
132
|
+
* @param {number} n - Number 0-999
|
|
133
|
+
* @returns {string} Czech words
|
|
118
134
|
*/
|
|
119
|
-
function buildSegmentWithHundreds
|
|
135
|
+
function buildSegmentWithHundreds(n) {
|
|
120
136
|
if (n === 0) return ''
|
|
121
137
|
|
|
122
138
|
const ones = n % 10
|
|
@@ -133,12 +149,14 @@ function buildSegmentWithHundreds (n) {
|
|
|
133
149
|
// Tens and ones use masculine form
|
|
134
150
|
if (tens === 1) {
|
|
135
151
|
parts.push(TEENS[ones])
|
|
136
|
-
}
|
|
152
|
+
}
|
|
153
|
+
else if (tens >= 2) {
|
|
137
154
|
parts.push(TENS[tens])
|
|
138
155
|
if (ones > 0) {
|
|
139
156
|
parts.push(ONES[ones]) // masculine
|
|
140
157
|
}
|
|
141
|
-
}
|
|
158
|
+
}
|
|
159
|
+
else if (ones > 0) {
|
|
142
160
|
parts.push(ONES[ones]) // masculine
|
|
143
161
|
}
|
|
144
162
|
|
|
@@ -152,12 +170,11 @@ function buildSegmentWithHundreds (n) {
|
|
|
152
170
|
/**
|
|
153
171
|
* Czech pluralization: 1 = singular, 2-4 = few, else = many.
|
|
154
172
|
* Teens (11-19) always use "many" form.
|
|
155
|
-
*
|
|
156
173
|
* @param {bigint} n - The number
|
|
157
174
|
* @param {string[]} forms - [singular, few, many]
|
|
158
175
|
* @returns {string} The appropriate form
|
|
159
176
|
*/
|
|
160
|
-
function pluralize
|
|
177
|
+
function pluralize(n, forms) {
|
|
161
178
|
if (n === 1n) return forms[0]
|
|
162
179
|
|
|
163
180
|
const lastDigit = n % 10n
|
|
@@ -174,13 +191,17 @@ function pluralize (n, forms) {
|
|
|
174
191
|
/**
|
|
175
192
|
* Gets the decimal separator word based on integer part.
|
|
176
193
|
* celá (0-1), celé (2-4), celých (5+)
|
|
194
|
+
* @param {bigint} integerPart - The integer part of the value
|
|
195
|
+
* @returns {string} The decimal separator word
|
|
177
196
|
*/
|
|
178
|
-
function getDecimalSeparator
|
|
197
|
+
function getDecimalSeparator(integerPart) {
|
|
179
198
|
if (integerPart === 0n || integerPart === 1n) {
|
|
180
199
|
return 'celá'
|
|
181
|
-
}
|
|
200
|
+
}
|
|
201
|
+
else if (integerPart >= 2n && integerPart <= 4n) {
|
|
182
202
|
return 'celé'
|
|
183
|
-
}
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
184
205
|
return 'celých'
|
|
185
206
|
}
|
|
186
207
|
}
|
|
@@ -191,11 +212,10 @@ function getDecimalSeparator (integerPart) {
|
|
|
191
212
|
|
|
192
213
|
/**
|
|
193
214
|
* Converts a non-negative integer to Czech words.
|
|
194
|
-
*
|
|
195
215
|
* @param {bigint} n - Non-negative integer to convert
|
|
196
216
|
* @returns {string} Czech words
|
|
197
217
|
*/
|
|
198
|
-
function integerToWords
|
|
218
|
+
function integerToWords(n) {
|
|
199
219
|
if (n === 0n) return ZERO
|
|
200
220
|
|
|
201
221
|
// Fast path: numbers < 1000
|
|
@@ -214,7 +234,8 @@ function integerToWords (n) {
|
|
|
214
234
|
if (thousands === 1n) {
|
|
215
235
|
// Omit "one" before tisíc
|
|
216
236
|
result = scaleWord
|
|
217
|
-
}
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
218
239
|
result = buildSegment(Number(thousands)) + ' ' + scaleWord
|
|
219
240
|
}
|
|
220
241
|
|
|
@@ -233,11 +254,10 @@ function integerToWords (n) {
|
|
|
233
254
|
/**
|
|
234
255
|
* Builds words for numbers >= 1,000,000.
|
|
235
256
|
* Uses BigInt division for faster segment extraction.
|
|
236
|
-
*
|
|
237
257
|
* @param {bigint} n - Number >= 1,000,000
|
|
238
258
|
* @returns {string} Czech words
|
|
239
259
|
*/
|
|
240
|
-
function buildLargeNumberWords
|
|
260
|
+
function buildLargeNumberWords(n) {
|
|
241
261
|
// Extract segments using BigInt division (faster than string slicing)
|
|
242
262
|
// Segments stored least-significant first (index 0 = ones, 1 = thousands, etc.)
|
|
243
263
|
const segmentValues = []
|
|
@@ -259,7 +279,8 @@ function buildLargeNumberWords (n) {
|
|
|
259
279
|
if (i === 0) {
|
|
260
280
|
// Units segment (no scale word) - use form with irregular hundreds
|
|
261
281
|
result += buildSegmentWithHundreds(Number(segment))
|
|
262
|
-
}
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
263
284
|
// Scale word needed
|
|
264
285
|
const forms = PLURAL_FORMS[i]
|
|
265
286
|
if (forms) {
|
|
@@ -268,11 +289,13 @@ function buildLargeNumberWords (n) {
|
|
|
268
289
|
if (segment === 1n) {
|
|
269
290
|
// Omit "one" before scale words
|
|
270
291
|
result += scaleWord
|
|
271
|
-
}
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
272
294
|
// Use masculine form for multiplier before scale words
|
|
273
295
|
result += buildSegment(Number(segment)) + ' ' + scaleWord
|
|
274
296
|
}
|
|
275
|
-
}
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
276
299
|
// Fallback for very large scales without defined forms
|
|
277
300
|
result += buildSegment(Number(segment))
|
|
278
301
|
}
|
|
@@ -284,11 +307,10 @@ function buildLargeNumberWords (n) {
|
|
|
284
307
|
|
|
285
308
|
/**
|
|
286
309
|
* Converts decimal digits to Czech words.
|
|
287
|
-
*
|
|
288
310
|
* @param {string} decimalPart - Decimal digits (without the point)
|
|
289
311
|
* @returns {string} Czech words for decimal part
|
|
290
312
|
*/
|
|
291
|
-
function decimalPartToWords
|
|
313
|
+
function decimalPartToWords(decimalPart) {
|
|
292
314
|
let result = ''
|
|
293
315
|
|
|
294
316
|
// Handle leading zeros
|
|
@@ -314,20 +336,21 @@ function decimalPartToWords (decimalPart) {
|
|
|
314
336
|
*
|
|
315
337
|
* This is the main public API. It accepts any valid numeric input
|
|
316
338
|
* (number, string, or bigint) and handles parsing internally.
|
|
317
|
-
*
|
|
318
339
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
319
340
|
* @returns {string} The number in Czech words
|
|
320
341
|
* @throws {TypeError} If value is not a valid numeric type
|
|
321
342
|
* @throws {Error} If value is not a valid number format
|
|
322
|
-
*
|
|
323
343
|
* @example
|
|
324
344
|
* toCardinal(21) // 'dvacet jedna'
|
|
325
345
|
* toCardinal(1000) // 'tisíc'
|
|
326
346
|
* toCardinal(2000) // 'dva tisíce'
|
|
327
347
|
* toCardinal(5000) // 'pět tisíc'
|
|
328
348
|
*/
|
|
329
|
-
function toCardinal
|
|
349
|
+
function toCardinal(value) {
|
|
330
350
|
const { isNegative, integerPart, decimalPart } = parseCardinalValue(value)
|
|
351
|
+
// Both the integer part and the decimal's significant digits are spelled via
|
|
352
|
+
// the scale builder, so both must clear the ceiling.
|
|
353
|
+
checkMax(integerPart, cardinalMax, decimalPart)
|
|
331
354
|
|
|
332
355
|
let result = ''
|
|
333
356
|
|
|
@@ -351,11 +374,10 @@ function toCardinal (value) {
|
|
|
351
374
|
|
|
352
375
|
/**
|
|
353
376
|
* Builds ordinal for a 0-99 segment when it's the final (ordinal) part.
|
|
354
|
-
*
|
|
355
377
|
* @param {number} n - Number 0-99
|
|
356
378
|
* @returns {string} Ordinal words
|
|
357
379
|
*/
|
|
358
|
-
function buildOrdinalTensOnes
|
|
380
|
+
function buildOrdinalTensOnes(n) {
|
|
359
381
|
if (n === 0) return ''
|
|
360
382
|
|
|
361
383
|
const onesDigit = n % 10
|
|
@@ -378,11 +400,10 @@ function buildOrdinalTensOnes (n) {
|
|
|
378
400
|
|
|
379
401
|
/**
|
|
380
402
|
* Converts a positive integer to Czech ordinal words (masculine nominative).
|
|
381
|
-
*
|
|
382
403
|
* @param {bigint} n - Positive integer to convert
|
|
383
404
|
* @returns {string} Ordinal Czech words
|
|
384
405
|
*/
|
|
385
|
-
function integerToOrdinal
|
|
406
|
+
function integerToOrdinal(n) {
|
|
386
407
|
if (n < 100n) {
|
|
387
408
|
return buildOrdinalTensOnes(Number(n))
|
|
388
409
|
}
|
|
@@ -420,11 +441,10 @@ function integerToOrdinal (n) {
|
|
|
420
441
|
|
|
421
442
|
/**
|
|
422
443
|
* Builds ordinal words for numbers >= 1,000,000.
|
|
423
|
-
*
|
|
424
444
|
* @param {bigint} n - Number >= 1,000,000
|
|
425
445
|
* @returns {string} Ordinal Czech words
|
|
426
446
|
*/
|
|
427
|
-
function buildLargeOrdinal
|
|
447
|
+
function buildLargeOrdinal(n) {
|
|
428
448
|
const segmentValues = []
|
|
429
449
|
let temp = n
|
|
430
450
|
while (temp > 0n) {
|
|
@@ -450,23 +470,28 @@ function buildLargeOrdinal (n) {
|
|
|
450
470
|
if (i === 0) {
|
|
451
471
|
if (isLastNonZero) {
|
|
452
472
|
parts.push(integerToOrdinal(segment))
|
|
453
|
-
}
|
|
473
|
+
}
|
|
474
|
+
else {
|
|
454
475
|
parts.push(buildSegmentWithHundreds(Number(segment)))
|
|
455
476
|
}
|
|
456
|
-
}
|
|
477
|
+
}
|
|
478
|
+
else {
|
|
457
479
|
if (isLastNonZero) {
|
|
458
480
|
if (segment === 1n) {
|
|
459
481
|
parts.push(ORDINAL_SCALES[i - 1] || PLURAL_FORMS[i][0])
|
|
460
|
-
}
|
|
482
|
+
}
|
|
483
|
+
else {
|
|
461
484
|
parts.push(buildSegment(Number(segment)) + ' ' + (ORDINAL_SCALES[i - 1] || PLURAL_FORMS[i][0]))
|
|
462
485
|
}
|
|
463
|
-
}
|
|
486
|
+
}
|
|
487
|
+
else {
|
|
464
488
|
const forms = PLURAL_FORMS[i]
|
|
465
489
|
if (forms) {
|
|
466
490
|
const scaleWord = pluralize(segment, forms)
|
|
467
491
|
if (segment === 1n) {
|
|
468
492
|
parts.push(scaleWord)
|
|
469
|
-
}
|
|
493
|
+
}
|
|
494
|
+
else {
|
|
470
495
|
parts.push(buildSegment(Number(segment)) + ' ' + scaleWord)
|
|
471
496
|
}
|
|
472
497
|
}
|
|
@@ -479,12 +504,10 @@ function buildLargeOrdinal (n) {
|
|
|
479
504
|
|
|
480
505
|
/**
|
|
481
506
|
* Converts a numeric value to Czech ordinal words (masculine nominative).
|
|
482
|
-
*
|
|
483
507
|
* @param {number | string | bigint} value - The numeric value to convert (must be a positive integer)
|
|
484
508
|
* @returns {string} The number as ordinal words
|
|
485
509
|
* @throws {TypeError} If value is not a valid numeric type
|
|
486
510
|
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
487
|
-
*
|
|
488
511
|
* @example
|
|
489
512
|
* toOrdinal(1) // 'první'
|
|
490
513
|
* toOrdinal(2) // 'druhý'
|
|
@@ -492,8 +515,10 @@ function buildLargeOrdinal (n) {
|
|
|
492
515
|
* toOrdinal(100) // 'stý'
|
|
493
516
|
* toOrdinal(1000) // 'tisící'
|
|
494
517
|
*/
|
|
495
|
-
function toOrdinal
|
|
518
|
+
function toOrdinal(value) {
|
|
496
519
|
const integerPart = parseOrdinalValue(value)
|
|
520
|
+
// Ordinals reuse the cardinal scale table, so they share its ceiling.
|
|
521
|
+
checkMax(integerPart, ordinalMax)
|
|
497
522
|
return integerToOrdinal(integerPart)
|
|
498
523
|
}
|
|
499
524
|
|
|
@@ -503,20 +528,19 @@ function toOrdinal (value) {
|
|
|
503
528
|
|
|
504
529
|
/**
|
|
505
530
|
* Converts a numeric value to Czech currency words (Koruna).
|
|
506
|
-
*
|
|
507
531
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
508
532
|
* @returns {string} The amount in Czech currency words
|
|
509
533
|
* @throws {TypeError} If value is not a valid numeric type
|
|
510
534
|
* @throws {Error} If value is not a valid number format
|
|
511
|
-
*
|
|
512
535
|
* @example
|
|
513
536
|
* toCurrency(42) // 'čtyřicet dva koruny'
|
|
514
537
|
* toCurrency(1) // 'jedna koruna'
|
|
515
538
|
* toCurrency(1.50) // 'jedna koruna padesát haléřů'
|
|
516
539
|
* toCurrency(-5) // 'mínus pět korun'
|
|
517
540
|
*/
|
|
518
|
-
function toCurrency
|
|
541
|
+
function toCurrency(value) {
|
|
519
542
|
const { isNegative, dollars: koruny, cents: halere } = parseCurrencyValue(value)
|
|
543
|
+
checkMax(koruny, currencyMax)
|
|
520
544
|
|
|
521
545
|
let result = ''
|
|
522
546
|
if (isNegative) {
|
package/src/da-DK.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
export const cardinalMax: bigint;
|
|
2
|
+
export const ordinalMax: bigint;
|
|
3
|
+
export const currencyMax: bigint;
|
|
1
4
|
/**
|
|
2
5
|
* Converts a numeric value to Danish words.
|
|
3
|
-
*
|
|
4
6
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
5
7
|
* @returns {string} The number in Danish words
|
|
6
8
|
* @throws {TypeError} If value is not a valid numeric type
|
|
7
9
|
* @throws {Error} If value is not a valid number format
|
|
8
|
-
*
|
|
9
10
|
* @example
|
|
10
11
|
* toCardinal(21) // 'enogtyve'
|
|
11
12
|
* toCardinal(1000) // 'ettusind'
|
|
@@ -14,12 +15,10 @@
|
|
|
14
15
|
export function toCardinal(value: number | string | bigint): string;
|
|
15
16
|
/**
|
|
16
17
|
* Converts a numeric value to Danish ordinal words.
|
|
17
|
-
*
|
|
18
18
|
* @param {number | string | bigint} value - The numeric value to convert (positive integer)
|
|
19
19
|
* @returns {string} The number as ordinal words
|
|
20
20
|
* @throws {TypeError} If value is not a valid numeric type
|
|
21
21
|
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
22
|
-
*
|
|
23
22
|
* @example
|
|
24
23
|
* toOrdinal(1) // 'første'
|
|
25
24
|
* toOrdinal(2) // 'anden'
|
|
@@ -30,12 +29,10 @@ export function toOrdinal(value: number | string | bigint): string;
|
|
|
30
29
|
* Converts a numeric value to Danish currency words (Danish Krone).
|
|
31
30
|
*
|
|
32
31
|
* Uses krone/kroner and øre (100 øre = 1 krone).
|
|
33
|
-
*
|
|
34
32
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
35
33
|
* @returns {string} The amount in Danish currency words
|
|
36
34
|
* @throws {TypeError} If value is not a valid numeric type
|
|
37
35
|
* @throws {Error} If value is not a valid number format
|
|
38
|
-
*
|
|
39
36
|
* @example
|
|
40
37
|
* toCurrency(1) // 'en krone'
|
|
41
38
|
* toCurrency(42) // 'toogfyrre kroner'
|