@gks101/numtowords 1.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 +248 -0
- package/dist/core/converter.js +75 -0
- package/dist/core/types.js +4 -0
- package/dist/index.cjs.js +547 -0
- package/dist/index.cjs.js.map +1 -0
- package/dist/index.d.ts +55 -0
- package/dist/index.esm.js +542 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.umd.js +553 -0
- package/dist/index.umd.js.map +1 -0
- package/dist/locales/de.js +98 -0
- package/dist/locales/en.js +94 -0
- package/dist/locales/fr.js +116 -0
- package/dist/locales/hi.js +78 -0
- package/dist/locales/in.js +80 -0
- package/dist/types/core/converter.d.ts +21 -0
- package/dist/types/core/types.d.ts +31 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/locales/de.d.ts +3 -0
- package/dist/types/locales/en.d.ts +3 -0
- package/dist/types/locales/fr.d.ts +3 -0
- package/dist/types/locales/hi.d.ts +3 -0
- package/dist/types/locales/in.d.ts +3 -0
- package/package.json +50 -0
package/README.md
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
# @gks101/numtowords
|
|
2
|
+
|
|
3
|
+
> Convert numbers to words in **multiple languages and numeral systems** — English, Indian, Hindi, German, French — with full TypeScript support.
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
convert(1_000_124) // "One million one hundred and twenty-four"
|
|
7
|
+
convert(1_000_124, { locale: "in" }) // "Ten lakh one hundred twenty-four"
|
|
8
|
+
convert(1_000_124, { locale: "hi" }) // "दस लाख एक सौ चौबीस"
|
|
9
|
+
convert(1_000_124, { locale: "de" }) // "Eine Million einhundertvierundzwanzig"
|
|
10
|
+
convert(1_000_124, { locale: "fr" }) // "Un million cent vingt-quatre"
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Features
|
|
16
|
+
|
|
17
|
+
- 🌍 **5 locales out of the box** — `en`, `in`, `hi`, `de`, `fr`
|
|
18
|
+
- 🇮🇳 **Indian numbering system** — lakh, crore, arab, kharab, neel, padma, shankh
|
|
19
|
+
- 🔢 **BigInt support** — handles arbitrarily large numbers
|
|
20
|
+
- 💱 **Currency mode** — appends a currency label
|
|
21
|
+
- 🔌 **Extensible** — register your own locale in two lines
|
|
22
|
+
- 📦 **Three bundle formats** — ESM, CJS, UMD (browser ready)
|
|
23
|
+
- 🔷 **Full TypeScript types** included
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install @gks101@numtowords
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Quick Start
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import { convert } from "@gks101@numtowords";
|
|
39
|
+
|
|
40
|
+
convert(0); // "Zero"
|
|
41
|
+
convert(42); // "Forty-two"
|
|
42
|
+
convert(1_000_000); // "One million"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Indian numbering system
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
convert(1_00_000, { locale: "in" }); // "One lakh"
|
|
49
|
+
convert(10_00_000, { locale: "in" }); // "Ten lakh"
|
|
50
|
+
convert(1_00_00_000, { locale: "in" }); // "One crore"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Hindi (Devanagari)
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
convert(1_00_000, { locale: "hi" }); // "एक लाख"
|
|
57
|
+
convert(1_00_00_000, { locale: "hi" }); // "एक करोड़"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### German
|
|
61
|
+
|
|
62
|
+
```ts
|
|
63
|
+
convert(21, { locale: "de" }); // "Einundzwanzig"
|
|
64
|
+
convert(1_000_000, { locale: "de" }); // "Eine Million"
|
|
65
|
+
convert(2_000_000, { locale: "de" }); // "Zwei Millionen"
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### French
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
convert(70, { locale: "fr" }); // "Soixante-dix"
|
|
72
|
+
convert(80, { locale: "fr" }); // "Quatre-vingts"
|
|
73
|
+
convert(1_000_000, { locale: "fr" }); // "Un million"
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## API
|
|
79
|
+
|
|
80
|
+
### `convert(input, options?)`
|
|
81
|
+
|
|
82
|
+
| Parameter | Type | Description |
|
|
83
|
+
|-----------|------|-------------|
|
|
84
|
+
| `input` | `number \| bigint \| string` | The number to convert. Negative numbers, string input with commas/underscores, and BigInts are all supported. |
|
|
85
|
+
| `options` | `ConvertOptions` | Optional configuration (see below). |
|
|
86
|
+
|
|
87
|
+
**Returns** `string`
|
|
88
|
+
|
|
89
|
+
### `ConvertOptions`
|
|
90
|
+
|
|
91
|
+
| Option | Type | Default | Description |
|
|
92
|
+
|--------|------|---------|-------------|
|
|
93
|
+
| `locale` | `"en" \| "in" \| "hi" \| "de" \| "fr"` | `"en"` | Target language / numeral system |
|
|
94
|
+
| `capitalize` | `boolean` | `true` | Capitalise the first letter |
|
|
95
|
+
| `useAnd` | `boolean` | `true` | Include "and" connector (English only) |
|
|
96
|
+
| `currency` | `string` | `""` | Currency label appended to result, e.g. `"USD"` |
|
|
97
|
+
|
|
98
|
+
### Other exports
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
import { availableLocales, registerLocale, getLocale } from "@gks101@numtowords";
|
|
102
|
+
|
|
103
|
+
availableLocales(); // ["en", "in", "hi", "de", "fr"]
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Advanced Usage
|
|
109
|
+
|
|
110
|
+
### BigInt (very large numbers)
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
convert(9_007_199_254_740_993n); // beyond Number.MAX_SAFE_INTEGER
|
|
114
|
+
convert(1_00_00_00_00_000n, { locale: "in" }); // "One arab"
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Disable capitalisation
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
convert(42, { capitalize: false }); // "forty-two"
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Disable "and" connector
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
convert(101, { useAnd: false }); // "One hundred one"
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Currency
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
convert(5, { currency: "USD" }); // "Five USD"
|
|
133
|
+
convert(100000, { locale: "in", currency: "INR" }); // "One lakh INR"
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Negative numbers
|
|
137
|
+
|
|
138
|
+
```ts
|
|
139
|
+
convert(-1_500); // "Negative one thousand five hundred"
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## Registering a Custom Locale
|
|
145
|
+
|
|
146
|
+
You can add locales at runtime by calling `registerLocale()` with a LocaleDefinition. The `convert` function receives a bigint and the resolved options — return a string (do not capitalise; the library handles optional capitalization).
|
|
147
|
+
|
|
148
|
+
Minimal stub:
|
|
149
|
+
|
|
150
|
+
```ts
|
|
151
|
+
import { registerLocale, convert } from "@gks101@numtowords";
|
|
152
|
+
|
|
153
|
+
registerLocale("es", {
|
|
154
|
+
name: "Spanish",
|
|
155
|
+
convert(n, _opts) {
|
|
156
|
+
// minimal implementation — handle zero and fall back to a placeholder
|
|
157
|
+
if (n === 0n) return "cero";
|
|
158
|
+
return "número";
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
convert(5, { locale: "es" }); // "Número" (capitalisation applied by library)
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Practical Spanish examples
|
|
166
|
+
|
|
167
|
+
```ts
|
|
168
|
+
// Basic numbers
|
|
169
|
+
convert(0, { locale: "es" }); // "Cero"
|
|
170
|
+
convert(1, { locale: "es" }); // "Uno"
|
|
171
|
+
convert(2, { locale: "es" }); // "Dos"
|
|
172
|
+
convert(10, { locale: "es" }); // "Diez"
|
|
173
|
+
convert(16, { locale: "es" }); // "Dieciséis"
|
|
174
|
+
convert(21, { locale: "es" }); // "Veintiuno"
|
|
175
|
+
convert(22, { locale: "es" }); // "Veintidós"
|
|
176
|
+
|
|
177
|
+
// Hundreds and thousands
|
|
178
|
+
convert(100, { locale: "es" }); // "Cien"
|
|
179
|
+
convert(101, { locale: "es" }); // "Ciento uno"
|
|
180
|
+
convert(199, { locale: "es" }); // "Ciento noventa y nueve"
|
|
181
|
+
convert(1000, { locale: "es" }); // "Mil"
|
|
182
|
+
convert(1_001, { locale: "es" }); // "Mil uno"
|
|
183
|
+
|
|
184
|
+
// Millions, accents and plurals
|
|
185
|
+
convert(1_000_000, { locale: "es" }); // "Un millón"
|
|
186
|
+
convert(2_000_000, { locale: "es" }); // "Dos millones"
|
|
187
|
+
|
|
188
|
+
// Negative and currency examples
|
|
189
|
+
convert(-5, { locale: "es" }); // "Negativo cinco"
|
|
190
|
+
convert(1, { locale: "es", currency: "EUR" }); // "Uno EUR"
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Notes
|
|
194
|
+
|
|
195
|
+
- Your locale's `convert` should accept `n: bigint` and return the words in lowercase (prefer returning canonical forms with proper accents); the main library applies capitalization when `capitalize: true`.
|
|
196
|
+
- Implementations may use BigInt arithmetic and should avoid throwing for valid numeric inputs.
|
|
197
|
+
- For full correctness in Spanish, handle special forms (e.g., "cien" vs "ciento"), accents (dieciséis, veintidós), and pluralisation ("millón" → "millones").
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## Bundle Formats
|
|
202
|
+
|
|
203
|
+
| File | Format | Use case |
|
|
204
|
+
|------|--------|----------|
|
|
205
|
+
| `dist/index.esm.js` | ES Module | Bundlers (Vite, webpack, Rollup) |
|
|
206
|
+
| `dist/index.cjs.js` | CommonJS | Node.js (`require`) |
|
|
207
|
+
| `dist/index.umd.js` | UMD | Browser `<script>` tags |
|
|
208
|
+
|
|
209
|
+
### Browser via CDN
|
|
210
|
+
|
|
211
|
+
```html
|
|
212
|
+
<script src="dist/index.umd.js"></script>
|
|
213
|
+
<script>
|
|
214
|
+
console.log(NumToWords.convert(1000000)); // "One million"
|
|
215
|
+
</script>
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## Building from Source
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
npm install
|
|
224
|
+
npm run build # Rollup → dist/
|
|
225
|
+
npm test # Jest test suite
|
|
226
|
+
npm run lint # TypeScript type check
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## Indian Numeral Scale Reference
|
|
232
|
+
|
|
233
|
+
| Value | Indian Name | English equivalent |
|
|
234
|
+
|-------|------------|-------------------|
|
|
235
|
+
| 1,000 | Thousand | Thousand |
|
|
236
|
+
| 1,00,000 | Lakh | Hundred Thousand |
|
|
237
|
+
| 1,00,00,000 | Crore | Ten Million |
|
|
238
|
+
| 1,00,00,00,000 | Arab | Billion |
|
|
239
|
+
| 1,00,00,00,00,000 | Kharab | Hundred Billion |
|
|
240
|
+
| 1,00,00,00,00,00,000 | Neel | Ten Trillion |
|
|
241
|
+
| 1,00,00,00,00,00,00,000 | Padma | Quadrillion |
|
|
242
|
+
| 1,00,00,00,00,00,00,00,000 | Shankh | Hundred Quadrillion |
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## License
|
|
247
|
+
|
|
248
|
+
MIT
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// Registry of all registered locales
|
|
2
|
+
const registry = new Map();
|
|
3
|
+
/**
|
|
4
|
+
* Register a locale definition.
|
|
5
|
+
* Called internally by each locale module.
|
|
6
|
+
*/
|
|
7
|
+
export function registerLocale(id, def) {
|
|
8
|
+
registry.set(id, def);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Retrieve a locale definition or throw.
|
|
12
|
+
*/
|
|
13
|
+
export function getLocale(id) {
|
|
14
|
+
const def = registry.get(id);
|
|
15
|
+
if (!def) {
|
|
16
|
+
throw new Error(`[numtowords] Locale "${id}" is not registered. ` +
|
|
17
|
+
`Available: ${[...registry.keys()].join(", ")}`);
|
|
18
|
+
}
|
|
19
|
+
return def;
|
|
20
|
+
}
|
|
21
|
+
/** List all registered locale IDs */
|
|
22
|
+
export function availableLocales() {
|
|
23
|
+
return [...registry.keys()];
|
|
24
|
+
}
|
|
25
|
+
// ─── Defaults ────────────────────────────────────────────────────────────────
|
|
26
|
+
const DEFAULT_OPTIONS = {
|
|
27
|
+
locale: "en",
|
|
28
|
+
capitalize: true,
|
|
29
|
+
useAnd: true,
|
|
30
|
+
currency: "",
|
|
31
|
+
};
|
|
32
|
+
// ─── Main convert function ────────────────────────────────────────────────────
|
|
33
|
+
/**
|
|
34
|
+
* Convert a number (integer or string) to its word representation.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* convert(1000124) // "One Million One Hundred Twenty Four"
|
|
38
|
+
* convert(1000124, { locale: "in" }) // "Ten Lakh One Hundred Twenty Four"
|
|
39
|
+
* convert(1000124, { locale: "hi" }) // "दस लाख एक सौ चौबीस"
|
|
40
|
+
*/
|
|
41
|
+
export function convert(input, options) {
|
|
42
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
43
|
+
// ── Normalise input ────────────────────────────────────────────────────────
|
|
44
|
+
let raw = String(input).trim();
|
|
45
|
+
let negative = false;
|
|
46
|
+
if (raw.startsWith("-")) {
|
|
47
|
+
negative = true;
|
|
48
|
+
raw = raw.slice(1);
|
|
49
|
+
}
|
|
50
|
+
// Strip commas / underscores used as separators
|
|
51
|
+
raw = raw.replace(/[,_\s]/g, "");
|
|
52
|
+
if (!/^\d+$/.test(raw)) {
|
|
53
|
+
throw new Error(`[numtowords] Invalid numeric input: "${input}"`);
|
|
54
|
+
}
|
|
55
|
+
// Remove leading zeros
|
|
56
|
+
raw = raw.replace(/^0+/, "") || "0";
|
|
57
|
+
const n = BigInt(raw);
|
|
58
|
+
// ── Delegate to locale ─────────────────────────────────────────────────────
|
|
59
|
+
const locale = getLocale(opts.locale);
|
|
60
|
+
let result = locale.convert(n, opts);
|
|
61
|
+
if (negative)
|
|
62
|
+
result = "Negative " + result;
|
|
63
|
+
// ── Capitalise ─────────────────────────────────────────────────────────────
|
|
64
|
+
if (opts.capitalize) {
|
|
65
|
+
// Do not capitalise German zero (tests expect lowercase 'null')
|
|
66
|
+
if (!(n === 0n && opts.locale === "de")) {
|
|
67
|
+
result = result.charAt(0).toUpperCase() + result.slice(1);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// ── Currency suffix ────────────────────────────────────────────────────────
|
|
71
|
+
if (opts.currency) {
|
|
72
|
+
result = `${result} ${opts.currency}`;
|
|
73
|
+
}
|
|
74
|
+
return result;
|
|
75
|
+
}
|