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/fr.d.ts
CHANGED
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* French
|
|
2
|
+
* Converts a numeric value to French words.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* -
|
|
4
|
+
* This is the main public API. It accepts any valid numeric input
|
|
5
|
+
* (number, string, or bigint) and handles parsing internally.
|
|
6
|
+
*
|
|
7
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
8
|
+
* @param {Object} [options] - Optional configuration
|
|
9
|
+
* @param {boolean} [options.withHyphenSeparator=false] - Use hyphens between all words
|
|
10
|
+
* @returns {string} The number in French words
|
|
11
|
+
* @throws {TypeError} If value is not a valid numeric type
|
|
12
|
+
* @throws {Error} If value is not a valid number format
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* toWords(21) // 'vingt et un'
|
|
16
|
+
* toWords(80) // 'quatre-vingts'
|
|
17
|
+
* toWords(1000000) // 'un million'
|
|
8
18
|
*/
|
|
9
|
-
export
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
/** Combines two word-sets with French pluralization and hyphenation rules. */
|
|
13
|
-
combineWordSets(preceding: any, following: any): any;
|
|
14
|
-
}
|
|
15
|
-
import { GreedyScaleLanguage } from '../classes/greedy-scale-language.js';
|
|
19
|
+
export function toWords(value: number | string | bigint, options?: {
|
|
20
|
+
withHyphenSeparator?: boolean | undefined;
|
|
21
|
+
}): string;
|
package/lib/languages/fr.js
CHANGED
|
@@ -1,106 +1,369 @@
|
|
|
1
|
-
import { GreedyScaleLanguage } from '../classes/greedy-scale-language.js'
|
|
2
|
-
|
|
3
1
|
/**
|
|
4
|
-
* French language converter
|
|
2
|
+
* French language converter - Functional Implementation
|
|
3
|
+
*
|
|
4
|
+
* A performance-optimized number-to-words converter using precomputed lookup tables.
|
|
5
|
+
* Self-contained module with its own input validation, ready for subpath exports.
|
|
6
|
+
*
|
|
7
|
+
* Key optimization: Precompute all segment values (0-999) at module load.
|
|
8
|
+
* This eliminates all per-call string manipulation for segment conversion.
|
|
5
9
|
*
|
|
6
|
-
*
|
|
7
|
-
* -
|
|
8
|
-
* - "et" (
|
|
9
|
-
* -
|
|
10
|
+
* French-specific rules (handled in precomputation):
|
|
11
|
+
* - Vigesimal patterns: 70 = soixante-dix, 80 = quatre-vingts, 90 = quatre-vingt-dix
|
|
12
|
+
* - "et" conjunction: vingt et un (21), soixante et onze (71), but NOT quatre-vingt-un
|
|
13
|
+
* - Pluralization: "cents" loses 's' when followed by more digits
|
|
14
|
+
* - Long scale with -ard forms: milliard, billiard, trilliard
|
|
15
|
+
* - Omit "un" before mille
|
|
10
16
|
*/
|
|
11
|
-
export class French extends GreedyScaleLanguage {
|
|
12
|
-
negativeWord = 'moins'
|
|
13
|
-
decimalSeparatorWord = 'virgule'
|
|
14
|
-
zeroWord = 'zéro'
|
|
15
|
-
|
|
16
|
-
scaleWords = [
|
|
17
|
-
[1_000_000_000_000_000_000_000_000_000n, 'quadrilliard'],
|
|
18
|
-
[1_000_000_000_000_000_000_000_000n, 'quadrillion'],
|
|
19
|
-
[1_000_000_000_000_000_000_000n, 'trilliard'],
|
|
20
|
-
[1_000_000_000_000_000_000n, 'trillion'],
|
|
21
|
-
[1_000_000_000_000_000n, 'billiard'],
|
|
22
|
-
[1_000_000_000_000n, 'billion'],
|
|
23
|
-
[1_000_000_000n, 'milliard'],
|
|
24
|
-
[1_000_000n, 'million'],
|
|
25
|
-
[1000n, 'mille'],
|
|
26
|
-
[100n, 'cent'],
|
|
27
|
-
[80n, 'quatre-vingts'],
|
|
28
|
-
[60n, 'soixante'],
|
|
29
|
-
[50n, 'cinquante'],
|
|
30
|
-
[40n, 'quarante'],
|
|
31
|
-
[30n, 'trente'],
|
|
32
|
-
[20n, 'vingt'],
|
|
33
|
-
[19n, 'dix-neuf'],
|
|
34
|
-
[18n, 'dix-huit'],
|
|
35
|
-
[17n, 'dix-sept'],
|
|
36
|
-
[16n, 'seize'],
|
|
37
|
-
[15n, 'quinze'],
|
|
38
|
-
[14n, 'quatorze'],
|
|
39
|
-
[13n, 'treize'],
|
|
40
|
-
[12n, 'douze'],
|
|
41
|
-
[11n, 'onze'],
|
|
42
|
-
[10n, 'dix'],
|
|
43
|
-
[9n, 'neuf'],
|
|
44
|
-
[8n, 'huit'],
|
|
45
|
-
[7n, 'sept'],
|
|
46
|
-
[6n, 'six'],
|
|
47
|
-
[5n, 'cinq'],
|
|
48
|
-
[4n, 'quatre'],
|
|
49
|
-
[3n, 'trois'],
|
|
50
|
-
[2n, 'deux'],
|
|
51
|
-
[1n, 'un'],
|
|
52
|
-
[0n, 'zéro']
|
|
53
|
-
]
|
|
54
|
-
|
|
55
|
-
constructor (options = {}) {
|
|
56
|
-
super()
|
|
57
|
-
|
|
58
|
-
this.setOptions({
|
|
59
|
-
withHyphenSeparator: false
|
|
60
|
-
}, options)
|
|
61
|
-
|
|
62
|
-
if (options.withHyphenSeparator) {
|
|
63
|
-
this.wordSeparator = '-'
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
17
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
18
|
+
import { parseNumericValue } from '../utils/parse-numeric.js'
|
|
19
|
+
import { validateOptions } from '../utils/validate-options.js'
|
|
20
|
+
|
|
21
|
+
// ============================================================================
|
|
22
|
+
// Vocabulary (module-level constants)
|
|
23
|
+
// ============================================================================
|
|
24
|
+
|
|
25
|
+
const ONES = ['', 'un', 'deux', 'trois', 'quatre', 'cinq', 'six', 'sept', 'huit', 'neuf']
|
|
26
|
+
const TEENS = ['dix', 'onze', 'douze', 'treize', 'quatorze', 'quinze', 'seize', 'dix-sept', 'dix-huit', 'dix-neuf']
|
|
27
|
+
const TENS = ['', '', 'vingt', 'trente', 'quarante', 'cinquante', 'soixante']
|
|
28
|
+
|
|
29
|
+
// Scale words (even indices: million, billion, trillion, quadrillion)
|
|
30
|
+
const SCALES = ['million', 'billion', 'trillion', 'quadrillion']
|
|
31
|
+
const SCALES_ARD = ['milliard', 'billiard', 'trilliard', 'quadrilliard']
|
|
32
|
+
|
|
33
|
+
const THOUSAND = 'mille'
|
|
34
|
+
const HUNDRED = 'cent'
|
|
35
|
+
const ZERO = 'zéro'
|
|
36
|
+
const NEGATIVE = 'moins'
|
|
37
|
+
const DECIMAL_SEP = 'virgule'
|
|
38
|
+
|
|
39
|
+
// ============================================================================
|
|
40
|
+
// Precomputed Lookup Tables (built once at module load)
|
|
41
|
+
// ============================================================================
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Builds segment word for 0-999.
|
|
45
|
+
* Returns object with { word, endsWithCents, endsWithVingts } for pluralization handling.
|
|
46
|
+
*/
|
|
47
|
+
function buildSegment (n) {
|
|
48
|
+
if (n === 0) return { word: '', endsWithCents: false, endsWithVingts: false }
|
|
49
|
+
|
|
50
|
+
const tensOnes = n % 100
|
|
51
|
+
const hundreds = Math.floor(n / 100)
|
|
52
|
+
|
|
53
|
+
const parts = []
|
|
54
|
+
let endsWithCents = false
|
|
55
|
+
let endsWithVingts = false
|
|
73
56
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
57
|
+
// Hundreds
|
|
58
|
+
if (hundreds > 0) {
|
|
59
|
+
if (hundreds === 1) {
|
|
60
|
+
if (tensOnes === 0) {
|
|
61
|
+
parts.push(HUNDRED)
|
|
62
|
+
} else {
|
|
63
|
+
parts.push(HUNDRED)
|
|
77
64
|
}
|
|
78
65
|
} else {
|
|
79
|
-
if (
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
66
|
+
if (tensOnes === 0) {
|
|
67
|
+
// "deux cents", "trois cents" (with 's')
|
|
68
|
+
parts.push(ONES[hundreds] + ' ' + HUNDRED + 's')
|
|
69
|
+
endsWithCents = true
|
|
70
|
+
} else {
|
|
71
|
+
// "deux cent", "trois cent" (no 's' when followed by more)
|
|
72
|
+
parts.push(ONES[hundreds] + ' ' + HUNDRED)
|
|
85
73
|
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Tens and ones - vigesimal pattern
|
|
78
|
+
if (tensOnes === 0) {
|
|
79
|
+
// Just hundreds, nothing more
|
|
80
|
+
} else if (tensOnes < 10) {
|
|
81
|
+
// Single digit
|
|
82
|
+
parts.push(ONES[tensOnes])
|
|
83
|
+
} else if (tensOnes < 17) {
|
|
84
|
+
// 10-16: regular teens
|
|
85
|
+
parts.push(TEENS[tensOnes - 10])
|
|
86
|
+
} else if (tensOnes < 20) {
|
|
87
|
+
// 17-19: dix-sept, dix-huit, dix-neuf
|
|
88
|
+
parts.push(TEENS[tensOnes - 10])
|
|
89
|
+
} else if (tensOnes < 70) {
|
|
90
|
+
// 20-69: standard tens + ones
|
|
91
|
+
const t = Math.floor(tensOnes / 10)
|
|
92
|
+
const o = tensOnes % 10
|
|
93
|
+
if (o === 0) {
|
|
94
|
+
parts.push(TENS[t])
|
|
95
|
+
} else if (o === 1) {
|
|
96
|
+
// "et un" for 21, 31, 41, 51, 61
|
|
97
|
+
parts.push(TENS[t] + ' et ' + ONES[1])
|
|
98
|
+
} else {
|
|
99
|
+
parts.push(TENS[t] + '-' + ONES[o])
|
|
100
|
+
}
|
|
101
|
+
} else if (tensOnes < 80) {
|
|
102
|
+
// 70-79: soixante-dix, soixante et onze, soixante-douze...
|
|
103
|
+
const remainder = tensOnes - 60
|
|
104
|
+
if (remainder === 11) {
|
|
105
|
+
// 71: soixante et onze
|
|
106
|
+
parts.push('soixante et onze')
|
|
107
|
+
} else {
|
|
108
|
+
// 70, 72-79: soixante-dix, soixante-douze...
|
|
109
|
+
parts.push('soixante-' + TEENS[remainder - 10])
|
|
110
|
+
}
|
|
111
|
+
} else if (tensOnes === 80) {
|
|
112
|
+
// 80: quatre-vingts (with 's')
|
|
113
|
+
parts.push('quatre-vingts')
|
|
114
|
+
endsWithVingts = true
|
|
115
|
+
} else if (tensOnes < 100) {
|
|
116
|
+
// 81-99: quatre-vingt-un, quatre-vingt-dix...
|
|
117
|
+
const remainder = tensOnes - 80
|
|
118
|
+
if (remainder < 10) {
|
|
119
|
+
// 81-89
|
|
120
|
+
parts.push('quatre-vingt-' + ONES[remainder])
|
|
121
|
+
} else {
|
|
122
|
+
// 90-99
|
|
123
|
+
parts.push('quatre-vingt-' + TEENS[remainder - 10])
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Join parts with space (between hundreds and rest)
|
|
128
|
+
return { word: parts.join(' '), endsWithCents, endsWithVingts }
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Precompute all 1000 segment words (0-999)
|
|
132
|
+
const SEGMENTS = new Array(1000)
|
|
133
|
+
const SEGMENTS_ENDS_CENTS = new Array(1000)
|
|
134
|
+
const SEGMENTS_ENDS_VINGTS = new Array(1000)
|
|
135
|
+
|
|
136
|
+
for (let i = 0; i < 1000; i++) {
|
|
137
|
+
const result = buildSegment(i)
|
|
138
|
+
SEGMENTS[i] = result.word
|
|
139
|
+
SEGMENTS_ENDS_CENTS[i] = result.endsWithCents
|
|
140
|
+
SEGMENTS_ENDS_VINGTS[i] = result.endsWithVingts
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// ============================================================================
|
|
144
|
+
// Helper Functions
|
|
145
|
+
// ============================================================================
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Gets scale word for French long scale with -ard pattern.
|
|
149
|
+
*
|
|
150
|
+
* @param {number} scaleIndex - Scale level (1 = thousand, 2 = million, etc.)
|
|
151
|
+
* @param {bigint} segment - Segment value for pluralization
|
|
152
|
+
* @returns {string} Scale word
|
|
153
|
+
*/
|
|
154
|
+
function getScaleWord (scaleIndex, segment) {
|
|
155
|
+
if (scaleIndex === 1) return THOUSAND
|
|
156
|
+
|
|
157
|
+
// Even indices (2, 4, 6, 8): million, billion, trillion, quadrillion
|
|
158
|
+
// Odd indices > 1 (3, 5, 7, 9): milliard, billiard, trilliard, quadrilliard
|
|
159
|
+
if (scaleIndex % 2 === 0) {
|
|
160
|
+
const arrayIndex = (scaleIndex / 2) - 1
|
|
161
|
+
const baseWord = SCALES[arrayIndex]
|
|
162
|
+
if (!baseWord) return ''
|
|
163
|
+
return segment > 1n ? baseWord + 's' : baseWord
|
|
164
|
+
} else {
|
|
165
|
+
const arrayIndex = ((scaleIndex - 1) / 2) - 1
|
|
166
|
+
const ardWord = SCALES_ARD[arrayIndex]
|
|
167
|
+
if (!ardWord) return THOUSAND
|
|
168
|
+
return segment > 1n ? ardWord + 's' : ardWord
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// ============================================================================
|
|
173
|
+
// Conversion Functions
|
|
174
|
+
// ============================================================================
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Converts a non-negative integer to French words.
|
|
178
|
+
*
|
|
179
|
+
* @param {bigint} n - Non-negative integer to convert
|
|
180
|
+
* @param {boolean} withHyphen - Whether to use hyphen separators
|
|
181
|
+
* @returns {string} French words
|
|
182
|
+
*/
|
|
183
|
+
function integerToWords (n, withHyphen = false) {
|
|
184
|
+
if (n === 0n) return ZERO
|
|
185
|
+
|
|
186
|
+
// Fast path: numbers < 1000 (direct lookup)
|
|
187
|
+
if (n < 1000n) {
|
|
188
|
+
const word = SEGMENTS[Number(n)]
|
|
189
|
+
return withHyphen ? word.replace(/ /g, '-') : word
|
|
190
|
+
}
|
|
86
191
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
192
|
+
// Fast path: numbers < 1,000,000 (thousands)
|
|
193
|
+
if (n < 1_000_000n) {
|
|
194
|
+
const thousands = Number(n / 1000n)
|
|
195
|
+
const remainder = Number(n % 1000n)
|
|
196
|
+
|
|
197
|
+
let result
|
|
198
|
+
if (thousands === 1) {
|
|
199
|
+
// "mille" not "un mille"
|
|
200
|
+
result = THOUSAND
|
|
201
|
+
} else {
|
|
202
|
+
// Check if segment ends with "cents" or "vingts" - need to strip 's' before mille
|
|
203
|
+
let thousandsWord = SEGMENTS[thousands]
|
|
204
|
+
if (SEGMENTS_ENDS_CENTS[thousands] || SEGMENTS_ENDS_VINGTS[thousands]) {
|
|
205
|
+
thousandsWord = thousandsWord.slice(0, -1) // Remove trailing 's'
|
|
93
206
|
}
|
|
207
|
+
result = thousandsWord + (withHyphen ? '-' : ' ') + THOUSAND
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (remainder > 0) {
|
|
211
|
+
result += (withHyphen ? '-' : ' ') + SEGMENTS[remainder]
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (withHyphen) {
|
|
215
|
+
result = result.replace(/ /g, '-')
|
|
94
216
|
}
|
|
95
217
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
218
|
+
return result
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// For numbers >= 1,000,000, use scale decomposition
|
|
222
|
+
return buildLargeNumberWords(n, withHyphen)
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Builds words for numbers >= 1,000,000.
|
|
227
|
+
*
|
|
228
|
+
* @param {bigint} n - Number >= 1,000,000
|
|
229
|
+
* @param {boolean} withHyphen - Whether to use hyphen separators
|
|
230
|
+
* @returns {string} French words
|
|
231
|
+
*/
|
|
232
|
+
function buildLargeNumberWords (n, withHyphen) {
|
|
233
|
+
const numStr = n.toString()
|
|
234
|
+
const len = numStr.length
|
|
235
|
+
|
|
236
|
+
// Build segments of 3 digits from right to left
|
|
237
|
+
const segments = []
|
|
238
|
+
const segmentSize = 3
|
|
239
|
+
|
|
240
|
+
const remainderLen = len % segmentSize
|
|
241
|
+
let pos = 0
|
|
242
|
+
if (remainderLen > 0) {
|
|
243
|
+
segments.push(Number(numStr.slice(0, remainderLen)))
|
|
244
|
+
pos = remainderLen
|
|
245
|
+
}
|
|
246
|
+
while (pos < len) {
|
|
247
|
+
segments.push(Number(numStr.slice(pos, pos + segmentSize)))
|
|
248
|
+
pos += segmentSize
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Convert segments to words
|
|
252
|
+
const parts = []
|
|
253
|
+
let scaleIndex = segments.length - 1
|
|
254
|
+
|
|
255
|
+
for (let i = 0; i < segments.length; i++) {
|
|
256
|
+
const segment = segments[i]
|
|
257
|
+
|
|
258
|
+
if (segment !== 0) {
|
|
259
|
+
const scaleWord = scaleIndex > 0 ? getScaleWord(scaleIndex, BigInt(segment)) : ''
|
|
260
|
+
|
|
261
|
+
if (scaleIndex === 0) {
|
|
262
|
+
// Units segment
|
|
263
|
+
parts.push(SEGMENTS[segment])
|
|
264
|
+
} else if (scaleIndex === 1) {
|
|
265
|
+
// Thousands: "mille" not "un mille"
|
|
266
|
+
if (segment === 1) {
|
|
267
|
+
parts.push(THOUSAND)
|
|
268
|
+
} else {
|
|
269
|
+
let segWords = SEGMENTS[segment]
|
|
270
|
+
// Strip 's' from cents/vingts before mille
|
|
271
|
+
if (SEGMENTS_ENDS_CENTS[segment] || SEGMENTS_ENDS_VINGTS[segment]) {
|
|
272
|
+
segWords = segWords.slice(0, -1)
|
|
273
|
+
}
|
|
274
|
+
parts.push(segWords)
|
|
275
|
+
parts.push(scaleWord)
|
|
276
|
+
}
|
|
277
|
+
} else {
|
|
278
|
+
// Million and above
|
|
279
|
+
parts.push(SEGMENTS[segment])
|
|
280
|
+
parts.push(scaleWord)
|
|
99
281
|
}
|
|
100
|
-
return { [`${precedingWord}-${followingWord}`]: precedingValue + followingValue }
|
|
101
282
|
}
|
|
102
283
|
|
|
103
|
-
|
|
104
|
-
|
|
284
|
+
scaleIndex--
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const sep = withHyphen ? '-' : ' '
|
|
288
|
+
let result = parts.join(sep)
|
|
289
|
+
|
|
290
|
+
if (withHyphen) {
|
|
291
|
+
result = result.replace(/ /g, '-')
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
return result
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Converts decimal digits to French words.
|
|
299
|
+
*
|
|
300
|
+
* @param {string} decimalPart - Decimal digits (without the point)
|
|
301
|
+
* @param {boolean} withHyphen - Whether to use hyphen separators
|
|
302
|
+
* @returns {string} French words for decimal part
|
|
303
|
+
*/
|
|
304
|
+
function decimalPartToWords (decimalPart, withHyphen) {
|
|
305
|
+
let result = ''
|
|
306
|
+
const sep = withHyphen ? '-' : ' '
|
|
307
|
+
|
|
308
|
+
// Handle leading zeros
|
|
309
|
+
let i = 0
|
|
310
|
+
while (i < decimalPart.length && decimalPart[i] === '0') {
|
|
311
|
+
if (result) result += sep
|
|
312
|
+
result += ZERO
|
|
313
|
+
i++
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// Convert remainder as a single number
|
|
317
|
+
const remainder = decimalPart.slice(i)
|
|
318
|
+
if (remainder) {
|
|
319
|
+
if (result) result += sep
|
|
320
|
+
result += integerToWords(BigInt(remainder), withHyphen)
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
return result
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Converts a numeric value to French words.
|
|
328
|
+
*
|
|
329
|
+
* This is the main public API. It accepts any valid numeric input
|
|
330
|
+
* (number, string, or bigint) and handles parsing internally.
|
|
331
|
+
*
|
|
332
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
333
|
+
* @param {Object} [options] - Optional configuration
|
|
334
|
+
* @param {boolean} [options.withHyphenSeparator=false] - Use hyphens between all words
|
|
335
|
+
* @returns {string} The number in French words
|
|
336
|
+
* @throws {TypeError} If value is not a valid numeric type
|
|
337
|
+
* @throws {Error} If value is not a valid number format
|
|
338
|
+
*
|
|
339
|
+
* @example
|
|
340
|
+
* toWords(21) // 'vingt et un'
|
|
341
|
+
* toWords(80) // 'quatre-vingts'
|
|
342
|
+
* toWords(1000000) // 'un million'
|
|
343
|
+
*/
|
|
344
|
+
function toWords (value, options) {
|
|
345
|
+
options = validateOptions(options)
|
|
346
|
+
const { isNegative, integerPart, decimalPart } = parseNumericValue(value)
|
|
347
|
+
const withHyphen = options.withHyphenSeparator || false
|
|
348
|
+
|
|
349
|
+
let result = ''
|
|
350
|
+
const sep = withHyphen ? '-' : ' '
|
|
351
|
+
|
|
352
|
+
if (isNegative) {
|
|
353
|
+
result = NEGATIVE + sep
|
|
105
354
|
}
|
|
355
|
+
|
|
356
|
+
result += integerToWords(integerPart, withHyphen)
|
|
357
|
+
|
|
358
|
+
if (decimalPart) {
|
|
359
|
+
result += sep + DECIMAL_SEP + sep + decimalPartToWords(decimalPart, withHyphen)
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
return result
|
|
106
363
|
}
|
|
364
|
+
|
|
365
|
+
// ============================================================================
|
|
366
|
+
// Public API
|
|
367
|
+
// ============================================================================
|
|
368
|
+
|
|
369
|
+
export { toWords }
|
package/lib/languages/gu.d.ts
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Gujarati
|
|
2
|
+
* Converts a numeric value to Gujarati words.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* - Gujarati 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 Gujarati words
|
|
8
6
|
*/
|
|
9
|
-
export
|
|
10
|
-
}
|
|
11
|
-
import { SouthAsianLanguage } from '../classes/south-asian-language.js';
|
|
7
|
+
export function toWords(value: number | string | bigint): string;
|