n2words 1.24.0 → 2.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/README.md +285 -156
- package/dist/ArabicConverter.js +3 -0
- package/dist/ArabicConverter.js.map +1 -0
- package/dist/AzerbaijaniConverter.js +3 -0
- package/dist/AzerbaijaniConverter.js.map +1 -0
- package/dist/BanglaConverter.js +3 -0
- package/dist/BanglaConverter.js.map +1 -0
- package/dist/BiblicalHebrewConverter.js +3 -0
- package/dist/BiblicalHebrewConverter.js.map +1 -0
- package/dist/CroatianConverter.js +3 -0
- package/dist/CroatianConverter.js.map +1 -0
- package/dist/CzechConverter.js +3 -0
- package/dist/CzechConverter.js.map +1 -0
- package/dist/DanishConverter.js +3 -0
- package/dist/DanishConverter.js.map +1 -0
- package/dist/DutchConverter.js +3 -0
- package/dist/DutchConverter.js.map +1 -0
- package/dist/EnglishConverter.js +3 -0
- package/dist/EnglishConverter.js.map +1 -0
- package/dist/FilipinoConverter.js +3 -0
- package/dist/FilipinoConverter.js.map +1 -0
- package/dist/FrenchBelgiumConverter.js +3 -0
- package/dist/FrenchBelgiumConverter.js.map +1 -0
- package/dist/FrenchConverter.js +3 -0
- package/dist/FrenchConverter.js.map +1 -0
- package/dist/GermanConverter.js +3 -0
- package/dist/GermanConverter.js.map +1 -0
- package/dist/GreekConverter.js +3 -0
- package/dist/GreekConverter.js.map +1 -0
- package/dist/GujaratiConverter.js +3 -0
- package/dist/GujaratiConverter.js.map +1 -0
- package/dist/HebrewConverter.js +3 -0
- package/dist/HebrewConverter.js.map +1 -0
- package/dist/HindiConverter.js +3 -0
- package/dist/HindiConverter.js.map +1 -0
- package/dist/HungarianConverter.js +3 -0
- package/dist/HungarianConverter.js.map +1 -0
- package/dist/IndonesianConverter.js +3 -0
- package/dist/IndonesianConverter.js.map +1 -0
- package/dist/ItalianConverter.js +3 -0
- package/dist/ItalianConverter.js.map +1 -0
- package/dist/JapaneseConverter.js +3 -0
- package/dist/JapaneseConverter.js.map +1 -0
- package/dist/KannadaConverter.js +3 -0
- package/dist/KannadaConverter.js.map +1 -0
- package/dist/KoreanConverter.js +3 -0
- package/dist/KoreanConverter.js.map +1 -0
- package/dist/LatvianConverter.js +3 -0
- package/dist/LatvianConverter.js.map +1 -0
- package/dist/LithuanianConverter.js +3 -0
- package/dist/LithuanianConverter.js.map +1 -0
- package/dist/MalayConverter.js +3 -0
- package/dist/MalayConverter.js.map +1 -0
- package/dist/MarathiConverter.js +3 -0
- package/dist/MarathiConverter.js.map +1 -0
- package/dist/NorwegianBokmalConverter.js +3 -0
- package/dist/NorwegianBokmalConverter.js.map +1 -0
- package/dist/PersianConverter.js +3 -0
- package/dist/PersianConverter.js.map +1 -0
- package/dist/PolishConverter.js +3 -0
- package/dist/PolishConverter.js.map +1 -0
- package/dist/PortugueseConverter.js +3 -0
- package/dist/PortugueseConverter.js.map +1 -0
- package/dist/PunjabiConverter.js +3 -0
- package/dist/PunjabiConverter.js.map +1 -0
- package/dist/RomanianConverter.js +3 -0
- package/dist/RomanianConverter.js.map +1 -0
- package/dist/RussianConverter.js +3 -0
- package/dist/RussianConverter.js.map +1 -0
- package/dist/SerbianCyrillicConverter.js +3 -0
- package/dist/SerbianCyrillicConverter.js.map +1 -0
- package/dist/SerbianLatinConverter.js +3 -0
- package/dist/SerbianLatinConverter.js.map +1 -0
- package/dist/SimplifiedChineseConverter.js +3 -0
- package/dist/SimplifiedChineseConverter.js.map +1 -0
- package/dist/SpanishConverter.js +3 -0
- package/dist/SpanishConverter.js.map +1 -0
- package/dist/SwahiliConverter.js +3 -0
- package/dist/SwahiliConverter.js.map +1 -0
- package/dist/SwedishConverter.js +3 -0
- package/dist/SwedishConverter.js.map +1 -0
- package/dist/TamilConverter.js +3 -0
- package/dist/TamilConverter.js.map +1 -0
- package/dist/TeluguConverter.js +3 -0
- package/dist/TeluguConverter.js.map +1 -0
- package/dist/ThaiConverter.js +3 -0
- package/dist/ThaiConverter.js.map +1 -0
- package/dist/TraditionalChineseConverter.js +3 -0
- package/dist/TraditionalChineseConverter.js.map +1 -0
- package/dist/TurkishConverter.js +3 -0
- package/dist/TurkishConverter.js.map +1 -0
- package/dist/UkrainianConverter.js +3 -0
- package/dist/UkrainianConverter.js.map +1 -0
- package/dist/UrduConverter.js +3 -0
- package/dist/UrduConverter.js.map +1 -0
- package/dist/VietnameseConverter.js +3 -0
- package/dist/VietnameseConverter.js.map +1 -0
- package/dist/n2words.js +3 -2
- package/dist/n2words.js.map +1 -1
- package/lib/classes/abstract-language.d.ts +178 -0
- package/lib/classes/abstract-language.js +192 -185
- package/lib/classes/greedy-scale-language.d.ts +109 -0
- package/lib/classes/greedy-scale-language.js +96 -90
- package/lib/classes/slavic-language.d.ts +148 -0
- package/lib/classes/slavic-language.js +136 -106
- package/lib/classes/south-asian-language.d.ts +70 -0
- package/lib/classes/south-asian-language.js +58 -65
- package/lib/classes/turkic-language.d.ts +26 -0
- package/lib/classes/turkic-language.js +22 -26
- package/lib/languages/ar.d.ts +30 -0
- package/lib/languages/ar.js +49 -133
- package/lib/languages/az.d.ts +12 -0
- package/lib/languages/az.js +7 -23
- package/lib/languages/bn.d.ts +11 -0
- package/lib/languages/bn.js +12 -7
- package/lib/languages/cs.d.ts +88 -0
- package/lib/languages/cs.js +44 -113
- package/lib/languages/da.d.ts +15 -0
- package/lib/languages/da.js +40 -87
- package/lib/languages/de.d.ts +14 -0
- package/lib/languages/de.js +34 -68
- package/lib/languages/el.d.ts +14 -0
- package/lib/languages/el.js +22 -48
- package/lib/languages/en.d.ts +16 -0
- package/lib/languages/en.js +22 -59
- package/lib/languages/es.d.ts +15 -0
- package/lib/languages/es.js +49 -81
- package/lib/languages/fa.d.ts +47 -0
- package/lib/languages/fa.js +90 -73
- package/lib/languages/fil.d.ts +16 -0
- package/lib/languages/fil.js +35 -76
- package/lib/languages/fr-BE.d.ts +11 -0
- package/lib/languages/fr-BE.js +15 -51
- package/lib/languages/fr.d.ts +15 -0
- package/lib/languages/fr.js +33 -72
- package/lib/languages/gu.d.ts +11 -0
- package/lib/languages/gu.js +10 -34
- package/lib/languages/hbo.d.ts +113 -0
- package/lib/languages/hbo.js +251 -0
- package/lib/languages/he.d.ts +80 -0
- package/lib/languages/he.js +41 -164
- package/lib/languages/hi.d.ts +11 -0
- package/lib/languages/hi.js +12 -7
- package/lib/languages/hr.d.ts +80 -0
- package/lib/languages/hr.js +51 -95
- package/lib/languages/hu.d.ts +22 -0
- package/lib/languages/hu.js +35 -53
- package/lib/languages/id.d.ts +37 -0
- package/lib/languages/id.js +29 -44
- package/lib/languages/it.d.ts +37 -0
- package/lib/languages/it.js +36 -52
- package/lib/languages/ja.d.ts +17 -0
- package/lib/languages/ja.js +22 -75
- package/lib/languages/kn.d.ts +11 -0
- package/lib/languages/kn.js +10 -39
- package/lib/languages/ko.d.ts +14 -0
- package/lib/languages/ko.js +17 -45
- package/lib/languages/lt.d.ts +70 -0
- package/lib/languages/lt.js +28 -63
- package/lib/languages/lv.d.ts +70 -0
- package/lib/languages/lv.js +35 -58
- package/lib/languages/mr.d.ts +11 -0
- package/lib/languages/mr.js +10 -34
- package/lib/languages/ms.d.ts +31 -0
- package/lib/languages/ms.js +24 -20
- package/lib/languages/nb.d.ts +12 -0
- package/lib/languages/nb.js +36 -56
- package/lib/languages/nl.d.ts +16 -0
- package/lib/languages/nl.js +58 -109
- package/lib/languages/pa.d.ts +11 -0
- package/lib/languages/{pa-Guru.js → pa.js} +12 -7
- package/lib/languages/pl.d.ts +80 -0
- package/lib/languages/pl.js +26 -105
- package/lib/languages/pt.d.ts +29 -0
- package/lib/languages/pt.js +29 -64
- package/lib/languages/ro.d.ts +158 -0
- package/lib/languages/ro.js +60 -167
- package/lib/languages/ru.d.ts +85 -0
- package/lib/languages/ru.js +17 -37
- package/lib/languages/sr-Cyrl.d.ts +80 -0
- package/lib/languages/sr-Cyrl.js +113 -0
- package/lib/languages/sr-Latn.d.ts +80 -0
- package/lib/languages/sr-Latn.js +54 -98
- package/lib/languages/sv.d.ts +14 -0
- package/lib/languages/sv.js +26 -63
- package/lib/languages/sw.d.ts +39 -0
- package/lib/languages/sw.js +26 -21
- package/lib/languages/ta.d.ts +20 -0
- package/lib/languages/ta.js +26 -26
- package/lib/languages/te.d.ts +22 -0
- package/lib/languages/te.js +28 -38
- package/lib/languages/th.d.ts +17 -0
- package/lib/languages/th.js +25 -31
- package/lib/languages/tr.d.ts +12 -0
- package/lib/languages/tr.js +11 -38
- package/lib/languages/uk.d.ts +85 -0
- package/lib/languages/uk.js +18 -44
- package/lib/languages/ur.d.ts +11 -0
- package/lib/languages/ur.js +12 -7
- package/lib/languages/vi.d.ts +72 -0
- package/lib/languages/vi.js +25 -71
- package/lib/languages/zh-Hans.d.ts +21 -0
- package/lib/languages/zh-Hans.js +33 -87
- package/lib/languages/zh-Hant.d.ts +21 -0
- package/lib/languages/zh-Hant.js +111 -0
- package/lib/n2words.d.ts +209 -0
- package/lib/n2words.js +474 -191
- package/package.json +106 -67
- package/dist/languages/ar.js +0 -2
- package/dist/languages/ar.js.map +0 -1
- package/dist/languages/az.js +0 -2
- package/dist/languages/az.js.map +0 -1
- package/dist/languages/bn.js +0 -2
- package/dist/languages/bn.js.map +0 -1
- package/dist/languages/cs.js +0 -2
- package/dist/languages/cs.js.map +0 -1
- package/dist/languages/da.js +0 -2
- package/dist/languages/da.js.map +0 -1
- package/dist/languages/de.js +0 -2
- package/dist/languages/de.js.map +0 -1
- package/dist/languages/el.js +0 -2
- package/dist/languages/el.js.map +0 -1
- package/dist/languages/en.js +0 -2
- package/dist/languages/en.js.map +0 -1
- package/dist/languages/es.js +0 -2
- package/dist/languages/es.js.map +0 -1
- package/dist/languages/fa.js +0 -2
- package/dist/languages/fa.js.map +0 -1
- package/dist/languages/fil.js +0 -2
- package/dist/languages/fil.js.map +0 -1
- package/dist/languages/fr-BE.js +0 -2
- package/dist/languages/fr-BE.js.map +0 -1
- package/dist/languages/fr.js +0 -2
- package/dist/languages/fr.js.map +0 -1
- package/dist/languages/gu.js +0 -2
- package/dist/languages/gu.js.map +0 -1
- package/dist/languages/he.js +0 -2
- package/dist/languages/he.js.map +0 -1
- package/dist/languages/hi.js +0 -2
- package/dist/languages/hi.js.map +0 -1
- package/dist/languages/hr.js +0 -2
- package/dist/languages/hr.js.map +0 -1
- package/dist/languages/hu.js +0 -2
- package/dist/languages/hu.js.map +0 -1
- package/dist/languages/id.js +0 -2
- package/dist/languages/id.js.map +0 -1
- package/dist/languages/it.js +0 -2
- package/dist/languages/it.js.map +0 -1
- package/dist/languages/ja.js +0 -2
- package/dist/languages/ja.js.map +0 -1
- package/dist/languages/kn.js +0 -2
- package/dist/languages/kn.js.map +0 -1
- package/dist/languages/ko.js +0 -2
- package/dist/languages/ko.js.map +0 -1
- package/dist/languages/lt.js +0 -2
- package/dist/languages/lt.js.map +0 -1
- package/dist/languages/lv.js +0 -2
- package/dist/languages/lv.js.map +0 -1
- package/dist/languages/mr.js +0 -2
- package/dist/languages/mr.js.map +0 -1
- package/dist/languages/ms.js +0 -2
- package/dist/languages/ms.js.map +0 -1
- package/dist/languages/nb.js +0 -2
- package/dist/languages/nb.js.map +0 -1
- package/dist/languages/nl.js +0 -2
- package/dist/languages/nl.js.map +0 -1
- package/dist/languages/pa-Guru.js +0 -2
- package/dist/languages/pa-Guru.js.map +0 -1
- package/dist/languages/pl.js +0 -2
- package/dist/languages/pl.js.map +0 -1
- package/dist/languages/pt.js +0 -2
- package/dist/languages/pt.js.map +0 -1
- package/dist/languages/ro.js +0 -2
- package/dist/languages/ro.js.map +0 -1
- package/dist/languages/ru.js +0 -2
- package/dist/languages/ru.js.map +0 -1
- package/dist/languages/sr-Latn.js +0 -2
- package/dist/languages/sr-Latn.js.map +0 -1
- package/dist/languages/sv.js +0 -2
- package/dist/languages/sv.js.map +0 -1
- package/dist/languages/sw.js +0 -2
- package/dist/languages/sw.js.map +0 -1
- package/dist/languages/ta.js +0 -2
- package/dist/languages/ta.js.map +0 -1
- package/dist/languages/te.js +0 -2
- package/dist/languages/te.js.map +0 -1
- package/dist/languages/th.js +0 -2
- package/dist/languages/th.js.map +0 -1
- package/dist/languages/tr.js +0 -2
- package/dist/languages/tr.js.map +0 -1
- package/dist/languages/uk.js +0 -2
- package/dist/languages/uk.js.map +0 -1
- package/dist/languages/ur.js +0 -2
- package/dist/languages/ur.js.map +0 -1
- package/dist/languages/vi.js +0 -2
- package/dist/languages/vi.js.map +0 -1
- package/dist/languages/zh-Hans.js +0 -2
- package/dist/languages/zh-Hans.js.map +0 -1
- package/typings/classes/abstract-language.d.ts +0 -144
- package/typings/classes/greedy-scale-language.d.ts +0 -148
- package/typings/classes/slavic-language.d.ts +0 -145
- package/typings/classes/south-asian-language.d.ts +0 -101
- package/typings/classes/turkic-language.d.ts +0 -42
- package/typings/languages/ar.d.ts +0 -93
- package/typings/languages/az.d.ts +0 -25
- package/typings/languages/bn.d.ts +0 -1
- package/typings/languages/cs.d.ts +0 -120
- package/typings/languages/da.d.ts +0 -53
- package/typings/languages/de.d.ts +0 -26
- package/typings/languages/el.d.ts +0 -11
- package/typings/languages/en.d.ts +0 -30
- package/typings/languages/es.d.ts +0 -43
- package/typings/languages/fa.d.ts +0 -81
- package/typings/languages/fil.d.ts +0 -12
- package/typings/languages/fr-BE.d.ts +0 -41
- package/typings/languages/fr.d.ts +0 -43
- package/typings/languages/gu.d.ts +0 -12
- package/typings/languages/he.d.ts +0 -197
- package/typings/languages/hi.d.ts +0 -1
- package/typings/languages/hr.d.ts +0 -110
- package/typings/languages/hu.d.ts +0 -37
- package/typings/languages/id.d.ts +0 -69
- package/typings/languages/it.d.ts +0 -51
- package/typings/languages/ja.d.ts +0 -58
- package/typings/languages/kn.d.ts +0 -11
- package/typings/languages/ko.d.ts +0 -25
- package/typings/languages/lt.d.ts +0 -110
- package/typings/languages/lv.d.ts +0 -99
- package/typings/languages/mr.d.ts +0 -12
- package/typings/languages/ms.d.ts +0 -37
- package/typings/languages/nb.d.ts +0 -27
- package/typings/languages/nl.d.ts +0 -65
- package/typings/languages/pa-Guru.d.ts +0 -1
- package/typings/languages/pl.d.ts +0 -116
- package/typings/languages/pt.d.ts +0 -39
- package/typings/languages/ro.d.ts +0 -229
- package/typings/languages/ru.d.ts +0 -108
- package/typings/languages/sr-Latn.d.ts +0 -98
- package/typings/languages/sv.d.ts +0 -30
- package/typings/languages/sw.d.ts +0 -1
- package/typings/languages/ta.d.ts +0 -1
- package/typings/languages/te.d.ts +0 -1
- package/typings/languages/th.d.ts +0 -1
- package/typings/languages/tr.d.ts +0 -46
- package/typings/languages/uk.d.ts +0 -117
- package/typings/languages/ur.d.ts +0 -1
- package/typings/languages/vi.d.ts +0 -116
- package/typings/languages/zh-Hans.d.ts +0 -57
- package/typings/n2words.d.ts +0 -177
package/lib/languages/pt.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import GreedyScaleLanguage from '../classes/greedy-scale-language.js'
|
|
1
|
+
import { GreedyScaleLanguage } from '../classes/greedy-scale-language.js'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* (European) Portuguese language converter.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* - Gender-aware hundreds (
|
|
8
|
-
* - Million/Billion pluralization
|
|
6
|
+
* Supports:
|
|
7
|
+
* - Gender-aware hundreds (duzentos, trezentos)
|
|
9
8
|
* - "e" (and) conjunction for number combinations
|
|
10
9
|
* - Post-processing to normalize word flow
|
|
11
10
|
*/
|
|
@@ -13,7 +12,8 @@ export class Portuguese extends GreedyScaleLanguage {
|
|
|
13
12
|
negativeWord = 'menos'
|
|
14
13
|
decimalSeparatorWord = 'vírgula'
|
|
15
14
|
zeroWord = 'zero'
|
|
16
|
-
|
|
15
|
+
|
|
16
|
+
scaleWords = [
|
|
17
17
|
[1_000_000_000_000_000_000_000_000n, 'quatrilião'],
|
|
18
18
|
[1_000_000_000_000_000_000n, 'trilião'],
|
|
19
19
|
[1_000_000_000_000n, 'bilião'],
|
|
@@ -50,7 +50,7 @@ export class Portuguese extends GreedyScaleLanguage {
|
|
|
50
50
|
[0n, 'zero']
|
|
51
51
|
]
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
hundredsWords = {
|
|
54
54
|
1: 'cento',
|
|
55
55
|
2: 'duzentos',
|
|
56
56
|
3: 'trezentos',
|
|
@@ -69,79 +69,44 @@ export class Portuguese extends GreedyScaleLanguage {
|
|
|
69
69
|
return words.replaceAll(Portuguese.POSTCLEAN_REGEX, ' $1 ')
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
/**
|
|
73
|
-
|
|
74
|
-
*
|
|
75
|
-
* Portuguese-specific rules:
|
|
76
|
-
* - Implicit "um": `mergeScales({ 'um': 1n }, { 'mil': 1000n })` → `{ 'mil': 1000n }`
|
|
77
|
-
* - "e" (and) between most combinations: `mergeScales({ 'vinte': 20n }, { 'três': 3n })` → `{ 'vinte e três': 23n }`
|
|
78
|
-
* - Special handling: "cem" (100) becomes "cento" when followed by non-thousands
|
|
79
|
-
* - Gender-aware hundreds: "duzentos", "trezentos", etc.
|
|
80
|
-
* - Million pluralization: "milhões" instead of "milhão" when coefficient > 1
|
|
81
|
-
* - Post-processing with postClean() to normalize word flow
|
|
82
|
-
*
|
|
83
|
-
* @param {Object} current The left operand as `{ word: BigInt }`.
|
|
84
|
-
* @param {Object} next The right operand as `{ word: BigInt }`.
|
|
85
|
-
* @returns {Object} Merged pair with combined word and resulting numeric value.
|
|
86
|
-
*
|
|
87
|
-
* @example
|
|
88
|
-
* mergeScales({ 'um': 1n }, { 'mil': 1000n }); // { 'mil': 1000n }
|
|
89
|
-
* mergeScales({ 'vinte': 20n }, { 'dois': 2n }); // { 'vinte e dois': 22n }
|
|
90
|
-
*/
|
|
91
|
-
mergeScales (current, next) {
|
|
72
|
+
/** Combines two word-sets according to Portuguese grammar rules. */
|
|
73
|
+
combineWordSets (preceding, following) {
|
|
92
74
|
// Extract words and numeric values
|
|
93
|
-
let
|
|
94
|
-
let
|
|
95
|
-
const
|
|
96
|
-
const
|
|
75
|
+
let precedingWord = Object.keys(preceding)[0]
|
|
76
|
+
let followingWord = Object.keys(following)[0]
|
|
77
|
+
const precedingValue = Object.values(preceding)[0] // BigInt
|
|
78
|
+
const followingValue = Object.values(following)[0] // BigInt
|
|
97
79
|
|
|
98
80
|
// Implicit "um": omit before millions ("um milhão" → "milhão")
|
|
99
|
-
if (
|
|
100
|
-
if (
|
|
101
|
-
|
|
102
|
-
} else if (
|
|
81
|
+
if (precedingValue === 1n) {
|
|
82
|
+
if (followingValue < 1_000_000n) return { [followingWord]: followingValue }
|
|
83
|
+
precedingWord = 'um'
|
|
84
|
+
} else if (precedingValue === 100n && followingValue % 1000n !== 0n) {
|
|
103
85
|
// Special handling: "cem" (100) becomes "cento" when followed by non-thousands
|
|
104
|
-
|
|
86
|
+
precedingWord = 'cento'
|
|
105
87
|
}
|
|
106
88
|
|
|
107
|
-
if (
|
|
108
|
-
return { [`${
|
|
89
|
+
if (followingValue < precedingValue) {
|
|
90
|
+
return { [`${precedingWord} e ${followingWord}`]: precedingValue + followingValue }
|
|
109
91
|
}
|
|
110
92
|
|
|
111
93
|
// Handle "milião" -> "milhão" conversion
|
|
112
|
-
if (
|
|
94
|
+
if (followingWord === 'milião') followingWord = 'milhão'
|
|
113
95
|
|
|
114
96
|
// Pluralization logic for large numbers
|
|
115
|
-
if (
|
|
116
|
-
if (
|
|
117
|
-
|
|
118
|
-
} else if (
|
|
119
|
-
|
|
97
|
+
if (precedingValue > 1n) {
|
|
98
|
+
if (followingValue % 1_000_000_000n === 0n) {
|
|
99
|
+
followingWord = followingWord.replace('bilião', 'biliões')
|
|
100
|
+
} else if (followingValue % 1_000_000n === 0n) {
|
|
101
|
+
followingWord = followingWord.replace('milhão', 'milhões')
|
|
120
102
|
}
|
|
121
103
|
}
|
|
122
104
|
|
|
123
|
-
if (
|
|
124
|
-
|
|
125
|
-
return { [`${
|
|
105
|
+
if (followingValue === 100n) {
|
|
106
|
+
precedingWord = this.hundredsWords[precedingValue]
|
|
107
|
+
return { [`${precedingWord}`]: precedingValue * followingValue }
|
|
126
108
|
}
|
|
127
109
|
|
|
128
|
-
return { [`${
|
|
110
|
+
return { [`${precedingWord} ${followingWord}`]: precedingValue * followingValue }
|
|
129
111
|
}
|
|
130
112
|
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Converts a number to Portuguese cardinal (written) form.
|
|
134
|
-
*
|
|
135
|
-
* @param {number|string|bigint} value The number to convert.
|
|
136
|
-
* @param {Object} [options] Conversion options (see Portuguese class options).
|
|
137
|
-
* @returns {string} The number expressed in Portuguese words.
|
|
138
|
-
* @throws {TypeError} If value is NaN or invalid type.
|
|
139
|
-
* @throws {Error} If value is an invalid number string.
|
|
140
|
-
*
|
|
141
|
-
* @example
|
|
142
|
-
* convertToWords(42); // 'quarenta e dois'
|
|
143
|
-
* convertToWords('100.5'); // 'cem vírgula cinco'
|
|
144
|
-
*/
|
|
145
|
-
export default function convertToWords (value, options = {}) {
|
|
146
|
-
return new Portuguese(options).convertToWords(value)
|
|
147
|
-
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Romanian language converter.
|
|
3
|
+
*
|
|
4
|
+
* Supports:
|
|
5
|
+
* - Gender agreement (unu/una, doi/două)
|
|
6
|
+
* - Complex pluralization (singular/plural forms)
|
|
7
|
+
* - "De" preposition insertion for groups >= 20
|
|
8
|
+
*/
|
|
9
|
+
export class Romanian extends AbstractLanguage {
|
|
10
|
+
constructor(options?: {});
|
|
11
|
+
onesWords: {
|
|
12
|
+
1: string;
|
|
13
|
+
2: string;
|
|
14
|
+
3: string;
|
|
15
|
+
4: string;
|
|
16
|
+
5: string;
|
|
17
|
+
6: string;
|
|
18
|
+
7: string;
|
|
19
|
+
8: string;
|
|
20
|
+
9: string;
|
|
21
|
+
};
|
|
22
|
+
onesFeminineWords: {
|
|
23
|
+
1: string;
|
|
24
|
+
2: string;
|
|
25
|
+
3: string;
|
|
26
|
+
4: string;
|
|
27
|
+
5: string;
|
|
28
|
+
6: string;
|
|
29
|
+
7: string;
|
|
30
|
+
8: string;
|
|
31
|
+
9: string;
|
|
32
|
+
};
|
|
33
|
+
teensWords: {
|
|
34
|
+
0: string;
|
|
35
|
+
1: string;
|
|
36
|
+
2: string;
|
|
37
|
+
3: string;
|
|
38
|
+
4: string;
|
|
39
|
+
5: string;
|
|
40
|
+
6: string;
|
|
41
|
+
7: string;
|
|
42
|
+
8: string;
|
|
43
|
+
9: string;
|
|
44
|
+
};
|
|
45
|
+
teensMasculineWords: {
|
|
46
|
+
0: string;
|
|
47
|
+
1: string;
|
|
48
|
+
2: string;
|
|
49
|
+
3: string;
|
|
50
|
+
4: string;
|
|
51
|
+
5: string;
|
|
52
|
+
6: string;
|
|
53
|
+
7: string;
|
|
54
|
+
8: string;
|
|
55
|
+
9: string;
|
|
56
|
+
};
|
|
57
|
+
twentiesWords: {
|
|
58
|
+
2: string;
|
|
59
|
+
3: string;
|
|
60
|
+
4: string;
|
|
61
|
+
5: string;
|
|
62
|
+
6: string;
|
|
63
|
+
7: string;
|
|
64
|
+
8: string;
|
|
65
|
+
9: string;
|
|
66
|
+
};
|
|
67
|
+
hundredsWords: {
|
|
68
|
+
1: string;
|
|
69
|
+
2: string;
|
|
70
|
+
3: string;
|
|
71
|
+
4: string;
|
|
72
|
+
5: string;
|
|
73
|
+
6: string;
|
|
74
|
+
7: string;
|
|
75
|
+
8: string;
|
|
76
|
+
9: string;
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* Romanian big units.
|
|
80
|
+
* For each power group we keep: singular, plural, feminineUnits?, needsDe?
|
|
81
|
+
* - 10^3: mie/mii (feminine units in segment; "de" for segment >= 20)
|
|
82
|
+
* - 10^6: milion/milioane ("de" for segment >= 20)
|
|
83
|
+
* - 10^9: miliard/miliarde ("de" for segment >= 20)
|
|
84
|
+
*/
|
|
85
|
+
scaleMetadata: {
|
|
86
|
+
1: {
|
|
87
|
+
singular: string;
|
|
88
|
+
plural: string;
|
|
89
|
+
feminine: boolean;
|
|
90
|
+
needsDe: boolean;
|
|
91
|
+
};
|
|
92
|
+
2: {
|
|
93
|
+
singular: string;
|
|
94
|
+
plural: string;
|
|
95
|
+
feminine: boolean;
|
|
96
|
+
needsDe: boolean;
|
|
97
|
+
};
|
|
98
|
+
3: {
|
|
99
|
+
singular: string;
|
|
100
|
+
plural: string;
|
|
101
|
+
feminine: boolean;
|
|
102
|
+
needsDe: boolean;
|
|
103
|
+
};
|
|
104
|
+
4: {
|
|
105
|
+
singular: string;
|
|
106
|
+
plural: string;
|
|
107
|
+
feminine: boolean;
|
|
108
|
+
needsDe: boolean;
|
|
109
|
+
};
|
|
110
|
+
5: {
|
|
111
|
+
singular: string;
|
|
112
|
+
plural: string;
|
|
113
|
+
feminine: boolean;
|
|
114
|
+
needsDe: boolean;
|
|
115
|
+
};
|
|
116
|
+
6: {
|
|
117
|
+
singular: string;
|
|
118
|
+
plural: string;
|
|
119
|
+
feminine: boolean;
|
|
120
|
+
needsDe: boolean;
|
|
121
|
+
};
|
|
122
|
+
7: {
|
|
123
|
+
singular: string;
|
|
124
|
+
plural: string;
|
|
125
|
+
feminine: boolean;
|
|
126
|
+
needsDe: boolean;
|
|
127
|
+
};
|
|
128
|
+
8: {
|
|
129
|
+
singular: string;
|
|
130
|
+
plural: string;
|
|
131
|
+
feminine: boolean;
|
|
132
|
+
needsDe: boolean;
|
|
133
|
+
};
|
|
134
|
+
9: {
|
|
135
|
+
singular: string;
|
|
136
|
+
plural: string;
|
|
137
|
+
feminine: boolean;
|
|
138
|
+
needsDe: boolean;
|
|
139
|
+
};
|
|
140
|
+
10: {
|
|
141
|
+
singular: string;
|
|
142
|
+
plural: string;
|
|
143
|
+
feminine: boolean;
|
|
144
|
+
needsDe: boolean;
|
|
145
|
+
};
|
|
146
|
+
};
|
|
147
|
+
/** Split numeric string into BigInt segments of specified size from left to right. */
|
|
148
|
+
splitToSegments(n: any, x: any): bigint[];
|
|
149
|
+
extractDigits(value: any): any;
|
|
150
|
+
/** Romanian pluralization & "de" rule for big units. */
|
|
151
|
+
romanianPluralize(segment: any, form: any): string;
|
|
152
|
+
spellUnder100(n: any, feminineUnits?: boolean, masculineTeens?: boolean): any;
|
|
153
|
+
spellUnder1000(n: any, feminineUnits?: boolean, masculineTeens?: boolean): any;
|
|
154
|
+
/** Decimals always use masculine forms regardless of gender option. */
|
|
155
|
+
decimalIntegerToWords(integerPart: any): any;
|
|
156
|
+
integerToWords(integerPart: any): string;
|
|
157
|
+
}
|
|
158
|
+
import { AbstractLanguage } from '../classes/abstract-language.js';
|
package/lib/languages/ro.js
CHANGED
|
@@ -1,43 +1,19 @@
|
|
|
1
|
-
import AbstractLanguage from '../classes/abstract-language.js'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @typedef {Object} RomanianOptions
|
|
5
|
-
* @property {boolean} [feminine=false] Use feminine forms for numbers.
|
|
6
|
-
*/
|
|
1
|
+
import { AbstractLanguage } from '../classes/abstract-language.js'
|
|
7
2
|
|
|
8
3
|
/**
|
|
9
4
|
* Romanian language converter.
|
|
10
5
|
*
|
|
11
|
-
*
|
|
12
|
-
* - Gender agreement (
|
|
6
|
+
* Supports:
|
|
7
|
+
* - Gender agreement (unu/una, doi/două)
|
|
13
8
|
* - Complex pluralization (singular/plural forms)
|
|
14
9
|
* - "De" preposition insertion for groups >= 20
|
|
15
|
-
* - Special feminine handling for thousands
|
|
16
|
-
* - Proper case and agreement patterns
|
|
17
|
-
*
|
|
18
|
-
* Key Features:
|
|
19
|
-
* - Gender-aware number forms (unu/una, doi/două, doisprezece/douăsprezece)
|
|
20
|
-
* - Group-based algorithm:
|
|
21
|
-
* 1. Split number into groups of 3 digits
|
|
22
|
-
* 2. Convert each group using gender rules and special forms
|
|
23
|
-
* 3. Insert "de" preposition for groups >= 20 (e.g., "douăzeci de mii")
|
|
24
|
-
* 4. Append magnitude word with proper singular/plural form (mie/mii, milion/milioane)
|
|
25
|
-
* 5. Join with spaces
|
|
26
|
-
* - Special feminine units for thousands group
|
|
27
|
-
* - Automatic "de" insertion rules (nouăsprezece mii vs douăzeci de mii)
|
|
28
|
-
* - Proper singular/plural forms (mie/mii, milion/milioane)
|
|
29
|
-
* - Support for very large numbers (up to decillions)
|
|
30
|
-
*
|
|
31
|
-
* Features:
|
|
32
|
-
* - Feminine units for thousands group
|
|
33
|
-
* - Support for very large numbers (up to decillions)
|
|
34
10
|
*/
|
|
35
11
|
export class Romanian extends AbstractLanguage {
|
|
36
12
|
negativeWord = 'minus'
|
|
37
13
|
decimalSeparatorWord = 'virgulă'
|
|
38
14
|
zeroWord = 'zero'
|
|
39
15
|
|
|
40
|
-
|
|
16
|
+
onesWords = {
|
|
41
17
|
1: 'unu',
|
|
42
18
|
2: 'doi',
|
|
43
19
|
3: 'trei',
|
|
@@ -49,7 +25,7 @@ export class Romanian extends AbstractLanguage {
|
|
|
49
25
|
9: 'nouă'
|
|
50
26
|
}
|
|
51
27
|
|
|
52
|
-
|
|
28
|
+
onesFeminineWords = {
|
|
53
29
|
1: 'una',
|
|
54
30
|
2: 'două',
|
|
55
31
|
3: 'trei',
|
|
@@ -61,7 +37,7 @@ export class Romanian extends AbstractLanguage {
|
|
|
61
37
|
9: 'nouă'
|
|
62
38
|
}
|
|
63
39
|
|
|
64
|
-
|
|
40
|
+
teensWords = {
|
|
65
41
|
0: 'zece',
|
|
66
42
|
1: 'unsprezece',
|
|
67
43
|
2: 'douăsprezece',
|
|
@@ -74,7 +50,7 @@ export class Romanian extends AbstractLanguage {
|
|
|
74
50
|
9: 'nouăsprezece'
|
|
75
51
|
}
|
|
76
52
|
|
|
77
|
-
|
|
53
|
+
teensMasculineWords = {
|
|
78
54
|
0: 'zece',
|
|
79
55
|
1: 'unsprezece',
|
|
80
56
|
2: 'doisprezece',
|
|
@@ -87,7 +63,7 @@ export class Romanian extends AbstractLanguage {
|
|
|
87
63
|
9: 'nouăsprezece'
|
|
88
64
|
}
|
|
89
65
|
|
|
90
|
-
|
|
66
|
+
twentiesWords = {
|
|
91
67
|
2: 'douăzeci',
|
|
92
68
|
3: 'treizeci',
|
|
93
69
|
4: 'patruzeci',
|
|
@@ -98,7 +74,7 @@ export class Romanian extends AbstractLanguage {
|
|
|
98
74
|
9: 'nouăzeci'
|
|
99
75
|
}
|
|
100
76
|
|
|
101
|
-
|
|
77
|
+
hundredsWords = {
|
|
102
78
|
1: 'o sută',
|
|
103
79
|
2: 'două sute',
|
|
104
80
|
3: 'trei sute',
|
|
@@ -113,11 +89,11 @@ export class Romanian extends AbstractLanguage {
|
|
|
113
89
|
/**
|
|
114
90
|
* Romanian big units.
|
|
115
91
|
* For each power group we keep: singular, plural, feminineUnits?, needsDe?
|
|
116
|
-
* - 10^3: mie/mii (feminine units in
|
|
117
|
-
* - 10^6: milion/milioane ("de" for
|
|
118
|
-
* - 10^9: miliard/miliarde ("de" for
|
|
92
|
+
* - 10^3: mie/mii (feminine units in segment; "de" for segment >= 20)
|
|
93
|
+
* - 10^6: milion/milioane ("de" for segment >= 20)
|
|
94
|
+
* - 10^9: miliard/miliarde ("de" for segment >= 20)
|
|
119
95
|
*/
|
|
120
|
-
|
|
96
|
+
scaleMetadata = {
|
|
121
97
|
1: { singular: 'mie', plural: 'mii', feminine: true, needsDe: true }, // 10^3
|
|
122
98
|
2: { singular: 'milion', plural: 'milioane', feminine: false, needsDe: true }, // 10^6
|
|
123
99
|
3: { singular: 'miliard', plural: 'miliarde', feminine: false, needsDe: true }, // 10^9
|
|
@@ -130,24 +106,16 @@ export class Romanian extends AbstractLanguage {
|
|
|
130
106
|
10: { singular: 'decilion', plural: 'decilioane', feminine: false, needsDe: true } // 10^33
|
|
131
107
|
}
|
|
132
108
|
|
|
133
|
-
|
|
134
|
-
* Initializes the Romanian converter with language-specific options.
|
|
135
|
-
*
|
|
136
|
-
* @param {RomanianOptions} [options={}] Configuration options.
|
|
137
|
-
*/
|
|
138
|
-
constructor ({ feminine = false } = {}) {
|
|
109
|
+
constructor (options = {}) {
|
|
139
110
|
super()
|
|
140
111
|
|
|
141
|
-
this.
|
|
112
|
+
this.setOptions({
|
|
113
|
+
gender: 'masculine'
|
|
114
|
+
}, options)
|
|
142
115
|
}
|
|
143
116
|
|
|
144
|
-
/**
|
|
145
|
-
|
|
146
|
-
* @param {string} n - The numeric string to split
|
|
147
|
-
* @param {number} x - The size of each group
|
|
148
|
-
* @returns {bigint[]} Array of BigInt groups
|
|
149
|
-
*/
|
|
150
|
-
splitByX (n, x) {
|
|
117
|
+
/** Split numeric string into BigInt segments of specified size from left to right. */
|
|
118
|
+
splitToSegments (n, x) {
|
|
151
119
|
const results = []
|
|
152
120
|
const l = n.length
|
|
153
121
|
let result
|
|
@@ -168,23 +136,15 @@ export class Romanian extends AbstractLanguage {
|
|
|
168
136
|
return results
|
|
169
137
|
}
|
|
170
138
|
|
|
171
|
-
|
|
139
|
+
extractDigits (value) {
|
|
172
140
|
const stringValue = value.toString().padStart(3, '0').slice(-3)
|
|
173
141
|
const a = [...stringValue].toReversed()
|
|
174
142
|
return a.map(BigInt)
|
|
175
143
|
}
|
|
176
144
|
|
|
177
|
-
/**
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
* - otherwise → spell chunk + (optional "de") + plural
|
|
181
|
-
* "de" is inserted when chunk >= 20 (e.g., "douăzeci de mii/milioane/miliarde").
|
|
182
|
-
* @param {bigint} chunk - The chunk value
|
|
183
|
-
* @param {object} form - The form object with singular, plural, feminine, needsDe properties
|
|
184
|
-
* @returns {string} The pluralized form
|
|
185
|
-
*/
|
|
186
|
-
romanianPluralize (chunk, form) {
|
|
187
|
-
const n = Number(chunk)
|
|
145
|
+
/** Romanian pluralization & "de" rule for big units. */
|
|
146
|
+
romanianPluralize (segment, form) {
|
|
147
|
+
const n = Number(segment)
|
|
188
148
|
|
|
189
149
|
if (n === 1) {
|
|
190
150
|
// article differs for feminine "mie" (o mie) vs the rest (un milion/miliard…)
|
|
@@ -197,7 +157,7 @@ export class Romanian extends AbstractLanguage {
|
|
|
197
157
|
return `douăzeci și una de ${form.plural}`
|
|
198
158
|
}
|
|
199
159
|
|
|
200
|
-
// spell the
|
|
160
|
+
// spell the segment itself (use feminine units for big numbers)
|
|
201
161
|
const words = this.spellUnder1000(n, true)
|
|
202
162
|
|
|
203
163
|
// "de" after >= 20 (covers 20, 21, 100, 101, 999, etc.)
|
|
@@ -207,144 +167,91 @@ export class Romanian extends AbstractLanguage {
|
|
|
207
167
|
return `${words}${de}${form.plural}`
|
|
208
168
|
}
|
|
209
169
|
|
|
210
|
-
spellUnder100 (n, feminineUnits = false) {
|
|
170
|
+
spellUnder100 (n, feminineUnits = false, masculineTeens = false) {
|
|
211
171
|
if (n < 10) {
|
|
212
|
-
return (feminineUnits ? this.
|
|
172
|
+
return (feminineUnits ? this.onesFeminineWords : this.onesWords)[n]
|
|
213
173
|
}
|
|
214
174
|
if (n < 20) {
|
|
215
|
-
return this.
|
|
175
|
+
return (masculineTeens ? this.teensMasculineWords : this.teensWords)[n - 10]
|
|
216
176
|
}
|
|
217
177
|
const t = Math.floor(n / 10)
|
|
218
178
|
const u = n % 10
|
|
219
179
|
return u
|
|
220
|
-
? `${this.
|
|
221
|
-
: this.
|
|
180
|
+
? `${this.twentiesWords[t]} și ${(feminineUnits ? this.onesFeminineWords : this.onesWords)[u]}`
|
|
181
|
+
: this.twentiesWords[t]
|
|
222
182
|
}
|
|
223
183
|
|
|
224
|
-
spellUnder1000 (n, feminineUnits = false) {
|
|
225
|
-
if (n < 100) return this.spellUnder100(n, feminineUnits)
|
|
184
|
+
spellUnder1000 (n, feminineUnits = false, masculineTeens = false) {
|
|
185
|
+
if (n < 100) return this.spellUnder100(n, feminineUnits, masculineTeens)
|
|
226
186
|
const h = Math.floor(n / 100)
|
|
227
187
|
const r = n % 100
|
|
228
|
-
const hundredWords = this.
|
|
188
|
+
const hundredWords = this.hundredsWords[h]
|
|
229
189
|
if (!r) return hundredWords
|
|
230
190
|
// Standard readable form: "o sută unu" (for units) or "o sută cincizeci" (for tens)
|
|
231
191
|
const separator = ' '
|
|
232
|
-
return `${hundredWords}${separator}${this.spellUnder100(r, feminineUnits)}`
|
|
192
|
+
return `${hundredWords}${separator}${this.spellUnder100(r, feminineUnits, masculineTeens)}`
|
|
233
193
|
}
|
|
234
194
|
|
|
235
|
-
/**
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
const words = []
|
|
242
|
-
|
|
243
|
-
const chars = [...decimal]
|
|
244
|
-
|
|
245
|
-
// Loop through characters adding leading zeros to words array
|
|
246
|
-
let index = 0
|
|
247
|
-
while (index < chars.length && chars[index] === '0') {
|
|
248
|
-
words.push(this.zeroWord)
|
|
249
|
-
index++
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
// Prevent further processing if entire string was zeros
|
|
253
|
-
if (index === chars.length) {
|
|
254
|
-
return words
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
// Convert and add remaining using masculine forms for decimal places
|
|
258
|
-
const decimalNumber = BigInt(decimal)
|
|
259
|
-
const masculineWords = this.toCardinalWithMasculine(decimalNumber)
|
|
260
|
-
return [...words, masculineWords]
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* Convert number to cardinal form using masculine units
|
|
265
|
-
* @param {bigint} number Number to convert
|
|
266
|
-
* @returns {string} Value in written format
|
|
267
|
-
*/
|
|
268
|
-
toCardinalWithMasculine (number) {
|
|
269
|
-
if (number === 0n) {
|
|
270
|
-
return this.zeroWord
|
|
271
|
-
}
|
|
272
|
-
|
|
195
|
+
/** Decimals always use masculine forms regardless of gender option. */
|
|
196
|
+
decimalIntegerToWords (integerPart) {
|
|
197
|
+
if (integerPart === 0n) return this.zeroWord
|
|
198
|
+
// Use spellUnder1000 with masculine forms (feminineUnits=false, masculineTeens=true)
|
|
199
|
+
if (integerPart < 1000n) return this.spellUnder1000(Number(integerPart), false, true)
|
|
200
|
+
// For larger decimals, process segments with masculine forms
|
|
273
201
|
const words = []
|
|
274
|
-
const
|
|
275
|
-
let index =
|
|
276
|
-
|
|
277
|
-
for (const x of chunks) {
|
|
278
|
-
let onesMap = []
|
|
202
|
+
const segments = this.splitToSegments(integerPart.toString(), 3)
|
|
203
|
+
let index = segments.length
|
|
204
|
+
for (const x of segments) {
|
|
279
205
|
index = index - 1
|
|
280
|
-
|
|
281
206
|
if (x === 0n) continue
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
// hundreds
|
|
286
|
-
if (n3 > 0n) {
|
|
287
|
-
words.push(this.hundreds[Number(n3)])
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
// tens & teens
|
|
291
|
-
if (n2 > 1n) {
|
|
292
|
-
words.push(this.twenties[Number(n2)])
|
|
293
|
-
}
|
|
294
|
-
|
|
207
|
+
const [n1, n2, n3] = this.extractDigits(x)
|
|
208
|
+
if (n3 > 0n) words.push(this.hundredsWords[Number(n3)])
|
|
209
|
+
if (n2 > 1n) words.push(this.twentiesWords[Number(n2)])
|
|
295
210
|
if (n2 === 1n) {
|
|
296
|
-
words.push(this.
|
|
211
|
+
words.push(this.teensMasculineWords[Number(n1)])
|
|
297
212
|
} else if (n1 > 0n) {
|
|
298
|
-
// Always use masculine units for decimal places
|
|
299
|
-
onesMap = this.ones
|
|
300
|
-
|
|
301
|
-
// if there is a twenty/treizeci/etc AND ones > 0 → add "și"
|
|
302
213
|
if (n2 > 1n) words.push('și')
|
|
303
|
-
words.push(
|
|
214
|
+
words.push(this.onesWords[Number(n1)])
|
|
304
215
|
}
|
|
305
|
-
|
|
306
|
-
// big unit name (mie/mii, milion/milioane, …)
|
|
307
216
|
if (index > 0) {
|
|
308
|
-
const form = this.
|
|
217
|
+
const form = this.scaleMetadata[index]
|
|
309
218
|
if (form) {
|
|
310
219
|
words.push(this.romanianPluralize(x, form))
|
|
311
220
|
} else {
|
|
312
|
-
// For very large numbers beyond our defined units, just spell out the number
|
|
313
221
|
words.push(this.spellUnder1000(Number(x), false))
|
|
314
222
|
}
|
|
315
223
|
}
|
|
316
224
|
}
|
|
317
|
-
|
|
318
225
|
return words.join(' ').replaceAll(/\s+/g, ' ').trim()
|
|
319
226
|
}
|
|
320
227
|
|
|
321
|
-
|
|
322
|
-
if (
|
|
228
|
+
integerToWords (integerPart) {
|
|
229
|
+
if (integerPart === 0n) {
|
|
323
230
|
return this.zeroWord
|
|
324
231
|
}
|
|
325
232
|
const words = []
|
|
326
|
-
const
|
|
327
|
-
let index =
|
|
328
|
-
for (const x of
|
|
233
|
+
const segments = this.splitToSegments(integerPart.toString(), 3)
|
|
234
|
+
let index = segments.length
|
|
235
|
+
for (const x of segments) {
|
|
329
236
|
let onesMap = []
|
|
330
237
|
index = index - 1
|
|
331
238
|
if (x === 0n) continue
|
|
332
|
-
const [n1, n2, n3] = this.
|
|
239
|
+
const [n1, n2, n3] = this.extractDigits(x) // units, tens, hundreds (as BigInt)
|
|
333
240
|
// hundreds (only for the last group, not for thousands)
|
|
334
241
|
if (n3 > 0n && index === 0) {
|
|
335
|
-
words.push(this.
|
|
242
|
+
words.push(this.hundredsWords[Number(n3)])
|
|
336
243
|
}
|
|
337
244
|
// tens & teens (only for the last group, not for thousands)
|
|
338
245
|
if (index === 0) {
|
|
339
246
|
if (n2 > 1n) {
|
|
340
|
-
words.push(this.
|
|
247
|
+
words.push(this.twentiesWords[Number(n2)])
|
|
341
248
|
}
|
|
342
249
|
if (n2 === 1n) {
|
|
343
|
-
words.push(this.
|
|
250
|
+
words.push(this.teensWords[Number(n1)])
|
|
344
251
|
} else if (n1 > 0n) {
|
|
345
252
|
// pick masculine/feminine units (only for the last group, not for thousands)
|
|
346
|
-
const feminineUnits = this.feminine && index === 0
|
|
347
|
-
onesMap = feminineUnits ? this.
|
|
253
|
+
const feminineUnits = this.options.gender === 'feminine' && index === 0
|
|
254
|
+
onesMap = feminineUnits ? this.onesFeminineWords : this.onesWords
|
|
348
255
|
// if there is a twenty/treizeci/etc AND ones > 0 → add "și"
|
|
349
256
|
if (n2 > 1n) words.push('și')
|
|
350
257
|
words.push(onesMap[Number(n1)])
|
|
@@ -352,7 +259,7 @@ export class Romanian extends AbstractLanguage {
|
|
|
352
259
|
}
|
|
353
260
|
// big unit name (mie/mii, milion/milioane, …)
|
|
354
261
|
if (index > 0) {
|
|
355
|
-
const form = this.
|
|
262
|
+
const form = this.scaleMetadata[index]
|
|
356
263
|
if (form) {
|
|
357
264
|
words.push(this.romanianPluralize(x, form))
|
|
358
265
|
} else {
|
|
@@ -364,17 +271,3 @@ export class Romanian extends AbstractLanguage {
|
|
|
364
271
|
return words.join(' ').replaceAll(/\s+/g, ' ').trim()
|
|
365
272
|
}
|
|
366
273
|
}
|
|
367
|
-
|
|
368
|
-
/**
|
|
369
|
-
* Converts a number to Romanian cardinal (written) form.
|
|
370
|
-
*
|
|
371
|
-
* @param {number|string|bigint} value The number to convert.
|
|
372
|
-
* @param {Object} [options={}] Configuration options.
|
|
373
|
-
* @param {boolean} [options.feminine=false] Use feminine forms for numbers.
|
|
374
|
-
* @returns {string} The number expressed in Romanian words.
|
|
375
|
-
* @throws {TypeError} If value is NaN or invalid type.
|
|
376
|
-
* @throws {Error} If value is an invalid number string.
|
|
377
|
-
*/
|
|
378
|
-
export default function convertToWords (value, options = {}) {
|
|
379
|
-
return new Romanian(options).convertToWords(value)
|
|
380
|
-
}
|