@gks101/numtowords 1.0.0 → 1.0.2
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/LICENSE +34 -0
- package/README.md +65 -68
- package/dist/core/converter.js +8 -8
- package/dist/index.cjs.js +321 -148
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.esm.js +321 -148
- package/dist/index.esm.js.map +1 -1
- package/dist/index.umd.js +321 -148
- package/dist/index.umd.js.map +1 -1
- package/dist/locales/de.js +52 -30
- package/dist/locales/en.js +49 -25
- package/dist/locales/fr.js +55 -31
- package/dist/locales/hi.js +116 -37
- package/dist/locales/in.js +46 -22
- package/dist/types/core/converter.d.ts +1 -1
- package/dist/types/core/types.d.ts +1 -1
- package/dist/types/index.d.ts +7 -7
- package/dist/types/locales/de.d.ts +1 -1
- package/dist/types/locales/en.d.ts +1 -1
- package/dist/types/locales/fr.d.ts +1 -1
- package/dist/types/locales/hi.d.ts +1 -1
- package/dist/types/locales/in.d.ts +1 -1
- package/package.json +23 -6
package/dist/index.umd.js
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
const def = registry.get(id);
|
|
26
26
|
if (!def) {
|
|
27
27
|
throw new Error(`[numtowords] Locale "${id}" is not registered. ` +
|
|
28
|
-
`Available: ${[...registry.keys()].join(
|
|
28
|
+
`Available: ${[...registry.keys()].join(', ')}`);
|
|
29
29
|
}
|
|
30
30
|
return def;
|
|
31
31
|
}
|
|
@@ -35,10 +35,10 @@
|
|
|
35
35
|
}
|
|
36
36
|
// ─── Defaults ────────────────────────────────────────────────────────────────
|
|
37
37
|
const DEFAULT_OPTIONS = {
|
|
38
|
-
locale:
|
|
38
|
+
locale: 'en',
|
|
39
39
|
capitalize: true,
|
|
40
40
|
useAnd: true,
|
|
41
|
-
currency:
|
|
41
|
+
currency: '',
|
|
42
42
|
};
|
|
43
43
|
// ─── Main convert function ────────────────────────────────────────────────────
|
|
44
44
|
/**
|
|
@@ -54,27 +54,27 @@
|
|
|
54
54
|
// ── Normalise input ────────────────────────────────────────────────────────
|
|
55
55
|
let raw = String(input).trim();
|
|
56
56
|
let negative = false;
|
|
57
|
-
if (raw.startsWith(
|
|
57
|
+
if (raw.startsWith('-')) {
|
|
58
58
|
negative = true;
|
|
59
59
|
raw = raw.slice(1);
|
|
60
60
|
}
|
|
61
61
|
// Strip commas / underscores used as separators
|
|
62
|
-
raw = raw.replace(/[,_\s]/g,
|
|
62
|
+
raw = raw.replace(/[,_\s]/g, '');
|
|
63
63
|
if (!/^\d+$/.test(raw)) {
|
|
64
64
|
throw new Error(`[numtowords] Invalid numeric input: "${input}"`);
|
|
65
65
|
}
|
|
66
66
|
// Remove leading zeros
|
|
67
|
-
raw = raw.replace(/^0+/,
|
|
67
|
+
raw = raw.replace(/^0+/, '') || '0';
|
|
68
68
|
const n = BigInt(raw);
|
|
69
69
|
// ── Delegate to locale ─────────────────────────────────────────────────────
|
|
70
70
|
const locale = getLocale(opts.locale);
|
|
71
71
|
let result = locale.convert(n, opts);
|
|
72
72
|
if (negative)
|
|
73
|
-
result =
|
|
73
|
+
result = 'Negative ' + result;
|
|
74
74
|
// ── Capitalise ─────────────────────────────────────────────────────────────
|
|
75
75
|
if (opts.capitalize) {
|
|
76
76
|
// Do not capitalise German zero (tests expect lowercase 'null')
|
|
77
|
-
if (!(n === 0n && opts.locale ===
|
|
77
|
+
if (!(n === 0n && opts.locale === 'de')) {
|
|
78
78
|
result = result.charAt(0).toUpperCase() + result.slice(1);
|
|
79
79
|
}
|
|
80
80
|
}
|
|
@@ -87,37 +87,61 @@
|
|
|
87
87
|
|
|
88
88
|
// ─── Word tables ──────────────────────────────────────────────────────────────
|
|
89
89
|
const ONES$1 = [
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
90
|
+
'',
|
|
91
|
+
'one',
|
|
92
|
+
'two',
|
|
93
|
+
'three',
|
|
94
|
+
'four',
|
|
95
|
+
'five',
|
|
96
|
+
'six',
|
|
97
|
+
'seven',
|
|
98
|
+
'eight',
|
|
99
|
+
'nine',
|
|
100
|
+
'ten',
|
|
101
|
+
'eleven',
|
|
102
|
+
'twelve',
|
|
103
|
+
'thirteen',
|
|
104
|
+
'fourteen',
|
|
105
|
+
'fifteen',
|
|
106
|
+
'sixteen',
|
|
107
|
+
'seventeen',
|
|
108
|
+
'eighteen',
|
|
109
|
+
'nineteen',
|
|
94
110
|
];
|
|
95
111
|
const TENS$1 = [
|
|
96
|
-
|
|
97
|
-
|
|
112
|
+
'',
|
|
113
|
+
'',
|
|
114
|
+
'twenty',
|
|
115
|
+
'thirty',
|
|
116
|
+
'forty',
|
|
117
|
+
'fifty',
|
|
118
|
+
'sixty',
|
|
119
|
+
'seventy',
|
|
120
|
+
'eighty',
|
|
121
|
+
'ninety',
|
|
98
122
|
];
|
|
99
123
|
/**
|
|
100
124
|
* Scale names in the short (American/modern British) scale.
|
|
101
125
|
* Index 0 = thousands, 1 = millions, …
|
|
102
126
|
*/
|
|
103
127
|
const SCALES = [
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
128
|
+
'thousand',
|
|
129
|
+
'million',
|
|
130
|
+
'billion',
|
|
131
|
+
'trillion',
|
|
132
|
+
'quadrillion',
|
|
133
|
+
'quintillion',
|
|
134
|
+
'sextillion',
|
|
135
|
+
'septillion',
|
|
136
|
+
'octillion',
|
|
137
|
+
'nonillion',
|
|
138
|
+
'decillion',
|
|
115
139
|
];
|
|
116
140
|
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
117
141
|
/** Convert 0–999 to words */
|
|
118
142
|
function hundredsToWords$1(n, useAnd) {
|
|
119
143
|
if (n === 0)
|
|
120
|
-
return
|
|
144
|
+
return '';
|
|
121
145
|
const parts = [];
|
|
122
146
|
const h = Math.floor(n / 100);
|
|
123
147
|
const remainder = n % 100;
|
|
@@ -127,7 +151,7 @@
|
|
|
127
151
|
if (remainder === 0) ;
|
|
128
152
|
else {
|
|
129
153
|
if (h > 0 && useAnd)
|
|
130
|
-
parts.push(
|
|
154
|
+
parts.push('and');
|
|
131
155
|
if (remainder < 20) {
|
|
132
156
|
parts.push(ONES$1[remainder]);
|
|
133
157
|
}
|
|
@@ -137,14 +161,14 @@
|
|
|
137
161
|
parts.push(o === 0 ? TENS$1[t] : `${TENS$1[t]}-${ONES$1[o]}`);
|
|
138
162
|
}
|
|
139
163
|
}
|
|
140
|
-
return parts.join(
|
|
164
|
+
return parts.join(' ');
|
|
141
165
|
}
|
|
142
166
|
// ─── Locale definition ────────────────────────────────────────────────────────
|
|
143
167
|
const en = {
|
|
144
|
-
name:
|
|
168
|
+
name: 'English',
|
|
145
169
|
convert(n, opts) {
|
|
146
170
|
if (n === 0n)
|
|
147
|
-
return
|
|
171
|
+
return 'zero';
|
|
148
172
|
const useAnd = opts.useAnd;
|
|
149
173
|
const chunks = [];
|
|
150
174
|
// Split number into groups of 3 from the right
|
|
@@ -171,21 +195,45 @@
|
|
|
171
195
|
parts.push(`${words} ${scaleName}`);
|
|
172
196
|
}
|
|
173
197
|
}
|
|
174
|
-
return parts.join(
|
|
198
|
+
return parts.join(' ');
|
|
175
199
|
},
|
|
176
200
|
};
|
|
177
|
-
registerLocale(
|
|
201
|
+
registerLocale('en', en);
|
|
178
202
|
|
|
179
203
|
// ─── Word tables ──────────────────────────────────────────────────────────────
|
|
180
204
|
const ONES = [
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
205
|
+
'',
|
|
206
|
+
'one',
|
|
207
|
+
'two',
|
|
208
|
+
'three',
|
|
209
|
+
'four',
|
|
210
|
+
'five',
|
|
211
|
+
'six',
|
|
212
|
+
'seven',
|
|
213
|
+
'eight',
|
|
214
|
+
'nine',
|
|
215
|
+
'ten',
|
|
216
|
+
'eleven',
|
|
217
|
+
'twelve',
|
|
218
|
+
'thirteen',
|
|
219
|
+
'fourteen',
|
|
220
|
+
'fifteen',
|
|
221
|
+
'sixteen',
|
|
222
|
+
'seventeen',
|
|
223
|
+
'eighteen',
|
|
224
|
+
'nineteen',
|
|
185
225
|
];
|
|
186
226
|
const TENS = [
|
|
187
|
-
|
|
188
|
-
|
|
227
|
+
'',
|
|
228
|
+
'',
|
|
229
|
+
'twenty',
|
|
230
|
+
'thirty',
|
|
231
|
+
'forty',
|
|
232
|
+
'fifty',
|
|
233
|
+
'sixty',
|
|
234
|
+
'seventy',
|
|
235
|
+
'eighty',
|
|
236
|
+
'ninety',
|
|
189
237
|
];
|
|
190
238
|
/**
|
|
191
239
|
* Indian scale names (each 100× the previous after thousand):
|
|
@@ -196,19 +244,19 @@
|
|
|
196
244
|
* …
|
|
197
245
|
*/
|
|
198
246
|
const INDIAN_SCALES = [
|
|
199
|
-
[100000000000000000n,
|
|
200
|
-
[1000000000000000n,
|
|
201
|
-
[10000000000000n,
|
|
202
|
-
[100000000000n,
|
|
203
|
-
[1000000000n,
|
|
204
|
-
[10000000n,
|
|
205
|
-
[100000n,
|
|
206
|
-
[1000n,
|
|
247
|
+
[100000000000000000n, 'shankh'], // 10^17
|
|
248
|
+
[1000000000000000n, 'padma'], // 10^15
|
|
249
|
+
[10000000000000n, 'neel'], // 10^13
|
|
250
|
+
[100000000000n, 'kharab'], // 10^11
|
|
251
|
+
[1000000000n, 'arab'], // 10^9
|
|
252
|
+
[10000000n, 'crore'], // 10^7
|
|
253
|
+
[100000n, 'lakh'], // 10^5
|
|
254
|
+
[1000n, 'thousand'],
|
|
207
255
|
];
|
|
208
256
|
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
209
257
|
function twoDigits(n) {
|
|
210
258
|
if (n === 0)
|
|
211
|
-
return
|
|
259
|
+
return '';
|
|
212
260
|
if (n < 20)
|
|
213
261
|
return ONES[n];
|
|
214
262
|
const t = Math.floor(n / 10);
|
|
@@ -217,7 +265,7 @@
|
|
|
217
265
|
}
|
|
218
266
|
function hundredsToWords(n) {
|
|
219
267
|
if (n === 0)
|
|
220
|
-
return
|
|
268
|
+
return '';
|
|
221
269
|
const h = Math.floor(n / 100);
|
|
222
270
|
const rem = n % 100;
|
|
223
271
|
const parts = [];
|
|
@@ -226,14 +274,14 @@
|
|
|
226
274
|
const two = twoDigits(rem);
|
|
227
275
|
if (two)
|
|
228
276
|
parts.push(two);
|
|
229
|
-
return parts.join(
|
|
277
|
+
return parts.join(' ');
|
|
230
278
|
}
|
|
231
279
|
// ─── Locale definition ────────────────────────────────────────────────────────
|
|
232
280
|
const indian = {
|
|
233
|
-
name:
|
|
281
|
+
name: 'Indian',
|
|
234
282
|
convert(n, _opts) {
|
|
235
283
|
if (n === 0n)
|
|
236
|
-
return
|
|
284
|
+
return 'zero';
|
|
237
285
|
const parts = [];
|
|
238
286
|
let remaining = n;
|
|
239
287
|
for (const [scale, name] of INDIAN_SCALES) {
|
|
@@ -250,53 +298,132 @@
|
|
|
250
298
|
if (remaining > 0n) {
|
|
251
299
|
parts.push(hundredsToWords(Number(remaining)));
|
|
252
300
|
}
|
|
253
|
-
return parts.join(
|
|
301
|
+
return parts.join(' ');
|
|
254
302
|
},
|
|
255
303
|
};
|
|
256
|
-
registerLocale(
|
|
304
|
+
registerLocale('in', indian);
|
|
257
305
|
|
|
258
306
|
// ─── Word tables ──────────────────────────────────────────────────────────────
|
|
259
307
|
/** 1–99 in Hindi */
|
|
260
308
|
const HINDI_ONES = {
|
|
261
|
-
1:
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
309
|
+
1: 'एक',
|
|
310
|
+
2: 'दो',
|
|
311
|
+
3: 'तीन',
|
|
312
|
+
4: 'चार',
|
|
313
|
+
5: 'पाँच',
|
|
314
|
+
6: 'छह',
|
|
315
|
+
7: 'सात',
|
|
316
|
+
8: 'आठ',
|
|
317
|
+
9: 'नौ',
|
|
318
|
+
10: 'दस',
|
|
319
|
+
11: 'ग्यारह',
|
|
320
|
+
12: 'बारह',
|
|
321
|
+
13: 'तेरह',
|
|
322
|
+
14: 'चौदह',
|
|
323
|
+
15: 'पन्द्रह',
|
|
324
|
+
16: 'सोलह',
|
|
325
|
+
17: 'सत्रह',
|
|
326
|
+
18: 'अट्ठारह',
|
|
327
|
+
19: 'उन्नीस',
|
|
328
|
+
20: 'बीस',
|
|
329
|
+
21: 'इक्कीस',
|
|
330
|
+
22: 'बाईस',
|
|
331
|
+
23: 'तेईस',
|
|
332
|
+
24: 'चौबीस',
|
|
333
|
+
25: 'पच्चीस',
|
|
334
|
+
26: 'छब्बीस',
|
|
335
|
+
27: 'सत्ताईस',
|
|
336
|
+
28: 'अट्ठाईस',
|
|
337
|
+
29: 'उनतीस',
|
|
338
|
+
30: 'तीस',
|
|
339
|
+
31: 'इकतीस',
|
|
340
|
+
32: 'बत्तीस',
|
|
341
|
+
33: 'तैंतीस',
|
|
342
|
+
34: 'चौंतीस',
|
|
343
|
+
35: 'पैंतीस',
|
|
344
|
+
36: 'छत्तीस',
|
|
345
|
+
37: 'सैंतीस',
|
|
346
|
+
38: 'अड़तीस',
|
|
347
|
+
39: 'उनतालीस',
|
|
348
|
+
40: 'चालीस',
|
|
349
|
+
41: 'इकतालीस',
|
|
350
|
+
42: 'बयालीस',
|
|
351
|
+
43: 'तैंतालीस',
|
|
352
|
+
44: 'चौवालीस',
|
|
353
|
+
45: 'पैंतालीस',
|
|
354
|
+
46: 'छियालीस',
|
|
355
|
+
47: 'सैंतालीस',
|
|
356
|
+
48: 'अड़तालीस',
|
|
357
|
+
49: 'उनचास',
|
|
358
|
+
50: 'पचास',
|
|
359
|
+
51: 'इक्यावन',
|
|
360
|
+
52: 'बावन',
|
|
361
|
+
53: 'तिरपन',
|
|
362
|
+
54: 'चौवन',
|
|
363
|
+
55: 'पचपन',
|
|
364
|
+
56: 'छप्पन',
|
|
365
|
+
57: 'सत्तावन',
|
|
366
|
+
58: 'अट्ठावन',
|
|
367
|
+
59: 'उनसठ',
|
|
368
|
+
60: 'साठ',
|
|
369
|
+
61: 'इकसठ',
|
|
370
|
+
62: 'बासठ',
|
|
371
|
+
63: 'तिरसठ',
|
|
372
|
+
64: 'चौंसठ',
|
|
373
|
+
65: 'पैंसठ',
|
|
374
|
+
66: 'छियासठ',
|
|
375
|
+
67: 'सड़सठ',
|
|
376
|
+
68: 'अड़सठ',
|
|
377
|
+
69: 'उनहत्तर',
|
|
378
|
+
70: 'सत्तर',
|
|
379
|
+
71: 'इकहत्तर',
|
|
380
|
+
72: 'बहत्तर',
|
|
381
|
+
73: 'तिहत्तर',
|
|
382
|
+
74: 'चौहत्तर',
|
|
383
|
+
75: 'पचहत्तर',
|
|
384
|
+
76: 'छिहत्तर',
|
|
385
|
+
77: 'सत्तहत्तर',
|
|
386
|
+
78: 'अठहत्तर',
|
|
387
|
+
79: 'उन्यासी',
|
|
388
|
+
80: 'अस्सी',
|
|
389
|
+
81: 'इक्यासी',
|
|
390
|
+
82: 'बयासी',
|
|
391
|
+
83: 'तिरासी',
|
|
392
|
+
84: 'चौरासी',
|
|
393
|
+
85: 'पचासी',
|
|
394
|
+
86: 'छियासी',
|
|
395
|
+
87: 'सत्तासी',
|
|
396
|
+
88: 'अट्ठासी',
|
|
397
|
+
89: 'नवासी',
|
|
398
|
+
90: 'नब्बे',
|
|
399
|
+
91: 'इक्यानबे',
|
|
400
|
+
92: 'बानवे',
|
|
401
|
+
93: 'तिरानवे',
|
|
402
|
+
94: 'चौरानवे',
|
|
403
|
+
95: 'पचानवे',
|
|
404
|
+
96: 'छियानवे',
|
|
405
|
+
97: 'सत्तानवे',
|
|
406
|
+
98: 'अट्ठानवे',
|
|
407
|
+
99: 'निन्यानवे',
|
|
281
408
|
};
|
|
282
|
-
const HINDI_HUNDRED =
|
|
409
|
+
const HINDI_HUNDRED = 'सौ';
|
|
283
410
|
const INDIAN_SCALES_HI = [
|
|
284
|
-
[100000000000000000n,
|
|
285
|
-
[1000000000000000n,
|
|
286
|
-
[10000000000000n,
|
|
287
|
-
[100000000000n,
|
|
288
|
-
[1000000000n,
|
|
289
|
-
[10000000n,
|
|
290
|
-
[100000n,
|
|
291
|
-
[1000n,
|
|
411
|
+
[100000000000000000n, 'शंख'], // 10^17
|
|
412
|
+
[1000000000000000n, 'पद्म'], // 10^15
|
|
413
|
+
[10000000000000n, 'नील'], // 10^13
|
|
414
|
+
[100000000000n, 'खरब'], // 10^11
|
|
415
|
+
[1000000000n, 'अरब'], // 10^9
|
|
416
|
+
[10000000n, 'करोड़'], // 10^7
|
|
417
|
+
[100000n, 'लाख'], // 10^5
|
|
418
|
+
[1000n, 'हज़ार'], // 10^3
|
|
292
419
|
];
|
|
293
420
|
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
294
421
|
function upToNinetyNine$2(n) {
|
|
295
|
-
return HINDI_ONES[n] ??
|
|
422
|
+
return HINDI_ONES[n] ?? '';
|
|
296
423
|
}
|
|
297
424
|
function hundredsHindi(n) {
|
|
298
425
|
if (n === 0)
|
|
299
|
-
return
|
|
426
|
+
return '';
|
|
300
427
|
const h = Math.floor(n / 100);
|
|
301
428
|
const rem = n % 100;
|
|
302
429
|
const parts = [];
|
|
@@ -306,14 +433,14 @@
|
|
|
306
433
|
}
|
|
307
434
|
if (rem > 0)
|
|
308
435
|
parts.push(upToNinetyNine$2(rem));
|
|
309
|
-
return parts.join(
|
|
436
|
+
return parts.join(' ');
|
|
310
437
|
}
|
|
311
438
|
// ─── Locale definition ────────────────────────────────────────────────────────
|
|
312
439
|
const hi = {
|
|
313
|
-
name:
|
|
440
|
+
name: 'Hindi',
|
|
314
441
|
convert(n, _opts) {
|
|
315
442
|
if (n === 0n)
|
|
316
|
-
return
|
|
443
|
+
return 'शून्य';
|
|
317
444
|
const parts = [];
|
|
318
445
|
let remaining = n;
|
|
319
446
|
for (const [scale, name] of INDIAN_SCALES_HI) {
|
|
@@ -327,26 +454,50 @@
|
|
|
327
454
|
if (remaining > 0n) {
|
|
328
455
|
parts.push(hundredsHindi(Number(remaining)));
|
|
329
456
|
}
|
|
330
|
-
return parts.join(
|
|
457
|
+
return parts.join(' ');
|
|
331
458
|
},
|
|
332
459
|
};
|
|
333
|
-
registerLocale(
|
|
460
|
+
registerLocale('hi', hi);
|
|
334
461
|
|
|
335
462
|
// ─── Word tables ──────────────────────────────────────────────────────────────
|
|
336
463
|
const ONES_DE = [
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
464
|
+
'',
|
|
465
|
+
'ein',
|
|
466
|
+
'zwei',
|
|
467
|
+
'drei',
|
|
468
|
+
'vier',
|
|
469
|
+
'fünf',
|
|
470
|
+
'sechs',
|
|
471
|
+
'sieben',
|
|
472
|
+
'acht',
|
|
473
|
+
'neun',
|
|
474
|
+
'zehn',
|
|
475
|
+
'elf',
|
|
476
|
+
'zwölf',
|
|
477
|
+
'dreizehn',
|
|
478
|
+
'vierzehn',
|
|
479
|
+
'fünfzehn',
|
|
480
|
+
'sechzehn',
|
|
481
|
+
'siebzehn',
|
|
482
|
+
'achtzehn',
|
|
483
|
+
'neunzehn',
|
|
341
484
|
];
|
|
342
485
|
const TENS_DE = [
|
|
343
|
-
|
|
344
|
-
|
|
486
|
+
'',
|
|
487
|
+
'',
|
|
488
|
+
'zwanzig',
|
|
489
|
+
'dreißig',
|
|
490
|
+
'vierzig',
|
|
491
|
+
'fünfzig',
|
|
492
|
+
'sechzig',
|
|
493
|
+
'siebzig',
|
|
494
|
+
'achtzig',
|
|
495
|
+
'neunzig',
|
|
345
496
|
];
|
|
346
497
|
/** German uses "und" between ones and tens: einundzwanzig */
|
|
347
498
|
function upToNinetyNine$1(n) {
|
|
348
499
|
if (n === 0)
|
|
349
|
-
return
|
|
500
|
+
return '';
|
|
350
501
|
if (n < 20)
|
|
351
502
|
return ONES_DE[n];
|
|
352
503
|
const t = Math.floor(n / 10);
|
|
@@ -357,42 +508,42 @@
|
|
|
357
508
|
}
|
|
358
509
|
function hundredsDE(n) {
|
|
359
510
|
if (n === 0)
|
|
360
|
-
return
|
|
511
|
+
return '';
|
|
361
512
|
const h = Math.floor(n / 100);
|
|
362
513
|
const rem = n % 100;
|
|
363
514
|
const parts = [];
|
|
364
515
|
if (h === 1)
|
|
365
|
-
parts.push(
|
|
516
|
+
parts.push('einhundert');
|
|
366
517
|
else if (h > 1)
|
|
367
518
|
parts.push(`${ONES_DE[h]}hundert`);
|
|
368
519
|
if (rem > 0)
|
|
369
520
|
parts.push(upToNinetyNine$1(rem));
|
|
370
|
-
return parts.join(
|
|
521
|
+
return parts.join('');
|
|
371
522
|
}
|
|
372
523
|
const SCALES_DE = [
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
524
|
+
'tausend',
|
|
525
|
+
'Million',
|
|
526
|
+
'Milliarde',
|
|
527
|
+
'Billion',
|
|
528
|
+
'Billiarde',
|
|
529
|
+
'Trillion',
|
|
379
530
|
];
|
|
380
531
|
/** Scales that are grammatically feminine in German (require "eine" not "ein") */
|
|
381
532
|
const FEMININE_SCALES = new Set([1, 2, 4, 6]); // indices: Million, Milliarde, Billiarde, Trillion
|
|
382
533
|
const SCALES_DE_PLURAL = [
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
534
|
+
'tausend',
|
|
535
|
+
'Millionen',
|
|
536
|
+
'Milliarden',
|
|
537
|
+
'Billionen',
|
|
538
|
+
'Billiarden',
|
|
539
|
+
'Trillionen',
|
|
389
540
|
];
|
|
390
541
|
// ─── Locale definition ────────────────────────────────────────────────────────
|
|
391
542
|
const de = {
|
|
392
|
-
name:
|
|
543
|
+
name: 'German',
|
|
393
544
|
convert(n, _opts) {
|
|
394
545
|
if (n === 0n)
|
|
395
|
-
return
|
|
546
|
+
return 'null';
|
|
396
547
|
const chunks = [];
|
|
397
548
|
let remaining = n;
|
|
398
549
|
let idx = 0;
|
|
@@ -417,52 +568,74 @@
|
|
|
417
568
|
const scaleIdx = scale - 1;
|
|
418
569
|
const isFeminine = FEMININE_SCALES.has(scaleIdx);
|
|
419
570
|
// Replace trailing "ein" with "eine" for feminine scales
|
|
420
|
-
const adjustedWords = value === 1 && isFeminine
|
|
421
|
-
? words.replace(/ein$/, "eine")
|
|
422
|
-
: words;
|
|
571
|
+
const adjustedWords = value === 1 && isFeminine ? words.replace(/ein$/, 'eine') : words;
|
|
423
572
|
const scaleName = value === 1 ? SCALES_DE[scaleIdx] : SCALES_DE_PLURAL[scaleIdx];
|
|
424
573
|
parts.push(`${adjustedWords} ${scaleName}`);
|
|
425
574
|
}
|
|
426
575
|
}
|
|
427
|
-
return parts.join(
|
|
576
|
+
return parts.join(' ').trim();
|
|
428
577
|
},
|
|
429
578
|
};
|
|
430
|
-
registerLocale(
|
|
579
|
+
registerLocale('de', de);
|
|
431
580
|
|
|
432
581
|
// ─── Word tables ──────────────────────────────────────────────────────────────
|
|
433
582
|
const ONES_FR = [
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
583
|
+
'',
|
|
584
|
+
'un',
|
|
585
|
+
'deux',
|
|
586
|
+
'trois',
|
|
587
|
+
'quatre',
|
|
588
|
+
'cinq',
|
|
589
|
+
'six',
|
|
590
|
+
'sept',
|
|
591
|
+
'huit',
|
|
592
|
+
'neuf',
|
|
593
|
+
'dix',
|
|
594
|
+
'onze',
|
|
595
|
+
'douze',
|
|
596
|
+
'treize',
|
|
597
|
+
'quatorze',
|
|
598
|
+
'quinze',
|
|
599
|
+
'seize',
|
|
600
|
+
'dix-sept',
|
|
601
|
+
'dix-huit',
|
|
602
|
+
'dix-neuf',
|
|
438
603
|
];
|
|
439
604
|
const TENS_FR = [
|
|
440
|
-
|
|
441
|
-
|
|
605
|
+
'',
|
|
606
|
+
'',
|
|
607
|
+
'vingt',
|
|
608
|
+
'trente',
|
|
609
|
+
'quarante',
|
|
610
|
+
'cinquante',
|
|
611
|
+
'soixante',
|
|
612
|
+
'soixante',
|
|
613
|
+
'quatre-vingt',
|
|
614
|
+
'quatre-vingt',
|
|
442
615
|
];
|
|
443
616
|
/**
|
|
444
617
|
* French has irregular 70s (soixante-dix + 10–19) and 90s (quatre-vingt-dix + 10–19).
|
|
445
618
|
*/
|
|
446
619
|
function upToNinetyNine(n) {
|
|
447
620
|
if (n === 0)
|
|
448
|
-
return
|
|
621
|
+
return '';
|
|
449
622
|
if (n < 20)
|
|
450
623
|
return ONES_FR[n];
|
|
451
624
|
const t = Math.floor(n / 10);
|
|
452
625
|
const o = n % 10;
|
|
453
626
|
if (t === 7) {
|
|
454
627
|
// soixante + (10 + o)
|
|
455
|
-
return o === 0 ?
|
|
628
|
+
return o === 0 ? 'soixante-dix' : `soixante-${ONES_FR[10 + o]}`;
|
|
456
629
|
}
|
|
457
630
|
if (t === 8) {
|
|
458
631
|
// quatre-vingt(s) + o
|
|
459
632
|
if (o === 0)
|
|
460
|
-
return
|
|
633
|
+
return 'quatre-vingts';
|
|
461
634
|
return `quatre-vingt-${ONES_FR[o]}`;
|
|
462
635
|
}
|
|
463
636
|
if (t === 9) {
|
|
464
637
|
// quatre-vingt-dix + (0 + o)
|
|
465
|
-
return o === 0 ?
|
|
638
|
+
return o === 0 ? 'quatre-vingt-dix' : `quatre-vingt-${ONES_FR[10 + o]}`;
|
|
466
639
|
}
|
|
467
640
|
if (o === 0)
|
|
468
641
|
return TENS_FR[t];
|
|
@@ -472,12 +645,12 @@
|
|
|
472
645
|
}
|
|
473
646
|
function hundredsFR(n) {
|
|
474
647
|
if (n === 0)
|
|
475
|
-
return
|
|
648
|
+
return '';
|
|
476
649
|
const h = Math.floor(n / 100);
|
|
477
650
|
const rem = n % 100;
|
|
478
651
|
const parts = [];
|
|
479
652
|
if (h === 1) {
|
|
480
|
-
parts.push(
|
|
653
|
+
parts.push('cent');
|
|
481
654
|
}
|
|
482
655
|
else if (h > 1) {
|
|
483
656
|
parts.push(`${ONES_FR[h]} cents`);
|
|
@@ -489,30 +662,30 @@
|
|
|
489
662
|
}
|
|
490
663
|
parts.push(upToNinetyNine(rem));
|
|
491
664
|
}
|
|
492
|
-
return parts.join(
|
|
665
|
+
return parts.join(' ');
|
|
493
666
|
}
|
|
494
667
|
const SCALES_FR = [
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
668
|
+
'mille',
|
|
669
|
+
'million',
|
|
670
|
+
'milliard',
|
|
671
|
+
'billion',
|
|
672
|
+
'billiard',
|
|
673
|
+
'trillion',
|
|
501
674
|
];
|
|
502
675
|
const SCALES_FR_PLURAL = [
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
676
|
+
'mille',
|
|
677
|
+
'millions',
|
|
678
|
+
'milliards',
|
|
679
|
+
'billions',
|
|
680
|
+
'billiards',
|
|
681
|
+
'trillions',
|
|
509
682
|
];
|
|
510
683
|
// ─── Locale definition ────────────────────────────────────────────────────────
|
|
511
684
|
const fr = {
|
|
512
|
-
name:
|
|
685
|
+
name: 'French',
|
|
513
686
|
convert(n, _opts) {
|
|
514
687
|
if (n === 0n)
|
|
515
|
-
return
|
|
688
|
+
return 'zéro';
|
|
516
689
|
const chunks = [];
|
|
517
690
|
let remaining = n;
|
|
518
691
|
let idx = 0;
|
|
@@ -531,7 +704,7 @@
|
|
|
531
704
|
}
|
|
532
705
|
else if (scale === 1) {
|
|
533
706
|
// "mille" does not pluralise and drops "un" prefix
|
|
534
|
-
parts.push(value === 1 ?
|
|
707
|
+
parts.push(value === 1 ? 'mille' : `${words} mille`);
|
|
535
708
|
}
|
|
536
709
|
else {
|
|
537
710
|
const scaleIdx = scale - 1;
|
|
@@ -539,10 +712,10 @@
|
|
|
539
712
|
parts.push(`${words} ${scaleName}`);
|
|
540
713
|
}
|
|
541
714
|
}
|
|
542
|
-
return parts.join(
|
|
715
|
+
return parts.join(' ').trim();
|
|
543
716
|
},
|
|
544
717
|
};
|
|
545
|
-
registerLocale(
|
|
718
|
+
registerLocale('fr', fr);
|
|
546
719
|
|
|
547
720
|
exports.availableLocales = availableLocales;
|
|
548
721
|
exports.convert = convert;
|