n2words 1.24.0 → 2.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/README.md +285 -156
- package/dist/ArabicConverter.js +3 -0
- package/dist/ArabicConverter.js.map +1 -0
- package/dist/AzerbaijaniConverter.js +3 -0
- package/dist/AzerbaijaniConverter.js.map +1 -0
- package/dist/BanglaConverter.js +3 -0
- package/dist/BanglaConverter.js.map +1 -0
- package/dist/BiblicalHebrewConverter.js +3 -0
- package/dist/BiblicalHebrewConverter.js.map +1 -0
- package/dist/CroatianConverter.js +3 -0
- package/dist/CroatianConverter.js.map +1 -0
- package/dist/CzechConverter.js +3 -0
- package/dist/CzechConverter.js.map +1 -0
- package/dist/DanishConverter.js +3 -0
- package/dist/DanishConverter.js.map +1 -0
- package/dist/DutchConverter.js +3 -0
- package/dist/DutchConverter.js.map +1 -0
- package/dist/EnglishConverter.js +3 -0
- package/dist/EnglishConverter.js.map +1 -0
- package/dist/FilipinoConverter.js +3 -0
- package/dist/FilipinoConverter.js.map +1 -0
- package/dist/FrenchBelgiumConverter.js +3 -0
- package/dist/FrenchBelgiumConverter.js.map +1 -0
- package/dist/FrenchConverter.js +3 -0
- package/dist/FrenchConverter.js.map +1 -0
- package/dist/GermanConverter.js +3 -0
- package/dist/GermanConverter.js.map +1 -0
- package/dist/GreekConverter.js +3 -0
- package/dist/GreekConverter.js.map +1 -0
- package/dist/GujaratiConverter.js +3 -0
- package/dist/GujaratiConverter.js.map +1 -0
- package/dist/HebrewConverter.js +3 -0
- package/dist/HebrewConverter.js.map +1 -0
- package/dist/HindiConverter.js +3 -0
- package/dist/HindiConverter.js.map +1 -0
- package/dist/HungarianConverter.js +3 -0
- package/dist/HungarianConverter.js.map +1 -0
- package/dist/IndonesianConverter.js +3 -0
- package/dist/IndonesianConverter.js.map +1 -0
- package/dist/ItalianConverter.js +3 -0
- package/dist/ItalianConverter.js.map +1 -0
- package/dist/JapaneseConverter.js +3 -0
- package/dist/JapaneseConverter.js.map +1 -0
- package/dist/KannadaConverter.js +3 -0
- package/dist/KannadaConverter.js.map +1 -0
- package/dist/KoreanConverter.js +3 -0
- package/dist/KoreanConverter.js.map +1 -0
- package/dist/LatvianConverter.js +3 -0
- package/dist/LatvianConverter.js.map +1 -0
- package/dist/LithuanianConverter.js +3 -0
- package/dist/LithuanianConverter.js.map +1 -0
- package/dist/MalayConverter.js +3 -0
- package/dist/MalayConverter.js.map +1 -0
- package/dist/MarathiConverter.js +3 -0
- package/dist/MarathiConverter.js.map +1 -0
- package/dist/NorwegianBokmalConverter.js +3 -0
- package/dist/NorwegianBokmalConverter.js.map +1 -0
- package/dist/PersianConverter.js +3 -0
- package/dist/PersianConverter.js.map +1 -0
- package/dist/PolishConverter.js +3 -0
- package/dist/PolishConverter.js.map +1 -0
- package/dist/PortugueseConverter.js +3 -0
- package/dist/PortugueseConverter.js.map +1 -0
- package/dist/PunjabiConverter.js +3 -0
- package/dist/PunjabiConverter.js.map +1 -0
- package/dist/RomanianConverter.js +3 -0
- package/dist/RomanianConverter.js.map +1 -0
- package/dist/RussianConverter.js +3 -0
- package/dist/RussianConverter.js.map +1 -0
- package/dist/SerbianCyrillicConverter.js +3 -0
- package/dist/SerbianCyrillicConverter.js.map +1 -0
- package/dist/SerbianLatinConverter.js +3 -0
- package/dist/SerbianLatinConverter.js.map +1 -0
- package/dist/SimplifiedChineseConverter.js +3 -0
- package/dist/SimplifiedChineseConverter.js.map +1 -0
- package/dist/SpanishConverter.js +3 -0
- package/dist/SpanishConverter.js.map +1 -0
- package/dist/SwahiliConverter.js +3 -0
- package/dist/SwahiliConverter.js.map +1 -0
- package/dist/SwedishConverter.js +3 -0
- package/dist/SwedishConverter.js.map +1 -0
- package/dist/TamilConverter.js +3 -0
- package/dist/TamilConverter.js.map +1 -0
- package/dist/TeluguConverter.js +3 -0
- package/dist/TeluguConverter.js.map +1 -0
- package/dist/ThaiConverter.js +3 -0
- package/dist/ThaiConverter.js.map +1 -0
- package/dist/TraditionalChineseConverter.js +3 -0
- package/dist/TraditionalChineseConverter.js.map +1 -0
- package/dist/TurkishConverter.js +3 -0
- package/dist/TurkishConverter.js.map +1 -0
- package/dist/UkrainianConverter.js +3 -0
- package/dist/UkrainianConverter.js.map +1 -0
- package/dist/UrduConverter.js +3 -0
- package/dist/UrduConverter.js.map +1 -0
- package/dist/VietnameseConverter.js +3 -0
- package/dist/VietnameseConverter.js.map +1 -0
- package/dist/n2words.js +3 -2
- package/dist/n2words.js.map +1 -1
- package/lib/classes/abstract-language.d.ts +178 -0
- package/lib/classes/abstract-language.js +192 -185
- package/lib/classes/greedy-scale-language.d.ts +109 -0
- package/lib/classes/greedy-scale-language.js +96 -90
- package/lib/classes/slavic-language.d.ts +148 -0
- package/lib/classes/slavic-language.js +136 -106
- package/lib/classes/south-asian-language.d.ts +70 -0
- package/lib/classes/south-asian-language.js +58 -65
- package/lib/classes/turkic-language.d.ts +26 -0
- package/lib/classes/turkic-language.js +22 -26
- package/lib/languages/ar.d.ts +30 -0
- package/lib/languages/ar.js +49 -133
- package/lib/languages/az.d.ts +12 -0
- package/lib/languages/az.js +7 -23
- package/lib/languages/bn.d.ts +11 -0
- package/lib/languages/bn.js +12 -7
- package/lib/languages/cs.d.ts +88 -0
- package/lib/languages/cs.js +44 -113
- package/lib/languages/da.d.ts +15 -0
- package/lib/languages/da.js +40 -87
- package/lib/languages/de.d.ts +14 -0
- package/lib/languages/de.js +34 -68
- package/lib/languages/el.d.ts +14 -0
- package/lib/languages/el.js +22 -48
- package/lib/languages/en.d.ts +16 -0
- package/lib/languages/en.js +22 -59
- package/lib/languages/es.d.ts +15 -0
- package/lib/languages/es.js +49 -81
- package/lib/languages/fa.d.ts +47 -0
- package/lib/languages/fa.js +90 -73
- package/lib/languages/fil.d.ts +16 -0
- package/lib/languages/fil.js +35 -76
- package/lib/languages/fr-BE.d.ts +11 -0
- package/lib/languages/fr-BE.js +15 -51
- package/lib/languages/fr.d.ts +15 -0
- package/lib/languages/fr.js +33 -72
- package/lib/languages/gu.d.ts +11 -0
- package/lib/languages/gu.js +10 -34
- package/lib/languages/hbo.d.ts +113 -0
- package/lib/languages/hbo.js +251 -0
- package/lib/languages/he.d.ts +80 -0
- package/lib/languages/he.js +41 -164
- package/lib/languages/hi.d.ts +11 -0
- package/lib/languages/hi.js +12 -7
- package/lib/languages/hr.d.ts +80 -0
- package/lib/languages/hr.js +51 -95
- package/lib/languages/hu.d.ts +22 -0
- package/lib/languages/hu.js +35 -53
- package/lib/languages/id.d.ts +37 -0
- package/lib/languages/id.js +29 -44
- package/lib/languages/it.d.ts +37 -0
- package/lib/languages/it.js +36 -52
- package/lib/languages/ja.d.ts +17 -0
- package/lib/languages/ja.js +22 -75
- package/lib/languages/kn.d.ts +11 -0
- package/lib/languages/kn.js +10 -39
- package/lib/languages/ko.d.ts +14 -0
- package/lib/languages/ko.js +17 -45
- package/lib/languages/lt.d.ts +70 -0
- package/lib/languages/lt.js +28 -63
- package/lib/languages/lv.d.ts +70 -0
- package/lib/languages/lv.js +35 -58
- package/lib/languages/mr.d.ts +11 -0
- package/lib/languages/mr.js +10 -34
- package/lib/languages/ms.d.ts +31 -0
- package/lib/languages/ms.js +24 -20
- package/lib/languages/nb.d.ts +12 -0
- package/lib/languages/nb.js +36 -56
- package/lib/languages/nl.d.ts +16 -0
- package/lib/languages/nl.js +58 -109
- package/lib/languages/pa.d.ts +11 -0
- package/lib/languages/{pa-Guru.js → pa.js} +12 -7
- package/lib/languages/pl.d.ts +80 -0
- package/lib/languages/pl.js +26 -105
- package/lib/languages/pt.d.ts +29 -0
- package/lib/languages/pt.js +29 -64
- package/lib/languages/ro.d.ts +158 -0
- package/lib/languages/ro.js +60 -167
- package/lib/languages/ru.d.ts +85 -0
- package/lib/languages/ru.js +17 -37
- package/lib/languages/sr-Cyrl.d.ts +80 -0
- package/lib/languages/sr-Cyrl.js +113 -0
- package/lib/languages/sr-Latn.d.ts +80 -0
- package/lib/languages/sr-Latn.js +54 -98
- package/lib/languages/sv.d.ts +14 -0
- package/lib/languages/sv.js +26 -63
- package/lib/languages/sw.d.ts +39 -0
- package/lib/languages/sw.js +26 -21
- package/lib/languages/ta.d.ts +20 -0
- package/lib/languages/ta.js +26 -26
- package/lib/languages/te.d.ts +22 -0
- package/lib/languages/te.js +28 -38
- package/lib/languages/th.d.ts +17 -0
- package/lib/languages/th.js +25 -31
- package/lib/languages/tr.d.ts +12 -0
- package/lib/languages/tr.js +11 -38
- package/lib/languages/uk.d.ts +85 -0
- package/lib/languages/uk.js +18 -44
- package/lib/languages/ur.d.ts +11 -0
- package/lib/languages/ur.js +12 -7
- package/lib/languages/vi.d.ts +72 -0
- package/lib/languages/vi.js +25 -71
- package/lib/languages/zh-Hans.d.ts +21 -0
- package/lib/languages/zh-Hans.js +33 -87
- package/lib/languages/zh-Hant.d.ts +21 -0
- package/lib/languages/zh-Hant.js +111 -0
- package/lib/n2words.d.ts +209 -0
- package/lib/n2words.js +474 -191
- package/package.json +106 -67
- package/dist/languages/ar.js +0 -2
- package/dist/languages/ar.js.map +0 -1
- package/dist/languages/az.js +0 -2
- package/dist/languages/az.js.map +0 -1
- package/dist/languages/bn.js +0 -2
- package/dist/languages/bn.js.map +0 -1
- package/dist/languages/cs.js +0 -2
- package/dist/languages/cs.js.map +0 -1
- package/dist/languages/da.js +0 -2
- package/dist/languages/da.js.map +0 -1
- package/dist/languages/de.js +0 -2
- package/dist/languages/de.js.map +0 -1
- package/dist/languages/el.js +0 -2
- package/dist/languages/el.js.map +0 -1
- package/dist/languages/en.js +0 -2
- package/dist/languages/en.js.map +0 -1
- package/dist/languages/es.js +0 -2
- package/dist/languages/es.js.map +0 -1
- package/dist/languages/fa.js +0 -2
- package/dist/languages/fa.js.map +0 -1
- package/dist/languages/fil.js +0 -2
- package/dist/languages/fil.js.map +0 -1
- package/dist/languages/fr-BE.js +0 -2
- package/dist/languages/fr-BE.js.map +0 -1
- package/dist/languages/fr.js +0 -2
- package/dist/languages/fr.js.map +0 -1
- package/dist/languages/gu.js +0 -2
- package/dist/languages/gu.js.map +0 -1
- package/dist/languages/he.js +0 -2
- package/dist/languages/he.js.map +0 -1
- package/dist/languages/hi.js +0 -2
- package/dist/languages/hi.js.map +0 -1
- package/dist/languages/hr.js +0 -2
- package/dist/languages/hr.js.map +0 -1
- package/dist/languages/hu.js +0 -2
- package/dist/languages/hu.js.map +0 -1
- package/dist/languages/id.js +0 -2
- package/dist/languages/id.js.map +0 -1
- package/dist/languages/it.js +0 -2
- package/dist/languages/it.js.map +0 -1
- package/dist/languages/ja.js +0 -2
- package/dist/languages/ja.js.map +0 -1
- package/dist/languages/kn.js +0 -2
- package/dist/languages/kn.js.map +0 -1
- package/dist/languages/ko.js +0 -2
- package/dist/languages/ko.js.map +0 -1
- package/dist/languages/lt.js +0 -2
- package/dist/languages/lt.js.map +0 -1
- package/dist/languages/lv.js +0 -2
- package/dist/languages/lv.js.map +0 -1
- package/dist/languages/mr.js +0 -2
- package/dist/languages/mr.js.map +0 -1
- package/dist/languages/ms.js +0 -2
- package/dist/languages/ms.js.map +0 -1
- package/dist/languages/nb.js +0 -2
- package/dist/languages/nb.js.map +0 -1
- package/dist/languages/nl.js +0 -2
- package/dist/languages/nl.js.map +0 -1
- package/dist/languages/pa-Guru.js +0 -2
- package/dist/languages/pa-Guru.js.map +0 -1
- package/dist/languages/pl.js +0 -2
- package/dist/languages/pl.js.map +0 -1
- package/dist/languages/pt.js +0 -2
- package/dist/languages/pt.js.map +0 -1
- package/dist/languages/ro.js +0 -2
- package/dist/languages/ro.js.map +0 -1
- package/dist/languages/ru.js +0 -2
- package/dist/languages/ru.js.map +0 -1
- package/dist/languages/sr-Latn.js +0 -2
- package/dist/languages/sr-Latn.js.map +0 -1
- package/dist/languages/sv.js +0 -2
- package/dist/languages/sv.js.map +0 -1
- package/dist/languages/sw.js +0 -2
- package/dist/languages/sw.js.map +0 -1
- package/dist/languages/ta.js +0 -2
- package/dist/languages/ta.js.map +0 -1
- package/dist/languages/te.js +0 -2
- package/dist/languages/te.js.map +0 -1
- package/dist/languages/th.js +0 -2
- package/dist/languages/th.js.map +0 -1
- package/dist/languages/tr.js +0 -2
- package/dist/languages/tr.js.map +0 -1
- package/dist/languages/uk.js +0 -2
- package/dist/languages/uk.js.map +0 -1
- package/dist/languages/ur.js +0 -2
- package/dist/languages/ur.js.map +0 -1
- package/dist/languages/vi.js +0 -2
- package/dist/languages/vi.js.map +0 -1
- package/dist/languages/zh-Hans.js +0 -2
- package/dist/languages/zh-Hans.js.map +0 -1
- package/typings/classes/abstract-language.d.ts +0 -144
- package/typings/classes/greedy-scale-language.d.ts +0 -148
- package/typings/classes/slavic-language.d.ts +0 -145
- package/typings/classes/south-asian-language.d.ts +0 -101
- package/typings/classes/turkic-language.d.ts +0 -42
- package/typings/languages/ar.d.ts +0 -93
- package/typings/languages/az.d.ts +0 -25
- package/typings/languages/bn.d.ts +0 -1
- package/typings/languages/cs.d.ts +0 -120
- package/typings/languages/da.d.ts +0 -53
- package/typings/languages/de.d.ts +0 -26
- package/typings/languages/el.d.ts +0 -11
- package/typings/languages/en.d.ts +0 -30
- package/typings/languages/es.d.ts +0 -43
- package/typings/languages/fa.d.ts +0 -81
- package/typings/languages/fil.d.ts +0 -12
- package/typings/languages/fr-BE.d.ts +0 -41
- package/typings/languages/fr.d.ts +0 -43
- package/typings/languages/gu.d.ts +0 -12
- package/typings/languages/he.d.ts +0 -197
- package/typings/languages/hi.d.ts +0 -1
- package/typings/languages/hr.d.ts +0 -110
- package/typings/languages/hu.d.ts +0 -37
- package/typings/languages/id.d.ts +0 -69
- package/typings/languages/it.d.ts +0 -51
- package/typings/languages/ja.d.ts +0 -58
- package/typings/languages/kn.d.ts +0 -11
- package/typings/languages/ko.d.ts +0 -25
- package/typings/languages/lt.d.ts +0 -110
- package/typings/languages/lv.d.ts +0 -99
- package/typings/languages/mr.d.ts +0 -12
- package/typings/languages/ms.d.ts +0 -37
- package/typings/languages/nb.d.ts +0 -27
- package/typings/languages/nl.d.ts +0 -65
- package/typings/languages/pa-Guru.d.ts +0 -1
- package/typings/languages/pl.d.ts +0 -116
- package/typings/languages/pt.d.ts +0 -39
- package/typings/languages/ro.d.ts +0 -229
- package/typings/languages/ru.d.ts +0 -108
- package/typings/languages/sr-Latn.d.ts +0 -98
- package/typings/languages/sv.d.ts +0 -30
- package/typings/languages/sw.d.ts +0 -1
- package/typings/languages/ta.d.ts +0 -1
- package/typings/languages/te.d.ts +0 -1
- package/typings/languages/th.d.ts +0 -1
- package/typings/languages/tr.d.ts +0 -46
- package/typings/languages/uk.d.ts +0 -117
- package/typings/languages/ur.d.ts +0 -1
- package/typings/languages/vi.d.ts +0 -116
- package/typings/languages/zh-Hans.d.ts +0 -57
- package/typings/n2words.d.ts +0 -177
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Abstract base class for language converters.
|
|
3
|
+
*
|
|
4
|
+
* This class provides the framework for converting numbers to words in any language.
|
|
5
|
+
* It handles the common conversion flow while delegating language-specific logic to subclasses.
|
|
6
|
+
*
|
|
7
|
+
* ## Responsibilities
|
|
8
|
+
*
|
|
9
|
+
* - Receives pre-validated and normalized input from the public API (n2words.js)
|
|
10
|
+
* - Handles negative number prefixing via `negativeWord`
|
|
11
|
+
* - Converts decimals via `decimalDigitsToWords()`, preserving leading zeros
|
|
12
|
+
* - Delegates integer conversion to `integerToWords()` (implemented by subclasses)
|
|
13
|
+
*
|
|
14
|
+
* ## Required Subclass Implementation
|
|
15
|
+
*
|
|
16
|
+
* Subclasses MUST provide:
|
|
17
|
+
* - `integerToWords(integerPart)` - Core conversion logic (abstract method)
|
|
18
|
+
* - `negativeWord` - Word preceding negative numbers (e.g., "minus"))
|
|
19
|
+
* - `zeroWord` - Word for the digit 0 (e.g., "zero")
|
|
20
|
+
* - `decimalSeparatorWord` - Word between whole and decimal parts (e.g., "point")
|
|
21
|
+
*
|
|
22
|
+
* ## Optional Overrides
|
|
23
|
+
*
|
|
24
|
+
* Subclasses MAY override:
|
|
25
|
+
* - `wordSeparator` - Character(s) between words (default: space, empty for CJK languages)
|
|
26
|
+
* - `usePerDigitDecimals` - Enable per-digit decimal mode (default: false)
|
|
27
|
+
* - `decimalIntegerToWords()` - Custom decimal conversion (e.g., Romanian masculine forms)
|
|
28
|
+
* - `decimalDigitsToWords()` - Complete decimal conversion override
|
|
29
|
+
* - `toWords()` - Override to capture integerPart for context-dependent rules (e.g., Czech)
|
|
30
|
+
*
|
|
31
|
+
* ## Input Contract
|
|
32
|
+
*
|
|
33
|
+
* Input validation and normalization happen at the public API boundary (n2words.js).
|
|
34
|
+
* This class assumes it receives clean, pre-processed data via `toWords()`.
|
|
35
|
+
*
|
|
36
|
+
* @abstract
|
|
37
|
+
*/
|
|
38
|
+
export class AbstractLanguage {
|
|
39
|
+
/**
|
|
40
|
+
* Word that precedes negative numbers (e.g., "minus", "negative", "moins").
|
|
41
|
+
* @type {string}
|
|
42
|
+
*/
|
|
43
|
+
negativeWord: string;
|
|
44
|
+
/**
|
|
45
|
+
* Word that separates integer and decimal parts (e.g., "point", "virgule", "comma").
|
|
46
|
+
* @type {string}
|
|
47
|
+
*/
|
|
48
|
+
decimalSeparatorWord: string;
|
|
49
|
+
/**
|
|
50
|
+
* Word representation for the digit 0 (e.g., "zero", "zéro", "null").
|
|
51
|
+
* Used for zero values and leading zeros in decimals.
|
|
52
|
+
* @type {string}
|
|
53
|
+
*/
|
|
54
|
+
zeroWord: string;
|
|
55
|
+
/**
|
|
56
|
+
* Character(s) used to separate words in the output.
|
|
57
|
+
*
|
|
58
|
+
* Defaults to a single space. Set to empty string for languages without
|
|
59
|
+
* word separators (e.g., Japanese, Thai, Chinese).
|
|
60
|
+
*
|
|
61
|
+
* @type {string}
|
|
62
|
+
*/
|
|
63
|
+
wordSeparator: string;
|
|
64
|
+
/**
|
|
65
|
+
* Whether to convert decimal digits individually rather than grouped.
|
|
66
|
+
*
|
|
67
|
+
* - `false` (default): Leading zeros preserved, remaining digits grouped as a number
|
|
68
|
+
* - Example: "05" → ["zero", "five"], "14" → ["fourteen"]
|
|
69
|
+
* - Used by: English, Spanish, French, German, etc.
|
|
70
|
+
*
|
|
71
|
+
* - `true`: Each digit converted separately
|
|
72
|
+
* - Example: "05" → ["zero", "five"], "14" → ["one", "four"]
|
|
73
|
+
* - Used by: Japanese, Thai, Tamil, Telugu, Greek, Hebrew, Filipino
|
|
74
|
+
*
|
|
75
|
+
* @type {boolean}
|
|
76
|
+
*/
|
|
77
|
+
usePerDigitDecimals: boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Read-only access to options set via `setOptions()`.
|
|
80
|
+
* @type {Object}
|
|
81
|
+
*/
|
|
82
|
+
get options(): Object;
|
|
83
|
+
/**
|
|
84
|
+
* Converts pre-normalized numeric components to words.
|
|
85
|
+
*
|
|
86
|
+
* This is the main entry point called by the public API (makeConverter in n2words.js).
|
|
87
|
+
* It assembles the final word representation from the provided components.
|
|
88
|
+
*
|
|
89
|
+
* **Caller contract (enforced by makeConverter):**
|
|
90
|
+
* - `integerPart` is a non-negative BigInt (>= 0n)
|
|
91
|
+
* - `decimalPart` is a string of digits only (no sign, no decimal point)
|
|
92
|
+
* - `isNegative` reflects the original input sign
|
|
93
|
+
*
|
|
94
|
+
* **Conversion flow:**
|
|
95
|
+
* 1. Prepend negative word if applicable
|
|
96
|
+
* 2. Convert integer part via `integerToWords()`
|
|
97
|
+
* 3. If decimals present: append separator and decimal words
|
|
98
|
+
* 4. Join all parts with `wordSeparator`
|
|
99
|
+
*
|
|
100
|
+
* Subclasses needing access to the integer part during decimal conversion
|
|
101
|
+
* (e.g., for context-dependent separator words) should override this
|
|
102
|
+
* method to cache the value before calling super.toWords().
|
|
103
|
+
*
|
|
104
|
+
* @public
|
|
105
|
+
* @param {boolean} isNegative Whether the original number was negative
|
|
106
|
+
* @param {bigint} integerPart The integer part (always non-negative)
|
|
107
|
+
* @param {string} [decimalPart] - Decimal digits if present (e.g., "14" for 3.14)
|
|
108
|
+
* @returns {string} The localized cardinal string
|
|
109
|
+
*/
|
|
110
|
+
public toWords(isNegative: boolean, integerPart: bigint, decimalPart?: string): string;
|
|
111
|
+
/**
|
|
112
|
+
* Converts a BigInt integer part to its cardinal word representation.
|
|
113
|
+
*
|
|
114
|
+
* This is the core template method that subclasses MUST implement to provide
|
|
115
|
+
* language-specific number conversion logic.
|
|
116
|
+
*
|
|
117
|
+
* @abstract
|
|
118
|
+
* @param {bigint} integerPart The integer part to convert (always >= 0n)
|
|
119
|
+
* @returns {string} The cardinal representation in the target language
|
|
120
|
+
* @throws {Error} If not implemented by subclass
|
|
121
|
+
*/
|
|
122
|
+
integerToWords(integerPart: bigint): string;
|
|
123
|
+
/**
|
|
124
|
+
* Sets options by merging language defaults with user-provided options.
|
|
125
|
+
*
|
|
126
|
+
* Merges defaults first, then user options (later keys override earlier ones).
|
|
127
|
+
* Stores the result in the private `#options` field, accessible via the
|
|
128
|
+
* read-only `options` getter.
|
|
129
|
+
*
|
|
130
|
+
* @protected
|
|
131
|
+
* @param {Object} [defaults={}] - Default option values for the language
|
|
132
|
+
* @param {Object} [userOptions={}] - Runtime options supplied by the caller
|
|
133
|
+
*
|
|
134
|
+
* @example
|
|
135
|
+
* constructor(options = {}) {
|
|
136
|
+
* super()
|
|
137
|
+
* this.setOptions({ gender: 'masculine' }, options)
|
|
138
|
+
* }
|
|
139
|
+
*/
|
|
140
|
+
protected setOptions(defaults?: Object, userOptions?: Object): void;
|
|
141
|
+
/**
|
|
142
|
+
* Converts an integer to words in decimal context.
|
|
143
|
+
*
|
|
144
|
+
* By default, delegates to `integerToWords()`. Override this method
|
|
145
|
+
* when decimal conversion requires different behavior than integer conversion.
|
|
146
|
+
*
|
|
147
|
+
* Called with:
|
|
148
|
+
* - Single digits (0-9) when `usePerDigitDecimals = true`
|
|
149
|
+
* - Grouped numbers when `usePerDigitDecimals = false`
|
|
150
|
+
*
|
|
151
|
+
* **Use cases for overriding:**
|
|
152
|
+
* - Romanian: Decimals always use masculine forms regardless of gender option
|
|
153
|
+
* - Languages with different plural/gender rules for decimal vs integer parts
|
|
154
|
+
*
|
|
155
|
+
* @protected
|
|
156
|
+
* @param {bigint} integerPart The integer to convert (single digit or grouped)
|
|
157
|
+
* @returns {string} The word representation for use in decimal context
|
|
158
|
+
*/
|
|
159
|
+
protected decimalIntegerToWords(integerPart: bigint): string;
|
|
160
|
+
/**
|
|
161
|
+
* Converts decimal fractional digits into an array of words.
|
|
162
|
+
*
|
|
163
|
+
* Leading zeros are always preserved individually. The remaining digits
|
|
164
|
+
* are converted based on `usePerDigitDecimals`:
|
|
165
|
+
*
|
|
166
|
+
* - `false` (default): Remaining digits grouped as a single number
|
|
167
|
+
* - "05" → ["zero", "five"], "14" → ["fourteen"]
|
|
168
|
+
*
|
|
169
|
+
* - `true`: Each remaining digit converted separately
|
|
170
|
+
* - "05" → ["zero", "five"], "14" → ["one", "four"]
|
|
171
|
+
*
|
|
172
|
+
* @protected
|
|
173
|
+
* @param {string} decimalPart Decimal digits as string (e.g., "05" for 3.05)
|
|
174
|
+
* @returns {string[]} Array of word tokens for the fractional part
|
|
175
|
+
*/
|
|
176
|
+
protected decimalDigitsToWords(decimalPart: string): string[];
|
|
177
|
+
#private;
|
|
178
|
+
}
|
|
@@ -1,25 +1,55 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Abstract base class for language converters.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* - Splits sign, whole, and decimal parts, caching the whole part for languages that need it.
|
|
7
|
-
* - Delegates whole-number wording to `convertWholePart(wholeNumber)` implemented by subclasses.
|
|
8
|
-
* - Converts decimals via `decimalDigitsToWords()`, preserving leading zeros and supporting per-digit mode when `convertDecimalsPerDigit` is true.
|
|
4
|
+
* This class provides the framework for converting numbers to words in any language.
|
|
5
|
+
* It handles the common conversion flow while delegating language-specific logic to subclasses.
|
|
9
6
|
*
|
|
10
|
-
*
|
|
11
|
-
* - `convertWholePart(wholeNumber)` method implementation (required; abstract).
|
|
12
|
-
* - `negativeWord` class property (word preceding negative numbers, e.g., "minus").
|
|
13
|
-
* - `zeroWord` class property (word for digit 0, e.g., "zero").
|
|
14
|
-
* - `decimalSeparatorWord` class property (word between whole and decimal, e.g., "point").
|
|
15
|
-
* - `wordSeparator` class property (word separator in output, typically a space).
|
|
16
|
-
* Optional: override `convertDecimalsPerDigit`, `digits`, or `convertDigitToWord()` for custom behavior.
|
|
7
|
+
* ## Responsibilities
|
|
17
8
|
*
|
|
18
|
-
*
|
|
9
|
+
* - Receives pre-validated and normalized input from the public API (n2words.js)
|
|
10
|
+
* - Handles negative number prefixing via `negativeWord`
|
|
11
|
+
* - Converts decimals via `decimalDigitsToWords()`, preserving leading zeros
|
|
12
|
+
* - Delegates integer conversion to `integerToWords()` (implemented by subclasses)
|
|
13
|
+
*
|
|
14
|
+
* ## Required Subclass Implementation
|
|
15
|
+
*
|
|
16
|
+
* Subclasses MUST provide:
|
|
17
|
+
* - `integerToWords(integerPart)` - Core conversion logic (abstract method)
|
|
18
|
+
* - `negativeWord` - Word preceding negative numbers (e.g., "minus"))
|
|
19
|
+
* - `zeroWord` - Word for the digit 0 (e.g., "zero")
|
|
20
|
+
* - `decimalSeparatorWord` - Word between whole and decimal parts (e.g., "point")
|
|
21
|
+
*
|
|
22
|
+
* ## Optional Overrides
|
|
23
|
+
*
|
|
24
|
+
* Subclasses MAY override:
|
|
25
|
+
* - `wordSeparator` - Character(s) between words (default: space, empty for CJK languages)
|
|
26
|
+
* - `usePerDigitDecimals` - Enable per-digit decimal mode (default: false)
|
|
27
|
+
* - `decimalIntegerToWords()` - Custom decimal conversion (e.g., Romanian masculine forms)
|
|
28
|
+
* - `decimalDigitsToWords()` - Complete decimal conversion override
|
|
29
|
+
* - `toWords()` - Override to capture integerPart for context-dependent rules (e.g., Czech)
|
|
30
|
+
*
|
|
31
|
+
* ## Input Contract
|
|
32
|
+
*
|
|
33
|
+
* Input validation and normalization happen at the public API boundary (n2words.js).
|
|
34
|
+
* This class assumes it receives clean, pre-processed data via `toWords()`.
|
|
19
35
|
*
|
|
20
36
|
* @abstract
|
|
21
37
|
*/
|
|
22
|
-
class AbstractLanguage {
|
|
38
|
+
export class AbstractLanguage {
|
|
39
|
+
// ============================================================================
|
|
40
|
+
// Private Fields
|
|
41
|
+
// ============================================================================
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Private storage for options.
|
|
45
|
+
* @type {Object}
|
|
46
|
+
*/
|
|
47
|
+
#options = {}
|
|
48
|
+
|
|
49
|
+
// ============================================================================
|
|
50
|
+
// Required Properties (subclasses must define)
|
|
51
|
+
// ============================================================================
|
|
52
|
+
|
|
23
53
|
/**
|
|
24
54
|
* Word that precedes negative numbers (e.g., "minus", "negative", "moins").
|
|
25
55
|
* @type {string}
|
|
@@ -27,235 +57,212 @@ class AbstractLanguage {
|
|
|
27
57
|
negativeWord = ''
|
|
28
58
|
|
|
29
59
|
/**
|
|
30
|
-
* Word that separates
|
|
60
|
+
* Word that separates integer and decimal parts (e.g., "point", "virgule", "comma").
|
|
31
61
|
* @type {string}
|
|
32
62
|
*/
|
|
33
63
|
decimalSeparatorWord = ''
|
|
34
64
|
|
|
35
65
|
/**
|
|
36
66
|
* Word representation for the digit 0 (e.g., "zero", "zéro", "null").
|
|
67
|
+
* Used for zero values and leading zeros in decimals.
|
|
37
68
|
* @type {string}
|
|
38
69
|
*/
|
|
39
70
|
zeroWord = ''
|
|
40
71
|
|
|
72
|
+
// ============================================================================
|
|
73
|
+
// Optional Properties (subclasses may override)
|
|
74
|
+
// ============================================================================
|
|
75
|
+
|
|
41
76
|
/**
|
|
42
|
-
* Character(s) used to separate words in the output
|
|
77
|
+
* Character(s) used to separate words in the output.
|
|
78
|
+
*
|
|
79
|
+
* Defaults to a single space. Set to empty string for languages without
|
|
80
|
+
* word separators (e.g., Japanese, Thai, Chinese).
|
|
81
|
+
*
|
|
43
82
|
* @type {string}
|
|
44
83
|
*/
|
|
45
84
|
wordSeparator = ' '
|
|
46
85
|
|
|
47
|
-
/**
|
|
48
|
-
* Cached whole number portion from the most recent conversion.
|
|
49
|
-
* Some languages need access to this value during conversion for
|
|
50
|
-
* pluralization rules or special cases (e.g., Czech, Hebrew).
|
|
51
|
-
* @type {bigint}
|
|
52
|
-
*/
|
|
53
|
-
cachedWholeNumber = 0n
|
|
54
|
-
|
|
55
86
|
/**
|
|
56
87
|
* Whether to convert decimal digits individually rather than grouped.
|
|
57
|
-
*
|
|
58
|
-
* - `false
|
|
59
|
-
*
|
|
88
|
+
*
|
|
89
|
+
* - `false` (default): Leading zeros preserved, remaining digits grouped as a number
|
|
90
|
+
* - Example: "05" → ["zero", "five"], "14" → ["fourteen"]
|
|
91
|
+
* - Used by: English, Spanish, French, German, etc.
|
|
92
|
+
*
|
|
93
|
+
* - `true`: Each digit converted separately
|
|
94
|
+
* - Example: "05" → ["zero", "five"], "14" → ["one", "four"]
|
|
95
|
+
* - Used by: Japanese, Thai, Tamil, Telugu, Greek, Hebrew, Filipino
|
|
96
|
+
*
|
|
60
97
|
* @type {boolean}
|
|
61
98
|
*/
|
|
62
|
-
|
|
99
|
+
usePerDigitDecimals = false
|
|
100
|
+
|
|
101
|
+
// ============================================================================
|
|
102
|
+
// Public Accessors
|
|
103
|
+
// ============================================================================
|
|
63
104
|
|
|
64
105
|
/**
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
* - Length 9: indices 0–8 map to words for digits 1–9
|
|
68
|
-
* - `null`: Falls back to `convertWholePart()` for digit conversion
|
|
69
|
-
* @type {string[]|null}
|
|
106
|
+
* Read-only access to options set via `setOptions()`.
|
|
107
|
+
* @type {Object}
|
|
70
108
|
*/
|
|
71
|
-
|
|
109
|
+
get options () {
|
|
110
|
+
return this.#options
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// ============================================================================
|
|
114
|
+
// Public Methods
|
|
115
|
+
// ============================================================================
|
|
72
116
|
|
|
73
117
|
/**
|
|
74
|
-
*
|
|
118
|
+
* Converts pre-normalized numeric components to words.
|
|
75
119
|
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
* - If a `digits` array is present, use it for direct lookup
|
|
79
|
-
* - Length 10: indices 0–9 map directly
|
|
80
|
-
* - Length 9: indices 1–9 map via `idx - 1`
|
|
81
|
-
* - Otherwise delegate to `convertWholePart(digit)`
|
|
120
|
+
* This is the main entry point called by the public API (makeConverter in n2words.js).
|
|
121
|
+
* It assembles the final word representation from the provided components.
|
|
82
122
|
*
|
|
83
|
-
*
|
|
123
|
+
* **Caller contract (enforced by makeConverter):**
|
|
124
|
+
* - `integerPart` is a non-negative BigInt (>= 0n)
|
|
125
|
+
* - `decimalPart` is a string of digits only (no sign, no decimal point)
|
|
126
|
+
* - `isNegative` reflects the original input sign
|
|
84
127
|
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
128
|
+
* **Conversion flow:**
|
|
129
|
+
* 1. Prepend negative word if applicable
|
|
130
|
+
* 2. Convert integer part via `integerToWords()`
|
|
131
|
+
* 3. If decimals present: append separator and decimal words
|
|
132
|
+
* 4. Join all parts with `wordSeparator`
|
|
133
|
+
*
|
|
134
|
+
* Subclasses needing access to the integer part during decimal conversion
|
|
135
|
+
* (e.g., for context-dependent separator words) should override this
|
|
136
|
+
* method to cache the value before calling super.toWords().
|
|
137
|
+
*
|
|
138
|
+
* @public
|
|
139
|
+
* @param {boolean} isNegative Whether the original number was negative
|
|
140
|
+
* @param {bigint} integerPart The integer part (always non-negative)
|
|
141
|
+
* @param {string} [decimalPart] - Decimal digits if present (e.g., "14" for 3.14)
|
|
142
|
+
* @returns {string} The localized cardinal string
|
|
88
143
|
*/
|
|
89
|
-
|
|
90
|
-
const
|
|
91
|
-
if (idx === 0) return this.zeroWord
|
|
144
|
+
toWords (isNegative, integerPart, decimalPart) {
|
|
145
|
+
const words = []
|
|
92
146
|
|
|
93
|
-
if (
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
147
|
+
if (isNegative) words.push(this.negativeWord)
|
|
148
|
+
|
|
149
|
+
words.push(this.integerToWords(integerPart))
|
|
150
|
+
|
|
151
|
+
if (decimalPart) {
|
|
152
|
+
words.push(this.decimalSeparatorWord)
|
|
153
|
+
words.push(...this.decimalDigitsToWords(decimalPart))
|
|
100
154
|
}
|
|
101
155
|
|
|
102
|
-
return this.
|
|
156
|
+
return words.join(this.wordSeparator)
|
|
103
157
|
}
|
|
104
158
|
|
|
159
|
+
// ============================================================================
|
|
160
|
+
// Abstract Methods (subclasses must implement)
|
|
161
|
+
// ============================================================================
|
|
162
|
+
|
|
105
163
|
/**
|
|
106
|
-
*
|
|
164
|
+
* Converts a BigInt integer part to its cardinal word representation.
|
|
107
165
|
*
|
|
108
|
-
|
|
166
|
+
* This is the core template method that subclasses MUST implement to provide
|
|
167
|
+
* language-specific number conversion logic.
|
|
109
168
|
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
169
|
+
* @abstract
|
|
170
|
+
* @param {bigint} integerPart The integer part to convert (always >= 0n)
|
|
171
|
+
* @returns {string} The cardinal representation in the target language
|
|
172
|
+
* @throws {Error} If not implemented by subclass
|
|
173
|
+
*/
|
|
174
|
+
integerToWords (integerPart) {
|
|
175
|
+
throw new Error('integerToWords() must be implemented by subclass')
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// ============================================================================
|
|
179
|
+
// Protected Methods (subclasses may override or call)
|
|
180
|
+
// ============================================================================
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Sets options by merging language defaults with user-provided options.
|
|
114
184
|
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
* -
|
|
118
|
-
* - Example: "05" -> [zero, 'five'], "14" -> ['fourteen']
|
|
119
|
-
* - Used by: Most languages (English, Spanish, French, etc.)
|
|
185
|
+
* Merges defaults first, then user options (later keys override earlier ones).
|
|
186
|
+
* Stores the result in the private `#options` field, accessible via the
|
|
187
|
+
* read-only `options` getter.
|
|
120
188
|
*
|
|
121
189
|
* @protected
|
|
122
|
-
* @param {
|
|
123
|
-
* @
|
|
190
|
+
* @param {Object} [defaults={}] - Default option values for the language
|
|
191
|
+
* @param {Object} [userOptions={}] - Runtime options supplied by the caller
|
|
124
192
|
*
|
|
125
193
|
* @example
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
* // Grouped mode
|
|
131
|
-
* decimalDigitsToWords('05'); // -> [this.zeroWord, 'five']
|
|
132
|
-
* decimalDigitsToWords('14'); // -> ['fourteen']
|
|
194
|
+
* constructor(options = {}) {
|
|
195
|
+
* super()
|
|
196
|
+
* this.setOptions({ gender: 'masculine' }, options)
|
|
197
|
+
* }
|
|
133
198
|
*/
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
if (this.convertDecimalsPerDigit) {
|
|
139
|
-
for (let i = 0; i < len; i++) {
|
|
140
|
-
const decimalDigit = BigInt(decimalString[i])
|
|
141
|
-
words.push(this.convertDigitToWord(decimalDigit))
|
|
142
|
-
}
|
|
143
|
-
return words
|
|
199
|
+
setOptions (defaults = {}, userOptions = {}) {
|
|
200
|
+
this.#options = {
|
|
201
|
+
...defaults,
|
|
202
|
+
...userOptions
|
|
144
203
|
}
|
|
204
|
+
}
|
|
145
205
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
206
|
+
/**
|
|
207
|
+
* Converts an integer to words in decimal context.
|
|
208
|
+
*
|
|
209
|
+
* By default, delegates to `integerToWords()`. Override this method
|
|
210
|
+
* when decimal conversion requires different behavior than integer conversion.
|
|
211
|
+
*
|
|
212
|
+
* Called with:
|
|
213
|
+
* - Single digits (0-9) when `usePerDigitDecimals = true`
|
|
214
|
+
* - Grouped numbers when `usePerDigitDecimals = false`
|
|
215
|
+
*
|
|
216
|
+
* **Use cases for overriding:**
|
|
217
|
+
* - Romanian: Decimals always use masculine forms regardless of gender option
|
|
218
|
+
* - Languages with different plural/gender rules for decimal vs integer parts
|
|
219
|
+
*
|
|
220
|
+
* @protected
|
|
221
|
+
* @param {bigint} integerPart The integer to convert (single digit or grouped)
|
|
222
|
+
* @returns {string} The word representation for use in decimal context
|
|
223
|
+
*/
|
|
224
|
+
decimalIntegerToWords (integerPart) {
|
|
225
|
+
return this.integerToWords(integerPart)
|
|
159
226
|
}
|
|
160
227
|
|
|
161
228
|
/**
|
|
162
|
-
*
|
|
229
|
+
* Converts decimal fractional digits into an array of words.
|
|
163
230
|
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
* fractional parts, and delegates whole-number conversion to
|
|
167
|
-
* `convertWholePart(BigInt)` and fractional conversion to `decimalDigitsToWords()`.
|
|
231
|
+
* Leading zeros are always preserved individually. The remaining digits
|
|
232
|
+
* are converted based on `usePerDigitDecimals`:
|
|
168
233
|
*
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
* - Passing a non-numeric `string` throws `Error`.
|
|
172
|
-
* - Passing an unsupported type throws `TypeError`.
|
|
234
|
+
* - `false` (default): Remaining digits grouped as a single number
|
|
235
|
+
* - "05" → ["zero", "five"], "14" → ["fourteen"]
|
|
173
236
|
*
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
*
|
|
177
|
-
* @
|
|
237
|
+
* - `true`: Each remaining digit converted separately
|
|
238
|
+
* - "05" → ["zero", "five"], "14" → ["one", "four"]
|
|
239
|
+
*
|
|
240
|
+
* @protected
|
|
241
|
+
* @param {string} decimalPart Decimal digits as string (e.g., "05" for 3.05)
|
|
242
|
+
* @returns {string[]} Array of word tokens for the fractional part
|
|
178
243
|
*/
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
const inputType = typeof value
|
|
244
|
+
decimalDigitsToWords (decimalPart) {
|
|
245
|
+
const words = []
|
|
182
246
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
if (value.length === 0 || Number.isNaN(Number(value))) { throw new Error('Invalid number format: "' + value + '"') }
|
|
189
|
-
} else if (inputType !== 'bigint') {
|
|
190
|
-
throw new TypeError(
|
|
191
|
-
'Invalid variable type, expected number|string|bigint, received: ' + inputType
|
|
192
|
-
)
|
|
247
|
+
// Always preserve leading zeros individually
|
|
248
|
+
let i = 0
|
|
249
|
+
while (i < decimalPart.length && decimalPart[i] === '0') {
|
|
250
|
+
words.push(this.zeroWord)
|
|
251
|
+
i++
|
|
193
252
|
}
|
|
194
253
|
|
|
195
|
-
const
|
|
254
|
+
const remainder = decimalPart.slice(i)
|
|
255
|
+
if (!remainder) return words
|
|
196
256
|
|
|
197
|
-
//
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
if (value < 0n) {
|
|
202
|
-
isNegative = true
|
|
203
|
-
value = -value
|
|
204
|
-
}
|
|
205
|
-
} else {
|
|
206
|
-
// For strings, check first character before normalization
|
|
207
|
-
if (value[0] === '-') {
|
|
208
|
-
isNegative = true
|
|
209
|
-
value = value.slice(1)
|
|
257
|
+
// Convert remainder: per-digit or as single number
|
|
258
|
+
if (this.usePerDigitDecimals) {
|
|
259
|
+
for (const char of remainder) {
|
|
260
|
+
words.push(this.decimalIntegerToWords(BigInt(char)))
|
|
210
261
|
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// Extract whole and decimal parts based on type.
|
|
214
|
-
// BigInt has no decimal point; strings may contain a single '.'.
|
|
215
|
-
// Default whole part to '0' if empty (e.g., '.5' -> '0' + '.5')
|
|
216
|
-
let wholeNumber
|
|
217
|
-
let decimalPart
|
|
218
|
-
if (inputType === 'bigint') {
|
|
219
|
-
wholeNumber = value
|
|
220
262
|
} else {
|
|
221
|
-
|
|
222
|
-
if (decimalPointIndex === -1) {
|
|
223
|
-
wholeNumber = BigInt(value)
|
|
224
|
-
} else {
|
|
225
|
-
const wholePartString = value.slice(0, decimalPointIndex) || '0'
|
|
226
|
-
wholeNumber = BigInt(wholePartString)
|
|
227
|
-
decimalPart = value.slice(decimalPointIndex + 1)
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
this.cachedWholeNumber = wholeNumber
|
|
232
|
-
|
|
233
|
-
if (isNegative) words.push(this.negativeWord)
|
|
234
|
-
|
|
235
|
-
words.push(this.convertWholePart(wholeNumber))
|
|
236
|
-
|
|
237
|
-
// Append decimal portion if present (separator + fractional digits)
|
|
238
|
-
if (decimalPart) {
|
|
239
|
-
words.push(this.decimalSeparatorWord)
|
|
240
|
-
words.push(...this.decimalDigitsToWords(decimalPart))
|
|
263
|
+
words.push(this.decimalIntegerToWords(BigInt(remainder)))
|
|
241
264
|
}
|
|
242
265
|
|
|
243
|
-
return words
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
/**
|
|
247
|
-
* Convert a BigInt whole number to its cardinal word representation.
|
|
248
|
-
*
|
|
249
|
-
* This is a template method that subclasses MUST implement to provide
|
|
250
|
-
* language-specific number conversion logic.
|
|
251
|
-
*
|
|
252
|
-
* @abstract
|
|
253
|
-
* @param {bigint} wholeNumber The whole number part to convert
|
|
254
|
-
* @returns {string} The cardinal representation in the target language
|
|
255
|
-
*/
|
|
256
|
-
convertWholePart (wholeNumber) {
|
|
257
|
-
throw new Error('convertWholePart() must be implemented by subclass')
|
|
266
|
+
return words
|
|
258
267
|
}
|
|
259
268
|
}
|
|
260
|
-
|
|
261
|
-
export default AbstractLanguage
|