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