@marcobytes/digits-to-words 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/Gemini_Generated_Image_kahs07kahs07kahs.png +0 -0
- package/README.md +78 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +29 -0
- package/dist/languages/en-SG.d.ts +1 -0
- package/dist/languages/en-SG.js +98 -0
- package/dist/languages/index.d.ts +2 -0
- package/dist/languages/index.js +18 -0
- package/dist/languages/km-KH.d.ts +1 -0
- package/dist/languages/km-KH.js +92 -0
- package/dist/test/en-SG.test.d.ts +1 -0
- package/dist/test/en-SG.test.js +35 -0
- package/dist/test/en.test.d.ts +1 -0
- package/dist/test/en.test.js +35 -0
- package/dist/test/km-KH.test.d.ts +1 -0
- package/dist/test/km-KH.test.js +31 -0
- package/dist/test/km.test.d.ts +1 -0
- package/dist/test/km.test.js +31 -0
- package/dist/types.d.ts +3 -0
- package/dist/types.js +2 -0
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +6 -0
- package/jest.config.js +6 -0
- package/package.json +33 -0
- package/src/index.ts +36 -0
- package/src/languages/en-SG.ts +101 -0
- package/src/languages/index.ts +2 -0
- package/src/languages/km-KH.ts +92 -0
- package/src/test/en-SG.test.ts +46 -0
- package/src/test/km-KH.test.ts +35 -0
- package/src/types.ts +3 -0
- package/src/utils.ts +3 -0
- package/tsconfig.json +12 -0
|
Binary file
|
package/README.md
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Convert Number to Words
|
|
2
|
+
|
|
3
|
+
Convert numbers to words easily. Currently supports **English (`en-SG`)** and **Khmer (Cambodia, `km-KH`)**.
|
|
4
|
+
|
|
5
|
+
> **Note:** Support for additional languages will be added in future releases.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install number-to-words
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { toWords } from 'number-to-words';
|
|
17
|
+
|
|
18
|
+
// English
|
|
19
|
+
console.log(toWords(181035, 'en-SG')); // "One Hundred and Eighty-One Thousand and Thirty-Five"
|
|
20
|
+
|
|
21
|
+
// Khmer
|
|
22
|
+
console.log(toWords(181035, 'km-KH')); // "មួយរយប៉ែតសិបមួយពាន់សូន្យសាមសិបប្រាំ"
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Example with Countries (Asia)
|
|
28
|
+
|
|
29
|
+
| Country | Language Code | Example: `181035` |
|
|
30
|
+
| ---------------- | ------------- | --------------------------------------------------- |
|
|
31
|
+
| Cambodia 🇰🇭 | `km-KH` | មួយរយប៉ែតសិបមួយពាន់សូន្យសាមសិបប្រាំ |
|
|
32
|
+
| Vietnam 🇻🇳 | `vi-VN` | (not supported yet) |
|
|
33
|
+
| Laos 🇱🇦 | `lo-LA` | (not supported yet) |
|
|
34
|
+
| Myanmar 🇲🇲 | `my-MM` | (not supported yet) |
|
|
35
|
+
| Malaysia 🇲🇾 | `ms-MY` | (not supported yet) |
|
|
36
|
+
| Singapore 🇸🇬 | `en-SG` | One Hundred and Eighty-One Thousand and Thirty-Five |
|
|
37
|
+
| Indonesia 🇮🇩 | `id-ID` | (not supported yet) |
|
|
38
|
+
| Philippines 🇵🇭 | `en-PH` | One Hundred and Eighty-One Thousand and Thirty-Five |
|
|
39
|
+
| Japan 🇯🇵 | `ja-JP` | (not supported yet) |
|
|
40
|
+
| South Korea 🇰🇷 | `ko-KR` | (not supported yet) |
|
|
41
|
+
| Thailand 🇹🇭 | `th-TH` | (not supported yet) |
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Example with Real Data
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
import { toWords } from 'number-to-words';
|
|
50
|
+
|
|
51
|
+
const populationCambodia = 181035; // Area in km²
|
|
52
|
+
console.log(`Area of Cambodia: ${toWords(populationCambodia, 'en-SG')} square kilometers`);
|
|
53
|
+
// "Area of Cambodia: One Hundred Eighty-One Thousand Thirty-Five square kilometers"
|
|
54
|
+
|
|
55
|
+
console.log(`ផ្ទៃដីប្រទេសកម្ពុជា: ${toWords(populationCambodia, 'km-KH')} គីឡូម៉ែត្រការេ`);
|
|
56
|
+
// "ផ្ទៃដីប្រទេសកម្ពុជា: មួយរយប៉ែតសិបមួយពាន់សូន្យសាមសិបប្រាំ គីឡូម៉ែត្រការេ"
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## API
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
toWords(number: number, lang: string): string
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
* `number` → The number you want to convert
|
|
68
|
+
* `lang` → Language code (`'en-SG'` or `'km-KH'`)
|
|
69
|
+
|
|
70
|
+
> Currently, only **English (`en-SG`)** and **Khmer (`km`)** are supported.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Contribution
|
|
75
|
+
|
|
76
|
+
Contributions are welcome! If you want to help add **more Asian languages**, feel free to submit a PR.
|
|
77
|
+
|
|
78
|
+
---
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toWords = toWords;
|
|
4
|
+
const en_SG_1 = require("./languages/en-SG");
|
|
5
|
+
const km_KH_1 = require("./languages/km-KH");
|
|
6
|
+
/**
|
|
7
|
+
* Map all localization codes to internal converters.
|
|
8
|
+
* You can easily add more later.
|
|
9
|
+
*/
|
|
10
|
+
const LANGUAGE_ROUTER = {
|
|
11
|
+
// English variants
|
|
12
|
+
"en": en_SG_1.convertNumberToEnglishWords,
|
|
13
|
+
"en-SG": en_SG_1.convertNumberToEnglishWords,
|
|
14
|
+
"en-PH": en_SG_1.convertNumberToEnglishWords,
|
|
15
|
+
// Khmer variants
|
|
16
|
+
"km": km_KH_1.convertNumberToKhmerWords,
|
|
17
|
+
"km-KH": km_KH_1.convertNumberToKhmerWords,
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Public API
|
|
21
|
+
*/
|
|
22
|
+
function toWords(number, lang = "en-SG") {
|
|
23
|
+
const key = lang.trim();
|
|
24
|
+
const converter = LANGUAGE_ROUTER[key] || LANGUAGE_ROUTER[key.toLowerCase()] || null;
|
|
25
|
+
if (!converter) {
|
|
26
|
+
throw new Error(`Language "${lang}" is not supported yet. Supported languages: ${Object.keys(LANGUAGE_ROUTER).join(", ")}`);
|
|
27
|
+
}
|
|
28
|
+
return converter(number);
|
|
29
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function convertNumberToEnglishWords(number: number | string): string;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.convertNumberToEnglishWords = convertNumberToEnglishWords;
|
|
4
|
+
function convertNumberToEnglishWords(number) {
|
|
5
|
+
const hyphen = " ";
|
|
6
|
+
const conjunction = " ";
|
|
7
|
+
const separator = " ";
|
|
8
|
+
const negative = "negative ";
|
|
9
|
+
const decimal = " point ";
|
|
10
|
+
const dictionary = {
|
|
11
|
+
0: "zero",
|
|
12
|
+
1: "one",
|
|
13
|
+
2: "two",
|
|
14
|
+
3: "three",
|
|
15
|
+
4: "four",
|
|
16
|
+
5: "five",
|
|
17
|
+
6: "six",
|
|
18
|
+
7: "seven",
|
|
19
|
+
8: "eight",
|
|
20
|
+
9: "nine",
|
|
21
|
+
10: "ten",
|
|
22
|
+
11: "eleven",
|
|
23
|
+
12: "twelve",
|
|
24
|
+
13: "thirteen",
|
|
25
|
+
14: "fourteen",
|
|
26
|
+
15: "fifteen",
|
|
27
|
+
16: "sixteen",
|
|
28
|
+
17: "seventeen",
|
|
29
|
+
18: "eighteen",
|
|
30
|
+
19: "nineteen",
|
|
31
|
+
20: "twenty",
|
|
32
|
+
30: "thirty",
|
|
33
|
+
40: "forty",
|
|
34
|
+
50: "fifty",
|
|
35
|
+
60: "sixty",
|
|
36
|
+
70: "seventy",
|
|
37
|
+
80: "eighty",
|
|
38
|
+
90: "ninety",
|
|
39
|
+
100: "hundred",
|
|
40
|
+
1000: "thousand",
|
|
41
|
+
1000000: "million",
|
|
42
|
+
1000000000: "billion",
|
|
43
|
+
1000000000000: "trillion",
|
|
44
|
+
};
|
|
45
|
+
if (typeof number === "string")
|
|
46
|
+
number = parseFloat(number);
|
|
47
|
+
if (isNaN(number))
|
|
48
|
+
return "";
|
|
49
|
+
if (number < 0)
|
|
50
|
+
return negative + convertNumberToEnglishWords(Math.abs(number));
|
|
51
|
+
let string = "";
|
|
52
|
+
let fraction = null;
|
|
53
|
+
let numberStr = number.toString();
|
|
54
|
+
if (numberStr.includes(".")) {
|
|
55
|
+
[numberStr, fraction] = numberStr.split(".");
|
|
56
|
+
number = parseInt(numberStr);
|
|
57
|
+
}
|
|
58
|
+
if (number < 21) {
|
|
59
|
+
string = dictionary[number];
|
|
60
|
+
}
|
|
61
|
+
else if (number < 100) {
|
|
62
|
+
const tens = Math.floor(number / 10) * 10;
|
|
63
|
+
const units = number % 10;
|
|
64
|
+
string = dictionary[tens];
|
|
65
|
+
if (units)
|
|
66
|
+
string += hyphen + dictionary[units];
|
|
67
|
+
}
|
|
68
|
+
else if (number < 1000) {
|
|
69
|
+
const hundreds = Math.floor(number / 100);
|
|
70
|
+
const remainder = number % 100;
|
|
71
|
+
string = dictionary[hundreds] + " " + dictionary[100];
|
|
72
|
+
if (remainder)
|
|
73
|
+
string += conjunction + convertNumberToEnglishWords(remainder);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
const baseUnit = Math.pow(1000, Math.floor(Math.log(number) / Math.log(1000)));
|
|
77
|
+
const numBaseUnits = Math.floor(number / baseUnit);
|
|
78
|
+
const remainder = number % baseUnit;
|
|
79
|
+
string =
|
|
80
|
+
convertNumberToEnglishWords(numBaseUnits) +
|
|
81
|
+
" " +
|
|
82
|
+
dictionary[baseUnit];
|
|
83
|
+
if (remainder)
|
|
84
|
+
string +=
|
|
85
|
+
remainder < 100
|
|
86
|
+
? conjunction
|
|
87
|
+
: separator + convertNumberToEnglishWords(remainder);
|
|
88
|
+
}
|
|
89
|
+
if (fraction) {
|
|
90
|
+
string +=
|
|
91
|
+
decimal +
|
|
92
|
+
fraction
|
|
93
|
+
.split("")
|
|
94
|
+
.map((d) => dictionary[parseInt(d)])
|
|
95
|
+
.join(" ");
|
|
96
|
+
}
|
|
97
|
+
return string;
|
|
98
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./km-KH"), exports);
|
|
18
|
+
__exportStar(require("./en-SG"), exports);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function convertNumberToKhmerWords(number: number | string): string;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.convertNumberToKhmerWords = convertNumberToKhmerWords;
|
|
4
|
+
function convertNumberToKhmerWords(number) {
|
|
5
|
+
const hyphen = "";
|
|
6
|
+
const conjunction = "";
|
|
7
|
+
const separator = "";
|
|
8
|
+
const negative = "negative ";
|
|
9
|
+
const decimal = "ចុច";
|
|
10
|
+
const dictionary = {
|
|
11
|
+
0: "សូន្យ",
|
|
12
|
+
1: "មួយ",
|
|
13
|
+
2: "ពីរ",
|
|
14
|
+
3: "បី",
|
|
15
|
+
4: "បួន",
|
|
16
|
+
5: "ប្រាំ",
|
|
17
|
+
6: "ប្រាំមួយ",
|
|
18
|
+
7: "ប្រាំពីរ",
|
|
19
|
+
8: "ប្រាំបី",
|
|
20
|
+
9: "ប្រាំបួន",
|
|
21
|
+
10: "ដប់",
|
|
22
|
+
11: "ដប់មួយ",
|
|
23
|
+
12: "ដប់ពីរ",
|
|
24
|
+
13: "ដប់បី",
|
|
25
|
+
14: "ដប់បួន",
|
|
26
|
+
15: "ដប់ប្រាំ",
|
|
27
|
+
16: "ដប់ប្រាំមួយ",
|
|
28
|
+
17: "ដប់ប្រាំពីរ",
|
|
29
|
+
18: "ដប់ប្រាំបី",
|
|
30
|
+
19: "ដប់ប្រាំបួន",
|
|
31
|
+
20: "ម្ភៃ",
|
|
32
|
+
30: "សាមសិប",
|
|
33
|
+
40: "សែសិប",
|
|
34
|
+
50: "ហាសិប",
|
|
35
|
+
60: "ហុកសិប",
|
|
36
|
+
70: "ចិតសិប",
|
|
37
|
+
80: "ប៉ែតសិប",
|
|
38
|
+
90: "កៅសិប",
|
|
39
|
+
100: "រយ",
|
|
40
|
+
1000: "ពាន់",
|
|
41
|
+
1000000: "លាន"
|
|
42
|
+
};
|
|
43
|
+
if (typeof number === "string")
|
|
44
|
+
number = parseFloat(number);
|
|
45
|
+
if (isNaN(number))
|
|
46
|
+
return "";
|
|
47
|
+
if (number < 0)
|
|
48
|
+
return negative + convertNumberToKhmerWords(Math.abs(number));
|
|
49
|
+
let string = "";
|
|
50
|
+
let fraction = null;
|
|
51
|
+
let numberStr = number.toString();
|
|
52
|
+
if (numberStr.includes(".")) {
|
|
53
|
+
[numberStr, fraction] = numberStr.split(".");
|
|
54
|
+
number = parseInt(numberStr);
|
|
55
|
+
}
|
|
56
|
+
if (number < 21) {
|
|
57
|
+
string = dictionary[number];
|
|
58
|
+
}
|
|
59
|
+
else if (number < 100) {
|
|
60
|
+
const tens = Math.floor(number / 10) * 10;
|
|
61
|
+
const units = number % 10;
|
|
62
|
+
string = dictionary[tens];
|
|
63
|
+
if (units)
|
|
64
|
+
string += hyphen + dictionary[units];
|
|
65
|
+
}
|
|
66
|
+
else if (number < 1000) {
|
|
67
|
+
const hundreds = Math.floor(number / 100);
|
|
68
|
+
const remainder = number % 100;
|
|
69
|
+
string = dictionary[hundreds] + dictionary[100];
|
|
70
|
+
if (remainder)
|
|
71
|
+
string += conjunction + convertNumberToKhmerWords(remainder);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
const baseUnit = Math.pow(1000, Math.floor(Math.log(number) / Math.log(1000)));
|
|
75
|
+
const numBaseUnits = Math.floor(number / baseUnit);
|
|
76
|
+
const remainder = number % baseUnit;
|
|
77
|
+
string =
|
|
78
|
+
convertNumberToKhmerWords(numBaseUnits) +
|
|
79
|
+
dictionary[baseUnit];
|
|
80
|
+
if (remainder)
|
|
81
|
+
string +=
|
|
82
|
+
remainder < 100
|
|
83
|
+
? conjunction
|
|
84
|
+
: separator + convertNumberToKhmerWords(remainder);
|
|
85
|
+
}
|
|
86
|
+
if (fraction) {
|
|
87
|
+
if (string === "")
|
|
88
|
+
string = "0";
|
|
89
|
+
string += decimal + convertNumberToKhmerWords(fraction);
|
|
90
|
+
}
|
|
91
|
+
return string;
|
|
92
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const languages_1 = require("../languages");
|
|
4
|
+
describe("Number to English Words", () => {
|
|
5
|
+
test('converts 0 to "zero"', () => {
|
|
6
|
+
expect((0, languages_1.convertNumberToEnglishWords)(0)).toBe("zero");
|
|
7
|
+
});
|
|
8
|
+
test("converts single digits", () => {
|
|
9
|
+
expect((0, languages_1.convertNumberToEnglishWords)(5)).toBe("five");
|
|
10
|
+
expect((0, languages_1.convertNumberToEnglishWords)(19)).toBe("nineteen");
|
|
11
|
+
});
|
|
12
|
+
test("converts tens correctly", () => {
|
|
13
|
+
expect((0, languages_1.convertNumberToEnglishWords)(20)).toBe("twenty");
|
|
14
|
+
expect((0, languages_1.convertNumberToEnglishWords)(42)).toBe("forty two");
|
|
15
|
+
expect((0, languages_1.convertNumberToEnglishWords)(99)).toBe("ninety nine");
|
|
16
|
+
});
|
|
17
|
+
test("converts hundreds correctly", () => {
|
|
18
|
+
expect((0, languages_1.convertNumberToEnglishWords)(100)).toBe("one hundred");
|
|
19
|
+
expect((0, languages_1.convertNumberToEnglishWords)(123)).toBe("one hundred twenty three");
|
|
20
|
+
expect((0, languages_1.convertNumberToEnglishWords)(999)).toBe("nine hundred ninety nine");
|
|
21
|
+
});
|
|
22
|
+
test("converts thousands and above", () => {
|
|
23
|
+
expect((0, languages_1.convertNumberToEnglishWords)(1000)).toBe("one thousand");
|
|
24
|
+
expect((0, languages_1.convertNumberToEnglishWords)(1234)).toBe("one thousand two hundred thirty four");
|
|
25
|
+
expect((0, languages_1.convertNumberToEnglishWords)(1000000)).toBe("one million");
|
|
26
|
+
});
|
|
27
|
+
test("converts negative numbers", () => {
|
|
28
|
+
expect((0, languages_1.convertNumberToEnglishWords)(-5)).toBe("negative five");
|
|
29
|
+
expect((0, languages_1.convertNumberToEnglishWords)(-1234)).toBe("negative one thousand two hundred thirty four");
|
|
30
|
+
});
|
|
31
|
+
test("converts decimal numbers", () => {
|
|
32
|
+
expect((0, languages_1.convertNumberToEnglishWords)(12.34)).toBe("twelve point three four");
|
|
33
|
+
expect((0, languages_1.convertNumberToEnglishWords)(-0.56)).toBe("negative zero point five six");
|
|
34
|
+
});
|
|
35
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const languages_1 = require("../languages");
|
|
4
|
+
describe("Number to English Words", () => {
|
|
5
|
+
test('converts 0 to "zero"', () => {
|
|
6
|
+
expect((0, languages_1.convertNumberToEnglishWords)(0)).toBe("zero");
|
|
7
|
+
});
|
|
8
|
+
test("converts single digits", () => {
|
|
9
|
+
expect((0, languages_1.convertNumberToEnglishWords)(5)).toBe("five");
|
|
10
|
+
expect((0, languages_1.convertNumberToEnglishWords)(19)).toBe("nineteen");
|
|
11
|
+
});
|
|
12
|
+
test("converts tens correctly", () => {
|
|
13
|
+
expect((0, languages_1.convertNumberToEnglishWords)(20)).toBe("twenty");
|
|
14
|
+
expect((0, languages_1.convertNumberToEnglishWords)(42)).toBe("forty two");
|
|
15
|
+
expect((0, languages_1.convertNumberToEnglishWords)(99)).toBe("ninety nine");
|
|
16
|
+
});
|
|
17
|
+
test("converts hundreds correctly", () => {
|
|
18
|
+
expect((0, languages_1.convertNumberToEnglishWords)(100)).toBe("one hundred");
|
|
19
|
+
expect((0, languages_1.convertNumberToEnglishWords)(123)).toBe("one hundred twenty three");
|
|
20
|
+
expect((0, languages_1.convertNumberToEnglishWords)(999)).toBe("nine hundred ninety nine");
|
|
21
|
+
});
|
|
22
|
+
test("converts thousands and above", () => {
|
|
23
|
+
expect((0, languages_1.convertNumberToEnglishWords)(1000)).toBe("one thousand");
|
|
24
|
+
expect((0, languages_1.convertNumberToEnglishWords)(1234)).toBe("one thousand two hundred thirty four");
|
|
25
|
+
expect((0, languages_1.convertNumberToEnglishWords)(1000000)).toBe("one million");
|
|
26
|
+
});
|
|
27
|
+
test("converts negative numbers", () => {
|
|
28
|
+
expect((0, languages_1.convertNumberToEnglishWords)(-5)).toBe("negative five");
|
|
29
|
+
expect((0, languages_1.convertNumberToEnglishWords)(-1234)).toBe("negative one thousand two hundred thirty four");
|
|
30
|
+
});
|
|
31
|
+
test("converts decimal numbers", () => {
|
|
32
|
+
expect((0, languages_1.convertNumberToEnglishWords)(12.34)).toBe("twelve point three four");
|
|
33
|
+
expect((0, languages_1.convertNumberToEnglishWords)(-0.56)).toBe("negative zero point five six");
|
|
34
|
+
});
|
|
35
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const languages_1 = require("../languages");
|
|
4
|
+
describe("Number to Khmer Words", () => {
|
|
5
|
+
test("converts 0 to empty string", () => {
|
|
6
|
+
expect((0, languages_1.convertNumberToKhmerWords)(0)).toBe("សូន្យ");
|
|
7
|
+
});
|
|
8
|
+
test("converts single digits", () => {
|
|
9
|
+
expect((0, languages_1.convertNumberToKhmerWords)(1)).toBe("មួយ");
|
|
10
|
+
expect((0, languages_1.convertNumberToKhmerWords)(19)).toBe("ដប់ប្រាំបួន");
|
|
11
|
+
});
|
|
12
|
+
test("converts tens correctly", () => {
|
|
13
|
+
expect((0, languages_1.convertNumberToKhmerWords)(20)).toBe("ម្ភៃ");
|
|
14
|
+
expect((0, languages_1.convertNumberToKhmerWords)(42)).toBe("សែសិបពីរ");
|
|
15
|
+
expect((0, languages_1.convertNumberToKhmerWords)(99)).toBe("កៅសិបប្រាំបួន");
|
|
16
|
+
});
|
|
17
|
+
test("converts hundreds correctly", () => {
|
|
18
|
+
expect((0, languages_1.convertNumberToKhmerWords)(100)).toBe("មួយរយ");
|
|
19
|
+
expect((0, languages_1.convertNumberToKhmerWords)(123)).toBe("មួយរយម្ភៃបី");
|
|
20
|
+
expect((0, languages_1.convertNumberToKhmerWords)(999)).toBe("ប្រាំបួនរយកៅសិបប្រាំបួន");
|
|
21
|
+
});
|
|
22
|
+
test("converts thousands and above", () => {
|
|
23
|
+
expect((0, languages_1.convertNumberToKhmerWords)(1000)).toBe("មួយពាន់");
|
|
24
|
+
expect((0, languages_1.convertNumberToKhmerWords)(1234)).toBe("មួយពាន់ពីររយសាមសិបបួន");
|
|
25
|
+
expect((0, languages_1.convertNumberToKhmerWords)(1000000)).toBe("មួយលាន");
|
|
26
|
+
});
|
|
27
|
+
test("converts decimal numbers", () => {
|
|
28
|
+
expect((0, languages_1.convertNumberToKhmerWords)(12.34)).toBe("ដប់ពីរចុចសាមសិបបួន");
|
|
29
|
+
expect((0, languages_1.convertNumberToKhmerWords)(0.56)).toBe("សូន្យចុចហាសិបប្រាំមួយ");
|
|
30
|
+
});
|
|
31
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const languages_1 = require("../languages");
|
|
4
|
+
describe("Number to Khmer Words", () => {
|
|
5
|
+
test("converts 0 to empty string", () => {
|
|
6
|
+
expect((0, languages_1.convertNumberToKhmerWords)(0)).toBe("សូន្យ");
|
|
7
|
+
});
|
|
8
|
+
test("converts single digits", () => {
|
|
9
|
+
expect((0, languages_1.convertNumberToKhmerWords)(1)).toBe("មួយ");
|
|
10
|
+
expect((0, languages_1.convertNumberToKhmerWords)(19)).toBe("ដប់ប្រាំបួន");
|
|
11
|
+
});
|
|
12
|
+
test("converts tens correctly", () => {
|
|
13
|
+
expect((0, languages_1.convertNumberToKhmerWords)(20)).toBe("ម្ភៃ");
|
|
14
|
+
expect((0, languages_1.convertNumberToKhmerWords)(42)).toBe("សែសិបពីរ");
|
|
15
|
+
expect((0, languages_1.convertNumberToKhmerWords)(99)).toBe("កៅសិបប្រាំបួន");
|
|
16
|
+
});
|
|
17
|
+
test("converts hundreds correctly", () => {
|
|
18
|
+
expect((0, languages_1.convertNumberToKhmerWords)(100)).toBe("មួយរយ");
|
|
19
|
+
expect((0, languages_1.convertNumberToKhmerWords)(123)).toBe("មួយរយម្ភៃបី");
|
|
20
|
+
expect((0, languages_1.convertNumberToKhmerWords)(999)).toBe("ប្រាំបួនរយកៅសិបប្រាំបួន");
|
|
21
|
+
});
|
|
22
|
+
test("converts thousands and above", () => {
|
|
23
|
+
expect((0, languages_1.convertNumberToKhmerWords)(1000)).toBe("មួយពាន់");
|
|
24
|
+
expect((0, languages_1.convertNumberToKhmerWords)(1234)).toBe("មួយពាន់ពីររយសាមសិបបួន");
|
|
25
|
+
expect((0, languages_1.convertNumberToKhmerWords)(1000000)).toBe("មួយលាន");
|
|
26
|
+
});
|
|
27
|
+
test("converts decimal numbers", () => {
|
|
28
|
+
expect((0, languages_1.convertNumberToKhmerWords)(12.34)).toBe("ដប់ពីរចុចសាមសិបបួន");
|
|
29
|
+
expect((0, languages_1.convertNumberToKhmerWords)(0.56)).toBe("សូន្យចុចហាសិបប្រាំមួយ");
|
|
30
|
+
});
|
|
31
|
+
});
|
package/dist/types.d.ts
ADDED
package/dist/types.js
ADDED
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function splitNumber(number: number): number[];
|
package/dist/utils.js
ADDED
package/jest.config.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@marcobytes/digits-to-words",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Convert numbers to words in multiple languages (Khmer, English, etc.)",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"test": "jest",
|
|
10
|
+
"test:watch": "jest --watch",
|
|
11
|
+
"prepare": "npm run build"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"numbers",
|
|
15
|
+
"words",
|
|
16
|
+
"english",
|
|
17
|
+
"khmer",
|
|
18
|
+
"cambodia",
|
|
19
|
+
"convert",
|
|
20
|
+
"multi-language"
|
|
21
|
+
],
|
|
22
|
+
"author": "Marco Bytes",
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@babel/core": "^7.28.5",
|
|
26
|
+
"@babel/preset-env": "^7.28.5",
|
|
27
|
+
"@types/jest": "^30.0.0",
|
|
28
|
+
"babel-jest": "^30.2.0",
|
|
29
|
+
"jest": "^30.2.0",
|
|
30
|
+
"ts-jest": "^29.4.6",
|
|
31
|
+
"typescript": "^5.9.3"
|
|
32
|
+
}
|
|
33
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { convertNumberToEnglishWords } from "./languages/en-SG";
|
|
2
|
+
import { convertNumberToKhmerWords } from "./languages/km-KH";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Map all localization codes to internal converters.
|
|
6
|
+
* You can easily add more later.
|
|
7
|
+
*/
|
|
8
|
+
const LANGUAGE_ROUTER: Record<string, (n: number) => string> = {
|
|
9
|
+
// English variants
|
|
10
|
+
"en": convertNumberToEnglishWords,
|
|
11
|
+
"en-SG": convertNumberToEnglishWords,
|
|
12
|
+
"en-PH": convertNumberToEnglishWords,
|
|
13
|
+
|
|
14
|
+
// Khmer variants
|
|
15
|
+
"km": convertNumberToKhmerWords,
|
|
16
|
+
"km-KH": convertNumberToKhmerWords,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Public API
|
|
21
|
+
*/
|
|
22
|
+
export function toWords(number: number, lang: string = "en-SG"): string {
|
|
23
|
+
const key = lang.trim();
|
|
24
|
+
|
|
25
|
+
const converter = LANGUAGE_ROUTER[key] || LANGUAGE_ROUTER[key.toLowerCase()] || null;
|
|
26
|
+
|
|
27
|
+
if (!converter) {
|
|
28
|
+
throw new Error(
|
|
29
|
+
`Language "${lang}" is not supported yet. Supported languages: ${Object.keys(
|
|
30
|
+
LANGUAGE_ROUTER
|
|
31
|
+
).join(", ")}`
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return converter(number);
|
|
36
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
export function convertNumberToEnglishWords(number: number | string): string {
|
|
2
|
+
const hyphen = " ";
|
|
3
|
+
const conjunction = " ";
|
|
4
|
+
const separator = " ";
|
|
5
|
+
const negative = "negative ";
|
|
6
|
+
const decimal = " point ";
|
|
7
|
+
|
|
8
|
+
const dictionary: Record<number, string> = {
|
|
9
|
+
0: "zero",
|
|
10
|
+
1: "one",
|
|
11
|
+
2: "two",
|
|
12
|
+
3: "three",
|
|
13
|
+
4: "four",
|
|
14
|
+
5: "five",
|
|
15
|
+
6: "six",
|
|
16
|
+
7: "seven",
|
|
17
|
+
8: "eight",
|
|
18
|
+
9: "nine",
|
|
19
|
+
10: "ten",
|
|
20
|
+
11: "eleven",
|
|
21
|
+
12: "twelve",
|
|
22
|
+
13: "thirteen",
|
|
23
|
+
14: "fourteen",
|
|
24
|
+
15: "fifteen",
|
|
25
|
+
16: "sixteen",
|
|
26
|
+
17: "seventeen",
|
|
27
|
+
18: "eighteen",
|
|
28
|
+
19: "nineteen",
|
|
29
|
+
20: "twenty",
|
|
30
|
+
30: "thirty",
|
|
31
|
+
40: "forty",
|
|
32
|
+
50: "fifty",
|
|
33
|
+
60: "sixty",
|
|
34
|
+
70: "seventy",
|
|
35
|
+
80: "eighty",
|
|
36
|
+
90: "ninety",
|
|
37
|
+
100: "hundred",
|
|
38
|
+
1000: "thousand",
|
|
39
|
+
1_000_000: "million",
|
|
40
|
+
1_000_000_000: "billion",
|
|
41
|
+
1_000_000_000_000: "trillion",
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
if (typeof number === "string") number = parseFloat(number);
|
|
45
|
+
|
|
46
|
+
if (isNaN(number)) return "";
|
|
47
|
+
|
|
48
|
+
if (number < 0)
|
|
49
|
+
return negative + convertNumberToEnglishWords(Math.abs(number));
|
|
50
|
+
|
|
51
|
+
let string = "";
|
|
52
|
+
let fraction: string | null = null;
|
|
53
|
+
|
|
54
|
+
let numberStr = number.toString();
|
|
55
|
+
if (numberStr.includes(".")) {
|
|
56
|
+
[numberStr, fraction] = numberStr.split(".");
|
|
57
|
+
number = parseInt(numberStr);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (number < 21) {
|
|
61
|
+
string = dictionary[number]!;
|
|
62
|
+
} else if (number < 100) {
|
|
63
|
+
const tens = Math.floor(number / 10) * 10;
|
|
64
|
+
const units = number % 10;
|
|
65
|
+
string = dictionary[tens]!;
|
|
66
|
+
if (units) string += hyphen + dictionary[units];
|
|
67
|
+
} else if (number < 1000) {
|
|
68
|
+
const hundreds = Math.floor(number / 100);
|
|
69
|
+
const remainder = number % 100;
|
|
70
|
+
string = dictionary[hundreds]! + " " + dictionary[100];
|
|
71
|
+
if (remainder)
|
|
72
|
+
string += conjunction + convertNumberToEnglishWords(remainder);
|
|
73
|
+
} else {
|
|
74
|
+
const baseUnit = Math.pow(
|
|
75
|
+
1000,
|
|
76
|
+
Math.floor(Math.log(number) / Math.log(1000))
|
|
77
|
+
);
|
|
78
|
+
const numBaseUnits = Math.floor(number / baseUnit);
|
|
79
|
+
const remainder = number % baseUnit;
|
|
80
|
+
string =
|
|
81
|
+
convertNumberToEnglishWords(numBaseUnits) +
|
|
82
|
+
" " +
|
|
83
|
+
dictionary[baseUnit as keyof typeof dictionary];
|
|
84
|
+
if (remainder)
|
|
85
|
+
string +=
|
|
86
|
+
remainder < 100
|
|
87
|
+
? conjunction
|
|
88
|
+
: separator + convertNumberToEnglishWords(remainder);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (fraction) {
|
|
92
|
+
string +=
|
|
93
|
+
decimal +
|
|
94
|
+
fraction
|
|
95
|
+
.split("")
|
|
96
|
+
.map((d) => dictionary[parseInt(d)])
|
|
97
|
+
.join(" ");
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return string;
|
|
101
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
export function convertNumberToKhmerWords(number: number | string): string {
|
|
2
|
+
const hyphen = "";
|
|
3
|
+
const conjunction = "";
|
|
4
|
+
const separator = "";
|
|
5
|
+
const negative = "negative ";
|
|
6
|
+
const decimal = "ចុច";
|
|
7
|
+
|
|
8
|
+
const dictionary: Record<number, string> = {
|
|
9
|
+
0: "សូន្យ",
|
|
10
|
+
1: "មួយ",
|
|
11
|
+
2: "ពីរ",
|
|
12
|
+
3: "បី",
|
|
13
|
+
4: "បួន",
|
|
14
|
+
5: "ប្រាំ",
|
|
15
|
+
6: "ប្រាំមួយ",
|
|
16
|
+
7: "ប្រាំពីរ",
|
|
17
|
+
8: "ប្រាំបី",
|
|
18
|
+
9: "ប្រាំបួន",
|
|
19
|
+
10: "ដប់",
|
|
20
|
+
11: "ដប់មួយ",
|
|
21
|
+
12: "ដប់ពីរ",
|
|
22
|
+
13: "ដប់បី",
|
|
23
|
+
14: "ដប់បួន",
|
|
24
|
+
15: "ដប់ប្រាំ",
|
|
25
|
+
16: "ដប់ប្រាំមួយ",
|
|
26
|
+
17: "ដប់ប្រាំពីរ",
|
|
27
|
+
18: "ដប់ប្រាំបី",
|
|
28
|
+
19: "ដប់ប្រាំបួន",
|
|
29
|
+
20: "ម្ភៃ",
|
|
30
|
+
30: "សាមសិប",
|
|
31
|
+
40: "សែសិប",
|
|
32
|
+
50: "ហាសិប",
|
|
33
|
+
60: "ហុកសិប",
|
|
34
|
+
70: "ចិតសិប",
|
|
35
|
+
80: "ប៉ែតសិប",
|
|
36
|
+
90: "កៅសិប",
|
|
37
|
+
100: "រយ",
|
|
38
|
+
1000: "ពាន់",
|
|
39
|
+
1_000_000: "លាន"
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
if (typeof number === "string") number = parseFloat(number);
|
|
43
|
+
|
|
44
|
+
if (isNaN(number)) return "";
|
|
45
|
+
|
|
46
|
+
if (number < 0) return negative + convertNumberToKhmerWords(Math.abs(number));
|
|
47
|
+
|
|
48
|
+
let string = "";
|
|
49
|
+
let fraction: string | null = null;
|
|
50
|
+
|
|
51
|
+
let numberStr = number.toString();
|
|
52
|
+
if (numberStr.includes(".")) {
|
|
53
|
+
[numberStr, fraction] = numberStr.split(".");
|
|
54
|
+
number = parseInt(numberStr);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (number < 21) {
|
|
58
|
+
string = dictionary[number]!;
|
|
59
|
+
} else if (number < 100) {
|
|
60
|
+
const tens = Math.floor(number / 10) * 10;
|
|
61
|
+
const units = number % 10;
|
|
62
|
+
string = dictionary[tens]!;
|
|
63
|
+
if (units) string += hyphen + dictionary[units];
|
|
64
|
+
} else if (number < 1000) {
|
|
65
|
+
const hundreds = Math.floor(number / 100);
|
|
66
|
+
const remainder = number % 100;
|
|
67
|
+
string = dictionary[hundreds]! + dictionary[100];
|
|
68
|
+
if (remainder) string += conjunction + convertNumberToKhmerWords(remainder);
|
|
69
|
+
} else {
|
|
70
|
+
const baseUnit = Math.pow(
|
|
71
|
+
1000,
|
|
72
|
+
Math.floor(Math.log(number) / Math.log(1000))
|
|
73
|
+
);
|
|
74
|
+
const numBaseUnits = Math.floor(number / baseUnit);
|
|
75
|
+
const remainder = number % baseUnit;
|
|
76
|
+
string =
|
|
77
|
+
convertNumberToKhmerWords(numBaseUnits) +
|
|
78
|
+
dictionary[baseUnit as keyof typeof dictionary];
|
|
79
|
+
if (remainder)
|
|
80
|
+
string +=
|
|
81
|
+
remainder < 100
|
|
82
|
+
? conjunction
|
|
83
|
+
: separator + convertNumberToKhmerWords(remainder);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (fraction) {
|
|
87
|
+
if (string === "") string = "0";
|
|
88
|
+
string += decimal + convertNumberToKhmerWords(fraction);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return string;
|
|
92
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { convertNumberToEnglishWords } from "../languages";
|
|
2
|
+
|
|
3
|
+
describe("Number to English Words", () => {
|
|
4
|
+
test('converts 0 to "zero"', () => {
|
|
5
|
+
expect(convertNumberToEnglishWords(0)).toBe("zero");
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
test("converts single digits", () => {
|
|
9
|
+
expect(convertNumberToEnglishWords(5)).toBe("five");
|
|
10
|
+
expect(convertNumberToEnglishWords(19)).toBe("nineteen");
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
test("converts tens correctly", () => {
|
|
14
|
+
expect(convertNumberToEnglishWords(20)).toBe("twenty");
|
|
15
|
+
expect(convertNumberToEnglishWords(42)).toBe("forty two");
|
|
16
|
+
expect(convertNumberToEnglishWords(99)).toBe("ninety nine");
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test("converts hundreds correctly", () => {
|
|
20
|
+
expect(convertNumberToEnglishWords(100)).toBe("one hundred");
|
|
21
|
+
expect(convertNumberToEnglishWords(123)).toBe("one hundred twenty three");
|
|
22
|
+
expect(convertNumberToEnglishWords(999)).toBe("nine hundred ninety nine");
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test("converts thousands and above", () => {
|
|
26
|
+
expect(convertNumberToEnglishWords(1000)).toBe("one thousand");
|
|
27
|
+
expect(convertNumberToEnglishWords(1234)).toBe(
|
|
28
|
+
"one thousand two hundred thirty four"
|
|
29
|
+
);
|
|
30
|
+
expect(convertNumberToEnglishWords(1_000_000)).toBe("one million");
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test("converts negative numbers", () => {
|
|
34
|
+
expect(convertNumberToEnglishWords(-5)).toBe("negative five");
|
|
35
|
+
expect(convertNumberToEnglishWords(-1234)).toBe(
|
|
36
|
+
"negative one thousand two hundred thirty four"
|
|
37
|
+
);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test("converts decimal numbers", () => {
|
|
41
|
+
expect(convertNumberToEnglishWords(12.34)).toBe("twelve point three four");
|
|
42
|
+
expect(convertNumberToEnglishWords(-0.56)).toBe(
|
|
43
|
+
"negative zero point five six"
|
|
44
|
+
);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { convertNumberToKhmerWords } from "../languages";
|
|
2
|
+
|
|
3
|
+
describe("Number to Khmer Words", () => {
|
|
4
|
+
test("converts 0 to empty string", () => {
|
|
5
|
+
expect(convertNumberToKhmerWords(0)).toBe("សូន្យ");
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
test("converts single digits", () => {
|
|
9
|
+
expect(convertNumberToKhmerWords(1)).toBe("មួយ");
|
|
10
|
+
expect(convertNumberToKhmerWords(19)).toBe("ដប់ប្រាំបួន");
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
test("converts tens correctly", () => {
|
|
14
|
+
expect(convertNumberToKhmerWords(20)).toBe("ម្ភៃ");
|
|
15
|
+
expect(convertNumberToKhmerWords(42)).toBe("សែសិបពីរ");
|
|
16
|
+
expect(convertNumberToKhmerWords(99)).toBe("កៅសិបប្រាំបួន");
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test("converts hundreds correctly", () => {
|
|
20
|
+
expect(convertNumberToKhmerWords(100)).toBe("មួយរយ");
|
|
21
|
+
expect(convertNumberToKhmerWords(123)).toBe("មួយរយម្ភៃបី");
|
|
22
|
+
expect(convertNumberToKhmerWords(999)).toBe("ប្រាំបួនរយកៅសិបប្រាំបួន");
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test("converts thousands and above", () => {
|
|
26
|
+
expect(convertNumberToKhmerWords(1000)).toBe("មួយពាន់");
|
|
27
|
+
expect(convertNumberToKhmerWords(1234)).toBe("មួយពាន់ពីររយសាមសិបបួន");
|
|
28
|
+
expect(convertNumberToKhmerWords(1_000_000)).toBe("មួយលាន");
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test("converts decimal numbers", () => {
|
|
32
|
+
expect(convertNumberToKhmerWords(12.34)).toBe("ដប់ពីរចុចសាមសិបបួន");
|
|
33
|
+
expect(convertNumberToKhmerWords(0.56)).toBe("សូន្យចុចហាសិបប្រាំមួយ");
|
|
34
|
+
});
|
|
35
|
+
});
|
package/src/types.ts
ADDED
package/src/utils.ts
ADDED