n2words 2.0.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +49 -0
- package/README.md +86 -188
- package/dist/languages/am-Latn.js +3 -0
- package/dist/languages/am-Latn.js.map +1 -0
- package/dist/languages/am.js +3 -0
- package/dist/languages/am.js.map +1 -0
- package/dist/languages/ar.js +3 -0
- package/dist/languages/ar.js.map +1 -0
- package/dist/languages/az.js +3 -0
- package/dist/languages/az.js.map +1 -0
- package/dist/languages/bn.js +3 -0
- package/dist/languages/bn.js.map +1 -0
- package/dist/languages/cs.js +3 -0
- package/dist/languages/cs.js.map +1 -0
- package/dist/languages/da.js +3 -0
- package/dist/languages/da.js.map +1 -0
- package/dist/languages/de.js +3 -0
- package/dist/languages/de.js.map +1 -0
- package/dist/languages/el.js +3 -0
- package/dist/languages/el.js.map +1 -0
- package/dist/languages/en.js +3 -0
- package/dist/languages/en.js.map +1 -0
- package/dist/languages/es.js +3 -0
- package/dist/languages/es.js.map +1 -0
- package/dist/languages/fa.js +3 -0
- package/dist/languages/fa.js.map +1 -0
- package/dist/languages/fi.js +3 -0
- package/dist/languages/fi.js.map +1 -0
- package/dist/languages/fil.js +3 -0
- package/dist/languages/fil.js.map +1 -0
- package/dist/languages/fr-BE.js +3 -0
- package/dist/languages/fr-BE.js.map +1 -0
- package/dist/languages/fr.js +3 -0
- package/dist/languages/fr.js.map +1 -0
- package/dist/languages/gu.js +3 -0
- package/dist/languages/gu.js.map +1 -0
- package/dist/languages/ha.js +3 -0
- package/dist/languages/ha.js.map +1 -0
- package/dist/languages/hbo.js +3 -0
- package/dist/languages/hbo.js.map +1 -0
- package/dist/languages/he.js +3 -0
- package/dist/languages/he.js.map +1 -0
- package/dist/languages/hi.js +3 -0
- package/dist/languages/hi.js.map +1 -0
- package/dist/languages/hr.js +3 -0
- package/dist/languages/hr.js.map +1 -0
- package/dist/languages/hu.js +3 -0
- package/dist/languages/hu.js.map +1 -0
- package/dist/languages/id.js +3 -0
- package/dist/languages/id.js.map +1 -0
- package/dist/languages/it.js +3 -0
- package/dist/languages/it.js.map +1 -0
- package/dist/languages/ja.js +3 -0
- package/dist/languages/ja.js.map +1 -0
- package/dist/languages/kn.js +3 -0
- package/dist/languages/kn.js.map +1 -0
- package/dist/languages/ko.js +3 -0
- package/dist/languages/ko.js.map +1 -0
- package/dist/languages/lt.js +3 -0
- package/dist/languages/lt.js.map +1 -0
- package/dist/languages/lv.js +3 -0
- package/dist/languages/lv.js.map +1 -0
- package/dist/languages/mr.js +3 -0
- package/dist/languages/mr.js.map +1 -0
- package/dist/languages/ms.js +3 -0
- package/dist/languages/ms.js.map +1 -0
- package/dist/languages/nb.js +3 -0
- package/dist/languages/nb.js.map +1 -0
- package/dist/languages/nl.js +3 -0
- package/dist/languages/nl.js.map +1 -0
- package/dist/languages/pa.js +3 -0
- package/dist/languages/pa.js.map +1 -0
- package/dist/languages/pl.js +3 -0
- package/dist/languages/pl.js.map +1 -0
- package/dist/languages/pt.js +3 -0
- package/dist/languages/pt.js.map +1 -0
- package/dist/languages/ro.js +3 -0
- package/dist/languages/ro.js.map +1 -0
- package/dist/languages/ru.js +3 -0
- package/dist/languages/ru.js.map +1 -0
- package/dist/languages/sr-Cyrl.js +3 -0
- package/dist/languages/sr-Cyrl.js.map +1 -0
- package/dist/languages/sr-Latn.js +3 -0
- package/dist/languages/sr-Latn.js.map +1 -0
- package/dist/languages/sv.js +3 -0
- package/dist/languages/sv.js.map +1 -0
- package/dist/languages/sw.js +3 -0
- package/dist/languages/sw.js.map +1 -0
- package/dist/languages/ta.js +3 -0
- package/dist/languages/ta.js.map +1 -0
- package/dist/languages/te.js +3 -0
- package/dist/languages/te.js.map +1 -0
- package/dist/languages/th.js +3 -0
- package/dist/languages/th.js.map +1 -0
- package/dist/languages/tr.js +3 -0
- package/dist/languages/tr.js.map +1 -0
- package/dist/languages/uk.js +3 -0
- package/dist/languages/uk.js.map +1 -0
- package/dist/languages/ur.js +3 -0
- package/dist/languages/ur.js.map +1 -0
- package/dist/languages/vi.js +3 -0
- package/dist/languages/vi.js.map +1 -0
- package/dist/languages/zh-Hans.js +3 -0
- package/dist/languages/zh-Hans.js.map +1 -0
- package/dist/languages/zh-Hant.js +3 -0
- package/dist/languages/zh-Hant.js.map +1 -0
- package/dist/n2words.js +2 -2
- package/dist/n2words.js.map +1 -1
- package/lib/languages/am-Latn.d.ts +7 -0
- package/lib/languages/am-Latn.js +164 -0
- package/lib/languages/am.d.ts +7 -0
- package/lib/languages/am.js +164 -0
- package/lib/languages/ar.d.ts +14 -27
- package/lib/languages/ar.js +175 -129
- package/lib/languages/az.d.ts +4 -9
- package/lib/languages/az.js +171 -37
- package/lib/languages/bn.d.ts +4 -8
- package/lib/languages/bn.js +138 -124
- package/lib/languages/cs.d.ts +15 -85
- package/lib/languages/cs.js +310 -114
- package/lib/languages/da.d.ts +11 -12
- package/lib/languages/da.js +276 -101
- package/lib/languages/de.d.ts +14 -11
- package/lib/languages/de.js +317 -86
- package/lib/languages/el.d.ts +11 -11
- package/lib/languages/el.js +231 -78
- package/lib/languages/en.d.ts +14 -13
- package/lib/languages/en.js +242 -72
- package/lib/languages/es.d.ts +18 -12
- package/lib/languages/es.js +317 -103
- package/lib/languages/fa.d.ts +4 -44
- package/lib/languages/fa.js +112 -122
- package/lib/languages/fi.d.ts +14 -0
- package/lib/languages/fi.js +245 -0
- package/lib/languages/fil.d.ts +4 -13
- package/lib/languages/fil.js +207 -106
- package/lib/languages/fr-BE.d.ts +8 -8
- package/lib/languages/fr-BE.js +294 -19
- package/lib/languages/fr.d.ts +18 -12
- package/lib/languages/fr.js +352 -89
- package/lib/languages/gu.d.ts +4 -8
- package/lib/languages/gu.js +130 -125
- package/lib/languages/ha.d.ts +7 -0
- package/lib/languages/ha.js +230 -0
- package/lib/languages/hbo.d.ts +10 -110
- package/lib/languages/hbo.js +263 -214
- package/lib/languages/he.d.ts +10 -77
- package/lib/languages/he.js +242 -172
- package/lib/languages/hi.d.ts +4 -8
- package/lib/languages/hi.js +138 -124
- package/lib/languages/hr.d.ts +8 -77
- package/lib/languages/hr.js +194 -89
- package/lib/languages/hu.d.ts +4 -19
- package/lib/languages/hu.js +198 -119
- package/lib/languages/id.d.ts +4 -34
- package/lib/languages/id.js +171 -129
- package/lib/languages/it.d.ts +16 -34
- package/lib/languages/it.js +339 -94
- package/lib/languages/ja.d.ts +14 -14
- package/lib/languages/ja.js +233 -111
- package/lib/languages/kn.d.ts +4 -8
- package/lib/languages/kn.js +130 -35
- package/lib/languages/ko.d.ts +11 -11
- package/lib/languages/ko.js +257 -49
- package/lib/languages/lt.d.ts +15 -67
- package/lib/languages/lt.js +296 -122
- package/lib/languages/lv.d.ts +15 -67
- package/lib/languages/lv.js +297 -106
- package/lib/languages/mr.d.ts +4 -8
- package/lib/languages/mr.js +130 -125
- package/lib/languages/ms.d.ts +4 -28
- package/lib/languages/ms.js +171 -116
- package/lib/languages/nb.d.ts +11 -9
- package/lib/languages/nb.js +282 -87
- package/lib/languages/nl.d.ts +23 -13
- package/lib/languages/nl.js +317 -133
- package/lib/languages/pa.d.ts +4 -8
- package/lib/languages/pa.js +156 -124
- package/lib/languages/pl.d.ts +19 -77
- package/lib/languages/pl.js +307 -87
- package/lib/languages/pt.d.ts +14 -26
- package/lib/languages/pt.js +286 -92
- package/lib/languages/ro.d.ts +15 -155
- package/lib/languages/ro.js +219 -235
- package/lib/languages/ru.d.ts +8 -82
- package/lib/languages/ru.js +222 -78
- package/lib/languages/sr-Cyrl.d.ts +8 -77
- package/lib/languages/sr-Cyrl.js +191 -89
- package/lib/languages/sr-Latn.d.ts +8 -77
- package/lib/languages/sr-Latn.js +191 -89
- package/lib/languages/sv.d.ts +11 -11
- package/lib/languages/sv.js +288 -74
- package/lib/languages/sw.d.ts +4 -36
- package/lib/languages/sw.js +133 -106
- package/lib/languages/ta.d.ts +4 -17
- package/lib/languages/ta.js +129 -201
- package/lib/languages/te.d.ts +4 -19
- package/lib/languages/te.js +141 -196
- package/lib/languages/th.d.ts +4 -14
- package/lib/languages/th.js +135 -91
- package/lib/languages/tr.d.ts +15 -9
- package/lib/languages/tr.js +256 -49
- package/lib/languages/uk.d.ts +8 -82
- package/lib/languages/uk.js +200 -78
- package/lib/languages/ur.d.ts +4 -8
- package/lib/languages/ur.js +156 -124
- package/lib/languages/vi.d.ts +14 -69
- package/lib/languages/vi.js +294 -125
- package/lib/languages/zh-Hans.d.ts +8 -18
- package/lib/languages/zh-Hans.js +163 -92
- package/lib/languages/zh-Hant.d.ts +8 -18
- package/lib/languages/zh-Hant.js +181 -90
- package/lib/n2words.d.ts +53 -209
- package/lib/n2words.js +111 -530
- package/lib/utils/is-plain-object.d.ts +13 -0
- package/lib/utils/is-plain-object.js +17 -0
- package/lib/utils/parse-numeric.d.ts +17 -0
- package/lib/utils/parse-numeric.js +108 -0
- package/lib/utils/validate-options.d.ts +8 -0
- package/lib/utils/validate-options.js +16 -0
- package/package.json +26 -14
- package/dist/ArabicConverter.js +0 -3
- package/dist/ArabicConverter.js.map +0 -1
- package/dist/AzerbaijaniConverter.js +0 -3
- package/dist/AzerbaijaniConverter.js.map +0 -1
- package/dist/BanglaConverter.js +0 -3
- package/dist/BanglaConverter.js.map +0 -1
- package/dist/BiblicalHebrewConverter.js +0 -3
- package/dist/BiblicalHebrewConverter.js.map +0 -1
- package/dist/CroatianConverter.js +0 -3
- package/dist/CroatianConverter.js.map +0 -1
- package/dist/CzechConverter.js +0 -3
- package/dist/CzechConverter.js.map +0 -1
- package/dist/DanishConverter.js +0 -3
- package/dist/DanishConverter.js.map +0 -1
- package/dist/DutchConverter.js +0 -3
- package/dist/DutchConverter.js.map +0 -1
- package/dist/EnglishConverter.js +0 -3
- package/dist/EnglishConverter.js.map +0 -1
- package/dist/FilipinoConverter.js +0 -3
- package/dist/FilipinoConverter.js.map +0 -1
- package/dist/FrenchBelgiumConverter.js +0 -3
- package/dist/FrenchBelgiumConverter.js.map +0 -1
- package/dist/FrenchConverter.js +0 -3
- package/dist/FrenchConverter.js.map +0 -1
- package/dist/GermanConverter.js +0 -3
- package/dist/GermanConverter.js.map +0 -1
- package/dist/GreekConverter.js +0 -3
- package/dist/GreekConverter.js.map +0 -1
- package/dist/GujaratiConverter.js +0 -3
- package/dist/GujaratiConverter.js.map +0 -1
- package/dist/HebrewConverter.js +0 -3
- package/dist/HebrewConverter.js.map +0 -1
- package/dist/HindiConverter.js +0 -3
- package/dist/HindiConverter.js.map +0 -1
- package/dist/HungarianConverter.js +0 -3
- package/dist/HungarianConverter.js.map +0 -1
- package/dist/IndonesianConverter.js +0 -3
- package/dist/IndonesianConverter.js.map +0 -1
- package/dist/ItalianConverter.js +0 -3
- package/dist/ItalianConverter.js.map +0 -1
- package/dist/JapaneseConverter.js +0 -3
- package/dist/JapaneseConverter.js.map +0 -1
- package/dist/KannadaConverter.js +0 -3
- package/dist/KannadaConverter.js.map +0 -1
- package/dist/KoreanConverter.js +0 -3
- package/dist/KoreanConverter.js.map +0 -1
- package/dist/LatvianConverter.js +0 -3
- package/dist/LatvianConverter.js.map +0 -1
- package/dist/LithuanianConverter.js +0 -3
- package/dist/LithuanianConverter.js.map +0 -1
- package/dist/MalayConverter.js +0 -3
- package/dist/MalayConverter.js.map +0 -1
- package/dist/MarathiConverter.js +0 -3
- package/dist/MarathiConverter.js.map +0 -1
- package/dist/NorwegianBokmalConverter.js +0 -3
- package/dist/NorwegianBokmalConverter.js.map +0 -1
- package/dist/PersianConverter.js +0 -3
- package/dist/PersianConverter.js.map +0 -1
- package/dist/PolishConverter.js +0 -3
- package/dist/PolishConverter.js.map +0 -1
- package/dist/PortugueseConverter.js +0 -3
- package/dist/PortugueseConverter.js.map +0 -1
- package/dist/PunjabiConverter.js +0 -3
- package/dist/PunjabiConverter.js.map +0 -1
- package/dist/RomanianConverter.js +0 -3
- package/dist/RomanianConverter.js.map +0 -1
- package/dist/RussianConverter.js +0 -3
- package/dist/RussianConverter.js.map +0 -1
- package/dist/SerbianCyrillicConverter.js +0 -3
- package/dist/SerbianCyrillicConverter.js.map +0 -1
- package/dist/SerbianLatinConverter.js +0 -3
- package/dist/SerbianLatinConverter.js.map +0 -1
- package/dist/SimplifiedChineseConverter.js +0 -3
- package/dist/SimplifiedChineseConverter.js.map +0 -1
- package/dist/SpanishConverter.js +0 -3
- package/dist/SpanishConverter.js.map +0 -1
- package/dist/SwahiliConverter.js +0 -3
- package/dist/SwahiliConverter.js.map +0 -1
- package/dist/SwedishConverter.js +0 -3
- package/dist/SwedishConverter.js.map +0 -1
- package/dist/TamilConverter.js +0 -3
- package/dist/TamilConverter.js.map +0 -1
- package/dist/TeluguConverter.js +0 -3
- package/dist/TeluguConverter.js.map +0 -1
- package/dist/ThaiConverter.js +0 -3
- package/dist/ThaiConverter.js.map +0 -1
- package/dist/TraditionalChineseConverter.js +0 -3
- package/dist/TraditionalChineseConverter.js.map +0 -1
- package/dist/TurkishConverter.js +0 -3
- package/dist/TurkishConverter.js.map +0 -1
- package/dist/UkrainianConverter.js +0 -3
- package/dist/UkrainianConverter.js.map +0 -1
- package/dist/UrduConverter.js +0 -3
- package/dist/UrduConverter.js.map +0 -1
- package/dist/VietnameseConverter.js +0 -3
- package/dist/VietnameseConverter.js.map +0 -1
- package/lib/classes/abstract-language.d.ts +0 -178
- package/lib/classes/abstract-language.js +0 -268
- package/lib/classes/greedy-scale-language.d.ts +0 -109
- package/lib/classes/greedy-scale-language.js +0 -201
- package/lib/classes/slavic-language.d.ts +0 -148
- package/lib/classes/slavic-language.js +0 -281
- package/lib/classes/south-asian-language.d.ts +0 -70
- package/lib/classes/south-asian-language.js +0 -154
- package/lib/classes/turkic-language.d.ts +0 -26
- package/lib/classes/turkic-language.js +0 -59
package/lib/languages/lv.js
CHANGED
|
@@ -1,130 +1,321 @@
|
|
|
1
|
-
import { SlavicLanguage } from '../classes/slavic-language.js'
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
|
-
* Latvian language converter
|
|
2
|
+
* Latvian language converter - Functional Implementation
|
|
3
|
+
*
|
|
4
|
+
* A performance-optimized number-to-words converter using precomputed lookup tables.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* -
|
|
8
|
-
* -
|
|
9
|
-
* -
|
|
6
|
+
* Key features:
|
|
7
|
+
* - Two-form pluralization (singular for 1 except 11, plural otherwise)
|
|
8
|
+
* - Gender agreement (masculine/feminine for numbers < 1000)
|
|
9
|
+
* - Special hundreds forms (simts/simti/simtu)
|
|
10
|
+
* - Omit "one" before scale words
|
|
11
|
+
* - Long scale naming
|
|
10
12
|
*/
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
13
|
+
|
|
14
|
+
import { parseNumericValue } from '../utils/parse-numeric.js'
|
|
15
|
+
import { validateOptions } from '../utils/validate-options.js'
|
|
16
|
+
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// Vocabulary (module-level constants)
|
|
19
|
+
// ============================================================================
|
|
20
|
+
|
|
21
|
+
const ONES_MASC = ['', 'viens', 'divi', 'trīs', 'četri', 'pieci', 'seši', 'septiņi', 'astoņi', 'deviņi']
|
|
22
|
+
const ONES_FEM = ['', 'viena', 'divas', 'trīs', 'četras', 'piecas', 'sešas', 'septiņas', 'astoņas', 'deviņas']
|
|
23
|
+
|
|
24
|
+
const TEENS = ['desmit', 'vienpadsmit', 'divpadsmit', 'trīspadsmit', 'četrpadsmit', 'piecpadsmit', 'sešpadsmit', 'septiņpadsmit', 'astoņpadsmit', 'deviņpadsmit']
|
|
25
|
+
const TENS = ['', '', 'divdesmit', 'trīsdesmit', 'četrdesmit', 'piecdesmit', 'sešdesmit', 'septiņdesmit', 'astoņdesmit', 'deviņdesmit']
|
|
26
|
+
|
|
27
|
+
// Hundreds: simts (100, 110-199), simti (200-999), simtu (101-109)
|
|
28
|
+
const HUNDRED_SINGULAR = 'simts'
|
|
29
|
+
const HUNDRED_PLURAL = 'simti'
|
|
30
|
+
const HUNDRED_GENITIVE = 'simtu'
|
|
31
|
+
|
|
32
|
+
const ZERO = 'nulle'
|
|
33
|
+
const NEGATIVE = 'mīnus'
|
|
34
|
+
const DECIMAL_SEP = 'komats'
|
|
35
|
+
|
|
36
|
+
// Scale words: [singular, plural, genitive]
|
|
37
|
+
const SCALE_FORMS = [
|
|
38
|
+
['tūkstotis', 'tūkstoši', 'tūkstošu'],
|
|
39
|
+
['miljons', 'miljoni', 'miljonu'],
|
|
40
|
+
['miljards', 'miljardi', 'miljardu'],
|
|
41
|
+
['triljons', 'triljoni', 'triljonu'],
|
|
42
|
+
['kvadriljons', 'kvadriljoni', 'kvadriljonu'],
|
|
43
|
+
['kvintiljons', 'kvintiljoni', 'kvintiljonu'],
|
|
44
|
+
['sikstiljons', 'sikstiljoni', 'sikstiljonu'],
|
|
45
|
+
['septiljons', 'septiljoni', 'septiljonu'],
|
|
46
|
+
['oktiljons', 'oktiljoni', 'oktiljonu']
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
// ============================================================================
|
|
50
|
+
// Precomputed Lookup Tables (built once at module load)
|
|
51
|
+
// ============================================================================
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Builds segment word for 0-999 (masculine form).
|
|
55
|
+
* Does NOT include special handling for segment=1 (omitOneBeforeScale).
|
|
56
|
+
* That's handled at join time.
|
|
57
|
+
*/
|
|
58
|
+
function buildSegment (n) {
|
|
59
|
+
if (n === 0) return ''
|
|
60
|
+
|
|
61
|
+
const ones = n % 10
|
|
62
|
+
const tens = Math.floor(n / 10) % 10
|
|
63
|
+
const hundreds = Math.floor(n / 100)
|
|
64
|
+
|
|
65
|
+
const parts = []
|
|
66
|
+
|
|
67
|
+
// Hundreds - Latvian has special forms
|
|
68
|
+
if (hundreds > 0) {
|
|
69
|
+
if (hundreds === 1 && tens === 0 && ones > 0) {
|
|
70
|
+
// 101-109: use genitive form "simtu"
|
|
71
|
+
parts.push(HUNDRED_GENITIVE)
|
|
72
|
+
} else if (hundreds > 1) {
|
|
73
|
+
// 200-999: use plural "simti"
|
|
74
|
+
parts.push(ONES_MASC[hundreds])
|
|
75
|
+
parts.push(HUNDRED_PLURAL)
|
|
76
|
+
} else {
|
|
77
|
+
// 100, 110-199: use singular "simts"
|
|
78
|
+
parts.push(HUNDRED_SINGULAR)
|
|
79
|
+
}
|
|
26
80
|
}
|
|
27
81
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
3: 'trīs',
|
|
32
|
-
4: 'četras',
|
|
33
|
-
5: 'piecas',
|
|
34
|
-
6: 'sešas',
|
|
35
|
-
7: 'septiņas',
|
|
36
|
-
8: 'astoņas',
|
|
37
|
-
9: 'deviņas'
|
|
82
|
+
// Tens
|
|
83
|
+
if (tens > 1) {
|
|
84
|
+
parts.push(TENS[tens])
|
|
38
85
|
}
|
|
39
86
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
87
|
+
// Teens or ones
|
|
88
|
+
if (tens === 1) {
|
|
89
|
+
parts.push(TEENS[ones])
|
|
90
|
+
} else if (ones > 0) {
|
|
91
|
+
parts.push(ONES_MASC[ones])
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return parts.join(' ')
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Builds segment word for 0-999 (feminine form - only differs in ones).
|
|
99
|
+
*/
|
|
100
|
+
function buildSegmentFeminine (n) {
|
|
101
|
+
if (n === 0) return ''
|
|
102
|
+
|
|
103
|
+
const ones = n % 10
|
|
104
|
+
const tens = Math.floor(n / 10) % 10
|
|
105
|
+
const hundreds = Math.floor(n / 100)
|
|
106
|
+
|
|
107
|
+
const parts = []
|
|
108
|
+
|
|
109
|
+
// Hundreds - always masculine
|
|
110
|
+
if (hundreds > 0) {
|
|
111
|
+
if (hundreds === 1 && tens === 0 && ones > 0) {
|
|
112
|
+
parts.push(HUNDRED_GENITIVE)
|
|
113
|
+
} else if (hundreds > 1) {
|
|
114
|
+
parts.push(ONES_MASC[hundreds])
|
|
115
|
+
parts.push(HUNDRED_PLURAL)
|
|
116
|
+
} else {
|
|
117
|
+
parts.push(HUNDRED_SINGULAR)
|
|
118
|
+
}
|
|
51
119
|
}
|
|
52
120
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
4: 'četrdesmit',
|
|
57
|
-
5: 'piecdesmit',
|
|
58
|
-
6: 'sešdesmit',
|
|
59
|
-
7: 'septiņdesmit',
|
|
60
|
-
8: 'astoņdesmit',
|
|
61
|
-
9: 'deviņdesmit'
|
|
121
|
+
// Tens
|
|
122
|
+
if (tens > 1) {
|
|
123
|
+
parts.push(TENS[tens])
|
|
62
124
|
}
|
|
63
125
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
3: ['miljards', 'miljardi', 'miljardu'],
|
|
70
|
-
4: ['triljons', 'triljoni', 'triljonu'],
|
|
71
|
-
5: ['kvadriljons', 'kvadriljoni', 'kvadriljonu'],
|
|
72
|
-
6: ['kvintiljons', 'kvintiljoni', 'kvintiljonu'],
|
|
73
|
-
7: ['sikstiljons', 'sikstiljoni', 'sikstiljonu'],
|
|
74
|
-
8: ['septiljons', 'septiljoni', 'septiljonu'],
|
|
75
|
-
9: ['oktiljons', 'oktiljoni', 'oktiljonu'],
|
|
76
|
-
10: ['nontiljons', 'nontiljoni', 'nontiljonu']
|
|
126
|
+
// Teens or ones - feminine for ones only
|
|
127
|
+
if (tens === 1) {
|
|
128
|
+
parts.push(TEENS[ones])
|
|
129
|
+
} else if (ones > 0) {
|
|
130
|
+
parts.push(ONES_FEM[ones])
|
|
77
131
|
}
|
|
78
132
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
return forms[2]
|
|
82
|
-
}
|
|
133
|
+
return parts.join(' ')
|
|
134
|
+
}
|
|
83
135
|
|
|
84
|
-
|
|
85
|
-
|
|
136
|
+
// Precompute all 1000 segment words (0-999)
|
|
137
|
+
const SEGMENTS_MASC = new Array(1000)
|
|
138
|
+
const SEGMENTS_FEM = new Array(1000)
|
|
86
139
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
140
|
+
for (let i = 0; i < 1000; i++) {
|
|
141
|
+
SEGMENTS_MASC[i] = buildSegment(i)
|
|
142
|
+
SEGMENTS_FEM[i] = buildSegmentFeminine(i)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// ============================================================================
|
|
146
|
+
// Pluralization
|
|
147
|
+
// ============================================================================
|
|
90
148
|
|
|
91
|
-
|
|
149
|
+
/**
|
|
150
|
+
* Latvian pluralization - simpler than Slavic.
|
|
151
|
+
* Singular: ends in 1 (except 11)
|
|
152
|
+
* Plural: everything else
|
|
153
|
+
*
|
|
154
|
+
* @param {number} n - The segment value
|
|
155
|
+
* @param {string[]} forms - [singular, plural, genitive]
|
|
156
|
+
* @returns {string} The appropriate form
|
|
157
|
+
*/
|
|
158
|
+
function pluralize (n, forms) {
|
|
159
|
+
if (n === 0) return forms[2]
|
|
160
|
+
|
|
161
|
+
const lastDigit = n % 10
|
|
162
|
+
const lastTwoDigits = n % 100
|
|
163
|
+
|
|
164
|
+
if (lastDigit === 1 && lastTwoDigits !== 11) {
|
|
165
|
+
return forms[0]
|
|
92
166
|
}
|
|
93
167
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
168
|
+
return forms[1]
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// ============================================================================
|
|
172
|
+
// Conversion Functions
|
|
173
|
+
// ============================================================================
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Converts a non-negative integer to Latvian words.
|
|
177
|
+
*
|
|
178
|
+
* @param {bigint} n - Non-negative integer to convert
|
|
179
|
+
* @param {Object} options - Conversion options
|
|
180
|
+
* @returns {string} Latvian words
|
|
181
|
+
*/
|
|
182
|
+
function integerToWords (n, options = {}) {
|
|
183
|
+
if (n === 0n) return ZERO
|
|
184
|
+
|
|
185
|
+
// Fast path: numbers < 1000 (direct lookup)
|
|
186
|
+
if (n < 1000n) {
|
|
187
|
+
const segments = options.gender === 'feminine' ? SEGMENTS_FEM : SEGMENTS_MASC
|
|
188
|
+
return segments[Number(n)]
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// For numbers >= 1000, feminine only applies to final segment if < 1000
|
|
192
|
+
// But we use masculine for all segments when n >= 1000
|
|
193
|
+
return buildLargeNumberWords(n, options)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Builds words for numbers >= 1000.
|
|
198
|
+
*
|
|
199
|
+
* @param {bigint} n - Number >= 1000
|
|
200
|
+
* @param {Object} options - Conversion options
|
|
201
|
+
* @returns {string} Latvian words
|
|
202
|
+
*/
|
|
203
|
+
function buildLargeNumberWords (n, options) {
|
|
204
|
+
const numStr = n.toString()
|
|
205
|
+
const len = numStr.length
|
|
206
|
+
|
|
207
|
+
// Build segments of 3 digits from right to left
|
|
208
|
+
const segments = []
|
|
209
|
+
const segmentSize = 3
|
|
210
|
+
|
|
211
|
+
const remainderLen = len % segmentSize
|
|
212
|
+
let pos = 0
|
|
213
|
+
if (remainderLen > 0) {
|
|
214
|
+
segments.push(Number(numStr.slice(0, remainderLen)))
|
|
215
|
+
pos = remainderLen
|
|
216
|
+
}
|
|
217
|
+
while (pos < len) {
|
|
218
|
+
segments.push(Number(numStr.slice(pos, pos + segmentSize)))
|
|
219
|
+
pos += segmentSize
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Convert segments to words
|
|
223
|
+
const parts = []
|
|
224
|
+
let scaleIndex = segments.length - 1
|
|
225
|
+
|
|
226
|
+
for (let i = 0; i < segments.length; i++) {
|
|
227
|
+
const segment = segments[i]
|
|
228
|
+
|
|
229
|
+
if (segment !== 0) {
|
|
230
|
+
const segmentWord = SEGMENTS_MASC[segment]
|
|
231
|
+
|
|
232
|
+
if (scaleIndex === 0) {
|
|
233
|
+
// Units segment - use masculine (feminine doesn't apply when n >= 1000)
|
|
234
|
+
parts.push(segmentWord)
|
|
235
|
+
} else {
|
|
236
|
+
// Segment with scale word
|
|
237
|
+
const scaleForms = SCALE_FORMS[scaleIndex - 1]
|
|
238
|
+
const scaleWord = pluralize(segment, scaleForms)
|
|
239
|
+
|
|
240
|
+
// Latvian omits "one" before scale words
|
|
241
|
+
if (segment === 1) {
|
|
242
|
+
parts.push(scaleWord)
|
|
112
243
|
} else {
|
|
113
|
-
|
|
244
|
+
parts.push(segmentWord + ' ' + scaleWord)
|
|
114
245
|
}
|
|
115
246
|
}
|
|
116
|
-
if (n2 > 1n) {
|
|
117
|
-
words.push(this.twentiesWords[n2])
|
|
118
|
-
}
|
|
119
|
-
if (n2 === 1n) {
|
|
120
|
-
words.push(this.teensWords[n1])
|
|
121
|
-
} else if (n1 > 0n && !(index > 0 && x === 1n)) {
|
|
122
|
-
words.push(this.onesWords[n1])
|
|
123
|
-
}
|
|
124
|
-
if (index > 0) {
|
|
125
|
-
words.push(this.pluralize(x, this.pluralForms[index]))
|
|
126
|
-
}
|
|
127
247
|
}
|
|
128
|
-
|
|
248
|
+
|
|
249
|
+
scaleIndex--
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return parts.join(' ')
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Converts decimal digits to Latvian words.
|
|
257
|
+
*
|
|
258
|
+
* @param {string} decimalPart - Decimal digits (without the point)
|
|
259
|
+
* @param {Object} options - Conversion options
|
|
260
|
+
* @returns {string} Latvian words for decimal part
|
|
261
|
+
*/
|
|
262
|
+
function decimalPartToWords (decimalPart, options) {
|
|
263
|
+
let result = ''
|
|
264
|
+
|
|
265
|
+
// Handle leading zeros
|
|
266
|
+
let i = 0
|
|
267
|
+
while (i < decimalPart.length && decimalPart[i] === '0') {
|
|
268
|
+
if (result) result += ' '
|
|
269
|
+
result += ZERO
|
|
270
|
+
i++
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Convert remainder as a single number
|
|
274
|
+
const remainder = decimalPart.slice(i)
|
|
275
|
+
if (remainder) {
|
|
276
|
+
if (result) result += ' '
|
|
277
|
+
result += integerToWords(BigInt(remainder), options)
|
|
129
278
|
}
|
|
279
|
+
|
|
280
|
+
return result
|
|
130
281
|
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Converts a numeric value to Latvian words.
|
|
285
|
+
*
|
|
286
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
287
|
+
* @param {Object} [options] - Conversion options
|
|
288
|
+
* @param {string} [options.gender='masculine'] - Gender for numbers < 1000
|
|
289
|
+
* @returns {string} The number in Latvian words
|
|
290
|
+
* @throws {TypeError} If value is not a valid numeric type
|
|
291
|
+
* @throws {Error} If value is not a valid number format
|
|
292
|
+
*
|
|
293
|
+
* @example
|
|
294
|
+
* toWords(42) // 'četrdesmit divi'
|
|
295
|
+
* toWords(1, { gender: 'feminine' }) // 'viena'
|
|
296
|
+
* toWords(1000) // 'tūkstotis'
|
|
297
|
+
*/
|
|
298
|
+
function toWords (value, options) {
|
|
299
|
+
options = validateOptions(options)
|
|
300
|
+
const { isNegative, integerPart, decimalPart } = parseNumericValue(value)
|
|
301
|
+
|
|
302
|
+
let result = ''
|
|
303
|
+
|
|
304
|
+
if (isNegative) {
|
|
305
|
+
result = NEGATIVE + ' '
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
result += integerToWords(integerPart, options)
|
|
309
|
+
|
|
310
|
+
if (decimalPart) {
|
|
311
|
+
result += ' ' + DECIMAL_SEP + ' ' + decimalPartToWords(decimalPart, options)
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
return result
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// ============================================================================
|
|
318
|
+
// Public API
|
|
319
|
+
// ============================================================================
|
|
320
|
+
|
|
321
|
+
export { toWords }
|
package/lib/languages/mr.d.ts
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Marathi
|
|
2
|
+
* Converts a numeric value to Marathi words.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* - Devanagari script
|
|
7
|
-
* - Complete word forms for 0-99
|
|
4
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
5
|
+
* @returns {string} The number in Marathi words
|
|
8
6
|
*/
|
|
9
|
-
export
|
|
10
|
-
}
|
|
11
|
-
import { SouthAsianLanguage } from '../classes/south-asian-language.js';
|
|
7
|
+
export function toWords(value: number | string | bigint): string;
|