n2words 2.0.0 → 3.1.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 +64 -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/ka.js +3 -0
- package/dist/languages/ka.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/yo.js +3 -0
- package/dist/languages/yo.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 +159 -0
- package/lib/languages/am.d.ts +7 -0
- package/lib/languages/am.js +159 -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 +166 -37
- package/lib/languages/bn.d.ts +4 -8
- package/lib/languages/bn.js +159 -124
- package/lib/languages/cs.d.ts +15 -85
- package/lib/languages/cs.js +293 -114
- package/lib/languages/da.d.ts +11 -12
- package/lib/languages/da.js +269 -101
- package/lib/languages/de.d.ts +14 -11
- package/lib/languages/de.js +305 -86
- package/lib/languages/el.d.ts +11 -11
- package/lib/languages/el.js +224 -78
- package/lib/languages/en.d.ts +14 -13
- package/lib/languages/en.js +228 -72
- package/lib/languages/es.d.ts +18 -12
- package/lib/languages/es.js +297 -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 +238 -0
- package/lib/languages/fil.d.ts +4 -13
- package/lib/languages/fil.js +196 -106
- package/lib/languages/fr-BE.d.ts +8 -8
- package/lib/languages/fr-BE.js +285 -19
- package/lib/languages/fr.d.ts +18 -12
- package/lib/languages/fr.js +339 -89
- package/lib/languages/gu.d.ts +4 -8
- package/lib/languages/gu.js +143 -125
- package/lib/languages/ha.d.ts +7 -0
- package/lib/languages/ha.js +225 -0
- package/lib/languages/hbo.d.ts +10 -110
- package/lib/languages/hbo.js +245 -214
- package/lib/languages/he.d.ts +10 -77
- package/lib/languages/he.js +231 -172
- package/lib/languages/hi.d.ts +4 -8
- package/lib/languages/hi.js +163 -124
- package/lib/languages/hr.d.ts +8 -77
- package/lib/languages/hr.js +200 -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 +166 -129
- package/lib/languages/it.d.ts +16 -34
- package/lib/languages/it.js +307 -97
- package/lib/languages/ja.d.ts +14 -14
- package/lib/languages/ja.js +221 -111
- package/lib/languages/ka.d.ts +17 -0
- package/lib/languages/ka.js +291 -0
- package/lib/languages/kn.d.ts +4 -8
- package/lib/languages/kn.js +143 -35
- package/lib/languages/ko.d.ts +11 -11
- package/lib/languages/ko.js +250 -49
- package/lib/languages/lt.d.ts +15 -67
- package/lib/languages/lt.js +287 -122
- package/lib/languages/lv.d.ts +15 -67
- package/lib/languages/lv.js +288 -106
- package/lib/languages/mr.d.ts +4 -8
- package/lib/languages/mr.js +143 -125
- package/lib/languages/ms.d.ts +4 -28
- package/lib/languages/ms.js +166 -116
- package/lib/languages/nb.d.ts +11 -9
- package/lib/languages/nb.js +272 -87
- package/lib/languages/nl.d.ts +23 -13
- package/lib/languages/nl.js +299 -133
- package/lib/languages/pa.d.ts +4 -8
- package/lib/languages/pa.js +151 -124
- package/lib/languages/pl.d.ts +19 -77
- package/lib/languages/pl.js +294 -87
- package/lib/languages/pt.d.ts +14 -26
- package/lib/languages/pt.js +272 -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 +239 -90
- package/lib/languages/sr-Cyrl.d.ts +8 -77
- package/lib/languages/sr-Cyrl.js +197 -89
- package/lib/languages/sr-Latn.d.ts +8 -77
- package/lib/languages/sr-Latn.js +197 -89
- package/lib/languages/sv.d.ts +11 -11
- package/lib/languages/sv.js +278 -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 +143 -202
- package/lib/languages/te.d.ts +4 -19
- package/lib/languages/te.js +133 -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 +245 -49
- package/lib/languages/uk.d.ts +8 -82
- package/lib/languages/uk.js +206 -78
- package/lib/languages/ur.d.ts +4 -8
- package/lib/languages/ur.js +151 -124
- package/lib/languages/vi.d.ts +14 -69
- package/lib/languages/vi.js +278 -129
- package/lib/languages/yo.d.ts +7 -0
- package/lib/languages/yo.js +303 -0
- 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 +55 -209
- package/lib/n2words.js +115 -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/cs.js
CHANGED
|
@@ -1,143 +1,322 @@
|
|
|
1
|
-
import { SlavicLanguage } from '../classes/slavic-language.js'
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
|
-
* Czech language converter
|
|
2
|
+
* Czech language converter - Functional Implementation
|
|
3
|
+
*
|
|
4
|
+
* Self-contained module with its own input validation, ready for subpath exports.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* - Three-form pluralization
|
|
8
|
-
* -
|
|
9
|
-
* - Gender
|
|
6
|
+
* Czech-specific rules:
|
|
7
|
+
* - Three-form pluralization: 1 = singular, 2-4 = few, 5+ = many
|
|
8
|
+
* - Irregular hundreds: sto, dvě stě, tři sta, čtyři sta, pět set...
|
|
9
|
+
* - Gender: dva (masc) vs dvě (fem) for 2
|
|
10
|
+
* - Omit "one" before scale words: "tisíc" not "jedna tisíc"
|
|
11
|
+
* - Dynamic decimal separator: celá/celé/celých based on integer
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { parseNumericValue } from '../utils/parse-numeric.js'
|
|
15
|
+
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// Vocabulary (module-level constants)
|
|
18
|
+
// ============================================================================
|
|
19
|
+
|
|
20
|
+
// Ones words (masculine form)
|
|
21
|
+
const ONES = ['', 'jedna', 'dva', 'tři', 'čtyři', 'pět', 'šest', 'sedm', 'osm', 'devět']
|
|
22
|
+
|
|
23
|
+
// Teens (10-19)
|
|
24
|
+
const TEENS = ['deset', 'jedenáct', 'dvanáct', 'třináct', 'čtrnáct', 'patnáct', 'šestnáct', 'sedmnáct', 'osmnáct', 'devatenáct']
|
|
25
|
+
|
|
26
|
+
// Tens (20-90)
|
|
27
|
+
const TENS = ['', '', 'dvacet', 'třicet', 'čtyřicet', 'padesát', 'šedesát', 'sedmdesát', 'osmdesát', 'devadesát']
|
|
28
|
+
|
|
29
|
+
// Irregular hundreds
|
|
30
|
+
const HUNDREDS = ['', 'sto', 'dvě stě', 'tři sta', 'čtyři sta', 'pět set', 'šest set', 'sedm set', 'osm set', 'devět set']
|
|
31
|
+
|
|
32
|
+
// Scale plural forms [singular, few (2-4), many (5+)]
|
|
33
|
+
const PLURAL_FORMS = {
|
|
34
|
+
1: ['tisíc', 'tisíce', 'tisíc'], // 10^3
|
|
35
|
+
2: ['milion', 'miliony', 'milionů'], // 10^6
|
|
36
|
+
3: ['miliarda', 'miliardy', 'miliard'], // 10^9
|
|
37
|
+
4: ['bilion', 'biliony', 'bilionů'], // 10^12
|
|
38
|
+
5: ['biliarda', 'biliardy', 'biliard'], // 10^15
|
|
39
|
+
6: ['trilion', 'triliony', 'trilionů'], // 10^18
|
|
40
|
+
7: ['triliarda', 'triliardy', 'triliard'], // 10^21
|
|
41
|
+
8: ['kvadrilion', 'kvadriliony', 'kvadrilionů'], // 10^24
|
|
42
|
+
9: ['kvadriliarda', 'kvadriliardy', 'kvadriliard'] // 10^27
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const ZERO = 'nula'
|
|
46
|
+
const NEGATIVE = 'mínus'
|
|
47
|
+
|
|
48
|
+
// ============================================================================
|
|
49
|
+
// Segment Building
|
|
50
|
+
// ============================================================================
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Builds segment word for 0-999 (masculine, default form).
|
|
10
54
|
*/
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
8: 'osm',
|
|
24
|
-
9: 'devět'
|
|
55
|
+
function buildSegment (n) {
|
|
56
|
+
if (n === 0) return ''
|
|
57
|
+
|
|
58
|
+
const ones = n % 10
|
|
59
|
+
const tens = Math.floor(n / 10) % 10
|
|
60
|
+
const hundreds = Math.floor(n / 100)
|
|
61
|
+
|
|
62
|
+
const parts = []
|
|
63
|
+
|
|
64
|
+
// Hundreds (irregular)
|
|
65
|
+
if (hundreds > 0) {
|
|
66
|
+
parts.push(HUNDREDS[hundreds])
|
|
25
67
|
}
|
|
26
68
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
69
|
+
// Tens and ones
|
|
70
|
+
if (tens === 1) {
|
|
71
|
+
// Teens
|
|
72
|
+
parts.push(TEENS[ones])
|
|
73
|
+
} else if (tens >= 2) {
|
|
74
|
+
parts.push(TENS[tens])
|
|
75
|
+
if (ones > 0) {
|
|
76
|
+
parts.push(ONES[ones])
|
|
77
|
+
}
|
|
78
|
+
} else if (ones > 0) {
|
|
79
|
+
parts.push(ONES[ones])
|
|
37
80
|
}
|
|
38
81
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
82
|
+
return parts.join(' ')
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Builds segment word for 0-999 with feminine hundreds.
|
|
87
|
+
* Hundreds use irregular forms (dvě stě, tři sta) but ones remain masculine.
|
|
88
|
+
*/
|
|
89
|
+
function buildSegmentWithHundreds (n) {
|
|
90
|
+
if (n === 0) return ''
|
|
91
|
+
|
|
92
|
+
const ones = n % 10
|
|
93
|
+
const tens = Math.floor(n / 10) % 10
|
|
94
|
+
const hundreds = Math.floor(n / 100)
|
|
95
|
+
|
|
96
|
+
const parts = []
|
|
97
|
+
|
|
98
|
+
// Hundreds use the irregular HUNDREDS array (already has "dvě stě" etc.)
|
|
99
|
+
if (hundreds > 0) {
|
|
100
|
+
parts.push(HUNDREDS[hundreds])
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Tens and ones use masculine form
|
|
104
|
+
if (tens === 1) {
|
|
105
|
+
parts.push(TEENS[ones])
|
|
106
|
+
} else if (tens >= 2) {
|
|
107
|
+
parts.push(TENS[tens])
|
|
108
|
+
if (ones > 0) {
|
|
109
|
+
parts.push(ONES[ones]) // masculine
|
|
110
|
+
}
|
|
111
|
+
} else if (ones > 0) {
|
|
112
|
+
parts.push(ONES[ones]) // masculine
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return parts.join(' ')
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// ============================================================================
|
|
119
|
+
// Helper Functions
|
|
120
|
+
// ============================================================================
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Czech pluralization: 1 = singular, 2-4 = few, else = many.
|
|
124
|
+
* Teens (11-19) always use "many" form.
|
|
125
|
+
*
|
|
126
|
+
* @param {bigint} n - The number
|
|
127
|
+
* @param {string[]} forms - [singular, few, many]
|
|
128
|
+
* @returns {string} The appropriate form
|
|
129
|
+
*/
|
|
130
|
+
function pluralize (n, forms) {
|
|
131
|
+
if (n === 1n) return forms[0]
|
|
132
|
+
|
|
133
|
+
const lastDigit = n % 10n
|
|
134
|
+
const lastTwoDigits = n % 100n
|
|
135
|
+
|
|
136
|
+
// 2-4, but not 12-14 (teens use "many")
|
|
137
|
+
if (lastDigit >= 2n && lastDigit <= 4n && (lastTwoDigits < 10n || lastTwoDigits > 20n)) {
|
|
138
|
+
return forms[1]
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return forms[2]
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Gets the decimal separator word based on integer part.
|
|
146
|
+
* celá (0-1), celé (2-4), celých (5+)
|
|
147
|
+
*/
|
|
148
|
+
function getDecimalSeparator (integerPart) {
|
|
149
|
+
if (integerPart === 0n || integerPart === 1n) {
|
|
150
|
+
return 'celá'
|
|
151
|
+
} else if (integerPart >= 2n && integerPart <= 4n) {
|
|
152
|
+
return 'celé'
|
|
153
|
+
} else {
|
|
154
|
+
return 'celých'
|
|
50
155
|
}
|
|
156
|
+
}
|
|
51
157
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
158
|
+
// ============================================================================
|
|
159
|
+
// Conversion Functions
|
|
160
|
+
// ============================================================================
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Converts a non-negative integer to Czech words.
|
|
164
|
+
*
|
|
165
|
+
* @param {bigint} n - Non-negative integer to convert
|
|
166
|
+
* @returns {string} Czech words
|
|
167
|
+
*/
|
|
168
|
+
function integerToWords (n) {
|
|
169
|
+
if (n === 0n) return ZERO
|
|
170
|
+
|
|
171
|
+
// Fast path: numbers < 1000
|
|
172
|
+
if (n < 1000n) {
|
|
173
|
+
return buildSegment(Number(n))
|
|
61
174
|
}
|
|
62
175
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
176
|
+
// Fast path: numbers < 1,000,000 (thousands)
|
|
177
|
+
if (n < 1_000_000n) {
|
|
178
|
+
const thousands = n / 1000n
|
|
179
|
+
const remainder = Number(n % 1000n)
|
|
180
|
+
|
|
181
|
+
const scaleWord = pluralize(thousands, PLURAL_FORMS[1])
|
|
182
|
+
|
|
183
|
+
let result
|
|
184
|
+
if (thousands === 1n) {
|
|
185
|
+
// Omit "one" before tisíc
|
|
186
|
+
result = scaleWord
|
|
187
|
+
} else {
|
|
188
|
+
result = buildSegment(Number(thousands)) + ' ' + scaleWord
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (remainder > 0) {
|
|
192
|
+
// Use form with irregular hundreds (for "dvě stě" etc.)
|
|
193
|
+
result += ' ' + buildSegmentWithHundreds(remainder)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return result
|
|
73
197
|
}
|
|
74
198
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
199
|
+
// For numbers >= 1,000,000, use scale decomposition
|
|
200
|
+
return buildLargeNumberWords(n)
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Builds words for numbers >= 1,000,000.
|
|
205
|
+
* Uses BigInt division for faster segment extraction.
|
|
206
|
+
*
|
|
207
|
+
* @param {bigint} n - Number >= 1,000,000
|
|
208
|
+
* @returns {string} Czech words
|
|
209
|
+
*/
|
|
210
|
+
function buildLargeNumberWords (n) {
|
|
211
|
+
// Extract segments using BigInt division (faster than string slicing)
|
|
212
|
+
// Segments stored least-significant first (index 0 = ones, 1 = thousands, etc.)
|
|
213
|
+
const segmentValues = []
|
|
214
|
+
let temp = n
|
|
215
|
+
while (temp > 0n) {
|
|
216
|
+
segmentValues.push(temp % 1000n)
|
|
217
|
+
temp = temp / 1000n
|
|
86
218
|
}
|
|
87
219
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
/** Returns decimal separator word based on integer part (celá/celé/celých). */
|
|
102
|
-
get decimalSeparatorWord () {
|
|
103
|
-
if (this.#integerPart === 0n || this.#integerPart === 1n) {
|
|
104
|
-
return 'celá'
|
|
105
|
-
} else if (this.#integerPart >= 2n && this.#integerPart <= 4n) {
|
|
106
|
-
return 'celé'
|
|
220
|
+
// Build result string directly
|
|
221
|
+
let result = ''
|
|
222
|
+
|
|
223
|
+
for (let i = segmentValues.length - 1; i >= 0; i--) {
|
|
224
|
+
const segment = segmentValues[i]
|
|
225
|
+
if (segment === 0n) continue
|
|
226
|
+
|
|
227
|
+
if (result) result += ' '
|
|
228
|
+
|
|
229
|
+
if (i === 0) {
|
|
230
|
+
// Units segment (no scale word) - use form with irregular hundreds
|
|
231
|
+
result += buildSegmentWithHundreds(Number(segment))
|
|
107
232
|
} else {
|
|
108
|
-
|
|
233
|
+
// Scale word needed
|
|
234
|
+
const forms = PLURAL_FORMS[i]
|
|
235
|
+
if (forms) {
|
|
236
|
+
const scaleWord = pluralize(segment, forms)
|
|
237
|
+
|
|
238
|
+
if (segment === 1n) {
|
|
239
|
+
// Omit "one" before scale words
|
|
240
|
+
result += scaleWord
|
|
241
|
+
} else {
|
|
242
|
+
// Use masculine form for multiplier before scale words
|
|
243
|
+
result += buildSegment(Number(segment)) + ' ' + scaleWord
|
|
244
|
+
}
|
|
245
|
+
} else {
|
|
246
|
+
// Fallback for very large scales without defined forms
|
|
247
|
+
result += buildSegment(Number(segment))
|
|
248
|
+
}
|
|
109
249
|
}
|
|
110
250
|
}
|
|
111
251
|
|
|
112
|
-
|
|
113
|
-
|
|
252
|
+
return result
|
|
253
|
+
}
|
|
114
254
|
|
|
115
|
-
|
|
116
|
-
|
|
255
|
+
/**
|
|
256
|
+
* Converts decimal digits to Czech words.
|
|
257
|
+
*
|
|
258
|
+
* @param {string} decimalPart - Decimal digits (without the point)
|
|
259
|
+
* @returns {string} Czech words for decimal part
|
|
260
|
+
*/
|
|
261
|
+
function decimalPartToWords (decimalPart) {
|
|
262
|
+
let result = ''
|
|
263
|
+
|
|
264
|
+
// Handle leading zeros
|
|
265
|
+
let i = 0
|
|
266
|
+
while (i < decimalPart.length && decimalPart[i] === '0') {
|
|
267
|
+
if (result) result += ' '
|
|
268
|
+
result += ZERO
|
|
269
|
+
i++
|
|
117
270
|
}
|
|
118
271
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
return super.toWords(isNegative, integerPart, decimalPart)
|
|
272
|
+
// Convert remainder as a single number
|
|
273
|
+
const remainder = decimalPart.slice(i)
|
|
274
|
+
if (remainder) {
|
|
275
|
+
if (result) result += ' '
|
|
276
|
+
result += integerToWords(BigInt(remainder))
|
|
125
277
|
}
|
|
126
278
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
if (n === 1n) {
|
|
130
|
-
return forms[0]
|
|
131
|
-
}
|
|
279
|
+
return result
|
|
280
|
+
}
|
|
132
281
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
282
|
+
/**
|
|
283
|
+
* Converts a numeric value to Czech words.
|
|
284
|
+
*
|
|
285
|
+
* This is the main public API. It accepts any valid numeric input
|
|
286
|
+
* (number, string, or bigint) and handles parsing internally.
|
|
287
|
+
*
|
|
288
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
289
|
+
* @returns {string} The number in Czech 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(21) // 'dvacet jedna'
|
|
295
|
+
* toWords(1000) // 'tisíc'
|
|
296
|
+
* toWords(2000) // 'dva tisíce'
|
|
297
|
+
* toWords(5000) // 'pět tisíc'
|
|
298
|
+
*/
|
|
299
|
+
function toWords (value) {
|
|
300
|
+
const { isNegative, integerPart, decimalPart } = parseNumericValue(value)
|
|
136
301
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
302
|
+
let result = ''
|
|
303
|
+
|
|
304
|
+
if (isNegative) {
|
|
305
|
+
result = NEGATIVE + ' '
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
result += integerToWords(integerPart)
|
|
140
309
|
|
|
141
|
-
|
|
310
|
+
if (decimalPart) {
|
|
311
|
+
const separator = getDecimalSeparator(integerPart)
|
|
312
|
+
result += ' ' + separator + ' ' + decimalPartToWords(decimalPart)
|
|
142
313
|
}
|
|
314
|
+
|
|
315
|
+
return result
|
|
143
316
|
}
|
|
317
|
+
|
|
318
|
+
// ============================================================================
|
|
319
|
+
// Public API
|
|
320
|
+
// ============================================================================
|
|
321
|
+
|
|
322
|
+
export { toWords }
|
package/lib/languages/da.d.ts
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Danish
|
|
2
|
+
* Converts a numeric value to Danish words.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
5
|
+
* @returns {string} The number in Danish words
|
|
6
|
+
* @throws {TypeError} If value is not a valid numeric type
|
|
7
|
+
* @throws {Error} If value is not a valid number format
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* toWords(21) // 'enogtyve'
|
|
11
|
+
* toWords(1000) // 'ettusind'
|
|
12
|
+
* toWords(1000000) // 'en millioner'
|
|
8
13
|
*/
|
|
9
|
-
export
|
|
10
|
-
constructor(options?: {});
|
|
11
|
-
scaleWords: (string | bigint)[][];
|
|
12
|
-
/** Combines two word-sets with Danish vigesimal and reversal rules. */
|
|
13
|
-
combineWordSets(preceding: any, following: any): any;
|
|
14
|
-
}
|
|
15
|
-
import { GreedyScaleLanguage } from '../classes/greedy-scale-language.js';
|
|
14
|
+
export function toWords(value: number | string | bigint): string;
|