n2words 1.13.0 → 1.15.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/.eslintrc.json +2 -2
- package/README.md +1 -1
- package/bench.mjs +94 -0
- package/dist/n2words.js +1 -1
- package/examples/node.mjs +10 -0
- package/lib/classes/AbstractLanguage.mjs +151 -0
- package/lib/classes/BaseLanguage.mjs +174 -0
- package/lib/i18n/AR.mjs +62 -38
- package/lib/i18n/AZ.mjs +44 -38
- package/lib/i18n/CZ.mjs +79 -69
- package/lib/i18n/DE.mjs +56 -50
- package/lib/i18n/DK.mjs +62 -50
- package/lib/i18n/EN.mjs +66 -54
- package/lib/i18n/ES.mjs +67 -55
- package/lib/i18n/FA.mjs +75 -63
- package/lib/i18n/FR.mjs +54 -48
- package/lib/i18n/HE.mjs +81 -23
- package/lib/i18n/HR.mjs +81 -70
- package/lib/i18n/HU.mjs +82 -76
- package/lib/i18n/ID.mjs +55 -46
- package/lib/i18n/IT.mjs +39 -27
- package/lib/i18n/KO.mjs +38 -32
- package/lib/i18n/LT.mjs +79 -67
- package/lib/i18n/LV.mjs +69 -57
- package/lib/i18n/NL.mjs +70 -60
- package/lib/i18n/NO.mjs +58 -52
- package/lib/i18n/PL.mjs +78 -67
- package/lib/i18n/PT.mjs +63 -56
- package/lib/i18n/RU.mjs +159 -122
- package/lib/i18n/SR.mjs +81 -70
- package/lib/i18n/TR.mjs +45 -43
- package/lib/i18n/UK.mjs +87 -75
- package/lib/i18n/VI.mjs +89 -79
- package/lib/i18n/ZH.mjs +40 -33
- package/lib/n2words.mjs +33 -107
- package/package.json +17 -11
- package/webpack.config.js +1 -1
- package/lib/classes/N2WordsAbs.mjs +0 -72
- package/lib/classes/N2WordsBase.mjs +0 -105
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/* eslint-disable import/no-nodejs-modules */
|
|
2
|
+
import n2words from '../lib/i18n/EN.mjs';
|
|
3
|
+
import * as readline from 'node:readline/promises';
|
|
4
|
+
import {stdin as input, stdout as output} from 'node:process';
|
|
5
|
+
|
|
6
|
+
const rl = readline.createInterface({input, output});
|
|
7
|
+
|
|
8
|
+
console.log(n2words(await rl.question('Value to convert? ')));
|
|
9
|
+
|
|
10
|
+
rl.close();
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates new language class that processes decimals separately.
|
|
3
|
+
* Requires implementing `toCardinal`.
|
|
4
|
+
*/
|
|
5
|
+
export default class {
|
|
6
|
+
#negativeWord;
|
|
7
|
+
#separatorWord;
|
|
8
|
+
#zero;
|
|
9
|
+
#spaceSeparator;
|
|
10
|
+
#wholeNumber;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @param {object} options Options for class.
|
|
14
|
+
* @param {string} [options.negativeWord = ''] Word that precedes a negative number (if any).
|
|
15
|
+
* @param {string} options.separatorWord Word that separates cardinal numbers (i.e. "and").
|
|
16
|
+
* @param {string} options.zero Word for 0 (i.e. "zero").
|
|
17
|
+
* @param {string} [options.spaceSeparator = ' '] Character that separates words.
|
|
18
|
+
*/
|
|
19
|
+
constructor(options) {
|
|
20
|
+
// Merge supplied options with defaults
|
|
21
|
+
options = Object.assign({
|
|
22
|
+
negativeWord: '',
|
|
23
|
+
separatorWord: undefined,
|
|
24
|
+
zeroWord: undefined,
|
|
25
|
+
spaceSeparator: ' '
|
|
26
|
+
}, options);
|
|
27
|
+
|
|
28
|
+
// Make options available to class
|
|
29
|
+
this.#negativeWord = options.negativeWord;
|
|
30
|
+
this.#separatorWord = options.separatorWord;
|
|
31
|
+
this.#zero = options.zero;
|
|
32
|
+
this.#spaceSeparator = options.spaceSeparator;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @returns {string} Word that precedes a negative number (if any).
|
|
37
|
+
*/
|
|
38
|
+
get negativeWord() {
|
|
39
|
+
return this.#negativeWord;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @returns {string} Word that separates cardinal numbers (i.e. "and").
|
|
44
|
+
*/
|
|
45
|
+
get separatorWord() {
|
|
46
|
+
return this.#separatorWord;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @returns {string} Word for 0 (i.e. "zero").
|
|
51
|
+
*/
|
|
52
|
+
get zero() {
|
|
53
|
+
return this.#zero;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* @returns {string} Character that separates words.
|
|
58
|
+
*/
|
|
59
|
+
get spaceSeparator() {
|
|
60
|
+
return this.#spaceSeparator;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @returns {number} Input value without decimal.
|
|
65
|
+
*/
|
|
66
|
+
get wholeNumber() {
|
|
67
|
+
return this.#wholeNumber;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Convert decimal number to a string array of cardinal numbers.
|
|
72
|
+
* @param {number} decimal Decimal number to convert.
|
|
73
|
+
* @returns {string} Value in written format.
|
|
74
|
+
*/
|
|
75
|
+
decimalToCardinal(decimal) {
|
|
76
|
+
const words = [];
|
|
77
|
+
|
|
78
|
+
// Split decimal portion into an array of characters in reverse
|
|
79
|
+
const chars = decimal.split('').reverse();
|
|
80
|
+
|
|
81
|
+
// Loop through array (from the end) adding words to output array
|
|
82
|
+
while (chars.pop() == '0') {
|
|
83
|
+
words.push(this.zero);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Add decimal number to word array
|
|
87
|
+
return words.concat(this.toCardinal(BigInt(decimal)));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Converts a number to written form.
|
|
92
|
+
* @param {number|string} value Number to be convert.
|
|
93
|
+
* @throws {Error} Value must be a valid number.
|
|
94
|
+
* @returns {string} Value in written format.
|
|
95
|
+
*/
|
|
96
|
+
floatToCardinal(value) {
|
|
97
|
+
// Validate user input value
|
|
98
|
+
if (typeof value == 'number') {
|
|
99
|
+
if (Number.isNaN(value)) {
|
|
100
|
+
throw new Error('NaN is not an accepted number.');
|
|
101
|
+
}
|
|
102
|
+
value = value.toString();
|
|
103
|
+
} else if (typeof value == 'string') {
|
|
104
|
+
value = value.trim();
|
|
105
|
+
if (value.length == 0 || Number.isNaN(Number(value))) {
|
|
106
|
+
throw new Error('"' + value + '" is not a valid number.');
|
|
107
|
+
}
|
|
108
|
+
} else if (typeof value != 'bigint') {
|
|
109
|
+
throw new TypeError('Invalid variable type: ' + typeof value);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
let words = [];
|
|
113
|
+
let wholeNumber;
|
|
114
|
+
let decimalNumber;
|
|
115
|
+
|
|
116
|
+
// If negative number add negative word
|
|
117
|
+
if (value < 0) {
|
|
118
|
+
words.push(this.negativeWord);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Split value decimal (if any) (excluding BigInt)
|
|
122
|
+
if (typeof value == 'bigint') {
|
|
123
|
+
wholeNumber = value;
|
|
124
|
+
} else {
|
|
125
|
+
const splitValue = value.split('.');
|
|
126
|
+
wholeNumber = BigInt(splitValue[0]);
|
|
127
|
+
decimalNumber = splitValue[1];
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Convert whole number to positive (if negative)
|
|
131
|
+
if (wholeNumber < 0) {
|
|
132
|
+
wholeNumber = -wholeNumber;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// NOTE: Only needed for CZ
|
|
136
|
+
this.#wholeNumber = wholeNumber;
|
|
137
|
+
|
|
138
|
+
// Add whole number in written form
|
|
139
|
+
words = words.concat(this.toCardinal(wholeNumber));
|
|
140
|
+
|
|
141
|
+
// Add decimal number in written form (if any)
|
|
142
|
+
if (decimalNumber) {
|
|
143
|
+
words.push(this.separatorWord);
|
|
144
|
+
|
|
145
|
+
words = words.concat(this.decimalToCardinal(decimalNumber));
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Join words with spaces
|
|
149
|
+
return words.join(this.spaceSeparator);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import AbstractLanguage from './AbstractLanguage.mjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Creates new common language class that uses a highest matching word value algorithm.
|
|
5
|
+
* Number matching word {@link cards} must be provided for this to work.
|
|
6
|
+
* See {@link AbstractLanguage} for further requirements.
|
|
7
|
+
* @classdesc Common class for (mostly european) languages.
|
|
8
|
+
*/
|
|
9
|
+
export default class extends AbstractLanguage {
|
|
10
|
+
#cards;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @param {object} options Options for class.
|
|
14
|
+
* @param {string} [options.negativeWord = ''] Word that precedes a negative number (if any).
|
|
15
|
+
* @param {string} options.separatorWord Word that separates cardinal numbers (i.e. "and").
|
|
16
|
+
* @param {string} options.zero Word for 0 (i.e. "zero").
|
|
17
|
+
* @param {string} [options.spaceSeparator = ' '] Character that separates words.
|
|
18
|
+
* @param {Array} cards Array of number matching "cards" from highest-to-lowest.
|
|
19
|
+
*/
|
|
20
|
+
constructor(options, cards) {
|
|
21
|
+
super(options);
|
|
22
|
+
|
|
23
|
+
this.#cards = cards;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Get array of number matching "cards" from highest-to-lowest.
|
|
28
|
+
* First element in card array is the number to match while the second is the word to use.
|
|
29
|
+
* @example
|
|
30
|
+
* [
|
|
31
|
+
* ...
|
|
32
|
+
* [100, 'hundred'],
|
|
33
|
+
* ...
|
|
34
|
+
* [1, 'one'],
|
|
35
|
+
* ]
|
|
36
|
+
* @returns {Array} Array of number matching "cards" from highest-to-lowest.
|
|
37
|
+
*/
|
|
38
|
+
get cards() {
|
|
39
|
+
return this.#cards;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Get word for number if it matches a language card.
|
|
44
|
+
* @param {number} number Card number value.
|
|
45
|
+
* @returns {string|undefined} Return card word or undefined if no card.
|
|
46
|
+
*/
|
|
47
|
+
getCardWord(number) {
|
|
48
|
+
// Get matching card from number
|
|
49
|
+
const card = this.cards.find(_card => _card[0] == number);
|
|
50
|
+
|
|
51
|
+
// Return card word or undefined if no card found
|
|
52
|
+
return (Array.isArray(card) ? card[1] : undefined);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Get array of card matches.
|
|
57
|
+
* @param {number} value The number value to convert to cardinal form.
|
|
58
|
+
* @returns {object} Word sets (and pairs) from value.
|
|
59
|
+
* @todo Simplify return object.
|
|
60
|
+
*/
|
|
61
|
+
toCardMatches(value) {
|
|
62
|
+
const out = [];
|
|
63
|
+
let remaining = value;
|
|
64
|
+
|
|
65
|
+
do {
|
|
66
|
+
// Find card with highest matching number
|
|
67
|
+
const card = this.cards.find(card => {
|
|
68
|
+
return remaining >= card[0];
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
let quantity; // Quantity of card set values
|
|
72
|
+
|
|
73
|
+
// Calculate quantity and remaining value
|
|
74
|
+
// Override variables for 0 as math will fail
|
|
75
|
+
if (remaining == 0) {
|
|
76
|
+
quantity = 1;
|
|
77
|
+
remaining = 0;
|
|
78
|
+
} else {
|
|
79
|
+
quantity = remaining / card[0];
|
|
80
|
+
remaining = remaining % card[0];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Is value perfect match of card number?
|
|
84
|
+
if (quantity == 1) {
|
|
85
|
+
/** @todo Merge word set pairs together (if possible) to simplify return object */
|
|
86
|
+
out.push({
|
|
87
|
+
[this.getCardWord(1)]: 1,
|
|
88
|
+
});
|
|
89
|
+
} else {
|
|
90
|
+
/** @todo Understand the logic for this */
|
|
91
|
+
/*if (quantity == remaining) {
|
|
92
|
+
return [(quantity * this.getCardWord(card[0]), quantity * card[0])];
|
|
93
|
+
}*/
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* @todo Remove reciprocating calls.
|
|
97
|
+
*/
|
|
98
|
+
out.push(this.toCardMatches(quantity));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Add matching word set to output list
|
|
102
|
+
out.push({
|
|
103
|
+
[card[1]]: card[0],
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
while (remaining > 0);
|
|
107
|
+
|
|
108
|
+
return out;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
scanNum(value) {
|
|
112
|
+
return value.split('').map(v => this.getCardWord(Number(v)));
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
clean(words) {
|
|
116
|
+
let out = words;
|
|
117
|
+
|
|
118
|
+
// Loop through word sets while array size is greater or less than 1
|
|
119
|
+
/** @todo Change logic to work in for loop to better understand loop intentions */
|
|
120
|
+
while (words.length != 1) {
|
|
121
|
+
out = [];
|
|
122
|
+
const left = words[0];
|
|
123
|
+
const right = words[1];
|
|
124
|
+
|
|
125
|
+
// Are the first & second word sets arrays?
|
|
126
|
+
if (!Array.isArray(left) && !Array.isArray(right)) {
|
|
127
|
+
// Merge word set pair and add to output array
|
|
128
|
+
out.push(this.merge(left, right));
|
|
129
|
+
|
|
130
|
+
/** @todo Understand */
|
|
131
|
+
if (words.slice(2).length > 0) {
|
|
132
|
+
out.push(words.slice(2));
|
|
133
|
+
}
|
|
134
|
+
} else {
|
|
135
|
+
// Loop through
|
|
136
|
+
for (let i = 0; i < words.length; i++) {
|
|
137
|
+
const elem = words[i];
|
|
138
|
+
|
|
139
|
+
if (Array.isArray(elem)) {
|
|
140
|
+
if (elem.length == 1) out.push(elem[0]);
|
|
141
|
+
else out.push(this.clean(elem));
|
|
142
|
+
} else {
|
|
143
|
+
out.push(elem);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
words = out;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return out[0];
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
postClean(out0) {
|
|
155
|
+
return out0.trimRight();
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Convert a whole number to written format.
|
|
160
|
+
* @param {number} value The number value to convert to cardinal form.
|
|
161
|
+
* @returns {string} Value in written format.
|
|
162
|
+
*/
|
|
163
|
+
toCardinal(value) {
|
|
164
|
+
// Convert value to word sets
|
|
165
|
+
const words = this.toCardMatches(value);
|
|
166
|
+
|
|
167
|
+
// Process word sets
|
|
168
|
+
const preWords = Object.keys(this.clean(words))[0];
|
|
169
|
+
|
|
170
|
+
// Process word sets some more and return result
|
|
171
|
+
/** @todo Look into language functions/events */
|
|
172
|
+
return this.postClean(preWords);
|
|
173
|
+
}
|
|
174
|
+
}
|
package/lib/i18n/AR.mjs
CHANGED
|
@@ -1,38 +1,52 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
export class
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
1
|
+
import AbstractLanguage from '../classes/AbstractLanguage.mjs';
|
|
2
|
+
|
|
3
|
+
export class Arabic extends AbstractLanguage {
|
|
4
|
+
integerValue = 0;
|
|
5
|
+
|
|
6
|
+
decimalValue = 0;
|
|
7
|
+
|
|
8
|
+
number = 0;
|
|
9
|
+
|
|
10
|
+
arabicOnes = [
|
|
11
|
+
'', 'واحد', 'اثنان', 'ثلاثة', 'أربعة', 'خمسة', 'ستة', 'سبعة', 'ثمانية',
|
|
12
|
+
'تسعة',
|
|
13
|
+
'عشرة', 'أحد عشر', 'اثنا عشر', 'ثلاثة عشر', 'أربعة عشر', 'خمسة عشر',
|
|
14
|
+
'ستة عشر', 'سبعة عشر', 'ثمانية عشر',
|
|
15
|
+
'تسعة عشر',
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
arabicFeminineOnes = [
|
|
19
|
+
'', 'إحدى', 'اثنتان', 'ثلاث', 'أربع', 'خمس', 'ست', 'سبع', 'ثمان',
|
|
20
|
+
'تسع',
|
|
21
|
+
'عشر', 'إحدى عشرة', 'اثنتا عشرة', 'ثلاث عشرة', 'أربع عشرة',
|
|
22
|
+
'خمس عشرة', 'ست عشرة', 'سبع عشرة', 'ثماني عشرة',
|
|
23
|
+
'تسع عشرة',
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
arabicTens = ['عشرون', 'ثلاثون', 'أربعون', 'خمسون', 'ستون', 'سبعون', 'ثمانون', 'تسعون'];
|
|
27
|
+
|
|
28
|
+
arabicHundreds = ['', 'مائة', 'مئتان', 'ثلاثمائة', 'أربعمائة', 'خمسمائة', 'ستمائة', 'سبعمائة', 'ثمانمائة', 'تسعمائة'];
|
|
29
|
+
|
|
30
|
+
arabicAppendedTwos = ['مئتا', 'ألفا', 'مليونا', 'مليارا', 'تريليونا', 'كوادريليونا', 'كوينتليونا', 'سكستيليونا'];
|
|
31
|
+
|
|
32
|
+
arabicTwos = ['مئتان', 'ألفان', 'مليونان', 'ملياران', 'تريليونان', 'كوادريليونان', 'كوينتليونان', 'سكستيليونان'];
|
|
33
|
+
|
|
34
|
+
arabicGroup = ['مائة', 'ألف', 'مليون', 'مليار', 'تريليون', 'كوادريليون', 'كوينتليون', 'سكستيليون'];
|
|
35
|
+
|
|
36
|
+
arabicAppendedGroup = ['', 'ألفاً', 'مليوناً', 'ملياراً', 'تريليوناً', 'كوادريليوناً', 'كوينتليوناً', 'سكستيليوناً'];
|
|
37
|
+
|
|
38
|
+
arabicPluralGroups = ['', 'آلاف', 'ملايين', 'مليارات', 'تريليونات', 'كوادريليونات', 'كوينتليونات', 'سكستيليونات'];
|
|
39
|
+
|
|
40
|
+
// isCurrencyPartNameFeminine = true
|
|
41
|
+
|
|
42
|
+
// isCurrencyNameFeminine = false
|
|
43
|
+
|
|
44
|
+
constructor(options) {
|
|
45
|
+
super(Object.assign({
|
|
46
|
+
negativeWord: 'ناقص',
|
|
47
|
+
separatorWord: 'فاصلة',
|
|
48
|
+
zero: 'صفر'
|
|
49
|
+
}, options));
|
|
36
50
|
}
|
|
37
51
|
|
|
38
52
|
digitFeminineStatus(digit/* , groupLevel */) {
|
|
@@ -93,7 +107,10 @@ export class N2WordsAR extends N2WordsAbs {
|
|
|
93
107
|
}
|
|
94
108
|
|
|
95
109
|
toCardinal(number) {
|
|
96
|
-
|
|
110
|
+
/** @todo Convert class to work with BigInt */
|
|
111
|
+
number = Number(number);
|
|
112
|
+
|
|
113
|
+
if (number == 0) {
|
|
97
114
|
return this.zero;
|
|
98
115
|
}
|
|
99
116
|
let tempNumber = number;
|
|
@@ -133,6 +150,13 @@ export class N2WordsAR extends N2WordsAbs {
|
|
|
133
150
|
}
|
|
134
151
|
}
|
|
135
152
|
|
|
136
|
-
|
|
137
|
-
|
|
153
|
+
/**
|
|
154
|
+
* Converts a value to cardinal (written) form.
|
|
155
|
+
* @param {number|string} value Number to be convert.
|
|
156
|
+
* @param {object} options Options for class.
|
|
157
|
+
* @throws {Error} Value cannot be invalid.
|
|
158
|
+
* @returns {string} Value in cardinal (written) format.
|
|
159
|
+
*/
|
|
160
|
+
export default function(value, options) {
|
|
161
|
+
return new Arabic(options).floatToCardinal(value);
|
|
138
162
|
}
|
package/lib/i18n/AZ.mjs
CHANGED
|
@@ -1,40 +1,39 @@
|
|
|
1
|
-
import
|
|
1
|
+
import BaseLanguage from '../classes/BaseLanguage.mjs';
|
|
2
2
|
|
|
3
|
-
export class N2WordsAZ extends
|
|
4
|
-
constructor() {
|
|
5
|
-
super(
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
];
|
|
3
|
+
export class N2WordsAZ extends BaseLanguage {
|
|
4
|
+
constructor(options) {
|
|
5
|
+
super(Object.assign({
|
|
6
|
+
negativeWord: 'mənfi',
|
|
7
|
+
separatorWord: 'nöqtə',
|
|
8
|
+
zero: 'sıfır'
|
|
9
|
+
}, options), [
|
|
10
|
+
[1000000000000000000n, 'kentilyon'],
|
|
11
|
+
[1000000000000000n, 'katrilyon'],
|
|
12
|
+
[1000000000000n, 'trilyon'],
|
|
13
|
+
[1000000000n, 'milyar'],
|
|
14
|
+
[1000000n, 'milyon'],
|
|
15
|
+
[1000n, 'min'],
|
|
16
|
+
[100n, 'yüz'],
|
|
17
|
+
[90n, 'doxsan'],
|
|
18
|
+
[80n, 'səksən'],
|
|
19
|
+
[70n, 'yetmiş'],
|
|
20
|
+
[60n, 'altmış'],
|
|
21
|
+
[50n, 'əlli'],
|
|
22
|
+
[40n, 'qırx'],
|
|
23
|
+
[30n, 'otuz'],
|
|
24
|
+
[20n, 'iyirmi'],
|
|
25
|
+
[10n, 'on'],
|
|
26
|
+
[9n, 'doqquz'],
|
|
27
|
+
[8n, 'səkkiz'],
|
|
28
|
+
[7n, 'yeddi'],
|
|
29
|
+
[6n, 'altı'],
|
|
30
|
+
[5n, 'beş'],
|
|
31
|
+
[4n, 'dörd'],
|
|
32
|
+
[3n, 'üç'],
|
|
33
|
+
[2n, 'iki'],
|
|
34
|
+
[1n, 'bir'],
|
|
35
|
+
[0n, 'sıfır']
|
|
36
|
+
]);
|
|
38
37
|
}
|
|
39
38
|
|
|
40
39
|
merge(lPair, rPair) {
|
|
@@ -52,6 +51,13 @@ export class N2WordsAZ extends N2WordsBase {
|
|
|
52
51
|
}
|
|
53
52
|
}
|
|
54
53
|
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
/**
|
|
55
|
+
* Converts a value to cardinal (written) form.
|
|
56
|
+
* @param {number|string} value Number to be convert.
|
|
57
|
+
* @param {object} options Options for class.
|
|
58
|
+
* @throws {Error} Value cannot be invalid.
|
|
59
|
+
* @returns {string} Value in cardinal (written) format.
|
|
60
|
+
*/
|
|
61
|
+
export default function(value, options) {
|
|
62
|
+
return new N2WordsAZ(options).floatToCardinal(value);
|
|
57
63
|
}
|