n2words 5.0.0 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +128 -42
- 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 +31 -22
- 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 +100 -38
- package/src/sr-Latn-RS.d.ts +35 -15
- package/src/sr-Latn-RS.js +100 -38
- package/src/sv-SE.d.ts +3 -6
- package/src/sv-SE.js +53 -34
- package/src/sw-KE.d.ts +3 -5
- package/src/sw-KE.js +50 -20
- package/src/ta-IN.d.ts +3 -5
- package/src/ta-IN.js +29 -17
- package/src/te-IN.d.ts +3 -5
- package/src/te-IN.js +31 -16
- package/src/th-TH.d.ts +3 -5
- package/src/th-TH.js +42 -19
- package/src/tr-TR.d.ts +17 -11
- package/src/tr-TR.js +63 -37
- package/src/uk-UA.d.ts +21 -10
- package/src/uk-UA.js +89 -33
- package/src/ur-PK.d.ts +3 -5
- package/src/ur-PK.js +32 -16
- package/src/utils/check-max.d.ts +26 -0
- package/src/utils/check-max.js +33 -0
- package/src/utils/expand-scientific.d.ts +0 -4
- package/src/utils/expand-scientific.js +7 -9
- package/src/utils/is-plain-object.d.ts +3 -4
- package/src/utils/is-plain-object.js +3 -4
- package/src/utils/parse-cardinal.d.ts +1 -2
- package/src/utils/parse-cardinal.js +12 -9
- package/src/utils/parse-currency.d.ts +1 -2
- package/src/utils/parse-currency.js +9 -11
- package/src/utils/parse-ordinal.d.ts +0 -1
- package/src/utils/parse-ordinal.js +9 -10
- package/src/utils/resolve-options.d.ts +17 -0
- package/src/utils/resolve-options.js +56 -0
- package/src/utils/scale.d.ts +49 -0
- package/src/utils/scale.js +65 -0
- package/src/vi-VN.d.ts +3 -6
- package/src/vi-VN.js +41 -28
- package/src/yo-NG.d.ts +3 -5
- package/src/yo-NG.js +49 -33
- package/src/zh-Hans-CN.d.ts +45 -20
- package/src/zh-Hans-CN.js +84 -31
- package/src/zh-Hant-TW.d.ts +45 -20
- package/src/zh-Hant-TW.js +85 -34
- package/src/utils/validate-options.d.ts +0 -8
- package/src/utils/validate-options.js +0 -16
package/src/th-TH.js
CHANGED
|
@@ -14,6 +14,14 @@
|
|
|
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 { UNBOUNDED } from './utils/scale.js'
|
|
18
|
+
|
|
19
|
+
// Thai spells large numbers by repeating ล้าน (10^6), so every form is
|
|
20
|
+
// magnitude-preserving with no fixed ceiling. Declared per form so the gate
|
|
21
|
+
// switches to its injectivity check and the docs read "no fixed limit".
|
|
22
|
+
export const cardinalMax = UNBOUNDED
|
|
23
|
+
export const ordinalMax = UNBOUNDED
|
|
24
|
+
export const currencyMax = UNBOUNDED
|
|
17
25
|
|
|
18
26
|
// ============================================================================
|
|
19
27
|
// Vocabulary
|
|
@@ -43,7 +51,11 @@ const BAHT_ONLY = 'ถ้วน' // "exactly" suffix when no satang
|
|
|
43
51
|
// Conversion Functions
|
|
44
52
|
// ============================================================================
|
|
45
53
|
|
|
46
|
-
|
|
54
|
+
/**
|
|
55
|
+
* @param {number} n A value below one million to convert.
|
|
56
|
+
* @returns {string} The number in Thai words.
|
|
57
|
+
*/
|
|
58
|
+
function convertBelowMillion(n) {
|
|
47
59
|
if (n === 0) return ''
|
|
48
60
|
|
|
49
61
|
let value = n
|
|
@@ -67,7 +79,8 @@ function convertBelowMillion (n) {
|
|
|
67
79
|
if (tenThousands > 0) {
|
|
68
80
|
if (tenThousands === 1) {
|
|
69
81
|
parts.push('หนึ่งหมื่น')
|
|
70
|
-
}
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
71
84
|
parts.push(ONES[tenThousands - 1] + 'หมื่น')
|
|
72
85
|
}
|
|
73
86
|
}
|
|
@@ -83,9 +96,11 @@ function convertBelowMillion (n) {
|
|
|
83
96
|
if (tens > 0) {
|
|
84
97
|
if (tens === 1) {
|
|
85
98
|
parts.push('สิบ')
|
|
86
|
-
}
|
|
99
|
+
}
|
|
100
|
+
else if (tens === 2) {
|
|
87
101
|
parts.push('ยี่สิบ')
|
|
88
|
-
}
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
89
104
|
parts.push(ONES[tens - 1] + 'สิบ')
|
|
90
105
|
}
|
|
91
106
|
}
|
|
@@ -94,7 +109,8 @@ function convertBelowMillion (n) {
|
|
|
94
109
|
const hasHigher = hundredThousands > 0 || tenThousands > 0 || thousands > 0 || hundreds > 0 || tens > 0
|
|
95
110
|
if (ones === 1 && (tens > 0 || hasHigher)) {
|
|
96
111
|
parts.push('เอ็ด')
|
|
97
|
-
}
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
98
114
|
parts.push(ONES[ones - 1])
|
|
99
115
|
}
|
|
100
116
|
}
|
|
@@ -102,7 +118,11 @@ function convertBelowMillion (n) {
|
|
|
102
118
|
return parts.join('')
|
|
103
119
|
}
|
|
104
120
|
|
|
105
|
-
|
|
121
|
+
/**
|
|
122
|
+
* @param {bigint} n The integer to split into million-based groups.
|
|
123
|
+
* @returns {number[]} The groups in most-significant-first order.
|
|
124
|
+
*/
|
|
125
|
+
function splitMillionGroups(n) {
|
|
106
126
|
const groups = []
|
|
107
127
|
let remaining = n
|
|
108
128
|
|
|
@@ -116,7 +136,11 @@ function splitMillionGroups (n) {
|
|
|
116
136
|
return groups
|
|
117
137
|
}
|
|
118
138
|
|
|
119
|
-
|
|
139
|
+
/**
|
|
140
|
+
* @param {bigint} n The integer to convert.
|
|
141
|
+
* @returns {string} The integer in Thai words.
|
|
142
|
+
*/
|
|
143
|
+
function integerToWords(n) {
|
|
120
144
|
if (n === 0n) return ZERO
|
|
121
145
|
|
|
122
146
|
const groups = splitMillionGroups(n)
|
|
@@ -136,7 +160,11 @@ function integerToWords (n) {
|
|
|
136
160
|
return parts.join('')
|
|
137
161
|
}
|
|
138
162
|
|
|
139
|
-
|
|
163
|
+
/**
|
|
164
|
+
* @param {string} decimalPart The fractional digits to read.
|
|
165
|
+
* @returns {string} The decimal digits in Thai words.
|
|
166
|
+
*/
|
|
167
|
+
function decimalPartToWords(decimalPart) {
|
|
140
168
|
// Per-digit decimal reading
|
|
141
169
|
const digits = []
|
|
142
170
|
for (const char of decimalPart) {
|
|
@@ -148,11 +176,10 @@ function decimalPartToWords (decimalPart) {
|
|
|
148
176
|
|
|
149
177
|
/**
|
|
150
178
|
* Converts a numeric value to Thai words.
|
|
151
|
-
*
|
|
152
179
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
153
180
|
* @returns {string} The number in Thai words
|
|
154
181
|
*/
|
|
155
|
-
function toCardinal
|
|
182
|
+
function toCardinal(value) {
|
|
156
183
|
const { isNegative, integerPart, decimalPart } = parseCardinalValue(value)
|
|
157
184
|
|
|
158
185
|
let result = ''
|
|
@@ -178,28 +205,25 @@ function toCardinal (value) {
|
|
|
178
205
|
* Converts a non-negative integer to Thai ordinal words.
|
|
179
206
|
*
|
|
180
207
|
* Thai ordinals use "ที่" prefix + cardinal number.
|
|
181
|
-
*
|
|
182
208
|
* @param {bigint} n - Positive integer to convert
|
|
183
209
|
* @returns {string} Thai ordinal words
|
|
184
210
|
*/
|
|
185
|
-
function integerToOrdinal
|
|
211
|
+
function integerToOrdinal(n) {
|
|
186
212
|
return ORDINAL_PREFIX + integerToWords(n)
|
|
187
213
|
}
|
|
188
214
|
|
|
189
215
|
/**
|
|
190
216
|
* Converts a numeric value to Thai ordinal words.
|
|
191
|
-
*
|
|
192
217
|
* @param {number | string | bigint} value - The numeric value to convert (positive integer)
|
|
193
218
|
* @returns {string} The number as ordinal words
|
|
194
219
|
* @throws {TypeError} If value is not a valid numeric type
|
|
195
220
|
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
196
|
-
*
|
|
197
221
|
* @example
|
|
198
222
|
* toOrdinal(1) // 'ที่หนึ่ง'
|
|
199
223
|
* toOrdinal(2) // 'ที่สอง'
|
|
200
224
|
* toOrdinal(10) // 'ที่สิบ'
|
|
201
225
|
*/
|
|
202
|
-
function toOrdinal
|
|
226
|
+
function toOrdinal(value) {
|
|
203
227
|
const integerPart = parseOrdinalValue(value)
|
|
204
228
|
return integerToOrdinal(integerPart)
|
|
205
229
|
}
|
|
@@ -213,18 +237,16 @@ function toOrdinal (value) {
|
|
|
213
237
|
*
|
|
214
238
|
* Thai Baht uses satang as subunit (100 satang = 1 baht).
|
|
215
239
|
* When whole amounts, adds "ถ้วน" (exactly) suffix.
|
|
216
|
-
*
|
|
217
240
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
218
241
|
* @returns {string} The amount in Thai currency words
|
|
219
242
|
* @throws {TypeError} If value is not a valid numeric type
|
|
220
243
|
* @throws {Error} If value is not a valid number format
|
|
221
|
-
*
|
|
222
244
|
* @example
|
|
223
245
|
* toCurrency(42) // 'สี่สิบสองบาทถ้วน'
|
|
224
246
|
* toCurrency(1.50) // 'หนึ่งบาทห้าสิบสตางค์'
|
|
225
247
|
* toCurrency(-5) // 'ลบห้าบาทถ้วน'
|
|
226
248
|
*/
|
|
227
|
-
function toCurrency
|
|
249
|
+
function toCurrency(value) {
|
|
228
250
|
const { isNegative, dollars: baht, cents: satang } = parseCurrencyValue(value)
|
|
229
251
|
|
|
230
252
|
let result = ''
|
|
@@ -240,7 +262,8 @@ function toCurrency (value) {
|
|
|
240
262
|
if (satang > 0n) {
|
|
241
263
|
result += integerToWords(satang)
|
|
242
264
|
result += SATANG
|
|
243
|
-
}
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
244
267
|
result += BAHT_ONLY
|
|
245
268
|
}
|
|
246
269
|
|
package/src/tr-TR.d.ts
CHANGED
|
@@ -1,29 +1,37 @@
|
|
|
1
|
+
export const cardinalMax: bigint;
|
|
2
|
+
export const ordinalMax: bigint;
|
|
3
|
+
export const currencyMax: bigint;
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {object} CardinalOptions
|
|
6
|
+
* @property {boolean} [dropSpaces] - Remove spaces for compound form
|
|
7
|
+
*/
|
|
8
|
+
/** @type {Required<CardinalOptions>} */
|
|
9
|
+
export const cardinalDefaults: Required<CardinalOptions>;
|
|
10
|
+
export type CardinalOptions = {
|
|
11
|
+
/**
|
|
12
|
+
* - Remove spaces for compound form
|
|
13
|
+
*/
|
|
14
|
+
dropSpaces?: boolean | undefined;
|
|
15
|
+
};
|
|
1
16
|
/**
|
|
2
17
|
* Converts a numeric value to Turkish words.
|
|
3
|
-
*
|
|
4
18
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
5
|
-
* @param {
|
|
6
|
-
* @param {boolean} [options.dropSpaces=false] - Remove spaces for compound form
|
|
19
|
+
* @param {CardinalOptions} [options] - Conversion options
|
|
7
20
|
* @returns {string} The number in Turkish words
|
|
8
21
|
* @throws {TypeError} If value is not a valid numeric type
|
|
9
22
|
* @throws {Error} If value is not a valid number format
|
|
10
|
-
*
|
|
11
23
|
* @example
|
|
12
24
|
* toCardinal(21) // 'yirmi bir'
|
|
13
25
|
* toCardinal(21, { dropSpaces: true }) // 'yirmibir'
|
|
14
26
|
* toCardinal(1000) // 'bin'
|
|
15
27
|
*/
|
|
16
|
-
export function toCardinal(value: number | string | bigint, options?:
|
|
17
|
-
dropSpaces?: boolean | undefined;
|
|
18
|
-
}): string;
|
|
28
|
+
export function toCardinal(value: number | string | bigint, options?: CardinalOptions): string;
|
|
19
29
|
/**
|
|
20
30
|
* Converts a numeric value to Turkish ordinal words.
|
|
21
|
-
*
|
|
22
31
|
* @param {number | string | bigint} value - The numeric value to convert (positive integer)
|
|
23
32
|
* @returns {string} The number as ordinal words
|
|
24
33
|
* @throws {TypeError} If value is not a valid numeric type
|
|
25
34
|
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
26
|
-
*
|
|
27
35
|
* @example
|
|
28
36
|
* toOrdinal(1) // 'birinci'
|
|
29
37
|
* toOrdinal(2) // 'ikinci'
|
|
@@ -34,12 +42,10 @@ export function toOrdinal(value: number | string | bigint): string;
|
|
|
34
42
|
* Converts a numeric value to Turkish currency words (Turkish Lira).
|
|
35
43
|
*
|
|
36
44
|
* Uses lira and kuruş (100 kuruş = 1 lira).
|
|
37
|
-
*
|
|
38
45
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
39
46
|
* @returns {string} The amount in Turkish currency words
|
|
40
47
|
* @throws {TypeError} If value is not a valid numeric type
|
|
41
48
|
* @throws {Error} If value is not a valid number format
|
|
42
|
-
*
|
|
43
49
|
* @example
|
|
44
50
|
* toCurrency(42) // 'kırk iki lira'
|
|
45
51
|
* toCurrency(1.50) // 'bir lira elli kuruş'
|
package/src/tr-TR.js
CHANGED
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
import { parseCardinalValue } from './utils/parse-cardinal.js'
|
|
13
13
|
import { parseCurrencyValue } from './utils/parse-currency.js'
|
|
14
14
|
import { parseOrdinalValue } from './utils/parse-ordinal.js'
|
|
15
|
-
import {
|
|
15
|
+
import { checkMax } from './utils/check-max.js'
|
|
16
|
+
import { western } from './utils/scale.js'
|
|
17
|
+
import { resolveOptions } from './utils/resolve-options.js'
|
|
16
18
|
|
|
17
19
|
// ============================================================================
|
|
18
20
|
// Vocabulary (module-level constants)
|
|
@@ -33,12 +35,23 @@ const DECIMAL_SEP = 'virgül'
|
|
|
33
35
|
// Short scale
|
|
34
36
|
const SCALES = ['milyon', 'milyar', 'trilyon', 'katrilyon', 'kentilyon']
|
|
35
37
|
|
|
38
|
+
// Supported magnitude ceiling (checked at the public entry points). SCALES is
|
|
39
|
+
// indexed [scaleIndex - 2] (units and thousands are separate), so segments are
|
|
40
|
+
// [units, thousands, then one per SCALES entry] -> the ceiling is
|
|
41
|
+
// 10^((SCALES.length + 2) * 3) = 10^21. Ordinal (integerToWords + suffix),
|
|
42
|
+
// currency, and the decimal all route through the cardinal builder, so all
|
|
43
|
+
// share the ceiling.
|
|
44
|
+
export const cardinalMax = western(SCALES.length + 1)
|
|
45
|
+
export const ordinalMax = western(SCALES.length + 1)
|
|
46
|
+
export const currencyMax = western(SCALES.length + 1)
|
|
47
|
+
|
|
36
48
|
// ============================================================================
|
|
37
49
|
// Ordinal Vocabulary
|
|
38
50
|
// ============================================================================
|
|
39
51
|
|
|
40
52
|
// Turkish ordinals use -(i/ı/u/ü)nci/ncı/ncu/ncü suffix with vowel harmony
|
|
41
53
|
// Special forms for 1-10
|
|
54
|
+
/** @type {Record<number, string>} */
|
|
42
55
|
const ORDINAL_SPECIAL = {
|
|
43
56
|
1: 'birinci',
|
|
44
57
|
2: 'ikinci',
|
|
@@ -49,7 +62,7 @@ const ORDINAL_SPECIAL = {
|
|
|
49
62
|
7: 'yedinci',
|
|
50
63
|
8: 'sekizinci',
|
|
51
64
|
9: 'dokuzuncu',
|
|
52
|
-
10: 'onuncu'
|
|
65
|
+
10: 'onuncu',
|
|
53
66
|
}
|
|
54
67
|
|
|
55
68
|
// ============================================================================
|
|
@@ -66,8 +79,11 @@ const KURUS = 'kuruş' // subunit (100 kuruş = 1 lira)
|
|
|
66
79
|
/**
|
|
67
80
|
* Builds segment word for 0-999.
|
|
68
81
|
* Omits "bir" before "yüz" (hundred).
|
|
82
|
+
* @param {number} n - Segment value (0-999)
|
|
83
|
+
* @param {string} [separator] - Separator between words
|
|
84
|
+
* @returns {string} Segment words
|
|
69
85
|
*/
|
|
70
|
-
function buildSegment
|
|
86
|
+
function buildSegment(n, separator = ' ') {
|
|
71
87
|
if (n === 0) return ''
|
|
72
88
|
|
|
73
89
|
const ones = n % 10
|
|
@@ -80,7 +96,8 @@ function buildSegment (n, separator = ' ') {
|
|
|
80
96
|
if (hundreds > 0) {
|
|
81
97
|
if (hundreds === 1) {
|
|
82
98
|
parts.push(HUNDRED)
|
|
83
|
-
}
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
84
101
|
parts.push(ONES[hundreds] + separator + HUNDRED)
|
|
85
102
|
}
|
|
86
103
|
}
|
|
@@ -90,13 +107,17 @@ function buildSegment (n, separator = ' ') {
|
|
|
90
107
|
|
|
91
108
|
if (tensOnes === 0) {
|
|
92
109
|
// Just hundreds
|
|
93
|
-
}
|
|
110
|
+
}
|
|
111
|
+
else if (tensOnes < 10) {
|
|
94
112
|
parts.push(ONES[ones])
|
|
95
|
-
}
|
|
113
|
+
}
|
|
114
|
+
else if (tensOnes < 20) {
|
|
96
115
|
parts.push(TEENS[ones].replace(' ', separator))
|
|
97
|
-
}
|
|
116
|
+
}
|
|
117
|
+
else if (ones === 0) {
|
|
98
118
|
parts.push(TENS[tens])
|
|
99
|
-
}
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
100
121
|
parts.push(TENS[tens] + separator + ONES[ones])
|
|
101
122
|
}
|
|
102
123
|
|
|
@@ -109,12 +130,11 @@ function buildSegment (n, separator = ' ') {
|
|
|
109
130
|
|
|
110
131
|
/**
|
|
111
132
|
* Converts a non-negative integer to Turkish words.
|
|
112
|
-
*
|
|
113
133
|
* @param {bigint} n - Non-negative integer to convert
|
|
114
|
-
* @param {
|
|
134
|
+
* @param {boolean} dropSpaces - Remove spaces for compound form
|
|
115
135
|
* @returns {string} Turkish words
|
|
116
136
|
*/
|
|
117
|
-
function integerToWords
|
|
137
|
+
function integerToWords(n, dropSpaces) {
|
|
118
138
|
if (n === 0n) return ZERO
|
|
119
139
|
|
|
120
140
|
const sep = dropSpaces ? '' : ' '
|
|
@@ -133,7 +153,8 @@ function integerToWords (n, dropSpaces) {
|
|
|
133
153
|
let result
|
|
134
154
|
if (thousands === 1) {
|
|
135
155
|
result = THOUSAND
|
|
136
|
-
}
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
137
158
|
result = buildSegment(thousands, sep) + sep + THOUSAND
|
|
138
159
|
}
|
|
139
160
|
|
|
@@ -150,12 +171,11 @@ function integerToWords (n, dropSpaces) {
|
|
|
150
171
|
|
|
151
172
|
/**
|
|
152
173
|
* Builds words for numbers >= 1,000,000.
|
|
153
|
-
*
|
|
154
174
|
* @param {bigint} n - Number >= 1,000,000
|
|
155
|
-
* @param {
|
|
175
|
+
* @param {boolean} dropSpaces - Remove spaces for compound form
|
|
156
176
|
* @returns {string} Turkish words
|
|
157
177
|
*/
|
|
158
|
-
function buildLargeNumberWords
|
|
178
|
+
function buildLargeNumberWords(n, dropSpaces) {
|
|
159
179
|
const sep = dropSpaces ? '' : ' '
|
|
160
180
|
|
|
161
181
|
const numStr = n.toString()
|
|
@@ -189,14 +209,17 @@ function buildLargeNumberWords (n, dropSpaces) {
|
|
|
189
209
|
if (scaleIndex === 0) {
|
|
190
210
|
// Units segment
|
|
191
211
|
parts.push(segmentWord)
|
|
192
|
-
}
|
|
212
|
+
}
|
|
213
|
+
else if (scaleIndex === 1) {
|
|
193
214
|
// Thousands - omit "bir" before bin
|
|
194
215
|
if (segment === 1) {
|
|
195
216
|
parts.push(THOUSAND)
|
|
196
|
-
}
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
197
219
|
parts.push(segmentWord + sep + THOUSAND)
|
|
198
220
|
}
|
|
199
|
-
}
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
200
223
|
// Millions+ - "bir" is kept before scale words
|
|
201
224
|
const scaleWord = SCALES[scaleIndex - 2]
|
|
202
225
|
parts.push(segmentWord + sep + scaleWord)
|
|
@@ -211,12 +234,11 @@ function buildLargeNumberWords (n, dropSpaces) {
|
|
|
211
234
|
|
|
212
235
|
/**
|
|
213
236
|
* Converts decimal digits to Turkish words.
|
|
214
|
-
*
|
|
215
237
|
* @param {string} decimalPart - Decimal digits (without the point)
|
|
216
|
-
* @param {
|
|
238
|
+
* @param {boolean} dropSpaces - Remove spaces for compound form
|
|
217
239
|
* @returns {string} Turkish words for decimal part
|
|
218
240
|
*/
|
|
219
|
-
function decimalPartToWords
|
|
241
|
+
function decimalPartToWords(decimalPart, dropSpaces) {
|
|
220
242
|
const sep = dropSpaces ? '' : ' '
|
|
221
243
|
let result = ''
|
|
222
244
|
|
|
@@ -238,27 +260,34 @@ function decimalPartToWords (decimalPart, dropSpaces) {
|
|
|
238
260
|
return result
|
|
239
261
|
}
|
|
240
262
|
|
|
263
|
+
/**
|
|
264
|
+
* @typedef {object} CardinalOptions
|
|
265
|
+
* @property {boolean} [dropSpaces] - Remove spaces for compound form
|
|
266
|
+
*/
|
|
267
|
+
|
|
268
|
+
/** @type {Required<CardinalOptions>} */
|
|
269
|
+
export const cardinalDefaults = { dropSpaces: false }
|
|
270
|
+
|
|
241
271
|
/**
|
|
242
272
|
* Converts a numeric value to Turkish words.
|
|
243
|
-
*
|
|
244
273
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
245
|
-
* @param {
|
|
246
|
-
* @param {boolean} [options.dropSpaces=false] - Remove spaces for compound form
|
|
274
|
+
* @param {CardinalOptions} [options] - Conversion options
|
|
247
275
|
* @returns {string} The number in Turkish words
|
|
248
276
|
* @throws {TypeError} If value is not a valid numeric type
|
|
249
277
|
* @throws {Error} If value is not a valid number format
|
|
250
|
-
*
|
|
251
278
|
* @example
|
|
252
279
|
* toCardinal(21) // 'yirmi bir'
|
|
253
280
|
* toCardinal(21, { dropSpaces: true }) // 'yirmibir'
|
|
254
281
|
* toCardinal(1000) // 'bin'
|
|
255
282
|
*/
|
|
256
|
-
function toCardinal
|
|
257
|
-
options = validateOptions(options)
|
|
283
|
+
function toCardinal(value, options) {
|
|
258
284
|
const { isNegative, integerPart, decimalPart } = parseCardinalValue(value)
|
|
285
|
+
// Both the integer part and the decimal's significant digits are spelled via
|
|
286
|
+
// the scale builder, so both must clear the ceiling.
|
|
287
|
+
checkMax(integerPart, cardinalMax, decimalPart)
|
|
259
288
|
|
|
260
289
|
// Apply option defaults
|
|
261
|
-
const { dropSpaces
|
|
290
|
+
const { dropSpaces } = resolveOptions(options, cardinalDefaults)
|
|
262
291
|
|
|
263
292
|
const sep = dropSpaces ? '' : ' '
|
|
264
293
|
let result = ''
|
|
@@ -285,7 +314,7 @@ function toCardinal (value, options) {
|
|
|
285
314
|
* @param {string} word - The cardinal word
|
|
286
315
|
* @returns {string} The appropriate suffix
|
|
287
316
|
*/
|
|
288
|
-
function getOrdinalSuffix
|
|
317
|
+
function getOrdinalSuffix(word) {
|
|
289
318
|
// Turkish vowel harmony: back vowels (a,ı,o,u) vs front vowels (e,i,ö,ü)
|
|
290
319
|
// Find last vowel to determine suffix
|
|
291
320
|
const backVowels = 'aıou'
|
|
@@ -313,11 +342,10 @@ function getOrdinalSuffix (word) {
|
|
|
313
342
|
*
|
|
314
343
|
* Turkish ordinals: birinci (1st), ikinci (2nd), üçüncü (3rd), etc.
|
|
315
344
|
* Uses vowel harmony for suffix selection.
|
|
316
|
-
*
|
|
317
345
|
* @param {bigint} n - Positive integer to convert
|
|
318
346
|
* @returns {string} Turkish ordinal words
|
|
319
347
|
*/
|
|
320
|
-
function integerToOrdinal
|
|
348
|
+
function integerToOrdinal(n) {
|
|
321
349
|
// Special forms for 1-10
|
|
322
350
|
if (n >= 1n && n <= 10n) {
|
|
323
351
|
return ORDINAL_SPECIAL[Number(n)]
|
|
@@ -331,19 +359,18 @@ function integerToOrdinal (n) {
|
|
|
331
359
|
|
|
332
360
|
/**
|
|
333
361
|
* Converts a numeric value to Turkish ordinal words.
|
|
334
|
-
*
|
|
335
362
|
* @param {number | string | bigint} value - The numeric value to convert (positive integer)
|
|
336
363
|
* @returns {string} The number as ordinal words
|
|
337
364
|
* @throws {TypeError} If value is not a valid numeric type
|
|
338
365
|
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
339
|
-
*
|
|
340
366
|
* @example
|
|
341
367
|
* toOrdinal(1) // 'birinci'
|
|
342
368
|
* toOrdinal(2) // 'ikinci'
|
|
343
369
|
* toOrdinal(21) // 'yirmibirinci'
|
|
344
370
|
*/
|
|
345
|
-
function toOrdinal
|
|
371
|
+
function toOrdinal(value) {
|
|
346
372
|
const integerPart = parseOrdinalValue(value)
|
|
373
|
+
checkMax(integerPart, ordinalMax)
|
|
347
374
|
return integerToOrdinal(integerPart)
|
|
348
375
|
}
|
|
349
376
|
|
|
@@ -355,19 +382,18 @@ function toOrdinal (value) {
|
|
|
355
382
|
* Converts a numeric value to Turkish currency words (Turkish Lira).
|
|
356
383
|
*
|
|
357
384
|
* Uses lira and kuruş (100 kuruş = 1 lira).
|
|
358
|
-
*
|
|
359
385
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
360
386
|
* @returns {string} The amount in Turkish currency words
|
|
361
387
|
* @throws {TypeError} If value is not a valid numeric type
|
|
362
388
|
* @throws {Error} If value is not a valid number format
|
|
363
|
-
*
|
|
364
389
|
* @example
|
|
365
390
|
* toCurrency(42) // 'kırk iki lira'
|
|
366
391
|
* toCurrency(1.50) // 'bir lira elli kuruş'
|
|
367
392
|
* toCurrency(-5) // 'eksi beş lira'
|
|
368
393
|
*/
|
|
369
|
-
function toCurrency
|
|
394
|
+
function toCurrency(value) {
|
|
370
395
|
const { isNegative, dollars: lira, cents: kurus } = parseCurrencyValue(value)
|
|
396
|
+
checkMax(lira, currencyMax)
|
|
371
397
|
|
|
372
398
|
let result = ''
|
|
373
399
|
if (isNegative) {
|
package/src/uk-UA.d.ts
CHANGED
|
@@ -1,22 +1,35 @@
|
|
|
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] - Grammatical gender
|
|
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
|
+
* - Grammatical gender
|
|
17
|
+
*/
|
|
18
|
+
gender?: "feminine" | "masculine" | undefined;
|
|
19
|
+
};
|
|
1
20
|
/**
|
|
2
21
|
* Converts a numeric value to Ukrainian words.
|
|
3
|
-
*
|
|
4
22
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
5
|
-
* @param {
|
|
6
|
-
* @param {('masculine'|'feminine')} [options.gender='masculine'] - Grammatical gender
|
|
23
|
+
* @param {CardinalOptions} [options] - Optional configuration
|
|
7
24
|
* @returns {string} The number in Ukrainian words
|
|
8
25
|
*/
|
|
9
|
-
export function toCardinal(value: number | string | bigint, options?:
|
|
10
|
-
gender?: "masculine" | "feminine" | undefined;
|
|
11
|
-
}): string;
|
|
26
|
+
export function toCardinal(value: number | string | bigint, options?: CardinalOptions): string;
|
|
12
27
|
/**
|
|
13
28
|
* Converts a numeric value to Ukrainian ordinal words (masculine nominative).
|
|
14
|
-
*
|
|
15
29
|
* @param {number | string | bigint} value - The numeric value to convert (must be a positive integer)
|
|
16
30
|
* @returns {string} The number as ordinal words
|
|
17
31
|
* @throws {TypeError} If value is not a valid numeric type
|
|
18
32
|
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
19
|
-
*
|
|
20
33
|
* @example
|
|
21
34
|
* toOrdinal(1) // 'перший'
|
|
22
35
|
* toOrdinal(2) // 'другий'
|
|
@@ -27,12 +40,10 @@ export function toCardinal(value: number | string | bigint, options?: {
|
|
|
27
40
|
export function toOrdinal(value: number | string | bigint): string;
|
|
28
41
|
/**
|
|
29
42
|
* Converts a numeric value to Ukrainian currency words (Hryvnia).
|
|
30
|
-
*
|
|
31
43
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
32
44
|
* @returns {string} The amount in Ukrainian currency words
|
|
33
45
|
* @throws {TypeError} If value is not a valid numeric type
|
|
34
46
|
* @throws {Error} If value is not a valid number format
|
|
35
|
-
*
|
|
36
47
|
* @example
|
|
37
48
|
* toCurrency(42) // 'сорок двi гривнi'
|
|
38
49
|
* toCurrency(1) // 'одна гривня'
|