numberstring 0.1.0 → 1.0.1

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.
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Japanese number-to-words converter
3
+ * Uses the man (万) system for grouping by 10,000
4
+ * @module languages/ja
5
+ */
6
+
7
+ const JA_DIGITS = Object.freeze(['', '一', '二', '三', '四', '五', '六', '七', '八', '九']);
8
+ const JA_SCALES = Object.freeze(['', '万', '億', '兆', '京', '垓', '𥝱', '穣', '溝']);
9
+
10
+ /** Maximum supported value (10^36 - 1, up to 溝) */
11
+ const MAX_VALUE = 10n ** 36n - 1n;
12
+
13
+
14
+ /**
15
+ * Convert a 4-digit group (0-9999) to Japanese
16
+ * @param {number} grp - The group value (0-9999)
17
+ * @returns {string} The Japanese representation
18
+ */
19
+ const groupToJa = (grp) => {
20
+ if (grp === 0) return '';
21
+
22
+ const thousands = Math.floor(grp / 1000);
23
+ const hundreds = Math.floor((grp % 1000) / 100);
24
+ const tens = Math.floor((grp % 100) / 10);
25
+ const ones = grp % 10;
26
+
27
+ let result = '';
28
+
29
+ // Thousands: 1 before 千 is omitted
30
+ if (thousands > 0) {
31
+ if (thousands === 1) {
32
+ result += '千';
33
+ } else {
34
+ result += JA_DIGITS[thousands] + '千';
35
+ }
36
+ }
37
+
38
+ // Hundreds: 1 before 百 is omitted
39
+ if (hundreds > 0) {
40
+ if (hundreds === 1) {
41
+ result += '百';
42
+ } else {
43
+ result += JA_DIGITS[hundreds] + '百';
44
+ }
45
+ }
46
+
47
+ // Tens: 1 before 十 is omitted
48
+ if (tens > 0) {
49
+ if (tens === 1) {
50
+ result += '十';
51
+ } else {
52
+ result += JA_DIGITS[tens] + '十';
53
+ }
54
+ }
55
+
56
+ // Ones
57
+ if (ones > 0) {
58
+ result += JA_DIGITS[ones];
59
+ }
60
+
61
+ return result;
62
+ };
63
+
64
+ /**
65
+ * Convert a number to Japanese words
66
+ * @param {number|bigint} n - The number to convert
67
+ * @returns {string|false} The Japanese word representation
68
+ *
69
+ * @example
70
+ * japanese(42) // '四十二'
71
+ * japanese(1000) // '千'
72
+ * japanese(10000) // '一万'
73
+ */
74
+ const japanese = (n) => {
75
+ let num;
76
+
77
+ if (typeof n === 'bigint') {
78
+ if (n < 0n || n > MAX_VALUE) return false;
79
+ num = n;
80
+ } else if (typeof n === 'number') {
81
+ if (isNaN(n) || n < 0 || !Number.isInteger(n)) return false;
82
+ if (n > Number.MAX_SAFE_INTEGER) return false;
83
+ num = BigInt(n);
84
+ } else {
85
+ return false;
86
+ }
87
+
88
+ if (num === 0n) return 'ゼロ';
89
+
90
+ const str = num.toString();
91
+ const len = str.length;
92
+
93
+ // Split into groups of 4 from the right
94
+ const groups = [];
95
+ for (let i = len; i > 0; i -= 4) {
96
+ const start = Math.max(0, i - 4);
97
+ groups.unshift(str.slice(start, i));
98
+ }
99
+
100
+ let result = '';
101
+
102
+ for (let i = 0; i < groups.length; i++) {
103
+ const grp = parseInt(groups[i], 10);
104
+ const grpIdx = groups.length - 1 - i;
105
+
106
+ if (grp === 0) continue;
107
+
108
+ const grpStr = groupToJa(grp);
109
+
110
+ // 1 before 万 and above IS included (handled naturally by groupToJa
111
+ // since grp=1 produces '一' for the ones digit in the group)
112
+ result += grpStr;
113
+ if (grpIdx > 0) {
114
+ result += JA_SCALES[grpIdx];
115
+ }
116
+ }
117
+
118
+ return result;
119
+ };
120
+
121
+ export default japanese;
122
+ export { japanese, JA_DIGITS, JA_SCALES, MAX_VALUE };
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Korean number-to-words converter (Sino-Korean)
3
+ * Uses the man (만) system for grouping by 10,000
4
+ * @module languages/ko
5
+ */
6
+
7
+ const KO_DIGITS = Object.freeze(['', '일', '이', '삼', '사', '오', '육', '칠', '팔', '구']);
8
+ const KO_SCALES = Object.freeze(['', '만', '억', '조', '경', '해', '자', '양', '구']);
9
+
10
+ /** Maximum supported value (10^36 - 1) */
11
+ const MAX_VALUE = 10n ** 36n - 1n;
12
+
13
+
14
+ /**
15
+ * Convert a 4-digit group (0-9999) to Sino-Korean
16
+ * @param {number} grp - The group value (0-9999)
17
+ * @returns {string} The Korean representation
18
+ */
19
+ const groupToKo = (grp) => {
20
+ if (grp === 0) return '';
21
+
22
+ const thousands = Math.floor(grp / 1000);
23
+ const hundreds = Math.floor((grp % 1000) / 100);
24
+ const tens = Math.floor((grp % 100) / 10);
25
+ const ones = grp % 10;
26
+
27
+ let result = '';
28
+
29
+ // Thousands: 1 before 천 is omitted
30
+ if (thousands > 0) {
31
+ if (thousands === 1) {
32
+ result += '천';
33
+ } else {
34
+ result += KO_DIGITS[thousands] + '천';
35
+ }
36
+ }
37
+
38
+ // Hundreds: 1 before 백 is omitted
39
+ if (hundreds > 0) {
40
+ if (hundreds === 1) {
41
+ result += '백';
42
+ } else {
43
+ result += KO_DIGITS[hundreds] + '백';
44
+ }
45
+ }
46
+
47
+ // Tens: 1 before 십 is omitted
48
+ if (tens > 0) {
49
+ if (tens === 1) {
50
+ result += '십';
51
+ } else {
52
+ result += KO_DIGITS[tens] + '십';
53
+ }
54
+ }
55
+
56
+ // Ones
57
+ if (ones > 0) {
58
+ result += KO_DIGITS[ones];
59
+ }
60
+
61
+ return result;
62
+ };
63
+
64
+ /**
65
+ * Convert a number to Korean words (Sino-Korean system)
66
+ * @param {number|bigint} n - The number to convert
67
+ * @returns {string|false} The Korean word representation
68
+ *
69
+ * @example
70
+ * korean(42) // '사십이'
71
+ * korean(1000) // '천'
72
+ * korean(10000) // '일만'
73
+ */
74
+ const korean = (n) => {
75
+ let num;
76
+
77
+ if (typeof n === 'bigint') {
78
+ if (n < 0n || n > MAX_VALUE) return false;
79
+ num = n;
80
+ } else if (typeof n === 'number') {
81
+ if (isNaN(n) || n < 0 || !Number.isInteger(n)) return false;
82
+ if (n > Number.MAX_SAFE_INTEGER) return false;
83
+ num = BigInt(n);
84
+ } else {
85
+ return false;
86
+ }
87
+
88
+ if (num === 0n) return '영';
89
+
90
+ const str = num.toString();
91
+ const len = str.length;
92
+
93
+ // Split into groups of 4 from the right
94
+ const groups = [];
95
+ for (let i = len; i > 0; i -= 4) {
96
+ const start = Math.max(0, i - 4);
97
+ groups.unshift(str.slice(start, i));
98
+ }
99
+
100
+ let result = '';
101
+
102
+ for (let i = 0; i < groups.length; i++) {
103
+ const grp = parseInt(groups[i], 10);
104
+ const grpIdx = groups.length - 1 - i;
105
+
106
+ if (grp === 0) continue;
107
+
108
+ const grpStr = groupToKo(grp);
109
+
110
+ // 1 before 만 and above IS included (handled naturally by groupToKo
111
+ // since grp=1 produces '일' for the ones digit in the group)
112
+ result += grpStr;
113
+ if (grpIdx > 0) {
114
+ result += KO_SCALES[grpIdx];
115
+ }
116
+ }
117
+
118
+ return result;
119
+ };
120
+
121
+ export default korean;
122
+ export { korean, KO_DIGITS, KO_SCALES, MAX_VALUE };
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Dutch number-to-words converter
3
+ * Dutch reverses ones and tens (eenentwintig = one-and-twenty)
4
+ * @module languages/nl
5
+ */
6
+
7
+ const NL_ONES = Object.freeze(['', 'een', 'twee', 'drie', 'vier', 'vijf', 'zes', 'zeven', 'acht', 'negen']);
8
+ const NL_TENS = Object.freeze(['', '', 'twintig', 'dertig', 'veertig', 'vijftig', 'zestig', 'zeventig', 'tachtig', 'negentig']);
9
+ const NL_TEENS = Object.freeze(['tien', 'elf', 'twaalf', 'dertien', 'veertien', 'vijftien', 'zestien', 'zeventien', 'achttien', 'negentien']);
10
+ const NL_ILLIONS = Object.freeze(['', 'duizend', 'miljoen', 'miljard', 'biljoen', 'biljard', 'triljoen', 'triljard', 'quadriljoen', 'quadriljard', 'quintiljoen', 'quintiljard']);
11
+ const NL_ILLIONS_PLURAL = Object.freeze(['', 'duizend', 'miljoen', 'miljard', 'biljoen', 'biljard', 'triljoen', 'triljard', 'quadriljoen', 'quadriljard', 'quintiljoen', 'quintiljard']);
12
+
13
+ /** Maximum supported value (10^36 - 1, up to decillions) */
14
+ const MAX_VALUE = 10n ** 36n - 1n;
15
+
16
+ const group = (n) => Math.ceil(n.toString().length / 3) - 1;
17
+ const power = (g) => 10n ** BigInt(g * 3);
18
+ const segment = (n, g) => n % power(g + 1);
19
+ const hundment = (n, g) => Number(segment(n, g) / power(g));
20
+ const tenment = (n, g) => hundment(n, g) % 100;
21
+
22
+ const tenNl = (n) => {
23
+ if (n === 0) return '';
24
+ if (n < 10) return NL_ONES[n];
25
+ if (n < 20) return NL_TEENS[n - 10];
26
+ const onesDigit = n % 10;
27
+ const tensDigit = Math.floor(n / 10);
28
+ if (onesDigit === 0) return NL_TENS[tensDigit];
29
+ // Use "en" connector between ones and tens
30
+ // Use "ën" after words ending in vowel-e (twee, drie)
31
+ const connector = (onesDigit === 2 || onesDigit === 3) ? 'ën' : 'en';
32
+ return `${NL_ONES[onesDigit]}${connector}${NL_TENS[tensDigit]}`;
33
+ };
34
+
35
+ const hundredNl = (n) => {
36
+ if (n < 100 || n >= 1000) return '';
37
+ const h = Math.floor(n / 100);
38
+ // 100 = "honderd" (not "eenhonderd")
39
+ if (h === 1) return 'honderd';
40
+ return `${NL_ONES[h]}honderd`;
41
+ };
42
+
43
+ /**
44
+ * Convert a number to Dutch words
45
+ * @param {number|bigint} n - The number to convert
46
+ * @returns {string|false} The Dutch word representation
47
+ *
48
+ * @example
49
+ * dutch(42) // 'tweeënveertig'
50
+ * dutch(1000) // 'duizend'
51
+ * dutch(21) // 'eenentwintig'
52
+ */
53
+ const dutch = (n) => {
54
+ let num;
55
+
56
+ if (typeof n === 'bigint') {
57
+ if (n < 0n || n > MAX_VALUE) return false;
58
+ num = n;
59
+ } else if (typeof n === 'number') {
60
+ if (isNaN(n) || n < 0 || !Number.isInteger(n)) return false;
61
+ if (n > Number.MAX_SAFE_INTEGER) return false;
62
+ num = BigInt(n);
63
+ } else {
64
+ return false;
65
+ }
66
+
67
+ if (num === 0n) return 'nul';
68
+
69
+ let s = '';
70
+ for (let i = group(num); i >= 0; i--) {
71
+ const h = hundment(num, i);
72
+ if (h > 0) {
73
+ if (i === 0) {
74
+ // Units group
75
+ if (h >= 100) s += hundredNl(h);
76
+ const t = tenment(num, i);
77
+ if (t > 0) s += tenNl(t);
78
+ } else if (i === 1) {
79
+ // Thousands: 1000 = "duizend" (not "eenduizend")
80
+ if (h === 1) {
81
+ s += 'duizend';
82
+ } else {
83
+ if (h >= 100) s += hundredNl(h);
84
+ const t = tenment(num, i);
85
+ if (t > 0) s += tenNl(t);
86
+ s += 'duizend';
87
+ }
88
+ } else {
89
+ // Millions and above: separated by spaces
90
+ // 1 million = "een miljoen", 2 million = "twee miljoen"
91
+ if (h >= 100) s += hundredNl(h);
92
+ const t = tenment(num, i);
93
+ if (t > 0) {
94
+ if (t === 1) {
95
+ s += 'een ';
96
+ } else {
97
+ s += tenNl(t) + ' ';
98
+ }
99
+ } else if (h < 100 && h === 1) {
100
+ s += 'een ';
101
+ }
102
+ const illionWord = h === 1 ? NL_ILLIONS[i] : NL_ILLIONS_PLURAL[i];
103
+ s += `${illionWord} `;
104
+ }
105
+ }
106
+ }
107
+
108
+ return s.trim();
109
+ };
110
+
111
+ export default dutch;
112
+ export { dutch };
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Norwegian (Bokmål) number-to-words converter
3
+ * Norwegian uses long scale like Danish but with simpler tens
4
+ * @module languages/no
5
+ */
6
+
7
+ const NO_ONES = Object.freeze(['', 'en', 'to', 'tre', 'fire', 'fem', 'seks', 'sju', 'åtte', 'ni']);
8
+ const NO_TENS = Object.freeze(['', '', 'tjue', 'tretti', 'førti', 'femti', 'seksti', 'sytti', 'åtti', 'nitti']);
9
+ const NO_TEENS = Object.freeze(['ti', 'elleve', 'tolv', 'tretten', 'fjorten', 'femten', 'seksten', 'sytten', 'atten', 'nitten']);
10
+ const NO_ILLIONS = Object.freeze(['', 'tusen', 'million', 'milliard', 'billion', 'billiard', 'trillion', 'trilliard', 'kvadrillion', 'kvadrilliard', 'kvintillion', 'kvintilliard']);
11
+ const NO_ILLIONS_PLURAL = Object.freeze(['', 'tusen', 'millioner', 'milliarder', 'billioner', 'billiarder', 'trillioner', 'trilliarder', 'kvadrillioner', 'kvadrilliarder', 'kvintillioner', 'kvintilliarder']);
12
+
13
+ const MAX_VALUE = 10n ** 36n - 1n;
14
+
15
+ const group = (n) => Math.ceil(n.toString().length / 3) - 1;
16
+ const power = (g) => 10n ** BigInt(g * 3);
17
+ const segment = (n, g) => n % power(g + 1);
18
+ const hundment = (n, g) => Number(segment(n, g) / power(g));
19
+ const tenment = (n, g) => hundment(n, g) % 100;
20
+
21
+ const tenNo = (n) => {
22
+ if (n === 0) return '';
23
+ if (n < 10) return NO_ONES[n];
24
+ if (n < 20) return NO_TEENS[n - 10];
25
+ const onesDigit = n % 10;
26
+ const tensDigit = Math.floor(n / 10);
27
+ if (onesDigit === 0) return NO_TENS[tensDigit];
28
+ return `${NO_TENS[tensDigit]}${NO_ONES[onesDigit]}`;
29
+ };
30
+
31
+ const hundredNo = (n) => {
32
+ if (n < 100 || n >= 1000) return '';
33
+ const h = Math.floor(n / 100);
34
+ if (h === 1) return 'etthundre';
35
+ return `${NO_ONES[h]}hundre`;
36
+ };
37
+
38
+ /**
39
+ * Convert a number to Norwegian words
40
+ * @param {number|bigint} n - The number to convert
41
+ * @returns {string|false} The Norwegian word representation
42
+ *
43
+ * @example
44
+ * norwegian(42) // 'førtito'
45
+ * norwegian(1000) // 'ettusen'
46
+ */
47
+ const norwegian = (n) => {
48
+ let num;
49
+
50
+ if (typeof n === 'bigint') {
51
+ if (n < 0n || n > MAX_VALUE) return false;
52
+ num = n;
53
+ } else if (typeof n === 'number') {
54
+ if (isNaN(n) || n < 0 || !Number.isInteger(n)) return false;
55
+ if (n > Number.MAX_SAFE_INTEGER) return false;
56
+ num = BigInt(n);
57
+ } else {
58
+ return false;
59
+ }
60
+
61
+ if (num === 0n) return 'null';
62
+ if (num === 1n) return 'en';
63
+
64
+ let s = '';
65
+ for (let i = group(num); i >= 0; i--) {
66
+ const h = hundment(num, i);
67
+ if (h > 0) {
68
+ if (i === 0) {
69
+ if (h >= 100) s += hundredNo(h) + ' ';
70
+ const t = tenment(num, i);
71
+ if (t > 0) s += tenNo(t);
72
+ } else if (i === 1) {
73
+ if (h === 1) {
74
+ s += 'ettusen ';
75
+ } else {
76
+ if (h >= 100) s += hundredNo(h) + ' ';
77
+ const t = tenment(num, i);
78
+ if (t > 0) s += tenNo(t);
79
+ s += 'tusen ';
80
+ }
81
+ } else {
82
+ if (h >= 100) s += hundredNo(h) + ' ';
83
+ const t = tenment(num, i);
84
+ if (t > 0) {
85
+ if (t === 1) {
86
+ s += 'en ';
87
+ } else {
88
+ s += tenNo(t) + ' ';
89
+ }
90
+ } else if (h < 100 && h >= 1 && h === 1) {
91
+ s += 'en ';
92
+ }
93
+ const illionWord = h === 1 ? NO_ILLIONS[i] : NO_ILLIONS_PLURAL[i];
94
+ s += `${illionWord} `;
95
+ }
96
+ }
97
+ }
98
+
99
+ return s.trim();
100
+ };
101
+
102
+ export default norwegian;
103
+ export { norwegian };
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Polish number-to-words converter
3
+ * Handles Polish plural forms (singular, 2-4, 5+)
4
+ * @module languages/pl
5
+ */
6
+
7
+ const PL_ONES = Object.freeze(['', 'jeden', 'dwa', 'trzy', 'cztery', 'pięć', 'sześć', 'siedem', 'osiem', 'dziewięć']);
8
+ const PL_TENS = Object.freeze(['', '', 'dwadzieścia', 'trzydzieści', 'czterdzieści', 'pięćdziesiąt', 'sześćdziesiąt', 'siedemdziesiąt', 'osiemdziesiąt', 'dziewięćdziesiąt']);
9
+ const PL_TEENS = Object.freeze(['dziesięć', 'jedenaście', 'dwanaście', 'trzynaście', 'czternaście', 'piętnaście', 'szesnaście', 'siedemnaście', 'osiemnaście', 'dziewiętnaście']);
10
+ const PL_HUNDREDS = Object.freeze(['', 'sto', 'dwieście', 'trzysta', 'czterysta', 'pięćset', 'sześćset', 'siedemset', 'osiemset', 'dziewięćset']);
11
+ const PL_ILLIONS = Object.freeze([
12
+ ['', '', ''], // ones
13
+ ['tysiąc', 'tysiące', 'tysięcy'], // thousands
14
+ ['milion', 'miliony', 'milionów'], // millions
15
+ ['miliard', 'miliardy', 'miliardów'], // billions
16
+ ['bilion', 'biliony', 'bilionów'], // trillions
17
+ ['biliard', 'biliardy', 'biliardów'], // quadrillions
18
+ ['trylion', 'tryliony', 'trylionów'], // quintillions
19
+ ['tryliard', 'tryliardy', 'tryliardów'], // sextillions
20
+ ['kwadrylion', 'kwadryliony', 'kwadrylionów'], // septillions
21
+ ['kwadryliard', 'kwadryliardy', 'kwadryliardów'], // octillions
22
+ ['kwintylion', 'kwintyliony', 'kwintylionów'], // nonillions
23
+ ['kwintyliard', 'kwintyliardy', 'kwintyliardów'] // decillions
24
+ ]);
25
+
26
+ /** Maximum supported value (10^36 - 1, up to decillions) */
27
+ const MAX_VALUE = 10n ** 36n - 1n;
28
+
29
+ const group = (n) => Math.ceil(n.toString().length / 3) - 1;
30
+ const power = (g) => 10n ** BigInt(g * 3);
31
+ const segment = (n, g) => n % power(g + 1);
32
+ const hundment = (n, g) => Number(segment(n, g) / power(g));
33
+ const tenment = (n, g) => hundment(n, g) % 100;
34
+
35
+ /**
36
+ * Get the correct Polish plural form based on number
37
+ * Polish has 3 forms: singular (1), plural 2-4, plural 5+
38
+ * @param {number} n - The number to check
39
+ * @param {string[]} forms - [singular, plural2_4, plural5_plus]
40
+ * @returns {string} The correct plural form
41
+ */
42
+ const getPlPlural = (n, forms) => {
43
+ if (n === 1) return forms[0];
44
+ const lastTwo = n % 100;
45
+ const lastOne = n % 10;
46
+ if (lastTwo >= 12 && lastTwo <= 14) return forms[2];
47
+ if (lastOne >= 2 && lastOne <= 4) return forms[1];
48
+ return forms[2];
49
+ };
50
+
51
+ const hundredPl = (n) => {
52
+ if (n < 100 || n >= 1000) return '';
53
+ return PL_HUNDREDS[Math.floor(n / 100)];
54
+ };
55
+
56
+ const tenPl = (n) => {
57
+ if (n === 0) return '';
58
+ if (n < 10) return PL_ONES[n];
59
+ if (n < 20) return PL_TEENS[n - 10];
60
+ const onesDigit = n % 10;
61
+ const tensDigit = Math.floor(n / 10);
62
+ if (onesDigit === 0) return PL_TENS[tensDigit];
63
+ return `${PL_TENS[tensDigit]} ${PL_ONES[onesDigit]}`;
64
+ };
65
+
66
+ /**
67
+ * Convert a number to Polish words
68
+ * @param {number|bigint} n - The number to convert
69
+ * @returns {string|false} The Polish word representation
70
+ *
71
+ * @example
72
+ * polish(42) // 'czterdzieści dwa'
73
+ * polish(1000) // 'tysiąc'
74
+ * polish(2000) // 'dwa tysiące'
75
+ * polish(5000) // 'pięć tysięcy'
76
+ */
77
+ const polish = (n) => {
78
+ let num;
79
+
80
+ if (typeof n === 'bigint') {
81
+ if (n < 0n || n > MAX_VALUE) return false;
82
+ num = n;
83
+ } else if (typeof n === 'number') {
84
+ if (isNaN(n) || n < 0 || !Number.isInteger(n)) return false;
85
+ if (n > Number.MAX_SAFE_INTEGER) return false;
86
+ num = BigInt(n);
87
+ } else {
88
+ return false;
89
+ }
90
+
91
+ if (num === 0n) return 'zero';
92
+
93
+ let s = '';
94
+ for (let i = group(num); i >= 0; i--) {
95
+ const h = hundment(num, i);
96
+ if (h > 0) {
97
+ const hund = hundredPl(h);
98
+ if (hund) s += hund + ' ';
99
+
100
+ const t = tenment(num, i);
101
+
102
+ if (i === 0) {
103
+ // Units group: just tens
104
+ const tenWord = tenPl(t);
105
+ if (tenWord) s += tenWord + ' ';
106
+ } else if (i === 1) {
107
+ // Thousands
108
+ if (h === 1 && t === 0) {
109
+ // Just "tysiąc" for exactly 1 thousand (with possible hundreds)
110
+ s += 'tysiąc ';
111
+ } else {
112
+ if (t > 0) {
113
+ // Skip "jeden" before "tysiąc" when it's just 1
114
+ if (t === 1) {
115
+ s += 'tysiąc ';
116
+ } else {
117
+ s += tenPl(t) + ' ';
118
+ s += getPlPlural(t, PL_ILLIONS[i]) + ' ';
119
+ }
120
+ } else {
121
+ // h >= 100 with no tens portion, use h for plural
122
+ s += getPlPlural(h, PL_ILLIONS[i]) + ' ';
123
+ }
124
+ }
125
+ } else {
126
+ // Millions and above
127
+ if (t > 0) {
128
+ if (t === 1) {
129
+ s += 'jeden ';
130
+ } else {
131
+ s += tenPl(t) + ' ';
132
+ }
133
+ } else if (h < 100 && h === 1) {
134
+ s += 'jeden ';
135
+ }
136
+ const illionWord = getPlPlural(t || h, PL_ILLIONS[i]);
137
+ s += illionWord + ' ';
138
+ }
139
+ }
140
+ }
141
+
142
+ return s.trim().replace(/\s+/g, ' ');
143
+ };
144
+
145
+ export default polish;
146
+ export { polish };