n2words 2.0.0 → 3.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 +64 -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/ka.js +3 -0
- package/dist/languages/ka.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/yo.js +3 -0
- package/dist/languages/yo.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 +159 -0
- package/lib/languages/am.d.ts +7 -0
- package/lib/languages/am.js +159 -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 +166 -37
- package/lib/languages/bn.d.ts +4 -8
- package/lib/languages/bn.js +159 -124
- package/lib/languages/cs.d.ts +15 -85
- package/lib/languages/cs.js +293 -114
- package/lib/languages/da.d.ts +11 -12
- package/lib/languages/da.js +269 -101
- package/lib/languages/de.d.ts +14 -11
- package/lib/languages/de.js +305 -86
- package/lib/languages/el.d.ts +11 -11
- package/lib/languages/el.js +224 -78
- package/lib/languages/en.d.ts +14 -13
- package/lib/languages/en.js +228 -72
- package/lib/languages/es.d.ts +18 -12
- package/lib/languages/es.js +297 -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 +238 -0
- package/lib/languages/fil.d.ts +4 -13
- package/lib/languages/fil.js +196 -106
- package/lib/languages/fr-BE.d.ts +8 -8
- package/lib/languages/fr-BE.js +285 -19
- package/lib/languages/fr.d.ts +18 -12
- package/lib/languages/fr.js +339 -89
- package/lib/languages/gu.d.ts +4 -8
- package/lib/languages/gu.js +143 -125
- package/lib/languages/ha.d.ts +7 -0
- package/lib/languages/ha.js +225 -0
- package/lib/languages/hbo.d.ts +10 -110
- package/lib/languages/hbo.js +245 -214
- package/lib/languages/he.d.ts +10 -77
- package/lib/languages/he.js +231 -172
- package/lib/languages/hi.d.ts +4 -8
- package/lib/languages/hi.js +163 -124
- package/lib/languages/hr.d.ts +8 -77
- package/lib/languages/hr.js +200 -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 +166 -129
- package/lib/languages/it.d.ts +16 -34
- package/lib/languages/it.js +307 -97
- package/lib/languages/ja.d.ts +14 -14
- package/lib/languages/ja.js +221 -111
- package/lib/languages/ka.d.ts +17 -0
- package/lib/languages/ka.js +291 -0
- package/lib/languages/kn.d.ts +4 -8
- package/lib/languages/kn.js +143 -35
- package/lib/languages/ko.d.ts +11 -11
- package/lib/languages/ko.js +250 -49
- package/lib/languages/lt.d.ts +15 -67
- package/lib/languages/lt.js +287 -122
- package/lib/languages/lv.d.ts +15 -67
- package/lib/languages/lv.js +288 -106
- package/lib/languages/mr.d.ts +4 -8
- package/lib/languages/mr.js +143 -125
- package/lib/languages/ms.d.ts +4 -28
- package/lib/languages/ms.js +166 -116
- package/lib/languages/nb.d.ts +11 -9
- package/lib/languages/nb.js +272 -87
- package/lib/languages/nl.d.ts +23 -13
- package/lib/languages/nl.js +299 -133
- package/lib/languages/pa.d.ts +4 -8
- package/lib/languages/pa.js +151 -124
- package/lib/languages/pl.d.ts +19 -77
- package/lib/languages/pl.js +294 -87
- package/lib/languages/pt.d.ts +14 -26
- package/lib/languages/pt.js +272 -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 +239 -90
- package/lib/languages/sr-Cyrl.d.ts +8 -77
- package/lib/languages/sr-Cyrl.js +197 -89
- package/lib/languages/sr-Latn.d.ts +8 -77
- package/lib/languages/sr-Latn.js +197 -89
- package/lib/languages/sv.d.ts +11 -11
- package/lib/languages/sv.js +278 -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 +143 -202
- package/lib/languages/te.d.ts +4 -19
- package/lib/languages/te.js +133 -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 +245 -49
- package/lib/languages/uk.d.ts +8 -82
- package/lib/languages/uk.js +206 -78
- package/lib/languages/ur.d.ts +4 -8
- package/lib/languages/ur.js +151 -124
- package/lib/languages/vi.d.ts +14 -69
- package/lib/languages/vi.js +278 -129
- package/lib/languages/yo.d.ts +7 -0
- package/lib/languages/yo.js +303 -0
- 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 +55 -209
- package/lib/n2words.js +115 -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/ja.js
CHANGED
|
@@ -1,137 +1,247 @@
|
|
|
1
|
-
import { AbstractLanguage } from '../classes/abstract-language.js'
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
|
-
* Japanese language converter
|
|
2
|
+
* Japanese language converter - Functional Implementation
|
|
3
|
+
*
|
|
4
|
+
* Self-contained module with its own input validation, ready for subpath exports.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* -
|
|
8
|
-
* -
|
|
9
|
-
* -
|
|
6
|
+
* Japanese-specific rules:
|
|
7
|
+
* - Myriad (万-based) grouping: 4 digits per segment instead of 3
|
|
8
|
+
* - 一 omission: Omit "一" before 十, 百, 千 but NOT before 万 and higher scales
|
|
9
|
+
* - Kanji numerals: 零一二三四五六七八九
|
|
10
|
+
* - No spaces between characters
|
|
10
11
|
*/
|
|
11
|
-
export class Japanese extends AbstractLanguage {
|
|
12
|
-
negativeWord = 'マイナス'
|
|
13
|
-
decimalSeparatorWord = '点'
|
|
14
|
-
zeroWord = '零'
|
|
15
|
-
wordSeparator = '' // Japanese doesn't use spaces between characters
|
|
16
|
-
usePerDigitDecimals = true // Enable digit-by-digit decimal conversion
|
|
17
|
-
|
|
18
|
-
// Ones words used for group conversion (1-9)
|
|
19
|
-
onesWords = ['一', '二', '三', '四', '五', '六', '七', '八', '九']
|
|
20
|
-
|
|
21
|
-
// Scale words for grouping by 10^4
|
|
22
|
-
scaleWords = [
|
|
23
|
-
'', // 10^0 (ones)
|
|
24
|
-
'万', // 10^4 (man)
|
|
25
|
-
'億', // 10^8 (oku)
|
|
26
|
-
'兆', // 10^12 (chō)
|
|
27
|
-
'京', // 10^16 (kei)
|
|
28
|
-
'垓', // 10^20 (gai)
|
|
29
|
-
'秭', // 10^24 (jo/shi)
|
|
30
|
-
'穣', // 10^28 (jō)
|
|
31
|
-
'溝', // 10^32 (kō)
|
|
32
|
-
'澗', // 10^36 (kan)
|
|
33
|
-
'正', // 10^40 (sei)
|
|
34
|
-
'載', // 10^44 (sai)
|
|
35
|
-
'極', // 10^48 (goku)
|
|
36
|
-
'恒河沙', // 10^52 (gōgasha)
|
|
37
|
-
'阿僧祇', // 10^56 (asōgi)
|
|
38
|
-
'那由他', // 10^60 (nayuta)
|
|
39
|
-
'不可思議', // 10^64 (fukashigi)
|
|
40
|
-
'無量大数' // 10^68 (muryōtaisū)
|
|
41
|
-
]
|
|
42
|
-
|
|
43
|
-
/** Converts a segment of up to 4 digits to Japanese kanji with 一 omission rules. */
|
|
44
|
-
segmentToWords (num) {
|
|
45
|
-
if (num === 0n) return ''
|
|
46
|
-
|
|
47
|
-
const thousands = num / 1000n
|
|
48
|
-
const hundreds = (num % 1000n) / 100n
|
|
49
|
-
const tens = (num % 100n) / 10n
|
|
50
|
-
const ones = num % 10n
|
|
51
|
-
|
|
52
|
-
let result = ''
|
|
53
|
-
|
|
54
|
-
// Thousands (千)
|
|
55
|
-
if (thousands > 0n) {
|
|
56
|
-
// Always omit 一 before 千 when thousands === 1
|
|
57
|
-
if (thousands === 1n) {
|
|
58
|
-
result += '千'
|
|
59
|
-
} else {
|
|
60
|
-
result += this.onesWords[Number(thousands) - 1] + '千'
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
12
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
13
|
+
import { parseNumericValue } from '../utils/parse-numeric.js'
|
|
14
|
+
|
|
15
|
+
// ============================================================================
|
|
16
|
+
// Vocabulary (module-level constants)
|
|
17
|
+
// ============================================================================
|
|
18
|
+
|
|
19
|
+
// Ones words (1-9), index 0 unused
|
|
20
|
+
const ONES = ['', '一', '二', '三', '四', '五', '六', '七', '八', '九']
|
|
21
|
+
|
|
22
|
+
// Scale words for powers of 10,000 (万-based system)
|
|
23
|
+
// Index 0 = 万 (10^4), 1 = 億 (10^8), 2 = 兆 (10^12), etc.
|
|
24
|
+
const SCALES = [
|
|
25
|
+
'万', // 10^4 (man)
|
|
26
|
+
'億', // 10^8 (oku)
|
|
27
|
+
'兆', // 10^12 (chō)
|
|
28
|
+
'京', // 10^16 (kei)
|
|
29
|
+
'垓', // 10^20 (gai)
|
|
30
|
+
'秭', // 10^24 (jo/shi)
|
|
31
|
+
'穣', // 10^28 (jō)
|
|
32
|
+
'溝', // 10^32 (kō)
|
|
33
|
+
'澗', // 10^36 (kan)
|
|
34
|
+
'正', // 10^40 (sei)
|
|
35
|
+
'載', // 10^44 (sai)
|
|
36
|
+
'極', // 10^48 (goku)
|
|
37
|
+
'恒河沙', // 10^52 (gōgasha)
|
|
38
|
+
'阿僧祇', // 10^56 (asōgi)
|
|
39
|
+
'那由他', // 10^60 (nayuta)
|
|
40
|
+
'不可思議', // 10^64 (fukashigi)
|
|
41
|
+
'無量大数' // 10^68 (muryōtaisū)
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
const ZERO = '零'
|
|
45
|
+
const NEGATIVE = 'マイナス'
|
|
46
|
+
const DECIMAL_SEP = '点'
|
|
47
|
+
|
|
48
|
+
// Internal scale words (within 4-digit segments)
|
|
49
|
+
const TEN = '十'
|
|
50
|
+
const HUNDRED = '百'
|
|
51
|
+
const THOUSAND = '千'
|
|
52
|
+
|
|
53
|
+
// ============================================================================
|
|
54
|
+
// Segment Building
|
|
55
|
+
// ============================================================================
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Builds segment word for 0-9999 with 一 omission rules.
|
|
59
|
+
* - Omit 一 before 十, 百, 千
|
|
60
|
+
*/
|
|
61
|
+
function buildSegment (n) {
|
|
62
|
+
if (n === 0) return ''
|
|
63
|
+
|
|
64
|
+
const ones = n % 10
|
|
65
|
+
const tens = Math.floor(n / 10) % 10
|
|
66
|
+
const hundreds = Math.floor(n / 100) % 10
|
|
67
|
+
const thousands = Math.floor(n / 1000)
|
|
68
|
+
|
|
69
|
+
let result = ''
|
|
70
|
+
|
|
71
|
+
// Thousands (千) - omit 一 when 1
|
|
72
|
+
if (thousands > 0) {
|
|
73
|
+
if (thousands === 1) {
|
|
74
|
+
result += THOUSAND
|
|
75
|
+
} else {
|
|
76
|
+
result += ONES[thousands] + THOUSAND
|
|
72
77
|
}
|
|
78
|
+
}
|
|
73
79
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
result += this.onesWords[Number(tens) - 1] + '十'
|
|
81
|
-
}
|
|
80
|
+
// Hundreds (百) - omit 一 when 1
|
|
81
|
+
if (hundreds > 0) {
|
|
82
|
+
if (hundreds === 1) {
|
|
83
|
+
result += HUNDRED
|
|
84
|
+
} else {
|
|
85
|
+
result += ONES[hundreds] + HUNDRED
|
|
82
86
|
}
|
|
87
|
+
}
|
|
83
88
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
89
|
+
// Tens (十) - omit 一 when 1
|
|
90
|
+
if (tens > 0) {
|
|
91
|
+
if (tens === 1) {
|
|
92
|
+
result += TEN
|
|
93
|
+
} else {
|
|
94
|
+
result += ONES[tens] + TEN
|
|
87
95
|
}
|
|
96
|
+
}
|
|
88
97
|
|
|
89
|
-
|
|
98
|
+
// Ones
|
|
99
|
+
if (ones > 0) {
|
|
100
|
+
result += ONES[ones]
|
|
90
101
|
}
|
|
91
102
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
if (integerPart === 0n) {
|
|
95
|
-
return this.zeroWord
|
|
96
|
-
}
|
|
103
|
+
return result
|
|
104
|
+
}
|
|
97
105
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
106
|
+
// ============================================================================
|
|
107
|
+
// Conversion Functions
|
|
108
|
+
// ============================================================================
|
|
101
109
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
+
/**
|
|
111
|
+
* Converts a non-negative integer to Japanese words.
|
|
112
|
+
*
|
|
113
|
+
* @param {bigint} n - Non-negative integer to convert
|
|
114
|
+
* @returns {string} Japanese kanji words
|
|
115
|
+
*/
|
|
116
|
+
function integerToWords (n) {
|
|
117
|
+
if (n === 0n) return ZERO
|
|
118
|
+
|
|
119
|
+
// Fast path: numbers < 10000
|
|
120
|
+
if (n < 10000n) {
|
|
121
|
+
return buildSegment(Number(n))
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Fast path: numbers < 100,000,000 (万 range)
|
|
125
|
+
if (n < 100_000_000n) {
|
|
126
|
+
const man = Number(n / 10000n)
|
|
127
|
+
const remainder = Number(n % 10000n)
|
|
128
|
+
|
|
129
|
+
// For 万 and above, we need 一 before the scale word when segment is 1
|
|
130
|
+
let result
|
|
131
|
+
if (man === 1) {
|
|
132
|
+
result = '一' + SCALES[0] // 一万
|
|
133
|
+
} else {
|
|
134
|
+
result = buildSegment(man) + SCALES[0]
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (remainder > 0) {
|
|
138
|
+
result += buildSegment(remainder)
|
|
110
139
|
}
|
|
111
140
|
|
|
112
|
-
|
|
113
|
-
|
|
141
|
+
return result
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// For numbers >= 100,000,000, use scale decomposition
|
|
145
|
+
return buildLargeNumberWords(n)
|
|
146
|
+
}
|
|
114
147
|
|
|
115
|
-
|
|
148
|
+
/**
|
|
149
|
+
* Builds words for numbers >= 100,000,000.
|
|
150
|
+
* Uses BigInt modulo for 4-digit (myriad) segment extraction.
|
|
151
|
+
*
|
|
152
|
+
* @param {bigint} n - Number >= 100,000,000
|
|
153
|
+
* @returns {string} Japanese kanji words
|
|
154
|
+
*/
|
|
155
|
+
function buildLargeNumberWords (n) {
|
|
156
|
+
// Extract segments using BigInt modulo (faster than string slicing)
|
|
157
|
+
// Segments stored least-significant first (index 0 = units, 1 = 万, etc.)
|
|
158
|
+
const segments = []
|
|
159
|
+
let temp = n
|
|
160
|
+
while (temp > 0n) {
|
|
161
|
+
segments.push(Number(temp % 10000n))
|
|
162
|
+
temp = temp / 10000n
|
|
163
|
+
}
|
|
116
164
|
|
|
117
|
-
|
|
118
|
-
|
|
165
|
+
// Build result string directly (process from most-significant to least)
|
|
166
|
+
let result = ''
|
|
119
167
|
|
|
120
|
-
|
|
168
|
+
for (let i = segments.length - 1; i >= 0; i--) {
|
|
169
|
+
const segment = segments[i]
|
|
170
|
+
if (segment === 0) continue
|
|
121
171
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
result += '一' + this.scaleWords[scale]
|
|
127
|
-
} else {
|
|
128
|
-
result += groupStr + this.scaleWords[scale]
|
|
129
|
-
}
|
|
172
|
+
if (i > 0) {
|
|
173
|
+
// For scales >= 万, we need 一 before scale word when segment is 1
|
|
174
|
+
if (segment === 1) {
|
|
175
|
+
result += '一' + SCALES[i - 1]
|
|
130
176
|
} else {
|
|
131
|
-
result +=
|
|
177
|
+
result += buildSegment(segment) + SCALES[i - 1]
|
|
132
178
|
}
|
|
179
|
+
} else {
|
|
180
|
+
// Units segment (no scale word)
|
|
181
|
+
result += buildSegment(segment)
|
|
133
182
|
}
|
|
183
|
+
}
|
|
134
184
|
|
|
135
|
-
|
|
185
|
+
return result || ZERO
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Converts decimal digits to Japanese words (digit by digit).
|
|
190
|
+
*
|
|
191
|
+
* @param {string} decimalPart - Decimal digits (without the point)
|
|
192
|
+
* @returns {string} Japanese kanji words for decimal part
|
|
193
|
+
*/
|
|
194
|
+
function decimalPartToWords (decimalPart) {
|
|
195
|
+
let result = ''
|
|
196
|
+
|
|
197
|
+
for (let i = 0; i < decimalPart.length; i++) {
|
|
198
|
+
const digit = parseInt(decimalPart[i], 10)
|
|
199
|
+
if (digit === 0) {
|
|
200
|
+
result += ZERO
|
|
201
|
+
} else {
|
|
202
|
+
result += ONES[digit]
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return result
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Converts a numeric value to Japanese words.
|
|
211
|
+
*
|
|
212
|
+
* This is the main public API. It accepts any valid numeric input
|
|
213
|
+
* (number, string, or bigint) and handles parsing internally.
|
|
214
|
+
*
|
|
215
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
216
|
+
* @returns {string} The number in Japanese kanji words
|
|
217
|
+
* @throws {TypeError} If value is not a valid numeric type
|
|
218
|
+
* @throws {Error} If value is not a valid number format
|
|
219
|
+
*
|
|
220
|
+
* @example
|
|
221
|
+
* toWords(42) // '四十二'
|
|
222
|
+
* toWords(10000) // '一万'
|
|
223
|
+
* toWords(100000000) // '一億'
|
|
224
|
+
*/
|
|
225
|
+
function toWords (value) {
|
|
226
|
+
const { isNegative, integerPart, decimalPart } = parseNumericValue(value)
|
|
227
|
+
|
|
228
|
+
let result = ''
|
|
229
|
+
|
|
230
|
+
if (isNegative) {
|
|
231
|
+
result = NEGATIVE
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
result += integerToWords(integerPart)
|
|
235
|
+
|
|
236
|
+
if (decimalPart) {
|
|
237
|
+
result += DECIMAL_SEP + decimalPartToWords(decimalPart)
|
|
136
238
|
}
|
|
239
|
+
|
|
240
|
+
return result
|
|
137
241
|
}
|
|
242
|
+
|
|
243
|
+
// ============================================================================
|
|
244
|
+
// Public API
|
|
245
|
+
// ============================================================================
|
|
246
|
+
|
|
247
|
+
export { toWords }
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts a numeric value to Georgian words.
|
|
3
|
+
*
|
|
4
|
+
* This is the main public API. It accepts any valid numeric input
|
|
5
|
+
* (number, string, or bigint) and handles parsing internally.
|
|
6
|
+
*
|
|
7
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
8
|
+
* @returns {string} The number in Georgian words
|
|
9
|
+
* @throws {TypeError} If value is not a valid numeric type
|
|
10
|
+
* @throws {Error} If value is not a valid number format
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* toWords(21) // 'ოცდაერთი'
|
|
14
|
+
* toWords(100) // 'ასი'
|
|
15
|
+
* toWords(1000) // 'ათასი'
|
|
16
|
+
*/
|
|
17
|
+
export function toWords(value: number | string | bigint): string;
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Georgian language converter - Functional Implementation
|
|
3
|
+
*
|
|
4
|
+
* Self-contained module with its own input validation, ready for subpath exports.
|
|
5
|
+
*
|
|
6
|
+
* Georgian-specific rules:
|
|
7
|
+
* - Vigesimal (base-20) system for 20-99
|
|
8
|
+
* - 40 = ორმოცი (2×20), 60 = სამოცი (3×20), 80 = ოთხმოცი (4×20)
|
|
9
|
+
* - 30/50/70/90 use "და" + "ათი": ოცდაათი (20+10), ორმოცდაათი (40+10)
|
|
10
|
+
* - Compound numbers use "და" (da = "and") connector
|
|
11
|
+
* - Hundreds: unit prefix + ას (ორასი = 200)
|
|
12
|
+
* - Short scale for large numbers (მილიონი, მილიარდი, ტრილიონი)
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { parseNumericValue } from '../utils/parse-numeric.js'
|
|
16
|
+
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// Vocabulary (module-level constants)
|
|
19
|
+
// ============================================================================
|
|
20
|
+
|
|
21
|
+
// Numbers 0-9 (primitives)
|
|
22
|
+
const ONES = ['ნული', 'ერთი', 'ორი', 'სამი', 'ოთხი', 'ხუთი', 'ექვსი', 'შვიდი', 'რვა', 'ცხრა']
|
|
23
|
+
|
|
24
|
+
// Numbers 10-19
|
|
25
|
+
const TEENS = ['ათი', 'თერთმეტი', 'თორმეტი', 'ცამეტი', 'თოთხმეტი', 'თხუთმეტი', 'თექვსმეტი', 'ჩვიდმეტი', 'თვრამეტი', 'ცხრამეტი']
|
|
26
|
+
|
|
27
|
+
// Vigesimal bases: 20, 40, 60, 80 (with და connector forms)
|
|
28
|
+
const VIGESIMAL = ['', 'ოცი', 'ორმოცი', 'სამოცი', 'ოთხმოცი']
|
|
29
|
+
const VIGESIMAL_DA = ['', 'ოცდა', 'ორმოცდა', 'სამოცდა', 'ოთხმოცდა']
|
|
30
|
+
|
|
31
|
+
// Prefixes for hundreds (unit forms without final vowel)
|
|
32
|
+
const HUNDRED_PREFIXES = ['', '', 'ორ', 'სამ', 'ოთხ', 'ხუთ', 'ექვს', 'შვიდ', 'რვა', 'ცხრა']
|
|
33
|
+
|
|
34
|
+
const HUNDRED = 'ასი'
|
|
35
|
+
const HUNDRED_STEM = 'ას' // Without final vowel
|
|
36
|
+
const THOUSAND = 'ათასი'
|
|
37
|
+
const THOUSAND_STEM = 'ათას' // Without final vowel
|
|
38
|
+
|
|
39
|
+
// Scale words (short scale) - indexed by segment position
|
|
40
|
+
const SCALES = ['', '', 'მილიონი', 'მილიარდი', 'ტრილიონი', 'კვადრილიონი', 'კვინტილიონი', 'სექსტილიონი']
|
|
41
|
+
|
|
42
|
+
const ZERO = 'ნული'
|
|
43
|
+
const NEGATIVE = 'მინუს'
|
|
44
|
+
const DECIMAL_SEP = 'მთელი'
|
|
45
|
+
|
|
46
|
+
// ============================================================================
|
|
47
|
+
// Segment Building
|
|
48
|
+
// ============================================================================
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Builds segment word for 0-99 using vigesimal system.
|
|
52
|
+
* @param {number} n - Number 0-99
|
|
53
|
+
* @returns {string} Georgian word
|
|
54
|
+
*/
|
|
55
|
+
function buildTens (n) {
|
|
56
|
+
if (n < 10) return ONES[n]
|
|
57
|
+
if (n < 20) return TEENS[n - 10]
|
|
58
|
+
|
|
59
|
+
const vigesimalGroup = Math.floor(n / 20)
|
|
60
|
+
const remainder = n % 20
|
|
61
|
+
|
|
62
|
+
if (remainder === 0) {
|
|
63
|
+
return VIGESIMAL[vigesimalGroup]
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Use და connector: ოცდა + remainder
|
|
67
|
+
const base = VIGESIMAL_DA[vigesimalGroup]
|
|
68
|
+
if (remainder < 10) {
|
|
69
|
+
return base + ONES[remainder]
|
|
70
|
+
}
|
|
71
|
+
return base + TEENS[remainder - 10]
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Builds segment word for 0-999.
|
|
76
|
+
* Returns object with full form and stem form (without final vowel).
|
|
77
|
+
* @param {number} n - Number 0-999
|
|
78
|
+
* @returns {{full: string, stem: string}} Georgian words
|
|
79
|
+
*/
|
|
80
|
+
function buildSegment (n) {
|
|
81
|
+
if (n === 0) return { full: '', stem: '' }
|
|
82
|
+
if (n < 100) {
|
|
83
|
+
const word = buildTens(n)
|
|
84
|
+
// Remove final vowel for stem
|
|
85
|
+
const lastChar = word.slice(-1)
|
|
86
|
+
const stem = (lastChar === 'ი' || lastChar === 'ა') ? word.slice(0, -1) : word
|
|
87
|
+
return { full: word, stem }
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const hundreds = Math.floor(n / 100)
|
|
91
|
+
const remainder = n % 100
|
|
92
|
+
|
|
93
|
+
// Build hundreds: ასი (100), ორასი (200), etc.
|
|
94
|
+
let hundredWord
|
|
95
|
+
if (hundreds === 1) {
|
|
96
|
+
hundredWord = remainder > 0 ? HUNDRED_STEM : HUNDRED
|
|
97
|
+
} else {
|
|
98
|
+
hundredWord = HUNDRED_PREFIXES[hundreds] + (remainder > 0 ? HUNDRED_STEM : HUNDRED)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (remainder > 0) {
|
|
102
|
+
const remainderWord = buildTens(remainder)
|
|
103
|
+
const full = hundredWord + ' ' + remainderWord
|
|
104
|
+
// Stem removes final vowel from remainder
|
|
105
|
+
const lastChar = remainderWord.slice(-1)
|
|
106
|
+
const remainderStem = (lastChar === 'ი' || lastChar === 'ა') ? remainderWord.slice(0, -1) : remainderWord
|
|
107
|
+
return { full, stem: hundredWord + ' ' + remainderStem }
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Hundreds only - stem removes final ი
|
|
111
|
+
return { full: hundredWord, stem: hundredWord.slice(0, -1) }
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// ============================================================================
|
|
115
|
+
// Conversion Functions
|
|
116
|
+
// ============================================================================
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Converts a non-negative integer to Georgian words.
|
|
120
|
+
*
|
|
121
|
+
* @param {bigint} n - Non-negative integer to convert
|
|
122
|
+
* @returns {string} Georgian words
|
|
123
|
+
*/
|
|
124
|
+
function integerToWords (n) {
|
|
125
|
+
if (n === 0n) return ZERO
|
|
126
|
+
|
|
127
|
+
// Fast path: numbers < 1000
|
|
128
|
+
if (n < 1000n) {
|
|
129
|
+
const { full } = buildSegment(Number(n))
|
|
130
|
+
return full
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Fast path: numbers < 1,000,000 (thousands)
|
|
134
|
+
if (n < 1_000_000n) {
|
|
135
|
+
const thousands = Number(n / 1000n)
|
|
136
|
+
const remainder = Number(n % 1000n)
|
|
137
|
+
|
|
138
|
+
let result
|
|
139
|
+
if (thousands === 1) {
|
|
140
|
+
// "ათასი" not "ერთი ათასი"
|
|
141
|
+
result = remainder > 0 ? THOUSAND_STEM : THOUSAND
|
|
142
|
+
} else {
|
|
143
|
+
// Use stem form before ათასი
|
|
144
|
+
const { stem: thousandsPart } = buildSegment(thousands)
|
|
145
|
+
result = thousandsPart + ' ' + (remainder > 0 ? THOUSAND_STEM : THOUSAND)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (remainder > 0) {
|
|
149
|
+
const { full: remainderWord } = buildSegment(remainder)
|
|
150
|
+
result += ' ' + remainderWord
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return result
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// For numbers >= 1,000,000, use scale decomposition
|
|
157
|
+
return buildLargeNumberWords(n)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Builds words for numbers >= 1,000,000.
|
|
162
|
+
*
|
|
163
|
+
* @param {bigint} n - Number >= 1,000,000
|
|
164
|
+
* @returns {string} Georgian words
|
|
165
|
+
*/
|
|
166
|
+
function buildLargeNumberWords (n) {
|
|
167
|
+
const numStr = n.toString()
|
|
168
|
+
const len = numStr.length
|
|
169
|
+
|
|
170
|
+
// Build segments of 3 digits from left to right
|
|
171
|
+
const segments = []
|
|
172
|
+
const segmentSize = 3
|
|
173
|
+
|
|
174
|
+
const remainderLen = len % segmentSize
|
|
175
|
+
let pos = 0
|
|
176
|
+
if (remainderLen > 0) {
|
|
177
|
+
segments.push(Number(numStr.slice(0, remainderLen)))
|
|
178
|
+
pos = remainderLen
|
|
179
|
+
}
|
|
180
|
+
while (pos < len) {
|
|
181
|
+
segments.push(Number(numStr.slice(pos, pos + segmentSize)))
|
|
182
|
+
pos += segmentSize
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Convert segments to words
|
|
186
|
+
const parts = []
|
|
187
|
+
let scaleIndex = segments.length - 1
|
|
188
|
+
|
|
189
|
+
for (let i = 0; i < segments.length; i++) {
|
|
190
|
+
const segment = segments[i]
|
|
191
|
+
|
|
192
|
+
if (segment !== 0) {
|
|
193
|
+
if (scaleIndex === 0) {
|
|
194
|
+
// Units (no scale)
|
|
195
|
+
const { full } = buildSegment(segment)
|
|
196
|
+
parts.push(full)
|
|
197
|
+
} else if (scaleIndex === 1) {
|
|
198
|
+
// Thousands - check if there's a remainder
|
|
199
|
+
const hasRemainder = segments.slice(i + 1).some(s => s !== 0)
|
|
200
|
+
const thousandWord = hasRemainder ? THOUSAND_STEM : THOUSAND
|
|
201
|
+
|
|
202
|
+
if (segment === 1) {
|
|
203
|
+
parts.push(thousandWord)
|
|
204
|
+
} else {
|
|
205
|
+
const { stem } = buildSegment(segment)
|
|
206
|
+
parts.push(stem + ' ' + thousandWord)
|
|
207
|
+
}
|
|
208
|
+
} else {
|
|
209
|
+
// Million and above
|
|
210
|
+
const scaleWord = SCALES[scaleIndex] || SCALES[SCALES.length - 1]
|
|
211
|
+
if (segment === 1) {
|
|
212
|
+
parts.push('ერთი ' + scaleWord)
|
|
213
|
+
} else {
|
|
214
|
+
const { full } = buildSegment(segment)
|
|
215
|
+
parts.push(full + ' ' + scaleWord)
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
scaleIndex--
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return parts.join(' ')
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Converts decimal digits to Georgian words.
|
|
228
|
+
*
|
|
229
|
+
* @param {string} decimalPart - Decimal digits (without the point)
|
|
230
|
+
* @returns {string} Georgian words for decimal part
|
|
231
|
+
*/
|
|
232
|
+
function decimalPartToWords (decimalPart) {
|
|
233
|
+
let result = ''
|
|
234
|
+
|
|
235
|
+
// Handle leading zeros
|
|
236
|
+
let i = 0
|
|
237
|
+
while (i < decimalPart.length && decimalPart[i] === '0') {
|
|
238
|
+
if (result) result += ' '
|
|
239
|
+
result += ZERO
|
|
240
|
+
i++
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Convert remainder as a single number
|
|
244
|
+
const remainder = decimalPart.slice(i)
|
|
245
|
+
if (remainder) {
|
|
246
|
+
if (result) result += ' '
|
|
247
|
+
result += integerToWords(BigInt(remainder))
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
return result
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Converts a numeric value to Georgian words.
|
|
255
|
+
*
|
|
256
|
+
* This is the main public API. It accepts any valid numeric input
|
|
257
|
+
* (number, string, or bigint) and handles parsing internally.
|
|
258
|
+
*
|
|
259
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
260
|
+
* @returns {string} The number in Georgian words
|
|
261
|
+
* @throws {TypeError} If value is not a valid numeric type
|
|
262
|
+
* @throws {Error} If value is not a valid number format
|
|
263
|
+
*
|
|
264
|
+
* @example
|
|
265
|
+
* toWords(21) // 'ოცდაერთი'
|
|
266
|
+
* toWords(100) // 'ასი'
|
|
267
|
+
* toWords(1000) // 'ათასი'
|
|
268
|
+
*/
|
|
269
|
+
function toWords (value) {
|
|
270
|
+
const { isNegative, integerPart, decimalPart } = parseNumericValue(value)
|
|
271
|
+
|
|
272
|
+
let result = ''
|
|
273
|
+
|
|
274
|
+
if (isNegative) {
|
|
275
|
+
result = NEGATIVE + ' '
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
result += integerToWords(integerPart)
|
|
279
|
+
|
|
280
|
+
if (decimalPart) {
|
|
281
|
+
result += ' ' + DECIMAL_SEP + ' ' + decimalPartToWords(decimalPart)
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
return result
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// ============================================================================
|
|
288
|
+
// Public API
|
|
289
|
+
// ============================================================================
|
|
290
|
+
|
|
291
|
+
export { toWords }
|
package/lib/languages/kn.d.ts
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Kannada
|
|
2
|
+
* Converts a numeric value to Kannada words.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* - Kannada script
|
|
7
|
-
* - Complete word forms for 0-99
|
|
4
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
5
|
+
* @returns {string} The number in Kannada words
|
|
8
6
|
*/
|
|
9
|
-
export
|
|
10
|
-
}
|
|
11
|
-
import { SouthAsianLanguage } from '../classes/south-asian-language.js';
|
|
7
|
+
export function toWords(value: number | string | bigint): string;
|