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/lt.js
CHANGED
|
@@ -1,136 +1,310 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Lithuanian language converter - Functional Implementation
|
|
3
|
+
*
|
|
4
|
+
* A performance-optimized number-to-words converter using precomputed lookup tables.
|
|
5
|
+
*
|
|
6
|
+
* Key features:
|
|
7
|
+
* - Three-form pluralization (singular/plural/genitive)
|
|
8
|
+
* - Gender agreement (masculine/feminine for numbers < 1000)
|
|
9
|
+
* - Two-form hundreds (šimtas/šimtai)
|
|
10
|
+
* - Long scale naming
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { parseNumericValue } from '../utils/parse-numeric.js'
|
|
14
|
+
import { validateOptions } from '../utils/validate-options.js'
|
|
15
|
+
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// Vocabulary (module-level constants)
|
|
18
|
+
// ============================================================================
|
|
19
|
+
|
|
20
|
+
const ONES_MASC = ['', 'vienas', 'du', 'trys', 'keturi', 'penki', 'šeši', 'septyni', 'aštuoni', 'devyni']
|
|
21
|
+
const ONES_FEM = ['', 'viena', 'dvi', 'trys', 'keturios', 'penkios', 'šešios', 'septynios', 'aštuonios', 'devynios']
|
|
22
|
+
|
|
23
|
+
const TEENS = ['dešimt', 'vienuolika', 'dvylika', 'trylika', 'keturiolika', 'penkiolika', 'šešiolika', 'septyniolika', 'aštuoniolika', 'devyniolika']
|
|
24
|
+
const TENS = ['', '', 'dvidešimt', 'trisdešimt', 'keturiasdešimt', 'penkiasdešimt', 'šešiasdešimt', 'septyniasdešimt', 'aštuoniasdešimt', 'devyniasdešimt']
|
|
25
|
+
|
|
26
|
+
// Hundreds: šimtas (singular), šimtai (plural)
|
|
27
|
+
const HUNDRED_SINGULAR = 'šimtas'
|
|
28
|
+
const HUNDRED_PLURAL = 'šimtai'
|
|
29
|
+
|
|
30
|
+
const ZERO = 'nulis'
|
|
31
|
+
const NEGATIVE = 'minus'
|
|
32
|
+
const DECIMAL_SEP = 'kablelis'
|
|
33
|
+
|
|
34
|
+
// Scale words: [singular, plural, genitive]
|
|
35
|
+
const SCALE_FORMS = [
|
|
36
|
+
['tūkstantis', 'tūkstančiai', 'tūkstančių'],
|
|
37
|
+
['milijonas', 'milijonai', 'milijonų'],
|
|
38
|
+
['milijardas', 'milijardai', 'milijardų'],
|
|
39
|
+
['trilijonas', 'trilijonai', 'trilijonų'],
|
|
40
|
+
['kvadrilijonas', 'kvadrilijonai', 'kvadrilijonų'],
|
|
41
|
+
['kvintilijonas', 'kvintilijonai', 'kvintilijonų'],
|
|
42
|
+
['sikstilijonas', 'sikstilijonai', 'sikstilijonų'],
|
|
43
|
+
['septilijonas', 'septilijonai', 'septilijonų'],
|
|
44
|
+
['oktilijonas', 'oktilijonai', 'oktilijonų']
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
// ============================================================================
|
|
48
|
+
// Precomputed Lookup Tables (built once at module load)
|
|
49
|
+
// ============================================================================
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Builds segment word for 0-999 (masculine form).
|
|
53
|
+
*/
|
|
54
|
+
function buildSegment (n) {
|
|
55
|
+
if (n === 0) return ''
|
|
56
|
+
|
|
57
|
+
const ones = n % 10
|
|
58
|
+
const tens = Math.floor(n / 10) % 10
|
|
59
|
+
const hundreds = Math.floor(n / 100)
|
|
60
|
+
|
|
61
|
+
const parts = []
|
|
62
|
+
|
|
63
|
+
// Hundreds - Lithuanian always includes the numeral
|
|
64
|
+
if (hundreds > 0) {
|
|
65
|
+
parts.push(ONES_MASC[hundreds])
|
|
66
|
+
parts.push(hundreds === 1 ? HUNDRED_SINGULAR : HUNDRED_PLURAL)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Tens
|
|
70
|
+
if (tens > 1) {
|
|
71
|
+
parts.push(TENS[tens])
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Teens or ones
|
|
75
|
+
if (tens === 1) {
|
|
76
|
+
parts.push(TEENS[ones])
|
|
77
|
+
} else if (ones > 0) {
|
|
78
|
+
parts.push(ONES_MASC[ones])
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return parts.join(' ')
|
|
82
|
+
}
|
|
2
83
|
|
|
3
84
|
/**
|
|
4
|
-
*
|
|
85
|
+
* Builds segment word for 0-999 (feminine form - only differs in ones).
|
|
86
|
+
*/
|
|
87
|
+
function buildSegmentFeminine (n) {
|
|
88
|
+
if (n === 0) return ''
|
|
89
|
+
|
|
90
|
+
const ones = n % 10
|
|
91
|
+
const tens = Math.floor(n / 10) % 10
|
|
92
|
+
const hundreds = Math.floor(n / 100)
|
|
93
|
+
|
|
94
|
+
const parts = []
|
|
95
|
+
|
|
96
|
+
// Hundreds - always masculine
|
|
97
|
+
if (hundreds > 0) {
|
|
98
|
+
parts.push(ONES_MASC[hundreds])
|
|
99
|
+
parts.push(hundreds === 1 ? HUNDRED_SINGULAR : HUNDRED_PLURAL)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Tens
|
|
103
|
+
if (tens > 1) {
|
|
104
|
+
parts.push(TENS[tens])
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Teens or ones - feminine for ones only
|
|
108
|
+
if (tens === 1) {
|
|
109
|
+
parts.push(TEENS[ones])
|
|
110
|
+
} else if (ones > 0) {
|
|
111
|
+
parts.push(ONES_FEM[ones])
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return parts.join(' ')
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Precompute all 1000 segment words (0-999)
|
|
118
|
+
const SEGMENTS_MASC = new Array(1000)
|
|
119
|
+
const SEGMENTS_FEM = new Array(1000)
|
|
120
|
+
|
|
121
|
+
for (let i = 0; i < 1000; i++) {
|
|
122
|
+
SEGMENTS_MASC[i] = buildSegment(i)
|
|
123
|
+
SEGMENTS_FEM[i] = buildSegmentFeminine(i)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// ============================================================================
|
|
127
|
+
// Pluralization
|
|
128
|
+
// ============================================================================
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Lithuanian pluralization rules.
|
|
132
|
+
* - Singular: ends in 1 (except 11)
|
|
133
|
+
* - Plural: ends in 2-9 (except 12-19)
|
|
134
|
+
* - Genitive: 0, 10-19, or ends in 0
|
|
5
135
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* - Baltic declension patterns
|
|
136
|
+
* @param {number} n - The segment value
|
|
137
|
+
* @param {string[]} forms - [singular, plural, genitive]
|
|
138
|
+
* @returns {string} The appropriate form
|
|
10
139
|
*/
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
decimalSeparatorWord = 'kablelis'
|
|
14
|
-
zeroWord = 'nulis'
|
|
15
|
-
|
|
16
|
-
onesWords = {
|
|
17
|
-
1: 'vienas',
|
|
18
|
-
2: 'du',
|
|
19
|
-
3: 'trys',
|
|
20
|
-
4: 'keturi',
|
|
21
|
-
5: 'penki',
|
|
22
|
-
6: 'šeši',
|
|
23
|
-
7: 'septyni',
|
|
24
|
-
8: 'aštuoni',
|
|
25
|
-
9: 'devyni'
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
onesFeminineWords = {
|
|
29
|
-
1: 'viena',
|
|
30
|
-
2: 'dvi',
|
|
31
|
-
3: 'trys',
|
|
32
|
-
4: 'keturios',
|
|
33
|
-
5: 'penkios',
|
|
34
|
-
6: 'šešios',
|
|
35
|
-
7: 'septynios',
|
|
36
|
-
8: 'aštuonios',
|
|
37
|
-
9: 'devynios'
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
teensWords = {
|
|
41
|
-
0: 'dešimt',
|
|
42
|
-
1: 'vienuolika',
|
|
43
|
-
2: 'dvylika',
|
|
44
|
-
3: 'trylika',
|
|
45
|
-
4: 'keturiolika',
|
|
46
|
-
5: 'penkiolika',
|
|
47
|
-
6: 'šešiolika',
|
|
48
|
-
7: 'septyniolika',
|
|
49
|
-
8: 'aštuoniolika',
|
|
50
|
-
9: 'devyniolika'
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
twentiesWords = {
|
|
54
|
-
2: 'dvidešimt',
|
|
55
|
-
3: 'trisdešimt',
|
|
56
|
-
4: 'keturiasdešimt',
|
|
57
|
-
5: 'penkiasdešimt',
|
|
58
|
-
6: 'šešiasdešimt',
|
|
59
|
-
7: 'septyniasdešimt',
|
|
60
|
-
8: 'aštuoniasdešimt',
|
|
61
|
-
9: 'devyniasdešimt'
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
hundredsWords = ['šimtas', 'šimtai']
|
|
65
|
-
|
|
66
|
-
pluralForms = {
|
|
67
|
-
1: ['tūkstantis', 'tūkstančiai', 'tūkstančių'],
|
|
68
|
-
2: ['milijonas', 'milijonai', 'milijonų'],
|
|
69
|
-
3: ['milijardas', 'milijardai', 'milijardų'],
|
|
70
|
-
4: ['trilijonas', 'trilijonai', 'trilijonų'],
|
|
71
|
-
5: ['kvadrilijonas', 'kvadrilijonai', 'kvadrilijonų'],
|
|
72
|
-
6: ['kvintilijonas', 'kvintilijonai', 'kvintilijonų'],
|
|
73
|
-
7: ['sikstilijonas', 'sikstilijonai', 'sikstilijonų'],
|
|
74
|
-
8: ['septilijonas', 'septilijonai', 'septilijonų'],
|
|
75
|
-
9: ['oktilijonas', 'oktilijonai', 'oktilijonų'],
|
|
76
|
-
10: ['naintilijonas', 'naintilijonai', 'naintilijonų']
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
pluralize (n, forms) {
|
|
80
|
-
if (n === 0n) {
|
|
81
|
-
return forms[2]
|
|
82
|
-
}
|
|
140
|
+
function pluralize (n, forms) {
|
|
141
|
+
if (n === 0) return forms[2]
|
|
83
142
|
|
|
84
|
-
|
|
143
|
+
const lastDigit = n % 10
|
|
144
|
+
const lastTwoDigits = n % 100
|
|
85
145
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
146
|
+
// 10-19 always use genitive
|
|
147
|
+
if (lastTwoDigits >= 10 && lastTwoDigits <= 19) {
|
|
148
|
+
return forms[2]
|
|
149
|
+
}
|
|
89
150
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
151
|
+
// Ends in 0 → genitive
|
|
152
|
+
if (lastDigit === 0) {
|
|
153
|
+
return forms[2]
|
|
154
|
+
}
|
|
93
155
|
|
|
94
|
-
|
|
156
|
+
// Ends in 1 → singular
|
|
157
|
+
if (lastDigit === 1) {
|
|
158
|
+
return forms[0]
|
|
95
159
|
}
|
|
96
160
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
161
|
+
// Ends in 2-9 → plural
|
|
162
|
+
return forms[1]
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// ============================================================================
|
|
166
|
+
// Conversion Functions
|
|
167
|
+
// ============================================================================
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Converts a non-negative integer to Lithuanian words.
|
|
171
|
+
*
|
|
172
|
+
* @param {bigint} n - Non-negative integer to convert
|
|
173
|
+
* @param {Object} options - Conversion options
|
|
174
|
+
* @returns {string} Lithuanian words
|
|
175
|
+
*/
|
|
176
|
+
function integerToWords (n, options = {}) {
|
|
177
|
+
if (n === 0n) return ZERO
|
|
178
|
+
|
|
179
|
+
// Fast path: numbers < 1000 (direct lookup)
|
|
180
|
+
if (n < 1000n) {
|
|
181
|
+
const segments = options.gender === 'feminine' ? SEGMENTS_FEM : SEGMENTS_MASC
|
|
182
|
+
return segments[Number(n)]
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// For numbers >= 1000, feminine only applies to final segment if < 1000
|
|
186
|
+
// But the fixture shows feminine NOT applying for n >= 1000
|
|
187
|
+
// So we use masculine for all segments when n >= 1000
|
|
188
|
+
return buildLargeNumberWords(n, options)
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Builds words for numbers >= 1000.
|
|
193
|
+
*
|
|
194
|
+
* @param {bigint} n - Number >= 1000
|
|
195
|
+
* @param {Object} options - Conversion options
|
|
196
|
+
* @returns {string} Lithuanian words
|
|
197
|
+
*/
|
|
198
|
+
function buildLargeNumberWords (n, options) {
|
|
199
|
+
const numStr = n.toString()
|
|
200
|
+
const len = numStr.length
|
|
201
|
+
|
|
202
|
+
// Build segments of 3 digits from right to left
|
|
203
|
+
const segments = []
|
|
204
|
+
const segmentSize = 3
|
|
205
|
+
|
|
206
|
+
const remainderLen = len % segmentSize
|
|
207
|
+
let pos = 0
|
|
208
|
+
if (remainderLen > 0) {
|
|
209
|
+
segments.push(Number(numStr.slice(0, remainderLen)))
|
|
210
|
+
pos = remainderLen
|
|
211
|
+
}
|
|
212
|
+
while (pos < len) {
|
|
213
|
+
segments.push(Number(numStr.slice(pos, pos + segmentSize)))
|
|
214
|
+
pos += segmentSize
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Convert segments to words
|
|
218
|
+
const parts = []
|
|
219
|
+
let scaleIndex = segments.length - 1
|
|
220
|
+
|
|
221
|
+
for (let i = 0; i < segments.length; i++) {
|
|
222
|
+
const segment = segments[i]
|
|
223
|
+
|
|
224
|
+
if (segment !== 0) {
|
|
225
|
+
const segmentWord = SEGMENTS_MASC[segment]
|
|
226
|
+
|
|
227
|
+
if (scaleIndex === 0) {
|
|
228
|
+
// Units segment - use masculine (feminine doesn't apply when n >= 1000)
|
|
229
|
+
parts.push(segmentWord)
|
|
230
|
+
} else {
|
|
231
|
+
// Segment with scale word
|
|
232
|
+
const scaleForms = SCALE_FORMS[scaleIndex - 1]
|
|
233
|
+
const scaleWord = pluralize(segment, scaleForms)
|
|
234
|
+
parts.push(segmentWord + ' ' + scaleWord)
|
|
132
235
|
}
|
|
133
236
|
}
|
|
134
|
-
|
|
237
|
+
|
|
238
|
+
scaleIndex--
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return parts.join(' ')
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Converts decimal digits to Lithuanian words.
|
|
246
|
+
*
|
|
247
|
+
* @param {string} decimalPart - Decimal digits (without the point)
|
|
248
|
+
* @param {Object} options - Conversion options
|
|
249
|
+
* @returns {string} Lithuanian words for decimal part
|
|
250
|
+
*/
|
|
251
|
+
function decimalPartToWords (decimalPart, options) {
|
|
252
|
+
let result = ''
|
|
253
|
+
|
|
254
|
+
// Handle leading zeros
|
|
255
|
+
let i = 0
|
|
256
|
+
while (i < decimalPart.length && decimalPart[i] === '0') {
|
|
257
|
+
if (result) result += ' '
|
|
258
|
+
result += ZERO
|
|
259
|
+
i++
|
|
135
260
|
}
|
|
261
|
+
|
|
262
|
+
// Convert remainder as a single number
|
|
263
|
+
const remainder = decimalPart.slice(i)
|
|
264
|
+
if (remainder) {
|
|
265
|
+
if (result) result += ' '
|
|
266
|
+
result += integerToWords(BigInt(remainder), options)
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return result
|
|
136
270
|
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Converts a numeric value to Lithuanian words.
|
|
274
|
+
*
|
|
275
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
276
|
+
* @param {Object} [options] - Conversion options
|
|
277
|
+
* @param {string} [options.gender='masculine'] - Gender for numbers < 1000
|
|
278
|
+
* @returns {string} The number in Lithuanian words
|
|
279
|
+
* @throws {TypeError} If value is not a valid numeric type
|
|
280
|
+
* @throws {Error} If value is not a valid number format
|
|
281
|
+
*
|
|
282
|
+
* @example
|
|
283
|
+
* toWords(42) // 'keturiasdešimt du'
|
|
284
|
+
* toWords(1, { gender: 'feminine' }) // 'viena'
|
|
285
|
+
* toWords(1000000) // 'vienas milijonas'
|
|
286
|
+
*/
|
|
287
|
+
function toWords (value, options) {
|
|
288
|
+
options = validateOptions(options)
|
|
289
|
+
const { isNegative, integerPart, decimalPart } = parseNumericValue(value)
|
|
290
|
+
|
|
291
|
+
let result = ''
|
|
292
|
+
|
|
293
|
+
if (isNegative) {
|
|
294
|
+
result = NEGATIVE + ' '
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
result += integerToWords(integerPart, options)
|
|
298
|
+
|
|
299
|
+
if (decimalPart) {
|
|
300
|
+
result += ' ' + DECIMAL_SEP + ' ' + decimalPartToWords(decimalPart, options)
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
return result
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// ============================================================================
|
|
307
|
+
// Public API
|
|
308
|
+
// ============================================================================
|
|
309
|
+
|
|
310
|
+
export { toWords }
|
package/lib/languages/lv.d.ts
CHANGED
|
@@ -1,70 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Latvian
|
|
2
|
+
* Converts a numeric value to Latvian words.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
5
|
+
* @param {Object} [options] - Conversion options
|
|
6
|
+
* @param {string} [options.gender='masculine'] - Gender for numbers < 1000
|
|
7
|
+
* @returns {string} The number in Latvian words
|
|
8
|
+
* @throws {TypeError} If value is not a valid numeric type
|
|
9
|
+
* @throws {Error} If value is not a valid number format
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* toWords(42) // 'četrdesmit divi'
|
|
13
|
+
* toWords(1, { gender: 'feminine' }) // 'viena'
|
|
14
|
+
* toWords(1000) // 'tūkstotis'
|
|
8
15
|
*/
|
|
9
|
-
export
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
2: string;
|
|
13
|
-
3: string;
|
|
14
|
-
4: string;
|
|
15
|
-
5: string;
|
|
16
|
-
6: string;
|
|
17
|
-
7: string;
|
|
18
|
-
8: string;
|
|
19
|
-
9: string;
|
|
20
|
-
};
|
|
21
|
-
onesFeminineWords: {
|
|
22
|
-
1: string;
|
|
23
|
-
2: string;
|
|
24
|
-
3: string;
|
|
25
|
-
4: string;
|
|
26
|
-
5: string;
|
|
27
|
-
6: string;
|
|
28
|
-
7: string;
|
|
29
|
-
8: string;
|
|
30
|
-
9: string;
|
|
31
|
-
};
|
|
32
|
-
teensWords: {
|
|
33
|
-
0: string;
|
|
34
|
-
1: string;
|
|
35
|
-
2: string;
|
|
36
|
-
3: string;
|
|
37
|
-
4: string;
|
|
38
|
-
5: string;
|
|
39
|
-
6: string;
|
|
40
|
-
7: string;
|
|
41
|
-
8: string;
|
|
42
|
-
9: string;
|
|
43
|
-
};
|
|
44
|
-
twentiesWords: {
|
|
45
|
-
2: string;
|
|
46
|
-
3: string;
|
|
47
|
-
4: string;
|
|
48
|
-
5: string;
|
|
49
|
-
6: string;
|
|
50
|
-
7: string;
|
|
51
|
-
8: string;
|
|
52
|
-
9: string;
|
|
53
|
-
};
|
|
54
|
-
hundredsWords: string[];
|
|
55
|
-
pluralForms: {
|
|
56
|
-
1: string[];
|
|
57
|
-
2: string[];
|
|
58
|
-
3: string[];
|
|
59
|
-
4: string[];
|
|
60
|
-
5: string[];
|
|
61
|
-
6: string[];
|
|
62
|
-
7: string[];
|
|
63
|
-
8: string[];
|
|
64
|
-
9: string[];
|
|
65
|
-
10: string[];
|
|
66
|
-
};
|
|
67
|
-
pluralize(n: any, forms: any): any;
|
|
68
|
-
integerToWords(integerPart: any): string;
|
|
69
|
-
}
|
|
70
|
-
import { SlavicLanguage } from '../classes/slavic-language.js';
|
|
16
|
+
export function toWords(value: number | string | bigint, options?: {
|
|
17
|
+
gender?: string | undefined;
|
|
18
|
+
}): string;
|