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
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts a numeric value to Amharic (Latin script) words.
|
|
3
|
+
*
|
|
4
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
5
|
+
* @returns {string} The number in Amharic Latin words
|
|
6
|
+
*/
|
|
7
|
+
export function toWords(value: number | string | bigint): string;
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Amharic Latin language converter - Functional Implementation
|
|
3
|
+
*
|
|
4
|
+
* Self-contained converter with precomputed lookup tables.
|
|
5
|
+
* Latin/ASCII romanization of Amharic numerals.
|
|
6
|
+
*
|
|
7
|
+
* Key features:
|
|
8
|
+
* - Romanized numerals (and, hulet, sost)
|
|
9
|
+
* - Teens formed with "asra" prefix
|
|
10
|
+
* - Keeps "one" before hundred: "and meto" (100)
|
|
11
|
+
* - Short scale naming
|
|
12
|
+
* - Per-digit decimal reading
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { parseNumericValue } from '../utils/parse-numeric.js'
|
|
16
|
+
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// Vocabulary
|
|
19
|
+
// ============================================================================
|
|
20
|
+
|
|
21
|
+
const ONES = ['', 'and', 'hulet', 'sost', 'arat', 'amist', 'siddist', 'sebat', 'siment', 'zeteny']
|
|
22
|
+
const TEENS = ['asir', 'asra and', 'asra hulet', 'asra sost', 'asra arat', 'asra amist', 'asra siddist', 'asra sebat', 'asra siment', 'asra zeteny']
|
|
23
|
+
const TENS = ['', '', 'haya', 'selasa', 'arba', 'hamsa', 'silsa', 'seba', 'semanya', 'zetena']
|
|
24
|
+
|
|
25
|
+
const HUNDRED = 'meto'
|
|
26
|
+
const THOUSAND = 'shi'
|
|
27
|
+
|
|
28
|
+
const ZERO = 'zero'
|
|
29
|
+
const NEGATIVE = 'asitegna'
|
|
30
|
+
const DECIMAL_SEP = 'netib'
|
|
31
|
+
|
|
32
|
+
// Short scale
|
|
33
|
+
const SCALE_WORDS = ['', THOUSAND, 'miliyon', 'billiyon']
|
|
34
|
+
|
|
35
|
+
// ============================================================================
|
|
36
|
+
// Precomputed Lookup Table
|
|
37
|
+
// ============================================================================
|
|
38
|
+
|
|
39
|
+
function buildSegment (n) {
|
|
40
|
+
if (n === 0) return ''
|
|
41
|
+
|
|
42
|
+
const ones = n % 10
|
|
43
|
+
const tensDigit = Math.floor(n / 10) % 10
|
|
44
|
+
const hundredsDigit = Math.floor(n / 100)
|
|
45
|
+
|
|
46
|
+
const parts = []
|
|
47
|
+
|
|
48
|
+
// Amharic keeps "one" before hundred: "and meto" (100)
|
|
49
|
+
if (hundredsDigit > 0) {
|
|
50
|
+
parts.push(ONES[hundredsDigit] + ' ' + HUNDRED)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (tensDigit === 1) {
|
|
54
|
+
parts.push(TEENS[ones])
|
|
55
|
+
} else {
|
|
56
|
+
if (tensDigit > 1) {
|
|
57
|
+
parts.push(TENS[tensDigit])
|
|
58
|
+
}
|
|
59
|
+
if (ones > 0) {
|
|
60
|
+
parts.push(ONES[ones])
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return parts.join(' ')
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const SEGMENTS = new Array(1000)
|
|
68
|
+
for (let i = 0; i < 1000; i++) {
|
|
69
|
+
SEGMENTS[i] = buildSegment(i)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// ============================================================================
|
|
73
|
+
// Conversion Functions
|
|
74
|
+
// ============================================================================
|
|
75
|
+
|
|
76
|
+
function integerToWords (n) {
|
|
77
|
+
if (n === 0n) return ZERO
|
|
78
|
+
|
|
79
|
+
if (n < 1000n) {
|
|
80
|
+
return SEGMENTS[Number(n)]
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return buildLargeNumberWords(n)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function buildLargeNumberWords (n) {
|
|
87
|
+
const numStr = n.toString()
|
|
88
|
+
const len = numStr.length
|
|
89
|
+
|
|
90
|
+
const segments = []
|
|
91
|
+
const segmentSize = 3
|
|
92
|
+
|
|
93
|
+
const remainderLen = len % segmentSize
|
|
94
|
+
let pos = 0
|
|
95
|
+
if (remainderLen > 0) {
|
|
96
|
+
segments.push(Number(numStr.slice(0, remainderLen)))
|
|
97
|
+
pos = remainderLen
|
|
98
|
+
}
|
|
99
|
+
while (pos < len) {
|
|
100
|
+
segments.push(Number(numStr.slice(pos, pos + segmentSize)))
|
|
101
|
+
pos += segmentSize
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const parts = []
|
|
105
|
+
let scaleIndex = segments.length - 1
|
|
106
|
+
|
|
107
|
+
for (let i = 0; i < segments.length; i++) {
|
|
108
|
+
const segment = segments[i]
|
|
109
|
+
|
|
110
|
+
if (segment !== 0) {
|
|
111
|
+
const scaleWord = SCALE_WORDS[scaleIndex] || ''
|
|
112
|
+
|
|
113
|
+
if (scaleIndex === 0) {
|
|
114
|
+
parts.push(SEGMENTS[segment])
|
|
115
|
+
} else {
|
|
116
|
+
parts.push(SEGMENTS[segment] + ' ' + scaleWord)
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
scaleIndex--
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return parts.join(' ')
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function decimalPartToWords (decimalPart) {
|
|
127
|
+
// Per-digit decimal reading
|
|
128
|
+
const digits = []
|
|
129
|
+
for (const char of decimalPart) {
|
|
130
|
+
const d = parseInt(char, 10)
|
|
131
|
+
digits.push(d === 0 ? ZERO : ONES[d])
|
|
132
|
+
}
|
|
133
|
+
return digits.join(' ')
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Converts a numeric value to Amharic (Latin script) words.
|
|
138
|
+
*
|
|
139
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
140
|
+
* @returns {string} The number in Amharic Latin words
|
|
141
|
+
*/
|
|
142
|
+
function toWords (value) {
|
|
143
|
+
const { isNegative, integerPart, decimalPart } = parseNumericValue(value)
|
|
144
|
+
|
|
145
|
+
let result = ''
|
|
146
|
+
|
|
147
|
+
if (isNegative) {
|
|
148
|
+
result = NEGATIVE + ' '
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
result += integerToWords(integerPart)
|
|
152
|
+
|
|
153
|
+
if (decimalPart) {
|
|
154
|
+
result += ' ' + DECIMAL_SEP + ' ' + decimalPartToWords(decimalPart)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return result
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// ============================================================================
|
|
161
|
+
// Exports
|
|
162
|
+
// ============================================================================
|
|
163
|
+
|
|
164
|
+
export { toWords }
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Amharic language converter - Functional Implementation
|
|
3
|
+
*
|
|
4
|
+
* Self-contained converter with precomputed lookup tables.
|
|
5
|
+
* Native Ge'ez script (ግዕዝ) output.
|
|
6
|
+
*
|
|
7
|
+
* Key features:
|
|
8
|
+
* - Ge'ez/Ethiopic script numerals
|
|
9
|
+
* - Teens formed with "አስራ" prefix
|
|
10
|
+
* - Keeps "one" before hundred: "አንድ መቶ" (100)
|
|
11
|
+
* - Short scale naming
|
|
12
|
+
* - Per-digit decimal reading
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { parseNumericValue } from '../utils/parse-numeric.js'
|
|
16
|
+
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// Vocabulary
|
|
19
|
+
// ============================================================================
|
|
20
|
+
|
|
21
|
+
const ONES = ['', 'አንድ', 'ሁለት', 'ሶስት', 'አራት', 'አምስት', 'ስድስት', 'ሰባት', 'ስምንት', 'ዘጠኝ']
|
|
22
|
+
const TEENS = ['አስር', 'አስራ አንድ', 'አስራ ሁለት', 'አስራ ሶስት', 'አስራ አራት', 'አስራ አምስት', 'አስራ ስድስት', 'አስራ ሰባት', 'አስራ ስምንት', 'አስራ ዘጠኝ']
|
|
23
|
+
const TENS = ['', '', 'ሃያ', 'ሰላሳ', 'አርባ', 'ሃምሳ', 'ስልሳ', 'ሰባ', 'ሰማንያ', 'ዘጠና']
|
|
24
|
+
|
|
25
|
+
const HUNDRED = 'መቶ'
|
|
26
|
+
const THOUSAND = 'ሺ'
|
|
27
|
+
|
|
28
|
+
const ZERO = 'ዜሮ'
|
|
29
|
+
const NEGATIVE = 'አሉታዊ'
|
|
30
|
+
const DECIMAL_SEP = 'ነጥብ'
|
|
31
|
+
|
|
32
|
+
// Short scale
|
|
33
|
+
const SCALE_WORDS = ['', THOUSAND, 'ሚሊዮን', 'ቢሊዮን']
|
|
34
|
+
|
|
35
|
+
// ============================================================================
|
|
36
|
+
// Precomputed Lookup Table
|
|
37
|
+
// ============================================================================
|
|
38
|
+
|
|
39
|
+
function buildSegment (n) {
|
|
40
|
+
if (n === 0) return ''
|
|
41
|
+
|
|
42
|
+
const ones = n % 10
|
|
43
|
+
const tensDigit = Math.floor(n / 10) % 10
|
|
44
|
+
const hundredsDigit = Math.floor(n / 100)
|
|
45
|
+
|
|
46
|
+
const parts = []
|
|
47
|
+
|
|
48
|
+
// Amharic keeps "one" before hundred: "አንድ መቶ" (100)
|
|
49
|
+
if (hundredsDigit > 0) {
|
|
50
|
+
parts.push(ONES[hundredsDigit] + ' ' + HUNDRED)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (tensDigit === 1) {
|
|
54
|
+
parts.push(TEENS[ones])
|
|
55
|
+
} else {
|
|
56
|
+
if (tensDigit > 1) {
|
|
57
|
+
parts.push(TENS[tensDigit])
|
|
58
|
+
}
|
|
59
|
+
if (ones > 0) {
|
|
60
|
+
parts.push(ONES[ones])
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return parts.join(' ')
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const SEGMENTS = new Array(1000)
|
|
68
|
+
for (let i = 0; i < 1000; i++) {
|
|
69
|
+
SEGMENTS[i] = buildSegment(i)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// ============================================================================
|
|
73
|
+
// Conversion Functions
|
|
74
|
+
// ============================================================================
|
|
75
|
+
|
|
76
|
+
function integerToWords (n) {
|
|
77
|
+
if (n === 0n) return ZERO
|
|
78
|
+
|
|
79
|
+
if (n < 1000n) {
|
|
80
|
+
return SEGMENTS[Number(n)]
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return buildLargeNumberWords(n)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function buildLargeNumberWords (n) {
|
|
87
|
+
const numStr = n.toString()
|
|
88
|
+
const len = numStr.length
|
|
89
|
+
|
|
90
|
+
const segments = []
|
|
91
|
+
const segmentSize = 3
|
|
92
|
+
|
|
93
|
+
const remainderLen = len % segmentSize
|
|
94
|
+
let pos = 0
|
|
95
|
+
if (remainderLen > 0) {
|
|
96
|
+
segments.push(Number(numStr.slice(0, remainderLen)))
|
|
97
|
+
pos = remainderLen
|
|
98
|
+
}
|
|
99
|
+
while (pos < len) {
|
|
100
|
+
segments.push(Number(numStr.slice(pos, pos + segmentSize)))
|
|
101
|
+
pos += segmentSize
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const parts = []
|
|
105
|
+
let scaleIndex = segments.length - 1
|
|
106
|
+
|
|
107
|
+
for (let i = 0; i < segments.length; i++) {
|
|
108
|
+
const segment = segments[i]
|
|
109
|
+
|
|
110
|
+
if (segment !== 0) {
|
|
111
|
+
const scaleWord = SCALE_WORDS[scaleIndex] || ''
|
|
112
|
+
|
|
113
|
+
if (scaleIndex === 0) {
|
|
114
|
+
parts.push(SEGMENTS[segment])
|
|
115
|
+
} else {
|
|
116
|
+
parts.push(SEGMENTS[segment] + ' ' + scaleWord)
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
scaleIndex--
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return parts.join(' ')
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function decimalPartToWords (decimalPart) {
|
|
127
|
+
// Per-digit decimal reading
|
|
128
|
+
const digits = []
|
|
129
|
+
for (const char of decimalPart) {
|
|
130
|
+
const d = parseInt(char, 10)
|
|
131
|
+
digits.push(d === 0 ? ZERO : ONES[d])
|
|
132
|
+
}
|
|
133
|
+
return digits.join(' ')
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Converts a numeric value to Amharic words.
|
|
138
|
+
*
|
|
139
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
140
|
+
* @returns {string} The number in Amharic words
|
|
141
|
+
*/
|
|
142
|
+
function toWords (value) {
|
|
143
|
+
const { isNegative, integerPart, decimalPart } = parseNumericValue(value)
|
|
144
|
+
|
|
145
|
+
let result = ''
|
|
146
|
+
|
|
147
|
+
if (isNegative) {
|
|
148
|
+
result = NEGATIVE + ' '
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
result += integerToWords(integerPart)
|
|
152
|
+
|
|
153
|
+
if (decimalPart) {
|
|
154
|
+
result += ' ' + DECIMAL_SEP + ' ' + decimalPartToWords(decimalPart)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return result
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// ============================================================================
|
|
161
|
+
// Exports
|
|
162
|
+
// ============================================================================
|
|
163
|
+
|
|
164
|
+
export { toWords }
|
package/lib/languages/ar.d.ts
CHANGED
|
@@ -1,30 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Arabic
|
|
2
|
+
* Converts a numeric value to Arabic words.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* -
|
|
7
|
-
* -
|
|
8
|
-
*
|
|
4
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
5
|
+
* @param {Object} [options] - Optional configuration
|
|
6
|
+
* @param {('masculine'|'feminine')} [options.gender='masculine'] - Grammatical gender
|
|
7
|
+
* @param {string} [options.negativeWord] - Custom word for negative numbers
|
|
8
|
+
* @returns {string} The number in Arabic words
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* toWords(1) // 'واحد'
|
|
12
|
+
* toWords(1, {gender: 'feminine'}) // 'واحدة'
|
|
9
13
|
*/
|
|
10
|
-
export
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
scaleWords: string[];
|
|
15
|
-
scaleAppendedWords: string[];
|
|
16
|
-
scalePluralWords: string[];
|
|
17
|
-
dualWords: string[];
|
|
18
|
-
dualAppendedWords: string[];
|
|
19
|
-
ones: {
|
|
20
|
-
masculine: string[];
|
|
21
|
-
feminine: string[];
|
|
22
|
-
};
|
|
23
|
-
/** Selects masculine or feminine number forms based on options. */
|
|
24
|
-
get selectedOnes(): string[];
|
|
25
|
-
/** Converts a 3-digit segment (0-999) to Arabic words with gender/plural rules. */
|
|
26
|
-
segmentToWords(groupNumber: any, groupLevel: any, fullNumber: any): string;
|
|
27
|
-
/** Converts integer part to Arabic words by processing 3-digit groups. */
|
|
28
|
-
integerToWords(integerPart: any): string;
|
|
29
|
-
}
|
|
30
|
-
import { AbstractLanguage } from '../classes/abstract-language.js';
|
|
14
|
+
export function toWords(value: number | string | bigint, options?: {
|
|
15
|
+
gender?: "masculine" | "feminine" | undefined;
|
|
16
|
+
negativeWord?: string | undefined;
|
|
17
|
+
}): string;
|