n2words 1.24.0 → 3.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.
Files changed (280) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/README.md +183 -156
  3. package/dist/languages/am-Latn.js +3 -0
  4. package/dist/languages/am-Latn.js.map +1 -0
  5. package/dist/languages/am.js +3 -0
  6. package/dist/languages/am.js.map +1 -0
  7. package/dist/languages/ar.js +3 -2
  8. package/dist/languages/ar.js.map +1 -1
  9. package/dist/languages/az.js +3 -2
  10. package/dist/languages/az.js.map +1 -1
  11. package/dist/languages/bn.js +3 -2
  12. package/dist/languages/bn.js.map +1 -1
  13. package/dist/languages/cs.js +3 -2
  14. package/dist/languages/cs.js.map +1 -1
  15. package/dist/languages/da.js +3 -2
  16. package/dist/languages/da.js.map +1 -1
  17. package/dist/languages/de.js +3 -2
  18. package/dist/languages/de.js.map +1 -1
  19. package/dist/languages/el.js +3 -2
  20. package/dist/languages/el.js.map +1 -1
  21. package/dist/languages/en.js +3 -2
  22. package/dist/languages/en.js.map +1 -1
  23. package/dist/languages/es.js +3 -2
  24. package/dist/languages/es.js.map +1 -1
  25. package/dist/languages/fa.js +3 -2
  26. package/dist/languages/fa.js.map +1 -1
  27. package/dist/languages/fi.js +3 -0
  28. package/dist/languages/fi.js.map +1 -0
  29. package/dist/languages/fil.js +3 -2
  30. package/dist/languages/fil.js.map +1 -1
  31. package/dist/languages/fr-BE.js +3 -2
  32. package/dist/languages/fr-BE.js.map +1 -1
  33. package/dist/languages/fr.js +3 -2
  34. package/dist/languages/fr.js.map +1 -1
  35. package/dist/languages/gu.js +3 -2
  36. package/dist/languages/gu.js.map +1 -1
  37. package/dist/languages/ha.js +3 -0
  38. package/dist/languages/ha.js.map +1 -0
  39. package/dist/languages/hbo.js +3 -0
  40. package/dist/languages/hbo.js.map +1 -0
  41. package/dist/languages/he.js +3 -2
  42. package/dist/languages/he.js.map +1 -1
  43. package/dist/languages/hi.js +3 -2
  44. package/dist/languages/hi.js.map +1 -1
  45. package/dist/languages/hr.js +3 -2
  46. package/dist/languages/hr.js.map +1 -1
  47. package/dist/languages/hu.js +3 -2
  48. package/dist/languages/hu.js.map +1 -1
  49. package/dist/languages/id.js +3 -2
  50. package/dist/languages/id.js.map +1 -1
  51. package/dist/languages/it.js +3 -2
  52. package/dist/languages/it.js.map +1 -1
  53. package/dist/languages/ja.js +3 -2
  54. package/dist/languages/ja.js.map +1 -1
  55. package/dist/languages/kn.js +3 -2
  56. package/dist/languages/kn.js.map +1 -1
  57. package/dist/languages/ko.js +3 -2
  58. package/dist/languages/ko.js.map +1 -1
  59. package/dist/languages/lt.js +3 -2
  60. package/dist/languages/lt.js.map +1 -1
  61. package/dist/languages/lv.js +3 -2
  62. package/dist/languages/lv.js.map +1 -1
  63. package/dist/languages/mr.js +3 -2
  64. package/dist/languages/mr.js.map +1 -1
  65. package/dist/languages/ms.js +3 -2
  66. package/dist/languages/ms.js.map +1 -1
  67. package/dist/languages/nb.js +3 -2
  68. package/dist/languages/nb.js.map +1 -1
  69. package/dist/languages/nl.js +3 -2
  70. package/dist/languages/nl.js.map +1 -1
  71. package/dist/languages/pa.js +3 -0
  72. package/dist/languages/pa.js.map +1 -0
  73. package/dist/languages/pl.js +3 -2
  74. package/dist/languages/pl.js.map +1 -1
  75. package/dist/languages/pt.js +3 -2
  76. package/dist/languages/pt.js.map +1 -1
  77. package/dist/languages/ro.js +3 -2
  78. package/dist/languages/ro.js.map +1 -1
  79. package/dist/languages/ru.js +3 -2
  80. package/dist/languages/ru.js.map +1 -1
  81. package/dist/languages/sr-Cyrl.js +3 -0
  82. package/dist/languages/sr-Cyrl.js.map +1 -0
  83. package/dist/languages/sr-Latn.js +3 -2
  84. package/dist/languages/sr-Latn.js.map +1 -1
  85. package/dist/languages/sv.js +3 -2
  86. package/dist/languages/sv.js.map +1 -1
  87. package/dist/languages/sw.js +3 -2
  88. package/dist/languages/sw.js.map +1 -1
  89. package/dist/languages/ta.js +3 -2
  90. package/dist/languages/ta.js.map +1 -1
  91. package/dist/languages/te.js +3 -2
  92. package/dist/languages/te.js.map +1 -1
  93. package/dist/languages/th.js +3 -2
  94. package/dist/languages/th.js.map +1 -1
  95. package/dist/languages/tr.js +3 -2
  96. package/dist/languages/tr.js.map +1 -1
  97. package/dist/languages/uk.js +3 -2
  98. package/dist/languages/uk.js.map +1 -1
  99. package/dist/languages/ur.js +3 -2
  100. package/dist/languages/ur.js.map +1 -1
  101. package/dist/languages/vi.js +3 -2
  102. package/dist/languages/vi.js.map +1 -1
  103. package/dist/languages/zh-Hans.js +3 -2
  104. package/dist/languages/zh-Hans.js.map +1 -1
  105. package/dist/languages/zh-Hant.js +3 -0
  106. package/dist/languages/zh-Hant.js.map +1 -0
  107. package/dist/n2words.js +3 -2
  108. package/dist/n2words.js.map +1 -1
  109. package/lib/languages/am-Latn.d.ts +7 -0
  110. package/lib/languages/am-Latn.js +164 -0
  111. package/lib/languages/am.d.ts +7 -0
  112. package/lib/languages/am.js +164 -0
  113. package/lib/languages/ar.d.ts +17 -0
  114. package/lib/languages/ar.js +171 -209
  115. package/lib/languages/az.d.ts +7 -0
  116. package/lib/languages/az.js +167 -49
  117. package/lib/languages/bn.d.ts +7 -0
  118. package/lib/languages/bn.js +142 -123
  119. package/lib/languages/cs.d.ts +18 -0
  120. package/lib/languages/cs.js +303 -176
  121. package/lib/languages/da.d.ts +14 -0
  122. package/lib/languages/da.js +267 -139
  123. package/lib/languages/de.d.ts +17 -0
  124. package/lib/languages/de.js +310 -113
  125. package/lib/languages/el.d.ts +14 -0
  126. package/lib/languages/el.js +225 -98
  127. package/lib/languages/en.d.ts +17 -0
  128. package/lib/languages/en.js +235 -102
  129. package/lib/languages/es.d.ts +21 -0
  130. package/lib/languages/es.js +307 -125
  131. package/lib/languages/fa.d.ts +7 -0
  132. package/lib/languages/fa.js +115 -108
  133. package/lib/languages/fi.d.ts +14 -0
  134. package/lib/languages/fi.js +245 -0
  135. package/lib/languages/fil.d.ts +7 -0
  136. package/lib/languages/fil.js +199 -139
  137. package/lib/languages/fr-BE.d.ts +11 -0
  138. package/lib/languages/fr-BE.js +287 -48
  139. package/lib/languages/fr.d.ts +21 -0
  140. package/lib/languages/fr.js +343 -119
  141. package/lib/languages/gu.d.ts +7 -0
  142. package/lib/languages/gu.js +125 -144
  143. package/lib/languages/ha.d.ts +7 -0
  144. package/lib/languages/ha.js +230 -0
  145. package/lib/languages/hbo.d.ts +13 -0
  146. package/lib/languages/hbo.js +300 -0
  147. package/lib/languages/he.d.ts +13 -0
  148. package/lib/languages/he.js +230 -283
  149. package/lib/languages/hi.d.ts +7 -0
  150. package/lib/languages/hi.js +142 -123
  151. package/lib/languages/hr.d.ts +11 -0
  152. package/lib/languages/hr.js +190 -129
  153. package/lib/languages/hu.d.ts +7 -0
  154. package/lib/languages/hu.js +194 -133
  155. package/lib/languages/id.d.ts +7 -0
  156. package/lib/languages/id.js +167 -140
  157. package/lib/languages/it.d.ts +19 -0
  158. package/lib/languages/it.js +337 -108
  159. package/lib/languages/ja.d.ts +17 -0
  160. package/lib/languages/ja.js +224 -155
  161. package/lib/languages/kn.d.ts +7 -0
  162. package/lib/languages/kn.js +128 -62
  163. package/lib/languages/ko.d.ts +14 -0
  164. package/lib/languages/ko.js +250 -70
  165. package/lib/languages/lt.d.ts +18 -0
  166. package/lib/languages/lt.js +287 -148
  167. package/lib/languages/lv.d.ts +18 -0
  168. package/lib/languages/lv.js +291 -123
  169. package/lib/languages/mr.d.ts +7 -0
  170. package/lib/languages/mr.js +125 -144
  171. package/lib/languages/ms.d.ts +7 -0
  172. package/lib/languages/ms.js +171 -112
  173. package/lib/languages/nb.d.ts +14 -0
  174. package/lib/languages/nb.js +275 -100
  175. package/lib/languages/nl.d.ts +26 -0
  176. package/lib/languages/nl.js +307 -174
  177. package/lib/languages/pa.d.ts +7 -0
  178. package/lib/languages/pa.js +163 -0
  179. package/lib/languages/pl.d.ts +22 -0
  180. package/lib/languages/pl.js +299 -158
  181. package/lib/languages/pt.d.ts +17 -0
  182. package/lib/languages/pt.js +279 -120
  183. package/lib/languages/ro.d.ts +18 -0
  184. package/lib/languages/ro.js +214 -337
  185. package/lib/languages/ru.d.ts +11 -0
  186. package/lib/languages/ru.js +219 -95
  187. package/lib/languages/sr-Cyrl.d.ts +11 -0
  188. package/lib/languages/sr-Cyrl.js +215 -0
  189. package/lib/languages/sr-Latn.d.ts +11 -0
  190. package/lib/languages/sr-Latn.js +190 -132
  191. package/lib/languages/sv.d.ts +14 -0
  192. package/lib/languages/sv.js +280 -103
  193. package/lib/languages/sw.d.ts +7 -0
  194. package/lib/languages/sw.js +135 -103
  195. package/lib/languages/ta.d.ts +7 -0
  196. package/lib/languages/ta.js +133 -205
  197. package/lib/languages/te.d.ts +7 -0
  198. package/lib/languages/te.js +148 -213
  199. package/lib/languages/th.d.ts +7 -0
  200. package/lib/languages/th.js +139 -101
  201. package/lib/languages/tr.d.ts +18 -0
  202. package/lib/languages/tr.js +246 -66
  203. package/lib/languages/uk.d.ts +11 -0
  204. package/lib/languages/uk.js +197 -101
  205. package/lib/languages/ur.d.ts +7 -0
  206. package/lib/languages/ur.js +160 -123
  207. package/lib/languages/vi.d.ts +17 -0
  208. package/lib/languages/vi.js +287 -164
  209. package/lib/languages/zh-Hans.d.ts +11 -0
  210. package/lib/languages/zh-Hans.js +159 -142
  211. package/lib/languages/zh-Hant.d.ts +11 -0
  212. package/lib/languages/zh-Hant.js +202 -0
  213. package/lib/n2words.d.ts +53 -0
  214. package/lib/n2words.js +91 -227
  215. package/lib/utils/is-plain-object.d.ts +13 -0
  216. package/lib/utils/is-plain-object.js +17 -0
  217. package/lib/utils/parse-numeric.d.ts +17 -0
  218. package/lib/utils/parse-numeric.js +108 -0
  219. package/lib/utils/validate-options.d.ts +8 -0
  220. package/lib/utils/validate-options.js +16 -0
  221. package/package.json +118 -67
  222. package/dist/languages/pa-Guru.js +0 -2
  223. package/dist/languages/pa-Guru.js.map +0 -1
  224. package/lib/classes/abstract-language.js +0 -261
  225. package/lib/classes/greedy-scale-language.js +0 -195
  226. package/lib/classes/slavic-language.js +0 -251
  227. package/lib/classes/south-asian-language.js +0 -161
  228. package/lib/classes/turkic-language.js +0 -63
  229. package/lib/languages/pa-Guru.js +0 -126
  230. package/typings/classes/abstract-language.d.ts +0 -144
  231. package/typings/classes/greedy-scale-language.d.ts +0 -148
  232. package/typings/classes/slavic-language.d.ts +0 -145
  233. package/typings/classes/south-asian-language.d.ts +0 -101
  234. package/typings/classes/turkic-language.d.ts +0 -42
  235. package/typings/languages/ar.d.ts +0 -93
  236. package/typings/languages/az.d.ts +0 -25
  237. package/typings/languages/bn.d.ts +0 -1
  238. package/typings/languages/cs.d.ts +0 -120
  239. package/typings/languages/da.d.ts +0 -53
  240. package/typings/languages/de.d.ts +0 -26
  241. package/typings/languages/el.d.ts +0 -11
  242. package/typings/languages/en.d.ts +0 -30
  243. package/typings/languages/es.d.ts +0 -43
  244. package/typings/languages/fa.d.ts +0 -81
  245. package/typings/languages/fil.d.ts +0 -12
  246. package/typings/languages/fr-BE.d.ts +0 -41
  247. package/typings/languages/fr.d.ts +0 -43
  248. package/typings/languages/gu.d.ts +0 -12
  249. package/typings/languages/he.d.ts +0 -197
  250. package/typings/languages/hi.d.ts +0 -1
  251. package/typings/languages/hr.d.ts +0 -110
  252. package/typings/languages/hu.d.ts +0 -37
  253. package/typings/languages/id.d.ts +0 -69
  254. package/typings/languages/it.d.ts +0 -51
  255. package/typings/languages/ja.d.ts +0 -58
  256. package/typings/languages/kn.d.ts +0 -11
  257. package/typings/languages/ko.d.ts +0 -25
  258. package/typings/languages/lt.d.ts +0 -110
  259. package/typings/languages/lv.d.ts +0 -99
  260. package/typings/languages/mr.d.ts +0 -12
  261. package/typings/languages/ms.d.ts +0 -37
  262. package/typings/languages/nb.d.ts +0 -27
  263. package/typings/languages/nl.d.ts +0 -65
  264. package/typings/languages/pa-Guru.d.ts +0 -1
  265. package/typings/languages/pl.d.ts +0 -116
  266. package/typings/languages/pt.d.ts +0 -39
  267. package/typings/languages/ro.d.ts +0 -229
  268. package/typings/languages/ru.d.ts +0 -108
  269. package/typings/languages/sr-Latn.d.ts +0 -98
  270. package/typings/languages/sv.d.ts +0 -30
  271. package/typings/languages/sw.d.ts +0 -1
  272. package/typings/languages/ta.d.ts +0 -1
  273. package/typings/languages/te.d.ts +0 -1
  274. package/typings/languages/th.d.ts +0 -1
  275. package/typings/languages/tr.d.ts +0 -46
  276. package/typings/languages/uk.d.ts +0 -117
  277. package/typings/languages/ur.d.ts +0 -1
  278. package/typings/languages/vi.d.ts +0 -116
  279. package/typings/languages/zh-Hans.d.ts +0 -57
  280. package/typings/n2words.d.ts +0 -177
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Converts a numeric value to Turkish words.
3
+ *
4
+ * @param {number | string | bigint} value - The numeric value to convert
5
+ * @param {Object} [options] - Conversion options
6
+ * @param {boolean} [options.dropSpaces=false] - Remove spaces for compound form
7
+ * @returns {string} The number in Turkish words
8
+ * @throws {TypeError} If value is not a valid numeric type
9
+ * @throws {Error} If value is not a valid number format
10
+ *
11
+ * @example
12
+ * toWords(21) // 'yirmi bir'
13
+ * toWords(21, { dropSpaces: true }) // 'yirmibir'
14
+ * toWords(1000) // 'bin'
15
+ */
16
+ export function toWords(value: number | string | bigint, options?: {
17
+ dropSpaces?: boolean | undefined;
18
+ }): string;
@@ -1,83 +1,263 @@
1
- import TurkicLanguage from '../classes/turkic-language.js'
1
+ /**
2
+ * Turkish language converter - Functional Implementation
3
+ *
4
+ * A performance-optimized number-to-words converter using precomputed lookup tables.
5
+ *
6
+ * Key features:
7
+ * - Omits 'bir' (one) before hundreds and thousands
8
+ * - Optional dropSpaces for compound form
9
+ * - Short scale naming
10
+ */
11
+
12
+ import { parseNumericValue } from '../utils/parse-numeric.js'
13
+ import { validateOptions } from '../utils/validate-options.js'
14
+
15
+ // ============================================================================
16
+ // Vocabulary (module-level constants)
17
+ // ============================================================================
18
+
19
+ const ONES = ['', 'bir', 'iki', 'üç', 'dört', 'beş', 'altı', 'yedi', 'sekiz', 'dokuz']
20
+
21
+ const TEENS = ['on', 'on bir', 'on iki', 'on üç', 'on dört', 'on beş', 'on altı', 'on yedi', 'on sekiz', 'on dokuz']
22
+ const TENS = ['', '', 'yirmi', 'otuz', 'kırk', 'elli', 'altmış', 'yetmiş', 'seksen', 'doksan']
23
+
24
+ const HUNDRED = 'yüz'
25
+ const THOUSAND = 'bin'
26
+
27
+ const ZERO = 'sıfır'
28
+ const NEGATIVE = 'eksi'
29
+ const DECIMAL_SEP = 'virgül'
30
+
31
+ // Short scale
32
+ const SCALES = ['milyon', 'milyar', 'trilyon', 'katrilyon', 'kentilyon']
33
+
34
+ // ============================================================================
35
+ // Precomputed Lookup Tables (built once at module load)
36
+ // ============================================================================
37
+
38
+ /**
39
+ * Builds segment word for 0-999.
40
+ * Omits "bir" before "yüz" (hundred).
41
+ */
42
+ function buildSegment (n, separator = ' ') {
43
+ if (n === 0) return ''
44
+
45
+ const ones = n % 10
46
+ const tens = Math.floor(n / 10) % 10
47
+ const hundreds = Math.floor(n / 100)
48
+
49
+ const parts = []
50
+
51
+ // Hundreds - omit "bir" before yüz
52
+ if (hundreds > 0) {
53
+ if (hundreds === 1) {
54
+ parts.push(HUNDRED)
55
+ } else {
56
+ parts.push(ONES[hundreds] + separator + HUNDRED)
57
+ }
58
+ }
59
+
60
+ // Tens and ones
61
+ const tensOnes = n % 100
62
+
63
+ if (tensOnes === 0) {
64
+ // Just hundreds
65
+ } else if (tensOnes < 10) {
66
+ parts.push(ONES[ones])
67
+ } else if (tensOnes < 20) {
68
+ parts.push(TEENS[ones].replace(' ', separator))
69
+ } else if (ones === 0) {
70
+ parts.push(TENS[tens])
71
+ } else {
72
+ parts.push(TENS[tens] + separator + ONES[ones])
73
+ }
74
+
75
+ return parts.join(separator)
76
+ }
77
+
78
+ // Precompute all 1000 segment words (0-999) with space separator
79
+ const SEGMENTS = new Array(1000)
80
+ const SEGMENTS_NO_SPACE = new Array(1000)
81
+
82
+ for (let i = 0; i < 1000; i++) {
83
+ SEGMENTS[i] = buildSegment(i, ' ')
84
+ SEGMENTS_NO_SPACE[i] = buildSegment(i, '')
85
+ }
86
+
87
+ // ============================================================================
88
+ // Conversion Functions
89
+ // ============================================================================
2
90
 
