n2words 2.0.0 → 3.0.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 +49 -0
- package/README.md +86 -188
- package/dist/languages/am-Latn.js +3 -0
- package/dist/languages/am-Latn.js.map +1 -0
- package/dist/languages/am.js +3 -0
- package/dist/languages/am.js.map +1 -0
- package/dist/languages/ar.js +3 -0
- package/dist/languages/ar.js.map +1 -0
- package/dist/languages/az.js +3 -0
- package/dist/languages/az.js.map +1 -0
- package/dist/languages/bn.js +3 -0
- package/dist/languages/bn.js.map +1 -0
- package/dist/languages/cs.js +3 -0
- package/dist/languages/cs.js.map +1 -0
- package/dist/languages/da.js +3 -0
- package/dist/languages/da.js.map +1 -0
- package/dist/languages/de.js +3 -0
- package/dist/languages/de.js.map +1 -0
- package/dist/languages/el.js +3 -0
- package/dist/languages/el.js.map +1 -0
- package/dist/languages/en.js +3 -0
- package/dist/languages/en.js.map +1 -0
- package/dist/languages/es.js +3 -0
- package/dist/languages/es.js.map +1 -0
- package/dist/languages/fa.js +3 -0
- package/dist/languages/fa.js.map +1 -0
- package/dist/languages/fi.js +3 -0
- package/dist/languages/fi.js.map +1 -0
- package/dist/languages/fil.js +3 -0
- package/dist/languages/fil.js.map +1 -0
- package/dist/languages/fr-BE.js +3 -0
- package/dist/languages/fr-BE.js.map +1 -0
- package/dist/languages/fr.js +3 -0
- package/dist/languages/fr.js.map +1 -0
- package/dist/languages/gu.js +3 -0
- package/dist/languages/gu.js.map +1 -0
- package/dist/languages/ha.js +3 -0
- package/dist/languages/ha.js.map +1 -0
- package/dist/languages/hbo.js +3 -0
- package/dist/languages/hbo.js.map +1 -0
- package/dist/languages/he.js +3 -0
- package/dist/languages/he.js.map +1 -0
- package/dist/languages/hi.js +3 -0
- package/dist/languages/hi.js.map +1 -0
- package/dist/languages/hr.js +3 -0
- package/dist/languages/hr.js.map +1 -0
- package/dist/languages/hu.js +3 -0
- package/dist/languages/hu.js.map +1 -0
- package/dist/languages/id.js +3 -0
- package/dist/languages/id.js.map +1 -0
- package/dist/languages/it.js +3 -0
- package/dist/languages/it.js.map +1 -0
- package/dist/languages/ja.js +3 -0
- package/dist/languages/ja.js.map +1 -0
- package/dist/languages/kn.js +3 -0
- package/dist/languages/kn.js.map +1 -0
- package/dist/languages/ko.js +3 -0
- package/dist/languages/ko.js.map +1 -0
- package/dist/languages/lt.js +3 -0
- package/dist/languages/lt.js.map +1 -0
- package/dist/languages/lv.js +3 -0
- package/dist/languages/lv.js.map +1 -0
- package/dist/languages/mr.js +3 -0
- package/dist/languages/mr.js.map +1 -0
- package/dist/languages/ms.js +3 -0
- package/dist/languages/ms.js.map +1 -0
- package/dist/languages/nb.js +3 -0
- package/dist/languages/nb.js.map +1 -0
- package/dist/languages/nl.js +3 -0
- package/dist/languages/nl.js.map +1 -0
- package/dist/languages/pa.js +3 -0
- package/dist/languages/pa.js.map +1 -0
- package/dist/languages/pl.js +3 -0
- package/dist/languages/pl.js.map +1 -0
- package/dist/languages/pt.js +3 -0
- package/dist/languages/pt.js.map +1 -0
- package/dist/languages/ro.js +3 -0
- package/dist/languages/ro.js.map +1 -0
- package/dist/languages/ru.js +3 -0
- package/dist/languages/ru.js.map +1 -0
- package/dist/languages/sr-Cyrl.js +3 -0
- package/dist/languages/sr-Cyrl.js.map +1 -0
- package/dist/languages/sr-Latn.js +3 -0
- package/dist/languages/sr-Latn.js.map +1 -0
- package/dist/languages/sv.js +3 -0
- package/dist/languages/sv.js.map +1 -0
- package/dist/languages/sw.js +3 -0
- package/dist/languages/sw.js.map +1 -0
- package/dist/languages/ta.js +3 -0
- package/dist/languages/ta.js.map +1 -0
- package/dist/languages/te.js +3 -0
- package/dist/languages/te.js.map +1 -0
- package/dist/languages/th.js +3 -0
- package/dist/languages/th.js.map +1 -0
- package/dist/languages/tr.js +3 -0
- package/dist/languages/tr.js.map +1 -0
- package/dist/languages/uk.js +3 -0
- package/dist/languages/uk.js.map +1 -0
- package/dist/languages/ur.js +3 -0
- package/dist/languages/ur.js.map +1 -0
- package/dist/languages/vi.js +3 -0
- package/dist/languages/vi.js.map +1 -0
- package/dist/languages/zh-Hans.js +3 -0
- package/dist/languages/zh-Hans.js.map +1 -0
- package/dist/languages/zh-Hant.js +3 -0
- package/dist/languages/zh-Hant.js.map +1 -0
- package/dist/n2words.js +2 -2
- package/dist/n2words.js.map +1 -1
- package/lib/languages/am-Latn.d.ts +7 -0
- package/lib/languages/am-Latn.js +164 -0
- package/lib/languages/am.d.ts +7 -0
- package/lib/languages/am.js +164 -0
- package/lib/languages/ar.d.ts +14 -27
- package/lib/languages/ar.js +175 -129
- package/lib/languages/az.d.ts +4 -9
- package/lib/languages/az.js +171 -37
- package/lib/languages/bn.d.ts +4 -8
- package/lib/languages/bn.js +138 -124
- package/lib/languages/cs.d.ts +15 -85
- package/lib/languages/cs.js +310 -114
- package/lib/languages/da.d.ts +11 -12
- package/lib/languages/da.js +276 -101
- package/lib/languages/de.d.ts +14 -11
- package/lib/languages/de.js +317 -86
- package/lib/languages/el.d.ts +11 -11
- package/lib/languages/el.js +231 -78
- package/lib/languages/en.d.ts +14 -13
- package/lib/languages/en.js +242 -72
- package/lib/languages/es.d.ts +18 -12
- package/lib/languages/es.js +317 -103
- package/lib/languages/fa.d.ts +4 -44
- package/lib/languages/fa.js +112 -122
- package/lib/languages/fi.d.ts +14 -0
- package/lib/languages/fi.js +245 -0
- package/lib/languages/fil.d.ts +4 -13
- package/lib/languages/fil.js +207 -106
- package/lib/languages/fr-BE.d.ts +8 -8
- package/lib/languages/fr-BE.js +294 -19
- package/lib/languages/fr.d.ts +18 -12
- package/lib/languages/fr.js +352 -89
- package/lib/languages/gu.d.ts +4 -8
- package/lib/languages/gu.js +130 -125
- package/lib/languages/ha.d.ts +7 -0
- package/lib/languages/ha.js +230 -0
- package/lib/languages/hbo.d.ts +10 -110
- package/lib/languages/hbo.js +263 -214
- package/lib/languages/he.d.ts +10 -77
- package/lib/languages/he.js +242 -172
- package/lib/languages/hi.d.ts +4 -8
- package/lib/languages/hi.js +138 -124
- package/lib/languages/hr.d.ts +8 -77
- package/lib/languages/hr.js +194 -89
- package/lib/languages/hu.d.ts +4 -19
- package/lib/languages/hu.js +198 -119
- package/lib/languages/id.d.ts +4 -34
- package/lib/languages/id.js +171 -129
- package/lib/languages/it.d.ts +16 -34
- package/lib/languages/it.js +339 -94
- package/lib/languages/ja.d.ts +14 -14
- package/lib/languages/ja.js +233 -111
- package/lib/languages/kn.d.ts +4 -8
- package/lib/languages/kn.js +130 -35
- package/lib/languages/ko.d.ts +11 -11
- package/lib/languages/ko.js +257 -49
- package/lib/languages/lt.d.ts +15 -67
- package/lib/languages/lt.js +296 -122
- package/lib/languages/lv.d.ts +15 -67
- package/lib/languages/lv.js +297 -106
- package/lib/languages/mr.d.ts +4 -8
- package/lib/languages/mr.js +130 -125
- package/lib/languages/ms.d.ts +4 -28
- package/lib/languages/ms.js +171 -116
- package/lib/languages/nb.d.ts +11 -9
- package/lib/languages/nb.js +282 -87
- package/lib/languages/nl.d.ts +23 -13
- package/lib/languages/nl.js +317 -133
- package/lib/languages/pa.d.ts +4 -8
- package/lib/languages/pa.js +156 -124
- package/lib/languages/pl.d.ts +19 -77
- package/lib/languages/pl.js +307 -87
- package/lib/languages/pt.d.ts +14 -26
- package/lib/languages/pt.js +286 -92
- package/lib/languages/ro.d.ts +15 -155
- package/lib/languages/ro.js +219 -235
- package/lib/languages/ru.d.ts +8 -82
- package/lib/languages/ru.js +222 -78
- package/lib/languages/sr-Cyrl.d.ts +8 -77
- package/lib/languages/sr-Cyrl.js +191 -89
- package/lib/languages/sr-Latn.d.ts +8 -77
- package/lib/languages/sr-Latn.js +191 -89
- package/lib/languages/sv.d.ts +11 -11
- package/lib/languages/sv.js +288 -74
- package/lib/languages/sw.d.ts +4 -36
- package/lib/languages/sw.js +133 -106
- package/lib/languages/ta.d.ts +4 -17
- package/lib/languages/ta.js +129 -201
- package/lib/languages/te.d.ts +4 -19
- package/lib/languages/te.js +141 -196
- package/lib/languages/th.d.ts +4 -14
- package/lib/languages/th.js +135 -91
- package/lib/languages/tr.d.ts +15 -9
- package/lib/languages/tr.js +256 -49
- package/lib/languages/uk.d.ts +8 -82
- package/lib/languages/uk.js +200 -78
- package/lib/languages/ur.d.ts +4 -8
- package/lib/languages/ur.js +156 -124
- package/lib/languages/vi.d.ts +14 -69
- package/lib/languages/vi.js +294 -125
- package/lib/languages/zh-Hans.d.ts +8 -18
- package/lib/languages/zh-Hans.js +163 -92
- package/lib/languages/zh-Hant.d.ts +8 -18
- package/lib/languages/zh-Hant.js +181 -90
- package/lib/n2words.d.ts +53 -209
- package/lib/n2words.js +111 -530
- package/lib/utils/is-plain-object.d.ts +13 -0
- package/lib/utils/is-plain-object.js +17 -0
- package/lib/utils/parse-numeric.d.ts +17 -0
- package/lib/utils/parse-numeric.js +108 -0
- package/lib/utils/validate-options.d.ts +8 -0
- package/lib/utils/validate-options.js +16 -0
- package/package.json +26 -14
- package/dist/ArabicConverter.js +0 -3
- package/dist/ArabicConverter.js.map +0 -1
- package/dist/AzerbaijaniConverter.js +0 -3
- package/dist/AzerbaijaniConverter.js.map +0 -1
- package/dist/BanglaConverter.js +0 -3
- package/dist/BanglaConverter.js.map +0 -1
- package/dist/BiblicalHebrewConverter.js +0 -3
- package/dist/BiblicalHebrewConverter.js.map +0 -1
- package/dist/CroatianConverter.js +0 -3
- package/dist/CroatianConverter.js.map +0 -1
- package/dist/CzechConverter.js +0 -3
- package/dist/CzechConverter.js.map +0 -1
- package/dist/DanishConverter.js +0 -3
- package/dist/DanishConverter.js.map +0 -1
- package/dist/DutchConverter.js +0 -3
- package/dist/DutchConverter.js.map +0 -1
- package/dist/EnglishConverter.js +0 -3
- package/dist/EnglishConverter.js.map +0 -1
- package/dist/FilipinoConverter.js +0 -3
- package/dist/FilipinoConverter.js.map +0 -1
- package/dist/FrenchBelgiumConverter.js +0 -3
- package/dist/FrenchBelgiumConverter.js.map +0 -1
- package/dist/FrenchConverter.js +0 -3
- package/dist/FrenchConverter.js.map +0 -1
- package/dist/GermanConverter.js +0 -3
- package/dist/GermanConverter.js.map +0 -1
- package/dist/GreekConverter.js +0 -3
- package/dist/GreekConverter.js.map +0 -1
- package/dist/GujaratiConverter.js +0 -3
- package/dist/GujaratiConverter.js.map +0 -1
- package/dist/HebrewConverter.js +0 -3
- package/dist/HebrewConverter.js.map +0 -1
- package/dist/HindiConverter.js +0 -3
- package/dist/HindiConverter.js.map +0 -1
- package/dist/HungarianConverter.js +0 -3
- package/dist/HungarianConverter.js.map +0 -1
- package/dist/IndonesianConverter.js +0 -3
- package/dist/IndonesianConverter.js.map +0 -1
- package/dist/ItalianConverter.js +0 -3
- package/dist/ItalianConverter.js.map +0 -1
- package/dist/JapaneseConverter.js +0 -3
- package/dist/JapaneseConverter.js.map +0 -1
- package/dist/KannadaConverter.js +0 -3
- package/dist/KannadaConverter.js.map +0 -1
- package/dist/KoreanConverter.js +0 -3
- package/dist/KoreanConverter.js.map +0 -1
- package/dist/LatvianConverter.js +0 -3
- package/dist/LatvianConverter.js.map +0 -1
- package/dist/LithuanianConverter.js +0 -3
- package/dist/LithuanianConverter.js.map +0 -1
- package/dist/MalayConverter.js +0 -3
- package/dist/MalayConverter.js.map +0 -1
- package/dist/MarathiConverter.js +0 -3
- package/dist/MarathiConverter.js.map +0 -1
- package/dist/NorwegianBokmalConverter.js +0 -3
- package/dist/NorwegianBokmalConverter.js.map +0 -1
- package/dist/PersianConverter.js +0 -3
- package/dist/PersianConverter.js.map +0 -1
- package/dist/PolishConverter.js +0 -3
- package/dist/PolishConverter.js.map +0 -1
- package/dist/PortugueseConverter.js +0 -3
- package/dist/PortugueseConverter.js.map +0 -1
- package/dist/PunjabiConverter.js +0 -3
- package/dist/PunjabiConverter.js.map +0 -1
- package/dist/RomanianConverter.js +0 -3
- package/dist/RomanianConverter.js.map +0 -1
- package/dist/RussianConverter.js +0 -3
- package/dist/RussianConverter.js.map +0 -1
- package/dist/SerbianCyrillicConverter.js +0 -3
- package/dist/SerbianCyrillicConverter.js.map +0 -1
- package/dist/SerbianLatinConverter.js +0 -3
- package/dist/SerbianLatinConverter.js.map +0 -1
- package/dist/SimplifiedChineseConverter.js +0 -3
- package/dist/SimplifiedChineseConverter.js.map +0 -1
- package/dist/SpanishConverter.js +0 -3
- package/dist/SpanishConverter.js.map +0 -1
- package/dist/SwahiliConverter.js +0 -3
- package/dist/SwahiliConverter.js.map +0 -1
- package/dist/SwedishConverter.js +0 -3
- package/dist/SwedishConverter.js.map +0 -1
- package/dist/TamilConverter.js +0 -3
- package/dist/TamilConverter.js.map +0 -1
- package/dist/TeluguConverter.js +0 -3
- package/dist/TeluguConverter.js.map +0 -1
- package/dist/ThaiConverter.js +0 -3
- package/dist/ThaiConverter.js.map +0 -1
- package/dist/TraditionalChineseConverter.js +0 -3
- package/dist/TraditionalChineseConverter.js.map +0 -1
- package/dist/TurkishConverter.js +0 -3
- package/dist/TurkishConverter.js.map +0 -1
- package/dist/UkrainianConverter.js +0 -3
- package/dist/UkrainianConverter.js.map +0 -1
- package/dist/UrduConverter.js +0 -3
- package/dist/UrduConverter.js.map +0 -1
- package/dist/VietnameseConverter.js +0 -3
- package/dist/VietnameseConverter.js.map +0 -1
- package/lib/classes/abstract-language.d.ts +0 -178
- package/lib/classes/abstract-language.js +0 -268
- package/lib/classes/greedy-scale-language.d.ts +0 -109
- package/lib/classes/greedy-scale-language.js +0 -201
- package/lib/classes/slavic-language.d.ts +0 -148
- package/lib/classes/slavic-language.js +0 -281
- package/lib/classes/south-asian-language.d.ts +0 -70
- package/lib/classes/south-asian-language.js +0 -154
- package/lib/classes/turkic-language.d.ts +0 -26
- package/lib/classes/turkic-language.js +0 -59
package/lib/languages/zh-Hans.js
CHANGED
|
@@ -1,111 +1,182 @@
|
|
|
1
|
-
import { GreedyScaleLanguage } from '../classes/greedy-scale-language.js'
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
|
-
* Simplified Chinese language converter
|
|
2
|
+
* Simplified Chinese language converter - Functional Implementation
|
|
3
|
+
*
|
|
4
|
+
* Self-contained converter for Simplified Chinese.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* -
|
|
6
|
+
* Key features:
|
|
7
|
+
* - Myriad-based (万, 亿) grouping - 4 digits
|
|
8
|
+
* - Formal (financial) vs common numerals
|
|
9
|
+
* - Zero insertion for skipped positions
|
|
8
10
|
* - No word separators (concatenated format)
|
|
9
|
-
* - Optional formal (financial) vs common numerals
|
|
10
11
|
*/
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
[2n, '二'],
|
|
59
|
-
[1n, '一'],
|
|
60
|
-
[0n, '零']
|
|
61
|
-
]
|
|
62
|
-
}
|
|
12
|
+
|
|
13
|
+
import { parseNumericValue } from '../utils/parse-numeric.js'
|
|
14
|
+
import { validateOptions } from '../utils/validate-options.js'
|
|
15
|
+
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// Vocabulary
|
|
18
|
+
// ============================================================================
|
|
19
|
+
|
|
20
|
+
// Common (everyday) numerals
|
|
21
|
+
const ONES_COMMON = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九']
|
|
22
|
+
const TEN_COMMON = '十'
|
|
23
|
+
const HUNDRED_COMMON = '百'
|
|
24
|
+
const THOUSAND_COMMON = '千'
|
|
25
|
+
|
|
26
|
+
// Formal (financial) numerals - harder to alter/forge
|
|
27
|
+
const ONES_FORMAL = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']
|
|
28
|
+
const TEN_FORMAL = '拾'
|
|
29
|
+
const HUNDRED_FORMAL = '佰'
|
|
30
|
+
const THOUSAND_FORMAL = '仟'
|
|
31
|
+
|
|
32
|
+
// Scale words
|
|
33
|
+
const WAN_WORD = '万' // 10,000
|
|
34
|
+
const YI_WORD = '亿' // 100,000,000
|
|
35
|
+
|
|
36
|
+
const ZERO = '零'
|
|
37
|
+
const NEGATIVE = '负'
|
|
38
|
+
const DECIMAL_SEP = '点'
|
|
39
|
+
|
|
40
|
+
// ============================================================================
|
|
41
|
+
// Conversion Functions
|
|
42
|
+
// ============================================================================
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Convert number below 万 (10,000) to words using direct string concatenation.
|
|
46
|
+
*/
|
|
47
|
+
function convertBelowWan (value, ones, ten, hundred, thousand) {
|
|
48
|
+
if (value === 0n) return ''
|
|
49
|
+
|
|
50
|
+
let result = ''
|
|
51
|
+
let needsZero = false
|
|
52
|
+
|
|
53
|
+
// Thousands (千)
|
|
54
|
+
const thousandsVal = value / 1000n
|
|
55
|
+
const thousandsRemainder = value % 1000n
|
|
56
|
+
if (thousandsVal > 0n) {
|
|
57
|
+
result = ones[Number(thousandsVal)] + thousand
|
|
58
|
+
needsZero = thousandsRemainder > 0n && thousandsRemainder < 100n
|
|
63
59
|
}
|
|
64
60
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
61
|
+
// Hundreds (百)
|
|
62
|
+
const hundredsVal = thousandsRemainder / 100n
|
|
63
|
+
const hundredsRemainder = thousandsRemainder % 100n
|
|
64
|
+
if (hundredsVal > 0n) {
|
|
65
|
+
if (needsZero) result += ZERO
|
|
66
|
+
result += ones[Number(hundredsVal)] + hundred
|
|
67
|
+
needsZero = hundredsRemainder > 0n && hundredsRemainder < 10n
|
|
68
|
+
} else if (thousandsVal > 0n && hundredsRemainder > 0n) {
|
|
69
|
+
needsZero = true
|
|
70
|
+
}
|
|
71
71
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
72
|
+
// Tens (十)
|
|
73
|
+
const tensVal = hundredsRemainder / 10n
|
|
74
|
+
const onesVal = hundredsRemainder % 10n
|
|
75
|
+
if (tensVal > 0n) {
|
|
76
|
+
if (needsZero) result += ZERO
|
|
77
|
+
result += ones[Number(tensVal)] + ten
|
|
78
|
+
needsZero = false
|
|
79
|
+
} else if ((hundredsVal > 0n || thousandsVal > 0n) && onesVal > 0n) {
|
|
80
|
+
needsZero = true
|
|
81
|
+
}
|
|
76
82
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
83
|
+
// Ones
|
|
84
|
+
if (onesVal > 0n) {
|
|
85
|
+
if (needsZero) result += ZERO
|
|
86
|
+
result += ones[Number(onesVal)]
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return result
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Convert number below 亿 (100 million) to words.
|
|
94
|
+
*/
|
|
95
|
+
function convertBelowYi (value, ones, ten, hundred, thousand) {
|
|
96
|
+
if (value === 0n) return ''
|
|
81
97
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
98
|
+
if (value >= 10_000n) {
|
|
99
|
+
const wanValue = value / 10_000n
|
|
100
|
+
const wanRemainder = value % 10_000n
|
|
101
|
+
|
|
102
|
+
let result = convertBelowWan(wanValue, ones, ten, hundred, thousand) + WAN_WORD
|
|
103
|
+
|
|
104
|
+
if (wanRemainder > 0n) {
|
|
105
|
+
const needsZero = (wanValue % 10n === 0n) || (wanRemainder < 1000n)
|
|
106
|
+
if (needsZero) result += ZERO
|
|
107
|
+
result += convertBelowWan(wanRemainder, ones, ten, hundred, thousand)
|
|
86
108
|
}
|
|
87
109
|
|
|
88
|
-
|
|
89
|
-
return { [`${precedingWord}${followingWord}`]: precedingValue + followingValue }
|
|
110
|
+
return result
|
|
90
111
|
}
|
|
91
112
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
113
|
+
return convertBelowWan(value, ones, ten, hundred, thousand)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function integerToWords (n, formal = true) {
|
|
117
|
+
if (n === 0n) return ZERO
|
|
118
|
+
|
|
119
|
+
const ones = formal ? ONES_FORMAL : ONES_COMMON
|
|
120
|
+
const ten = formal ? TEN_FORMAL : TEN_COMMON
|
|
121
|
+
const hundred = formal ? HUNDRED_FORMAL : HUNDRED_COMMON
|
|
122
|
+
const thousand = formal ? THOUSAND_FORMAL : THOUSAND_COMMON
|
|
123
|
+
|
|
124
|
+
// Handle numbers >= 亿 (100 million)
|
|
125
|
+
if (n >= 100_000_000n) {
|
|
126
|
+
const yiValue = n / 100_000_000n
|
|
127
|
+
const yiRemainder = n % 100_000_000n
|
|
128
|
+
|
|
129
|
+
let result = convertBelowYi(yiValue, ones, ten, hundred, thousand) + YI_WORD
|
|
130
|
+
|
|
131
|
+
if (yiRemainder > 0n) {
|
|
132
|
+
if (yiRemainder < 10_000_000n) result += ZERO
|
|
133
|
+
result += convertBelowYi(yiRemainder, ones, ten, hundred, thousand)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return result
|
|
95
137
|
}
|
|
96
138
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
139
|
+
return convertBelowYi(n, ones, ten, hundred, thousand)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Convert decimal digits to words using direct concatenation.
|
|
144
|
+
*/
|
|
145
|
+
function decimalDigitsToWords (decimalString, ones) {
|
|
146
|
+
let result = ''
|
|
147
|
+
for (let i = 0; i < decimalString.length; i++) {
|
|
148
|
+
result += ones[Number(decimalString[i])]
|
|
100
149
|
}
|
|
150
|
+
return result
|
|
151
|
+
}
|
|
101
152
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
153
|
+
/**
|
|
154
|
+
* Converts a numeric value to Simplified Chinese words.
|
|
155
|
+
*
|
|
156
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
157
|
+
* @param {Object} [options] - Optional configuration
|
|
158
|
+
* @param {boolean} [options.formal=true] - Use formal/financial numerals
|
|
159
|
+
* @returns {string} The number in Simplified Chinese words
|
|
160
|
+
*/
|
|
161
|
+
function toWords (value, options) {
|
|
162
|
+
options = validateOptions(options)
|
|
163
|
+
const { isNegative, integerPart, decimalPart } = parseNumericValue(value)
|
|
164
|
+
const formal = options.formal !== false // Default to true
|
|
165
|
+
|
|
166
|
+
let result = isNegative ? NEGATIVE : ''
|
|
167
|
+
|
|
168
|
+
result += integerToWords(integerPart, formal)
|
|
169
|
+
|
|
170
|
+
if (decimalPart) {
|
|
171
|
+
const ones = formal ? ONES_FORMAL : ONES_COMMON
|
|
172
|
+
result += DECIMAL_SEP + decimalDigitsToWords(decimalPart, ones)
|
|
110
173
|
}
|
|
174
|
+
|
|
175
|
+
return result
|
|
111
176
|
}
|
|
177
|
+
|
|
178
|
+
// ============================================================================
|
|
179
|
+
// Exports
|
|
180
|
+
// ============================================================================
|
|
181
|
+
|
|
182
|
+
export { toWords }
|
|
@@ -1,21 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Traditional Chinese
|
|
2
|
+
* Converts a numeric value to Traditional Chinese words.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
5
|
+
* @param {Object} [options] - Optional configuration
|
|
6
|
+
* @param {boolean} [options.formal=true] - Use formal/financial numerals
|
|
7
|
+
* @returns {string} The number in Traditional Chinese words
|
|
8
8
|
*/
|
|
9
|
-
export
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
/** Combines two word-sets with Traditional Chinese grammar rules and zero insertion. */
|
|
13
|
-
combineWordSets(preceding: any, following: any): any;
|
|
14
|
-
/** Returns the number of digits in a number. */
|
|
15
|
-
digit(number_: any): any;
|
|
16
|
-
/** Counts the number of zero digits in a number. */
|
|
17
|
-
zeroDigit(number_: any): number;
|
|
18
|
-
/** Converts decimal digits to words by reading each digit individually. */
|
|
19
|
-
decimalDigitsToWords(decimalString: any): string[];
|
|
20
|
-
}
|
|
21
|
-
import { GreedyScaleLanguage } from '../classes/greedy-scale-language.js';
|
|
9
|
+
export function toWords(value: number | string | bigint, options?: {
|
|
10
|
+
formal?: boolean | undefined;
|
|
11
|
+
}): string;
|
package/lib/languages/zh-Hant.js
CHANGED
|
@@ -1,111 +1,202 @@
|
|
|
1
|
-
import { GreedyScaleLanguage } from '../classes/greedy-scale-language.js'
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
|
-
* Traditional Chinese language converter
|
|
2
|
+
* Traditional Chinese language converter - Functional Implementation
|
|
3
|
+
*
|
|
4
|
+
* Self-contained converter for Traditional Chinese.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* -
|
|
6
|
+
* Key features:
|
|
7
|
+
* - Myriad-based (萬, 億) grouping - 4 digits
|
|
8
|
+
* - Formal (financial) vs common numerals
|
|
9
|
+
* - Zero insertion for skipped positions
|
|
8
10
|
* - No word separators (concatenated format)
|
|
9
|
-
*
|
|
11
|
+
*
|
|
12
|
+
* Differences from Simplified:
|
|
13
|
+
* - Different character forms (e.g., 負/负, 點/点, 億/亿, 萬/万)
|
|
14
|
+
* - Some formal numerals differ (參/叁, 貳/贰, 陸/陆)
|
|
10
15
|
*/
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
16
|
+
|
|
17
|
+
import { parseNumericValue } from '../utils/parse-numeric.js'
|
|
18
|
+
import { validateOptions } from '../utils/validate-options.js'
|
|
19
|
+
|
|
20
|
+
// ============================================================================
|
|
21
|
+
// Vocabulary
|
|
22
|
+
// ============================================================================
|
|
23
|
+
|
|
24
|
+
// Common (everyday) numerals - Traditional forms
|
|
25
|
+
const ONES_COMMON = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九']
|
|
26
|
+
const TEN_COMMON = '十'
|
|
27
|
+
const HUNDRED_COMMON = '百'
|
|
28
|
+
const THOUSAND_COMMON = '千'
|
|
29
|
+
|
|
30
|
+
// Formal (financial) numerals - Traditional forms
|
|
31
|
+
const ONES_FORMAL = ['零', '壹', '貳', '參', '肆', '伍', '陸', '柒', '捌', '玖']
|
|
32
|
+
const TEN_FORMAL = '拾'
|
|
33
|
+
const HUNDRED_FORMAL = '佰'
|
|
34
|
+
const THOUSAND_FORMAL = '仟'
|
|
35
|
+
|
|
36
|
+
// Scale words - Traditional forms
|
|
37
|
+
const WAN_WORD = '萬' // 10,000
|
|
38
|
+
const YI_WORD = '億' // 100,000,000
|
|
39
|
+
|
|
40
|
+
const ZERO = '零'
|
|
41
|
+
const NEGATIVE = '負'
|
|
42
|
+
const DECIMAL_SEP = '點'
|
|
43
|
+
|
|
44
|
+
// ============================================================================
|
|
45
|
+
// Conversion Functions
|
|
46
|
+
// ============================================================================
|
|
47
|
+
|
|
48
|
+
function integerToWords (n, formal = true) {
|
|
49
|
+
if (n === 0n) return ZERO
|
|
50
|
+
|
|
51
|
+
const ones = formal ? ONES_FORMAL : ONES_COMMON
|
|
52
|
+
const ten = formal ? TEN_FORMAL : TEN_COMMON
|
|
53
|
+
const hundred = formal ? HUNDRED_FORMAL : HUNDRED_COMMON
|
|
54
|
+
const thousand = formal ? THOUSAND_FORMAL : THOUSAND_COMMON
|
|
55
|
+
|
|
56
|
+
// Convert number below 萬 (10,000)
|
|
57
|
+
function convertBelowWan (value) {
|
|
58
|
+
if (value === 0n) return ''
|
|
59
|
+
|
|
60
|
+
const parts = []
|
|
61
|
+
let needsZero = false
|
|
62
|
+
|
|
63
|
+
// Thousands (千)
|
|
64
|
+
const thousandsVal = value / 1000n
|
|
65
|
+
const thousandsRemainder = value % 1000n
|
|
66
|
+
if (thousandsVal > 0n) {
|
|
67
|
+
parts.push(ones[Number(thousandsVal)] + thousand)
|
|
68
|
+
needsZero = thousandsRemainder > 0n && thousandsRemainder < 100n
|
|
62
69
|
}
|
|
63
|
-
}
|
|
64
70
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
+
// Hundreds (百)
|
|
72
|
+
const hundredsVal = thousandsRemainder / 100n
|
|
73
|
+
const hundredsRemainder = thousandsRemainder % 100n
|
|
74
|
+
if (hundredsVal > 0n) {
|
|
75
|
+
if (needsZero) {
|
|
76
|
+
parts.push(ZERO)
|
|
77
|
+
needsZero = false
|
|
78
|
+
}
|
|
79
|
+
parts.push(ones[Number(hundredsVal)] + hundred)
|
|
80
|
+
needsZero = hundredsRemainder > 0n && hundredsRemainder < 10n
|
|
81
|
+
} else if (thousandsVal > 0n && hundredsRemainder > 0n) {
|
|
82
|
+
needsZero = true
|
|
83
|
+
}
|
|
71
84
|
|
|
72
|
-
//
|
|
73
|
-
|
|
74
|
-
|
|
85
|
+
// Tens (十)
|
|
86
|
+
const tensVal = hundredsRemainder / 10n
|
|
87
|
+
const onesVal = hundredsRemainder % 10n
|
|
88
|
+
if (tensVal > 0n) {
|
|
89
|
+
if (needsZero) {
|
|
90
|
+
parts.push(ZERO)
|
|
91
|
+
needsZero = false
|
|
92
|
+
}
|
|
93
|
+
parts.push(ones[Number(tensVal)] + ten)
|
|
94
|
+
} else if ((hundredsVal > 0n || thousandsVal > 0n) && onesVal > 0n) {
|
|
95
|
+
needsZero = true
|
|
75
96
|
}
|
|
76
97
|
|
|
77
|
-
//
|
|
78
|
-
if (
|
|
79
|
-
|
|
98
|
+
// Ones
|
|
99
|
+
if (onesVal > 0n) {
|
|
100
|
+
if (needsZero) {
|
|
101
|
+
parts.push(ZERO)
|
|
102
|
+
}
|
|
103
|
+
parts.push(ones[Number(onesVal)])
|
|
80
104
|
}
|
|
81
105
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
106
|
+
return parts.join('')
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Convert number below 億 (100 million)
|
|
110
|
+
function convertBelowYi (value) {
|
|
111
|
+
if (value === 0n) return ''
|
|
112
|
+
|
|
113
|
+
const parts = []
|
|
114
|
+
|
|
115
|
+
if (value >= 10_000n) {
|
|
116
|
+
const wanValue = value / 10_000n
|
|
117
|
+
const wanRemainder = value % 10_000n
|
|
118
|
+
|
|
119
|
+
parts.push(convertBelowWan(wanValue) + WAN_WORD)
|
|
120
|
+
|
|
121
|
+
if (wanRemainder > 0n) {
|
|
122
|
+
const wanEndsWithZero = wanValue % 10n === 0n
|
|
123
|
+
const remainderMissesThousands = wanRemainder < 1000n
|
|
124
|
+
const needsZero = wanEndsWithZero || remainderMissesThousands
|
|
125
|
+
if (needsZero) {
|
|
126
|
+
parts.push(ZERO)
|
|
127
|
+
}
|
|
128
|
+
parts.push(convertBelowWan(wanRemainder))
|
|
129
|
+
}
|
|
130
|
+
} else {
|
|
131
|
+
parts.push(convertBelowWan(value))
|
|
86
132
|
}
|
|
87
133
|
|
|
88
|
-
|
|
89
|
-
return { [`${precedingWord}${followingWord}`]: precedingValue + followingValue }
|
|
134
|
+
return parts.join('')
|
|
90
135
|
}
|
|
91
136
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
137
|
+
// Main conversion
|
|
138
|
+
const parts = []
|
|
139
|
+
|
|
140
|
+
if (n >= 100_000_000n) {
|
|
141
|
+
const yiValue = n / 100_000_000n
|
|
142
|
+
const yiRemainder = n % 100_000_000n
|
|
143
|
+
|
|
144
|
+
const yiWords = convertBelowYi(yiValue)
|
|
145
|
+
parts.push(yiWords + YI_WORD)
|
|
146
|
+
|
|
147
|
+
if (yiRemainder > 0n) {
|
|
148
|
+
const needsZero = yiRemainder < 10_000_000n
|
|
149
|
+
if (needsZero) {
|
|
150
|
+
parts.push(ZERO)
|
|
151
|
+
}
|
|
152
|
+
parts.push(convertBelowYi(yiRemainder))
|
|
153
|
+
}
|
|
154
|
+
} else {
|
|
155
|
+
parts.push(convertBelowYi(n))
|
|
95
156
|
}
|
|
96
157
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
158
|
+
return parts.join('')
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function decimalDigitsToWords (decimalString, formal = true) {
|
|
162
|
+
const ones = formal ? ONES_FORMAL : ONES_COMMON
|
|
163
|
+
const words = []
|
|
164
|
+
for (const char of decimalString) {
|
|
165
|
+
words.push(ones[Number(char)])
|
|
100
166
|
}
|
|
167
|
+
return words
|
|
168
|
+
}
|
|
101
169
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
170
|
+
/**
|
|
171
|
+
* Converts a numeric value to Traditional Chinese words.
|
|
172
|
+
*
|
|
173
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
174
|
+
* @param {Object} [options] - Optional configuration
|
|
175
|
+
* @param {boolean} [options.formal=true] - Use formal/financial numerals
|
|
176
|
+
* @returns {string} The number in Traditional Chinese words
|
|
177
|
+
*/
|
|
178
|
+
function toWords (value, options) {
|
|
179
|
+
options = validateOptions(options)
|
|
180
|
+
const { isNegative, integerPart, decimalPart } = parseNumericValue(value)
|
|
181
|
+
const formal = options.formal !== false // Default to true
|
|
182
|
+
|
|
183
|
+
let result = ''
|
|
184
|
+
|
|
185
|
+
if (isNegative) {
|
|
186
|
+
result = NEGATIVE
|
|
110
187
|
}
|
|
188
|
+
|
|
189
|
+
result += integerToWords(integerPart, formal)
|
|
190
|
+
|
|
191
|
+
if (decimalPart) {
|
|
192
|
+
result += DECIMAL_SEP + decimalDigitsToWords(decimalPart, formal).join('')
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return result
|
|
111
196
|
}
|
|
197
|
+
|
|
198
|
+
// ============================================================================
|
|
199
|
+
// Exports
|
|
200
|
+
// ============================================================================
|
|
201
|
+
|
|
202
|
+
export { toWords }
|