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
|
@@ -1,196 +1,228 @@
|
|
|
1
|
-
import AbstractLanguage from './abstract-language.js'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @typedef {string[]} SlavicPluralForms
|
|
5
|
-
* Array of three plural forms for Slavic languages:
|
|
6
|
-
* - [0]: Singular form (for numbers ending in 1, except 11)
|
|
7
|
-
* - [1]: Few form (for numbers ending in 2-4, except 12-14)
|
|
8
|
-
* - [2]: Many form (for all other numbers: 0, 5-20, and numbers ending in 0, 5-9, 11-19)
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* @typedef {Object.<string, SlavicPluralForms>} SlavicThousandsMap
|
|
13
|
-
* Mapping from power indices to their plural forms.
|
|
14
|
-
* Example: { '0': ['тысяча', 'тысячи', 'тысяч'], '1': ['миллион', 'миллиона', 'миллионов'] }
|
|
15
|
-
*/
|
|
1
|
+
import { AbstractLanguage } from './abstract-language.js'
|
|
16
2
|
|
|
17
3
|
/**
|
|
18
4
|
* Base class for Slavic and related languages with complex pluralization.
|
|
19
5
|
*
|
|
20
6
|
* This class provides a reusable implementation for languages that share:
|
|
21
7
|
* - Three-form pluralization (singular/few/many)
|
|
22
|
-
* - Gender-aware number forms (masculine/feminine for 1
|
|
23
|
-
* - Hundreds, tens, ones decomposition
|
|
24
|
-
* -
|
|
8
|
+
* - Gender-aware number forms (masculine/feminine for 1-9)
|
|
9
|
+
* - Hundreds, tens, ones decomposition pattern
|
|
10
|
+
* - Segment-based large number handling (thousands, millions, etc.)
|
|
25
11
|
* - Inherits decimal handling from AbstractLanguage (supports both grouped and
|
|
26
|
-
* per-digit modes via the `
|
|
12
|
+
* per-digit modes via the `usePerDigitDecimals` class property).
|
|
27
13
|
*
|
|
28
|
-
* Used by: Russian, Czech, Polish, Ukrainian, Serbian
|
|
29
|
-
*
|
|
14
|
+
* Used by: Russian (ru), Czech (cs), Polish (pl), Ukrainian (uk), Serbian (sr-Latn),
|
|
15
|
+
* Croatian (hr), Lithuanian (lt), Latvian (lv), Hebrew (he), and Biblical Hebrew (hbo).
|
|
30
16
|
*
|
|
31
17
|
* Subclasses MUST define these properties with language-specific vocabulary:
|
|
32
|
-
* - `
|
|
33
|
-
* - `
|
|
34
|
-
* - `
|
|
35
|
-
* - `
|
|
36
|
-
* - `
|
|
37
|
-
* - `
|
|
38
|
-
*
|
|
18
|
+
* - `onesWords` - Object mapping 1-9 to masculine forms (or default forms)
|
|
19
|
+
* - `onesFeminineWords` - Object mapping 1-9 to feminine forms (if gender distinction exists)
|
|
20
|
+
* - `teensWords` - Object mapping 0-9 to teen numbers (10-19)
|
|
21
|
+
* - `twentiesWords` - Object mapping 2-9 to tens (20-90)
|
|
22
|
+
* - `hundredsWords` - Object mapping 1-9 to hundreds (100-900) or special hundreds handling
|
|
23
|
+
* - `pluralForms` - Object mapping segment indices to [singular, few, many] plural forms
|
|
24
|
+
*
|
|
25
|
+
* Optional properties:
|
|
26
|
+
* - `scaleGenders` - Object mapping segment indices to boolean (true = feminine scale word)
|
|
27
|
+
* If not defined, defaults to thousands (index 1) being feminine, others masculine.
|
|
39
28
|
*
|
|
40
29
|
* @abstract
|
|
41
30
|
* @extends AbstractLanguage
|
|
42
31
|
*/
|
|
43
|
-
class SlavicLanguage extends AbstractLanguage {
|
|
32
|
+
export class SlavicLanguage extends AbstractLanguage {
|
|
33
|
+
// ============================================================================
|
|
34
|
+
// Required Properties (subclasses must define)
|
|
35
|
+
// ============================================================================
|
|
36
|
+
|
|
44
37
|
/**
|
|
45
|
-
* Masculine forms for digits 1-9.
|
|
38
|
+
* Masculine forms for digits 1-9 (or default forms if no gender distinction).
|
|
46
39
|
*
|
|
47
|
-
* @type {
|
|
40
|
+
* @type {Object.<number, string>}
|
|
48
41
|
*/
|
|
49
|
-
|
|
42
|
+
onesWords = {}
|
|
50
43
|
|
|
51
44
|
/**
|
|
52
|
-
* Feminine forms for digits 1-9.
|
|
45
|
+
* Feminine forms for digits 1-9 (if language has gender distinction).
|
|
53
46
|
*
|
|
54
|
-
* @type {
|
|
47
|
+
* @type {Object.<number, string>}
|
|
55
48
|
*/
|
|
56
|
-
|
|
49
|
+
onesFeminineWords = {}
|
|
57
50
|
|
|
58
51
|
/**
|
|
59
|
-
* Words for
|
|
52
|
+
* Words for teen numbers (10-19).
|
|
60
53
|
*
|
|
61
|
-
* @type {
|
|
54
|
+
* @type {Object.<number, string>}
|
|
62
55
|
*/
|
|
63
|
-
|
|
56
|
+
teensWords = {}
|
|
64
57
|
|
|
65
58
|
/**
|
|
66
|
-
*
|
|
59
|
+
* Words for multiples of ten (20, 30, 40, etc.).
|
|
67
60
|
*
|
|
68
|
-
* @type {
|
|
61
|
+
* @type {Object.<number, string>}
|
|
69
62
|
*/
|
|
70
|
-
|
|
63
|
+
twentiesWords = {}
|
|
71
64
|
|
|
72
65
|
/**
|
|
73
|
-
* Words for hundreds (100, 200, 300, etc.).
|
|
66
|
+
* Words for hundreds (100, 200, 300, etc.) or special hundreds handling.
|
|
74
67
|
*
|
|
75
|
-
* @type {
|
|
68
|
+
* @type {Object.<number, string>}
|
|
76
69
|
*/
|
|
77
|
-
|
|
70
|
+
hundredsWords = {}
|
|
78
71
|
|
|
79
72
|
/**
|
|
80
|
-
*
|
|
73
|
+
* Plural forms for scale words (thousands, millions, billions, etc.).
|
|
74
|
+
* Maps segment indices to [singular, few, many] forms.
|
|
81
75
|
*
|
|
82
|
-
* @type {
|
|
76
|
+
* @type {Object.<number, string[]>}
|
|
83
77
|
*/
|
|
84
|
-
|
|
78
|
+
pluralForms = {}
|
|
79
|
+
|
|
80
|
+
// ============================================================================
|
|
81
|
+
// Optional Properties (subclasses may override)
|
|
82
|
+
// ============================================================================
|
|
85
83
|
|
|
86
84
|
/**
|
|
87
|
-
*
|
|
85
|
+
* Gender of each scale word.
|
|
86
|
+
* Maps segment indices to boolean: true = feminine, false = masculine.
|
|
87
|
+
* Default is empty (all masculine). Languages with feminine thousands
|
|
88
|
+
* (Russian, Ukrainian, Serbian, Croatian) should set `{ 1: true }`.
|
|
89
|
+
*
|
|
90
|
+
* @type {Object.<number, boolean>}
|
|
91
|
+
*/
|
|
92
|
+
scaleGenders = {}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Whether to omit "one" before scale words (e.g., "thousand" instead of "one thousand").
|
|
96
|
+
* When true, 1000 becomes "tysiąc" (Polish) instead of "jeden tysiąc".
|
|
97
|
+
* Used by Polish, Czech, and similar languages.
|
|
88
98
|
*
|
|
89
99
|
* @type {boolean}
|
|
90
100
|
*/
|
|
91
|
-
|
|
101
|
+
omitOneBeforeScale = false
|
|
102
|
+
|
|
103
|
+
// ============================================================================
|
|
104
|
+
// Constructor
|
|
105
|
+
// ============================================================================
|
|
92
106
|
|
|
93
107
|
/**
|
|
94
|
-
*
|
|
108
|
+
* Constructs a SlavicLanguage instance with optional configuration.
|
|
95
109
|
*
|
|
96
|
-
* @param {Object} [options
|
|
97
|
-
* @param {
|
|
110
|
+
* @param {Object} [options] Configuration options.
|
|
111
|
+
* @param {('masculine'|'feminine')} [options.gender='masculine'] Grammatical gender for number forms.
|
|
98
112
|
*/
|
|
99
|
-
constructor (
|
|
113
|
+
constructor (options = {}) {
|
|
100
114
|
super()
|
|
101
115
|
|
|
102
|
-
this.
|
|
116
|
+
this.setOptions({
|
|
117
|
+
gender: 'masculine'
|
|
118
|
+
}, options)
|
|
103
119
|
}
|
|
104
120
|
|
|
121
|
+
// ============================================================================
|
|
122
|
+
// Public Methods
|
|
123
|
+
// ============================================================================
|
|
124
|
+
|
|
105
125
|
/**
|
|
106
|
-
* Converts
|
|
126
|
+
* Converts an integer to its word representation.
|
|
107
127
|
*
|
|
108
128
|
* This method implements the Slavic number construction algorithm:
|
|
109
|
-
* 1. Split number into 3-digit
|
|
110
|
-
* 2. For each
|
|
111
|
-
* 3. Apply gender rules
|
|
112
|
-
* 4. Add pluralized
|
|
129
|
+
* 1. Split number into 3-digit segments from right to left (567, 234, 1 for 1,234,567)
|
|
130
|
+
* 2. For each segment (processing left to right): convert hundreds, tens, ones
|
|
131
|
+
* 3. Apply gender rules: feminine forms for thousands segment or when feminine=true
|
|
132
|
+
* 4. Add appropriate pluralized scale word (thousand/million/billion/etc.)
|
|
113
133
|
* 5. Join all parts with spaces
|
|
114
134
|
*
|
|
115
|
-
* @param {bigint}
|
|
135
|
+
* @param {bigint} integerPart The integer to convert (non-negative).
|
|
116
136
|
* @returns {string} The number in words.
|
|
117
137
|
*/
|
|
118
|
-
|
|
119
|
-
if (
|
|
138
|
+
integerToWords (integerPart) {
|
|
139
|
+
if (integerPart === 0n) {
|
|
120
140
|
return this.zeroWord
|
|
121
141
|
}
|
|
122
142
|
|
|
123
143
|
const words = []
|
|
124
|
-
const
|
|
125
|
-
let
|
|
144
|
+
const segments = this.splitToSegments(integerPart.toString(), 3)
|
|
145
|
+
let segmentIndex = segments.length
|
|
126
146
|
|
|
127
|
-
for (const
|
|
128
|
-
|
|
147
|
+
for (const segmentValue of segments) {
|
|
148
|
+
segmentIndex = segmentIndex - 1
|
|
129
149
|
|
|
130
|
-
if (
|
|
150
|
+
if (segmentValue === 0n) {
|
|
131
151
|
continue
|
|
132
152
|
}
|
|
133
153
|
|
|
134
|
-
const [onesDigit, tensDigit, hundredsDigit] = this.
|
|
154
|
+
const [onesDigit, tensDigit, hundredsDigit] = this.extractDigits(segmentValue)
|
|
135
155
|
|
|
136
156
|
if (hundredsDigit > 0n) {
|
|
137
|
-
words.push(this.
|
|
157
|
+
words.push(this.hundredsWords[hundredsDigit])
|
|
138
158
|
}
|
|
139
159
|
|
|
140
160
|
if (tensDigit > 1n) {
|
|
141
|
-
words.push(this.
|
|
161
|
+
words.push(this.twentiesWords[tensDigit])
|
|
142
162
|
}
|
|
143
163
|
|
|
144
164
|
// Handle teens (10-19) or ones (1-9)
|
|
145
165
|
if (tensDigit === 1n) {
|
|
146
|
-
// Teens: use
|
|
147
|
-
words.push(this.
|
|
166
|
+
// Teens: use teensWords array directly
|
|
167
|
+
words.push(this.teensWords[onesDigit])
|
|
148
168
|
} else if (onesDigit > 0n) {
|
|
149
|
-
//
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
169
|
+
// Skip "one" before scale words if omitOneBeforeScale is set
|
|
170
|
+
// e.g., Polish says "tysiąc" not "jeden tysiąc" for 1000
|
|
171
|
+
const shouldOmitOne = this.omitOneBeforeScale && segmentIndex > 0 && segmentValue === 1n
|
|
172
|
+
|
|
173
|
+
if (!shouldOmitOne) {
|
|
174
|
+
// Determine if feminine forms should be used:
|
|
175
|
+
// 1. Check scaleGenders for this segment index (e.g., thousands = index 1)
|
|
176
|
+
// 2. Also use feminine if user requested gender='feminine' for the ones segment
|
|
177
|
+
const isScaleFeminine = this.scaleGenders[segmentIndex] === true
|
|
178
|
+
const isFeminine = isScaleFeminine || (this.options.gender === 'feminine' && segmentIndex === 0)
|
|
179
|
+
const onesArray = isFeminine ? this.onesFeminineWords : this.onesWords
|
|
180
|
+
words.push(onesArray[onesDigit])
|
|
181
|
+
}
|
|
155
182
|
}
|
|
156
183
|
|
|
157
184
|
// Add power word (thousand, million, etc.) with proper pluralization
|
|
158
|
-
if (
|
|
159
|
-
words.push(this.pluralize(
|
|
185
|
+
if (segmentIndex > 0) {
|
|
186
|
+
words.push(this.pluralize(segmentValue, this.pluralForms[segmentIndex]))
|
|
160
187
|
}
|
|
161
188
|
}
|
|
162
189
|
|
|
163
190
|
return words.join(' ')
|
|
164
191
|
}
|
|
165
192
|
|
|
193
|
+
// ============================================================================
|
|
194
|
+
// Protected Methods (subclasses may call or override)
|
|
195
|
+
// ============================================================================
|
|
196
|
+
|
|
166
197
|
/**
|
|
167
|
-
* Splits a number string into
|
|
198
|
+
* Splits a number string into segments of specified size from right to left.
|
|
168
199
|
*
|
|
169
|
-
* Example:
|
|
200
|
+
* Example: splitToSegments('1234567', 3) => [1n, 234n, 567n]
|
|
201
|
+
* This represents: 1 million + 234 thousand + 567 ones
|
|
170
202
|
*
|
|
171
203
|
* @param {string} numberString The number as a string.
|
|
172
|
-
* @param {number}
|
|
173
|
-
* @returns {bigint[]} Array of BigInt
|
|
204
|
+
* @param {number} segmentSize Segment size (typically 3 for thousands grouping).
|
|
205
|
+
* @returns {bigint[]} Array of BigInt segments from highest to lowest scale.
|
|
174
206
|
*/
|
|
175
|
-
|
|
176
|
-
const
|
|
207
|
+
splitToSegments (numberString, segmentSize) {
|
|
208
|
+
const segments = []
|
|
177
209
|
const stringLength = numberString.length
|
|
178
210
|
|
|
179
|
-
if (stringLength >
|
|
180
|
-
const remainderLength = stringLength %
|
|
211
|
+
if (stringLength > segmentSize) {
|
|
212
|
+
const remainderLength = stringLength % segmentSize
|
|
181
213
|
|
|
182
214
|
if (remainderLength > 0) {
|
|
183
|
-
|
|
215
|
+
segments.push(BigInt(numberString.slice(0, remainderLength)))
|
|
184
216
|
}
|
|
185
217
|
|
|
186
|
-
for (let i = remainderLength; i < stringLength; i +=
|
|
187
|
-
|
|
218
|
+
for (let i = remainderLength; i < stringLength; i += segmentSize) {
|
|
219
|
+
segments.push(BigInt(numberString.slice(i, i + segmentSize)))
|
|
188
220
|
}
|
|
189
221
|
} else {
|
|
190
|
-
|
|
222
|
+
segments.push(BigInt(numberString))
|
|
191
223
|
}
|
|
192
224
|
|
|
193
|
-
return
|
|
225
|
+
return segments
|
|
194
226
|
}
|
|
195
227
|
|
|
196
228
|
/**
|
|
@@ -202,7 +234,7 @@ class SlavicLanguage extends AbstractLanguage {
|
|
|
202
234
|
* @param {bigint} value The number to extract digits from (0-999).
|
|
203
235
|
* @returns {bigint[]} Array of [ones, tens, hundreds] as BigInts.
|
|
204
236
|
*/
|
|
205
|
-
|
|
237
|
+
extractDigits (value) {
|
|
206
238
|
// Direct BigInt arithmetic is faster than string manipulation
|
|
207
239
|
const onesPlace = value % 10n
|
|
208
240
|
const tensPlace = (value / 10n) % 10n
|
|
@@ -213,18 +245,18 @@ class SlavicLanguage extends AbstractLanguage {
|
|
|
213
245
|
/**
|
|
214
246
|
* Selects the correct plural form based on Slavic pluralization rules.
|
|
215
247
|
*
|
|
216
|
-
* Slavic languages use three forms:
|
|
217
|
-
* - Form 0 (singular): numbers ending in 1 (
|
|
218
|
-
* - Form 1 (few): numbers ending in 2-4 (
|
|
219
|
-
* - Form 2 (many): all other numbers (0, 5-20, 25-30,
|
|
248
|
+
* Slavic languages typically use three forms:
|
|
249
|
+
* - Form 0 (singular): numbers ending in 1, except 11 (1, 21, 31, 101...)
|
|
250
|
+
* - Form 1 (few): numbers ending in 2-4, except 12-14 (2-4, 22-24, 32-34...)
|
|
251
|
+
* - Form 2 (many): all other numbers (0, 5-20, 25-30, 100, 111-119...)
|
|
220
252
|
*
|
|
221
|
-
* Examples (
|
|
222
|
-
* - 1, 21, 31...
|
|
223
|
-
* - 2-4, 22-24, 32-34...
|
|
224
|
-
* - 0, 5-20, 25-30...
|
|
253
|
+
* Examples using Russian тысяча (thousand):
|
|
254
|
+
* - 1, 21, 31... ⇒ тысяча (form 0, singular)
|
|
255
|
+
* - 2-4, 22-24, 32-34... ⇒ тысячи (form 1, few)
|
|
256
|
+
* - 0, 5-20, 25-30, 100... ⇒ тысяч (form 2, many)
|
|
225
257
|
*
|
|
226
|
-
* @param {bigint}
|
|
227
|
-
* @param {string[]}
|
|
258
|
+
* @param {bigint} number The number to check.
|
|
259
|
+
* @param {string[]} pluralForms Array of [singular, few, many] forms.
|
|
228
260
|
* @returns {string} The appropriate form for the number.
|
|
229
261
|
*/
|
|
230
262
|
pluralize (number, pluralForms) {
|
|
@@ -247,5 +279,3 @@ class SlavicLanguage extends AbstractLanguage {
|
|
|
247
279
|
return pluralForms[2] // Many
|
|
248
280
|
}
|
|
249
281
|
}
|
|
250
|
-
|
|
251
|
-
export default SlavicLanguage
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base class for South Asian languages with shared grouping patterns.
|
|
3
|
+
*
|
|
4
|
+
* This class provides a reusable implementation for South Asian languages that share:
|
|
5
|
+
* - Indian-style number grouping: last 3 digits, then 2-2 (1,23,45,67,89)
|
|
6
|
+
* - Lakh (100,000), Crore (10,000,000), Arab (1,000,000,000) scale words
|
|
7
|
+
* - Standard negative and decimal handling (inherits AbstractLanguage decimal logic,
|
|
8
|
+
* including `usePerDigitDecimals` support when set by subclasses)
|
|
9
|
+
*
|
|
10
|
+
* Used by: Hindi (hi), Bengali (bn), Urdu (ur), Punjabi (pa), Marathi (mr), Gujarati (gu), Kannada (kn)
|
|
11
|
+
*
|
|
12
|
+
* Subclasses MUST define language-specific vocabulary via class properties:
|
|
13
|
+
* - `belowHundredWords` array with digit and teen words (0-99)
|
|
14
|
+
* - `hundredWord` string used inside `segmentToWords`
|
|
15
|
+
* - `scaleWords` array with grouping words (hazaar, lakh, crore, etc.) indexed by grouping level
|
|
16
|
+
* - `negativeWord`, `decimalSeparatorWord`, `zeroWord`, `wordSeparator`
|
|
17
|
+
*
|
|
18
|
+
* @abstract
|
|
19
|
+
* @extends AbstractLanguage
|
|
20
|
+
*/
|
|
21
|
+
export class SouthAsianLanguage extends AbstractLanguage {
|
|
22
|
+
/**
|
|
23
|
+
* Array of words for numbers 0-99 (digits and teens).
|
|
24
|
+
* Index directly: belowHundredWords[0] through belowHundredWords[99].
|
|
25
|
+
* @type {Array<string>}
|
|
26
|
+
*/
|
|
27
|
+
belowHundredWords: Array<string>;
|
|
28
|
+
/**
|
|
29
|
+
* Word for "hundred" in the language (e.g., 'सौ' in Hindi, 'শত' in Bengali).
|
|
30
|
+
* Used to construct hundreds (e.g., "1 hundred", "2 hundred").
|
|
31
|
+
* @type {string}
|
|
32
|
+
*/
|
|
33
|
+
hundredWord: string;
|
|
34
|
+
/**
|
|
35
|
+
* Array of scale words for Indian-style grouping (hazaar, lakh, crore, arab, etc.).
|
|
36
|
+
* Index 0 contains empty string (ones place has no scale word).
|
|
37
|
+
* Index 1 is for thousands, Index 2 for lakhs, Index 3 for crores, etc.
|
|
38
|
+
* @type {Array<string>}
|
|
39
|
+
*/
|
|
40
|
+
scaleWords: Array<string>;
|
|
41
|
+
/**
|
|
42
|
+
* Splits a number into Indian numbering system segments.
|
|
43
|
+
*
|
|
44
|
+
* The Indian system segments differently than Western (3-3-3) systems:
|
|
45
|
+
* - First segment (rightmost): Up to 3 digits (ones, tens, hundreds)
|
|
46
|
+
* - Subsequent segments: Exactly 2 digits each (thousands, lakhs, crores, etc.)
|
|
47
|
+
*
|
|
48
|
+
* This creates the familiar Indian comma pattern: 1,23,45,67,890
|
|
49
|
+
*
|
|
50
|
+
* @protected
|
|
51
|
+
* @param {bigint} integerPart The integer to split into segments.
|
|
52
|
+
* @returns {Array<number>} Array of segments from most significant to least significant.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* // splitToSegments(1234567n) → [12, 34, 567]
|
|
56
|
+
* // Reads as: 12 lakhs, 34 thousands, 567 units
|
|
57
|
+
* // splitToSegments(98765432n) → [9, 87, 65, 432]
|
|
58
|
+
* // Reads as: 9 crores, 87 lakhs, 65 thousands, 432 units
|
|
59
|
+
*/
|
|
60
|
+
protected splitToSegments(integerPart: bigint): Array<number>;
|
|
61
|
+
/**
|
|
62
|
+
* Converts a segment (0-999) to words.
|
|
63
|
+
*
|
|
64
|
+
* @protected
|
|
65
|
+
* @param {number} segmentValue Value between 0 and 999.
|
|
66
|
+
* @returns {string} Language-specific word representation.
|
|
67
|
+
*/
|
|
68
|
+
protected segmentToWords(segmentValue: number): string;
|
|
69
|
+
}
|
|
70
|
+
import { AbstractLanguage } from './abstract-language.js';
|
|
@@ -1,21 +1,4 @@
|
|
|
1
|
-
import AbstractLanguage from './abstract-language.js'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @typedef {Array<string>} SouthAsianScaleWords
|
|
5
|
-
* Array of scale words for the Indian numbering system, in ascending order.
|
|
6
|
-
* - Index 0: Usually empty/unused (ones place)
|
|
7
|
-
* - Index 1: Thousands (hazaar/হাজার/हजार)
|
|
8
|
-
* - Index 2: Lakhs (lakh/লাখ/लाख)
|
|
9
|
-
* - Index 3: Crores (crore/কোটি/करोड़)
|
|
10
|
-
* - Index 4: Arabs (arab/আরব/अरब)
|
|
11
|
-
* Each index i represents the scale word for groups at position i in the Indian system.
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* @typedef {Array<string>} SouthAsianBelowHundred
|
|
16
|
-
* Array of words for numbers 0-99, indexed directly.
|
|
17
|
-
* belowHundred[0] = word for 0, belowHundred[42] = word for 42, etc.
|
|
18
|
-
*/
|
|
1
|
+
import { AbstractLanguage } from './abstract-language.js'
|
|
19
2
|
|
|
20
3
|
/**
|
|
21
4
|
* Base class for South Asian languages with shared grouping patterns.
|
|
@@ -24,26 +7,30 @@ import AbstractLanguage from './abstract-language.js'
|
|
|
24
7
|
* - Indian-style number grouping: last 3 digits, then 2-2 (1,23,45,67,89)
|
|
25
8
|
* - Lakh (100,000), Crore (10,000,000), Arab (1,000,000,000) scale words
|
|
26
9
|
* - Standard negative and decimal handling (inherits AbstractLanguage decimal logic,
|
|
27
|
-
* including `
|
|
10
|
+
* including `usePerDigitDecimals` support when set by subclasses)
|
|
28
11
|
*
|
|
29
12
|
* Used by: Hindi (hi), Bengali (bn), Urdu (ur), Punjabi (pa), Marathi (mr), Gujarati (gu), Kannada (kn)
|
|
30
13
|
*
|
|
31
14
|
* Subclasses MUST define language-specific vocabulary via class properties:
|
|
32
|
-
* - `
|
|
33
|
-
* - `hundredWord` string used inside `
|
|
15
|
+
* - `belowHundredWords` array with digit and teen words (0-99)
|
|
16
|
+
* - `hundredWord` string used inside `segmentToWords`
|
|
34
17
|
* - `scaleWords` array with grouping words (hazaar, lakh, crore, etc.) indexed by grouping level
|
|
35
18
|
* - `negativeWord`, `decimalSeparatorWord`, `zeroWord`, `wordSeparator`
|
|
36
19
|
*
|
|
37
20
|
* @abstract
|
|
38
21
|
* @extends AbstractLanguage
|
|
39
22
|
*/
|
|
40
|
-
class SouthAsianLanguage extends AbstractLanguage {
|
|
23
|
+
export class SouthAsianLanguage extends AbstractLanguage {
|
|
24
|
+
// ============================================================================
|
|
25
|
+
// Required Properties (subclasses must define)
|
|
26
|
+
// ============================================================================
|
|
27
|
+
|
|
41
28
|
/**
|
|
42
29
|
* Array of words for numbers 0-99 (digits and teens).
|
|
43
|
-
* Index directly:
|
|
30
|
+
* Index directly: belowHundredWords[0] through belowHundredWords[99].
|
|
44
31
|
* @type {Array<string>}
|
|
45
32
|
*/
|
|
46
|
-
|
|
33
|
+
belowHundredWords
|
|
47
34
|
|
|
48
35
|
/**
|
|
49
36
|
* Word for "hundred" in the language (e.g., 'सौ' in Hindi, 'শত' in Bengali).
|
|
@@ -54,101 +41,109 @@ class SouthAsianLanguage extends AbstractLanguage {
|
|
|
54
41
|
|
|
55
42
|
/**
|
|
56
43
|
* Array of scale words for Indian-style grouping (hazaar, lakh, crore, arab, etc.).
|
|
57
|
-
* Index 0
|
|
44
|
+
* Index 0 contains empty string (ones place has no scale word).
|
|
58
45
|
* Index 1 is for thousands, Index 2 for lakhs, Index 3 for crores, etc.
|
|
59
46
|
* @type {Array<string>}
|
|
60
47
|
*/
|
|
61
48
|
scaleWords
|
|
62
49
|
|
|
50
|
+
// ============================================================================
|
|
51
|
+
// Protected Methods (subclasses may call or override)
|
|
52
|
+
// ============================================================================
|
|
53
|
+
|
|
63
54
|
/**
|
|
64
|
-
*
|
|
55
|
+
* Splits a number into Indian numbering system segments.
|
|
65
56
|
*
|
|
66
|
-
* The Indian system
|
|
67
|
-
* - First
|
|
68
|
-
* - Subsequent
|
|
57
|
+
* The Indian system segments differently than Western (3-3-3) systems:
|
|
58
|
+
* - First segment (rightmost): Up to 3 digits (ones, tens, hundreds)
|
|
59
|
+
* - Subsequent segments: Exactly 2 digits each (thousands, lakhs, crores, etc.)
|
|
69
60
|
*
|
|
70
61
|
* This creates the familiar Indian comma pattern: 1,23,45,67,890
|
|
71
62
|
*
|
|
72
63
|
* @protected
|
|
73
|
-
* @param {bigint}
|
|
74
|
-
* @returns {Array<number>} Array of
|
|
64
|
+
* @param {bigint} integerPart The integer to split into segments.
|
|
65
|
+
* @returns {Array<number>} Array of segments from most significant to least significant.
|
|
75
66
|
*
|
|
76
67
|
* @example
|
|
77
|
-
* //
|
|
68
|
+
* // splitToSegments(1234567n) → [12, 34, 567]
|
|
78
69
|
* // Reads as: 12 lakhs, 34 thousands, 567 units
|
|
79
|
-
* //
|
|
70
|
+
* // splitToSegments(98765432n) → [9, 87, 65, 432]
|
|
80
71
|
* // Reads as: 9 crores, 87 lakhs, 65 thousands, 432 units
|
|
81
72
|
*/
|
|
82
|
-
|
|
83
|
-
const numStr =
|
|
73
|
+
splitToSegments (integerPart) {
|
|
74
|
+
const numStr = integerPart.toString()
|
|
84
75
|
|
|
85
76
|
if (numStr.length <= 3) {
|
|
86
77
|
return [Number(numStr)]
|
|
87
78
|
}
|
|
88
79
|
|
|
89
|
-
const
|
|
80
|
+
const segments = []
|
|
90
81
|
const last3 = numStr.slice(-3)
|
|
91
|
-
|
|
82
|
+
segments.unshift(Number(last3))
|
|
92
83
|
|
|
93
84
|
let remaining = numStr.slice(0, -3)
|
|
94
85
|
while (remaining.length > 0) {
|
|
95
|
-
const
|
|
96
|
-
|
|
86
|
+
const segment = remaining.slice(-2)
|
|
87
|
+
segments.unshift(Number(segment))
|
|
97
88
|
remaining = remaining.slice(0, -2)
|
|
98
89
|
}
|
|
99
90
|
|
|
100
|
-
return
|
|
91
|
+
return segments
|
|
101
92
|
}
|
|
102
93
|
|
|
103
94
|
/**
|
|
104
|
-
*
|
|
95
|
+
* Converts a segment (0-999) to words.
|
|
105
96
|
*
|
|
106
97
|
* @protected
|
|
107
|
-
* @param {number}
|
|
108
|
-
* @returns {string} Language-specific word representation
|
|
98
|
+
* @param {number} segmentValue Value between 0 and 999.
|
|
99
|
+
* @returns {string} Language-specific word representation.
|
|
109
100
|
*/
|
|
110
|
-
|
|
111
|
-
if (
|
|
112
|
-
if (
|
|
101
|
+
segmentToWords (segmentValue) {
|
|
102
|
+
if (segmentValue === 0) return ''
|
|
103
|
+
if (segmentValue < 100) return this.belowHundredWords[segmentValue]
|
|
113
104
|
|
|
114
|
-
const hundreds = Math.trunc(
|
|
115
|
-
const remainder =
|
|
105
|
+
const hundreds = Math.trunc(segmentValue / 100)
|
|
106
|
+
const remainder = segmentValue % 100
|
|
116
107
|
const parts = []
|
|
117
108
|
|
|
118
109
|
if (hundreds === 1) {
|
|
119
|
-
parts.push(this.
|
|
110
|
+
parts.push(this.belowHundredWords[1] + ' ' + this.hundredWord)
|
|
120
111
|
} else {
|
|
121
|
-
parts.push(this.
|
|
112
|
+
parts.push(this.belowHundredWords[hundreds] + ' ' + this.hundredWord)
|
|
122
113
|
}
|
|
123
114
|
|
|
124
115
|
if (remainder > 0) {
|
|
125
|
-
parts.push(this.
|
|
116
|
+
parts.push(this.belowHundredWords[remainder])
|
|
126
117
|
}
|
|
127
118
|
|
|
128
119
|
return parts.join(' ')
|
|
129
120
|
}
|
|
130
121
|
|
|
122
|
+
// ============================================================================
|
|
123
|
+
// Public Methods
|
|
124
|
+
// ============================================================================
|
|
125
|
+
|
|
131
126
|
/**
|
|
132
|
-
*
|
|
127
|
+
* Converts integer to cardinal words using South Asian grouping.
|
|
133
128
|
*
|
|
134
|
-
* @param {bigint}
|
|
135
|
-
* @returns {string} Cardinal representation
|
|
129
|
+
* @param {bigint} integerPart Number to convert.
|
|
130
|
+
* @returns {string} Cardinal representation.
|
|
136
131
|
*/
|
|
137
|
-
|
|
138
|
-
if (
|
|
132
|
+
integerToWords (integerPart) {
|
|
133
|
+
if (integerPart === 0n) {
|
|
139
134
|
return this.zeroWord
|
|
140
135
|
}
|
|
141
136
|
|
|
142
|
-
const
|
|
143
|
-
const
|
|
137
|
+
const segments = this.splitToSegments(integerPart)
|
|
138
|
+
const segmentCount = segments.length
|
|
144
139
|
const words = []
|
|
145
140
|
|
|
146
|
-
for (let i = 0; i <
|
|
147
|
-
const
|
|
148
|
-
if (
|
|
141
|
+
for (let i = 0; i < segmentCount; i++) {
|
|
142
|
+
const segmentValue = segments[i]
|
|
143
|
+
if (segmentValue === 0) continue
|
|
149
144
|
|
|
150
|
-
const scaleIndex =
|
|
151
|
-
words.push(this.
|
|
145
|
+
const scaleIndex = segmentCount - i - 1
|
|
146
|
+
words.push(this.segmentToWords(segmentValue))
|
|
152
147
|
if (scaleIndex > 0 && this.scaleWords[scaleIndex]) {
|
|
153
148
|
words.push(this.scaleWords[scaleIndex])
|
|
154
149
|
}
|
|
@@ -157,5 +152,3 @@ class SouthAsianLanguage extends AbstractLanguage {
|
|
|
157
152
|
return words.join(' ').trim()
|
|
158
153
|
}
|
|
159
154
|
}
|
|
160
|
-
|
|
161
|
-
export default SouthAsianLanguage
|