3
91
  /**
4
- * @typedef {Object} TurkishOptions
5
- * @property {boolean} [dropSpaces=false] Remove spaces between words if true.
92
+ * Converts a non-negative integer to Turkish words.
93
+ *
94
+ * @param {bigint} n - Non-negative integer to convert
95
+ * @param {Object} options - Conversion options
96
+ * @returns {string} Turkish words
6
97
  */
98
+ function integerToWords (n, options = {}) {
99
+ if (n === 0n) return ZERO
100
+
101
+ const sep = options.dropSpaces ? '' : ' '
102
+ const segments = options.dropSpaces ? SEGMENTS_NO_SPACE : SEGMENTS
103
+
104
+ // Fast path: numbers < 1000 (direct lookup)
105
+ if (n < 1000n) {
106
+ return segments[Number(n)]
107
+ }
108
+
109
+ // Fast path: numbers < 1,000,000 (thousands)
110
+ if (n < 1_000_000n) {
111
+ const thousands = Number(n / 1000n)
112
+ const remainder = Number(n % 1000n)
113
+
114
+ // Omit "bir" before bin (thousand)
115
+ let result
116
+ if (thousands === 1) {
117
+ result = THOUSAND
118
+ } else {
119
+ result = segments[thousands] + sep + THOUSAND
120
+ }
121
+
122
+ if (remainder > 0) {
123
+ result += sep + segments[remainder]
124
+ }
125
+
126
+ return result
127
+ }
128
+
129
+ // For numbers >= 1,000,000, use scale decomposition
130
+ return buildLargeNumberWords(n, options)
131
+ }
7
132
 
8
133
  /**
9
- * Turkish language converter.
134
+ * Builds words for numbers >= 1,000,000.
10
135
  *
11
- * Inherits from TurkicLanguage shared patterns:
12
- * - Space-separated number combinations
13
- * - Omits '1' before hundreds and thousands
14
- * - Optional word spacing (dropSpaces option)
15
- * - Supports 'ş', 'ç', 'ğ', 'ı', 'ü', 'ö' characters
136
+ * @param {bigint} n - Number >= 1,000,000
137
+ * @param {Object} options - Conversion options
138
+ * @returns {string} Turkish words
16
139
  */
17
- export class Turkish extends TurkicLanguage {
18
- negativeWord = 'eksi'
19
- decimalSeparatorWord = 'virgül'
20
- zeroWord = 'sıfır'
21
- wordSeparator = ' '
22
- scaleWordPairs = [
23
- [1_000_000_000_000_000_000n, 'kentilyon'],
24
- [1_000_000_000_000_000n, 'katrilyon'],
25
- [1_000_000_000_000n, 'trilyon'],
26
- [1_000_000_000n, 'milyar'],
27
- [1_000_000n, 'milyon'],
28
- [1000n, 'bin'],
29
- [100n, 'yüz'],
30
- [90n, 'doksan'],
31
- [80n, 'seksen'],
32
- [70n, 'yetmiş'],
33
- [60n, 'altmış'],
34
- [50n, 'elli'],
35
- [40n, 'kırk'],
36
- [30n, 'otuz'],
37
- [20n, 'yirmi'],
38
- [10n, 'on'],
39
- [9n, 'dokuz'],
40
- [8n, 'sekiz'],
41
- [7n, 'yedi'],
42
- [6n, 'altı'],
43
- [5n, 'beş'],
44
- [4n, 'dört'],
45
- [3n, 'üç'],
46
- [2n, 'iki'],
47
- [1n, 'bir'],
48
- [0n, 'sıfır']
49
- ]
50
-
51
- /**
52
- * Initializes the Turkish converter with language-specific options.
53
- *
54
- * @param {TurkishOptions} [options={}] Configuration options.
55
- */
56
- constructor ({ dropSpaces = false } = {}) {
57
- super()
58
-
59
- this.dropSpaces = dropSpaces
60
-
61
- if (this.dropSpaces === true) {
62
- this.wordSeparator = ''
140
+ function buildLargeNumberWords (n, options) {
141
+ const sep = options.dropSpaces ? '' : ' '
142
+ const segmentsArr = options.dropSpaces ? SEGMENTS_NO_SPACE : SEGMENTS
143
+
144
+ const numStr = n.toString()
145
+ const len = numStr.length
146
+
147
+ // Build segments of 3 digits from right to left
148
+ const segments = []
149
+ const segmentSize = 3
150
+
151
+ const remainderLen = len % segmentSize
152
+ let pos = 0
153
+ if (remainderLen > 0) {
154
+ segments.push(Number(numStr.slice(0, remainderLen)))
155
+ pos = remainderLen
156
+ }
157
+ while (pos < len) {
158
+ segments.push(Number(numStr.slice(pos, pos + segmentSize)))
159
+ pos += segmentSize
160
+ }
161
+
162
+ // Convert segments to words
163
+ const parts = []
164
+ let scaleIndex = segments.length - 1
165
+
166
+ for (let i = 0; i < segments.length; i++) {
167
+ const segment = segments[i]
168
+
169
+ if (segment !== 0) {
170
+ const segmentWord = segmentsArr[segment]
171
+
172
+ if (scaleIndex === 0) {
173
+ // Units segment
174
+ parts.push(segmentWord)
175
+ } else if (scaleIndex === 1) {
176
+ // Thousands - omit "bir" before bin
177
+ if (segment === 1) {
178
+ parts.push(THOUSAND)
179
+ } else {
180
+ parts.push(segmentWord + sep + THOUSAND)
181
+ }
182
+ } else {
183
+ // Millions+ - "bir" is kept before scale words
184
+ const scaleWord = SCALES[scaleIndex - 2]
185
+ parts.push(segmentWord + sep + scaleWord)
186
+ }
63
187
  }
188
+
189
+ scaleIndex--
190
+ }
191
+
192
+ return parts.join(sep)
193
+ }
194
+
195
+ /**
196
+ * Converts decimal digits to Turkish words.
197
+ *
198
+ * @param {string} decimalPart - Decimal digits (without the point)
199
+ * @param {Object} options - Conversion options
200
+ * @returns {string} Turkish words for decimal part
201
+ */
202
+ function decimalPartToWords (decimalPart, options) {
203
+ const sep = options.dropSpaces ? '' : ' '
204
+ let result = ''
205
+
206
+ // Handle leading zeros
207
+ let i = 0
208
+ while (i < decimalPart.length && decimalPart[i] === '0') {
209
+ if (result) result += sep
210
+ result += ZERO
211
+ i++
212
+ }
213
+
214
+ // Convert remainder as a single number
215
+ const remainder = decimalPart.slice(i)
216
+ if (remainder) {
217
+ if (result) result += sep
218
+ result += integerToWords(BigInt(remainder), options)
64
219
  }
220
+
221
+ return result
65
222
  }
66
223
 
67
224
  /**
68
- * Converts a number to Turkish cardinal (written) form.
225
+ * Converts a numeric value to Turkish words.
69
226
  *
70
- * @param {number|string|bigint} value The number to convert.
71
- * @param {Object} [options] Conversion options (see TR class).
72
- * @param {boolean} [options.dropSpaces=false] Remove spaces between words if true.
73
- * @returns {string} The number expressed in Turkish words.
74
- * @throws {TypeError} If value is NaN or invalid type.
75
- * @throws {Error} If value is an invalid number string.
227
+ * @param {number | string | bigint} value - The numeric value to convert
228
+ * @param {Object} [options] - Conversion options
229
+ * @param {boolean} [options.dropSpaces=false] - Remove spaces for compound form
230
+ * @returns {string} The number in Turkish words
231
+ * @throws {TypeError} If value is not a valid numeric type
232
+ * @throws {Error} If value is not a valid number format
76
233
  *
77
234
  * @example
78
- * convertToWords(42, { lang: 'tr' }); // 'kırk iki'
79
- * convertToWords(42, { lang: 'tr', dropSpaces: true }); // 'kırkiki'
235
+ * toWords(21) // 'yirmi bir'
236
+ * toWords(21, { dropSpaces: true }) // 'yirmibir'
237
+ * toWords(1000) // 'bin'
80
238
  */
81
- export default function convertToWords (value, options = {}) {
82
- return new Turkish(options).convertToWords(value)
239
+ function toWords (value, options) {
240
+ options = validateOptions(options)
241
+ const { isNegative, integerPart, decimalPart } = parseNumericValue(value)
242
+
243
+ const sep = options.dropSpaces ? '' : ' '
244
+ let result = ''
245
+
246
+ if (isNegative) {
247
+ result = NEGATIVE + sep
248
+ }
249
+
250
+ result += integerToWords(integerPart, options)
251
+
252
+ if (decimalPart) {
253
+ result += sep + DECIMAL_SEP + sep + decimalPartToWords(decimalPart, options)
254
+ }
255
+
256
+ return result
83
257
  }
258
+
259
+ // ============================================================================
260
+ // Public API
261
+ // ============================================================================
262
+
263
+ export { toWords }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Converts a numeric value to Ukrainian words.
3
+ *
4
+ * @param {number | string | bigint} value - The numeric value to convert
5
+ * @param {Object} [options] - Optional configuration
6
+ * @param {('masculine'|'feminine')} [options.gender='masculine'] - Grammatical gender
7
+ * @returns {string} The number in Ukrainian words
8
+ */
9
+ export function toWords(value: number | string | bigint, options?: {
10
+ gender?: "masculine" | "feminine" | undefined;
11
+ }): string;