n2words 2.0.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 (327) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/README.md +86 -188
  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 -0
  8. package/dist/languages/ar.js.map +1 -0
  9. package/dist/languages/az.js +3 -0
  10. package/dist/languages/az.js.map +1 -0
  11. package/dist/languages/bn.js +3 -0
  12. package/dist/languages/bn.js.map +1 -0
  13. package/dist/languages/cs.js +3 -0
  14. package/dist/languages/cs.js.map +1 -0
  15. package/dist/languages/da.js +3 -0
  16. package/dist/languages/da.js.map +1 -0
  17. package/dist/languages/de.js +3 -0
  18. package/dist/languages/de.js.map +1 -0
  19. package/dist/languages/el.js +3 -0
  20. package/dist/languages/el.js.map +1 -0
  21. package/dist/languages/en.js +3 -0
  22. package/dist/languages/en.js.map +1 -0
  23. package/dist/languages/es.js +3 -0
  24. package/dist/languages/es.js.map +1 -0
  25. package/dist/languages/fa.js +3 -0
  26. package/dist/languages/fa.js.map +1 -0
  27. package/dist/languages/fi.js +3 -0
  28. package/dist/languages/fi.js.map +1 -0
  29. package/dist/languages/fil.js +3 -0
  30. package/dist/languages/fil.js.map +1 -0
  31. package/dist/languages/fr-BE.js +3 -0
  32. package/dist/languages/fr-BE.js.map +1 -0
  33. package/dist/languages/fr.js +3 -0
  34. package/dist/languages/fr.js.map +1 -0
  35. package/dist/languages/gu.js +3 -0
  36. package/dist/languages/gu.js.map +1 -0
  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 -0
  42. package/dist/languages/he.js.map +1 -0
  43. package/dist/languages/hi.js +3 -0
  44. package/dist/languages/hi.js.map +1 -0
  45. package/dist/languages/hr.js +3 -0
  46. package/dist/languages/hr.js.map +1 -0
  47. package/dist/languages/hu.js +3 -0
  48. package/dist/languages/hu.js.map +1 -0
  49. package/dist/languages/id.js +3 -0
  50. package/dist/languages/id.js.map +1 -0
  51. package/dist/languages/it.js +3 -0
  52. package/dist/languages/it.js.map +1 -0
  53. package/dist/languages/ja.js +3 -0
  54. package/dist/languages/ja.js.map +1 -0
  55. package/dist/languages/kn.js +3 -0
  56. package/dist/languages/kn.js.map +1 -0
  57. package/dist/languages/ko.js +3 -0
  58. package/dist/languages/ko.js.map +1 -0
  59. package/dist/languages/lt.js +3 -0
  60. package/dist/languages/lt.js.map +1 -0
  61. package/dist/languages/lv.js +3 -0
  62. package/dist/languages/lv.js.map +1 -0
  63. package/dist/languages/mr.js +3 -0
  64. package/dist/languages/mr.js.map +1 -0
  65. package/dist/languages/ms.js +3 -0
  66. package/dist/languages/ms.js.map +1 -0
  67. package/dist/languages/nb.js +3 -0
  68. package/dist/languages/nb.js.map +1 -0
  69. package/dist/languages/nl.js +3 -0
  70. package/dist/languages/nl.js.map +1 -0
  71. package/dist/languages/pa.js +3 -0
  72. package/dist/languages/pa.js.map +1 -0
  73. package/dist/languages/pl.js +3 -0
  74. package/dist/languages/pl.js.map +1 -0
  75. package/dist/languages/pt.js +3 -0
  76. package/dist/languages/pt.js.map +1 -0
  77. package/dist/languages/ro.js +3 -0
  78. package/dist/languages/ro.js.map +1 -0
  79. package/dist/languages/ru.js +3 -0
  80. package/dist/languages/ru.js.map +1 -0
  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 -0
  84. package/dist/languages/sr-Latn.js.map +1 -0
  85. package/dist/languages/sv.js +3 -0
  86. package/dist/languages/sv.js.map +1 -0
  87. package/dist/languages/sw.js +3 -0
  88. package/dist/languages/sw.js.map +1 -0
  89. package/dist/languages/ta.js +3 -0
  90. package/dist/languages/ta.js.map +1 -0
  91. package/dist/languages/te.js +3 -0
  92. package/dist/languages/te.js.map +1 -0
  93. package/dist/languages/th.js +3 -0
  94. package/dist/languages/th.js.map +1 -0
  95. package/dist/languages/tr.js +3 -0
  96. package/dist/languages/tr.js.map +1 -0
  97. package/dist/languages/uk.js +3 -0
  98. package/dist/languages/uk.js.map +1 -0
  99. package/dist/languages/ur.js +3 -0
  100. package/dist/languages/ur.js.map +1 -0
  101. package/dist/languages/vi.js +3 -0
  102. package/dist/languages/vi.js.map +1 -0
  103. package/dist/languages/zh-Hans.js +3 -0
  104. package/dist/languages/zh-Hans.js.map +1 -0
  105. package/dist/languages/zh-Hant.js +3 -0
  106. package/dist/languages/zh-Hant.js.map +1 -0
  107. package/dist/n2words.js +2 -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 +14 -27
  114. package/lib/languages/ar.js +175 -129
  115. package/lib/languages/az.d.ts +4 -9
  116. package/lib/languages/az.js +171 -37
  117. package/lib/languages/bn.d.ts +4 -8
  118. package/lib/languages/bn.js +138 -124
  119. package/lib/languages/cs.d.ts +15 -85
  120. package/lib/languages/cs.js +310 -114
  121. package/lib/languages/da.d.ts +11 -12
  122. package/lib/languages/da.js +276 -101
  123. package/lib/languages/de.d.ts +14 -11
  124. package/lib/languages/de.js +317 -86
  125. package/lib/languages/el.d.ts +11 -11
  126. package/lib/languages/el.js +231 -78
  127. package/lib/languages/en.d.ts +14 -13
  128. package/lib/languages/en.js +242 -72
  129. package/lib/languages/es.d.ts +18 -12
  130. package/lib/languages/es.js +317 -103
  131. package/lib/languages/fa.d.ts +4 -44
  132. package/lib/languages/fa.js +112 -122
  133. package/lib/languages/fi.d.ts +14 -0
  134. package/lib/languages/fi.js +245 -0
  135. package/lib/languages/fil.d.ts +4 -13
  136. package/lib/languages/fil.js +207 -106
  137. package/lib/languages/fr-BE.d.ts +8 -8
  138. package/lib/languages/fr-BE.js +294 -19
  139. package/lib/languages/fr.d.ts +18 -12
  140. package/lib/languages/fr.js +352 -89
  141. package/lib/languages/gu.d.ts +4 -8
  142. package/lib/languages/gu.js +130 -125
  143. package/lib/languages/ha.d.ts +7 -0
  144. package/lib/languages/ha.js +230 -0
  145. package/lib/languages/hbo.d.ts +10 -110
  146. package/lib/languages/hbo.js +263 -214
  147. package/lib/languages/he.d.ts +10 -77
  148. package/lib/languages/he.js +242 -172
  149. package/lib/languages/hi.d.ts +4 -8
  150. package/lib/languages/hi.js +138 -124
  151. package/lib/languages/hr.d.ts +8 -77
  152. package/lib/languages/hr.js +194 -89
  153. package/lib/languages/hu.d.ts +4 -19
  154. package/lib/languages/hu.js +198 -119
  155. package/lib/languages/id.d.ts +4 -34
  156. package/lib/languages/id.js +171 -129
  157. package/lib/languages/it.d.ts +16 -34
  158. package/lib/languages/it.js +339 -94
  159. package/lib/languages/ja.d.ts +14 -14
  160. package/lib/languages/ja.js +233 -111
  161. package/lib/languages/kn.d.ts +4 -8
  162. package/lib/languages/kn.js +130 -35
  163. package/lib/languages/ko.d.ts +11 -11
  164. package/lib/languages/ko.js +257 -49
  165. package/lib/languages/lt.d.ts +15 -67
  166. package/lib/languages/lt.js +296 -122
  167. package/lib/languages/lv.d.ts +15 -67
  168. package/lib/languages/lv.js +297 -106
  169. package/lib/languages/mr.d.ts +4 -8
  170. package/lib/languages/mr.js +130 -125
  171. package/lib/languages/ms.d.ts +4 -28
  172. package/lib/languages/ms.js +171 -116
  173. package/lib/languages/nb.d.ts +11 -9
  174. package/lib/languages/nb.js +282 -87
  175. package/lib/languages/nl.d.ts +23 -13
  176. package/lib/languages/nl.js +317 -133
  177. package/lib/languages/pa.d.ts +4 -8
  178. package/lib/languages/pa.js +156 -124
  179. package/lib/languages/pl.d.ts +19 -77
  180. package/lib/languages/pl.js +307 -87
  181. package/lib/languages/pt.d.ts +14 -26
  182. package/lib/languages/pt.js +286 -92
  183. package/lib/languages/ro.d.ts +15 -155
  184. package/lib/languages/ro.js +219 -235
  185. package/lib/languages/ru.d.ts +8 -82
  186. package/lib/languages/ru.js +222 -78
  187. package/lib/languages/sr-Cyrl.d.ts +8 -77
  188. package/lib/languages/sr-Cyrl.js +191 -89
  189. package/lib/languages/sr-Latn.d.ts +8 -77
  190. package/lib/languages/sr-Latn.js +191 -89
  191. package/lib/languages/sv.d.ts +11 -11
  192. package/lib/languages/sv.js +288 -74
  193. package/lib/languages/sw.d.ts +4 -36
  194. package/lib/languages/sw.js +133 -106
  195. package/lib/languages/ta.d.ts +4 -17
  196. package/lib/languages/ta.js +129 -201
  197. package/lib/languages/te.d.ts +4 -19
  198. package/lib/languages/te.js +141 -196
  199. package/lib/languages/th.d.ts +4 -14
  200. package/lib/languages/th.js +135 -91
  201. package/lib/languages/tr.d.ts +15 -9
  202. package/lib/languages/tr.js +256 -49
  203. package/lib/languages/uk.d.ts +8 -82
  204. package/lib/languages/uk.js +200 -78
  205. package/lib/languages/ur.d.ts +4 -8
  206. package/lib/languages/ur.js +156 -124
  207. package/lib/languages/vi.d.ts +14 -69
  208. package/lib/languages/vi.js +294 -125
  209. package/lib/languages/zh-Hans.d.ts +8 -18
  210. package/lib/languages/zh-Hans.js +163 -92
  211. package/lib/languages/zh-Hant.d.ts +8 -18
  212. package/lib/languages/zh-Hant.js +181 -90
  213. package/lib/n2words.d.ts +53 -209
  214. package/lib/n2words.js +111 -530
  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 +26 -14
  222. package/dist/ArabicConverter.js +0 -3
  223. package/dist/ArabicConverter.js.map +0 -1
  224. package/dist/AzerbaijaniConverter.js +0 -3
  225. package/dist/AzerbaijaniConverter.js.map +0 -1
  226. package/dist/BanglaConverter.js +0 -3
  227. package/dist/BanglaConverter.js.map +0 -1
  228. package/dist/BiblicalHebrewConverter.js +0 -3
  229. package/dist/BiblicalHebrewConverter.js.map +0 -1
  230. package/dist/CroatianConverter.js +0 -3
  231. package/dist/CroatianConverter.js.map +0 -1
  232. package/dist/CzechConverter.js +0 -3
  233. package/dist/CzechConverter.js.map +0 -1
  234. package/dist/DanishConverter.js +0 -3
  235. package/dist/DanishConverter.js.map +0 -1
  236. package/dist/DutchConverter.js +0 -3
  237. package/dist/DutchConverter.js.map +0 -1
  238. package/dist/EnglishConverter.js +0 -3
  239. package/dist/EnglishConverter.js.map +0 -1
  240. package/dist/FilipinoConverter.js +0 -3
  241. package/dist/FilipinoConverter.js.map +0 -1
  242. package/dist/FrenchBelgiumConverter.js +0 -3
  243. package/dist/FrenchBelgiumConverter.js.map +0 -1
  244. package/dist/FrenchConverter.js +0 -3
  245. package/dist/FrenchConverter.js.map +0 -1
  246. package/dist/GermanConverter.js +0 -3
  247. package/dist/GermanConverter.js.map +0 -1
  248. package/dist/GreekConverter.js +0 -3
  249. package/dist/GreekConverter.js.map +0 -1
  250. package/dist/GujaratiConverter.js +0 -3
  251. package/dist/GujaratiConverter.js.map +0 -1
  252. package/dist/HebrewConverter.js +0 -3
  253. package/dist/HebrewConverter.js.map +0 -1
  254. package/dist/HindiConverter.js +0 -3
  255. package/dist/HindiConverter.js.map +0 -1
  256. package/dist/HungarianConverter.js +0 -3
  257. package/dist/HungarianConverter.js.map +0 -1
  258. package/dist/IndonesianConverter.js +0 -3
  259. package/dist/IndonesianConverter.js.map +0 -1
  260. package/dist/ItalianConverter.js +0 -3
  261. package/dist/ItalianConverter.js.map +0 -1
  262. package/dist/JapaneseConverter.js +0 -3
  263. package/dist/JapaneseConverter.js.map +0 -1
  264. package/dist/KannadaConverter.js +0 -3
  265. package/dist/KannadaConverter.js.map +0 -1
  266. package/dist/KoreanConverter.js +0 -3
  267. package/dist/KoreanConverter.js.map +0 -1
  268. package/dist/LatvianConverter.js +0 -3
  269. package/dist/LatvianConverter.js.map +0 -1
  270. package/dist/LithuanianConverter.js +0 -3
  271. package/dist/LithuanianConverter.js.map +0 -1
  272. package/dist/MalayConverter.js +0 -3
  273. package/dist/MalayConverter.js.map +0 -1
  274. package/dist/MarathiConverter.js +0 -3
  275. package/dist/MarathiConverter.js.map +0 -1
  276. package/dist/NorwegianBokmalConverter.js +0 -3
  277. package/dist/NorwegianBokmalConverter.js.map +0 -1
  278. package/dist/PersianConverter.js +0 -3
  279. package/dist/PersianConverter.js.map +0 -1
  280. package/dist/PolishConverter.js +0 -3
  281. package/dist/PolishConverter.js.map +0 -1
  282. package/dist/PortugueseConverter.js +0 -3
  283. package/dist/PortugueseConverter.js.map +0 -1
  284. package/dist/PunjabiConverter.js +0 -3
  285. package/dist/PunjabiConverter.js.map +0 -1
  286. package/dist/RomanianConverter.js +0 -3
  287. package/dist/RomanianConverter.js.map +0 -1
  288. package/dist/RussianConverter.js +0 -3
  289. package/dist/RussianConverter.js.map +0 -1
  290. package/dist/SerbianCyrillicConverter.js +0 -3
  291. package/dist/SerbianCyrillicConverter.js.map +0 -1
  292. package/dist/SerbianLatinConverter.js +0 -3
  293. package/dist/SerbianLatinConverter.js.map +0 -1
  294. package/dist/SimplifiedChineseConverter.js +0 -3
  295. package/dist/SimplifiedChineseConverter.js.map +0 -1
  296. package/dist/SpanishConverter.js +0 -3
  297. package/dist/SpanishConverter.js.map +0 -1
  298. package/dist/SwahiliConverter.js +0 -3
  299. package/dist/SwahiliConverter.js.map +0 -1
  300. package/dist/SwedishConverter.js +0 -3
  301. package/dist/SwedishConverter.js.map +0 -1
  302. package/dist/TamilConverter.js +0 -3
  303. package/dist/TamilConverter.js.map +0 -1
  304. package/dist/TeluguConverter.js +0 -3
  305. package/dist/TeluguConverter.js.map +0 -1
  306. package/dist/ThaiConverter.js +0 -3
  307. package/dist/ThaiConverter.js.map +0 -1
  308. package/dist/TraditionalChineseConverter.js +0 -3
  309. package/dist/TraditionalChineseConverter.js.map +0 -1
  310. package/dist/TurkishConverter.js +0 -3
  311. package/dist/TurkishConverter.js.map +0 -1
  312. package/dist/UkrainianConverter.js +0 -3
  313. package/dist/UkrainianConverter.js.map +0 -1
  314. package/dist/UrduConverter.js +0 -3
  315. package/dist/UrduConverter.js.map +0 -1
  316. package/dist/VietnameseConverter.js +0 -3
  317. package/dist/VietnameseConverter.js.map +0 -1
  318. package/lib/classes/abstract-language.d.ts +0 -178
  319. package/lib/classes/abstract-language.js +0 -268
  320. package/lib/classes/greedy-scale-language.d.ts +0 -109
  321. package/lib/classes/greedy-scale-language.js +0 -201
  322. package/lib/classes/slavic-language.d.ts +0 -148
  323. package/lib/classes/slavic-language.js +0 -281
  324. package/lib/classes/south-asian-language.d.ts +0 -70
  325. package/lib/classes/south-asian-language.js +0 -154
  326. package/lib/classes/turkic-language.d.ts +0 -26
  327. package/lib/classes/turkic-language.js +0 -59
@@ -1,56 +1,263 @@
1
- import { TurkicLanguage } from '../classes/turkic-language.js'
2
-
3
1
  /**
4
- * Turkish language converter.
2
+ * Turkish language converter - Functional Implementation
3
+ *
4
+ * A performance-optimized number-to-words converter using precomputed lookup tables.
5
5
  *
6
- * Supports:
6
+ * Key features:
7
7
  * - Omits 'bir' (one) before hundreds and thousands
8
- * - Optional space removal via dropSpaces option
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
+ // ============================================================================
90
+
91
+ /**
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
9
97
  */
10
- export class Turkish extends TurkicLanguage {
11
- negativeWord = 'eksi'
12
- decimalSeparatorWord = 'virgül'
13
- zeroWord = 'sıfır'
14
- wordSeparator = ' '
15
-
16
- scaleWords = [
17
- [1_000_000_000_000_000_000n, 'kentilyon'],
18
- [1_000_000_000_000_000n, 'katrilyon'],
19
- [1_000_000_000_000n, 'trilyon'],
20
- [1_000_000_000n, 'milyar'],
21
- [1_000_000n, 'milyon'],
22
- [1000n, 'bin'],
23
- [100n, 'yüz'],
24
- [90n, 'doksan'],
25
- [80n, 'seksen'],
26
- [70n, 'yetmiş'],
27
- [60n, 'altmış'],
28
- [50n, 'elli'],
29
- [40n, 'kırk'],
30
- [30n, 'otuz'],
31
- [20n, 'yirmi'],
32
- [10n, 'on'],
33
- [9n, 'dokuz'],
34
- [8n, 'sekiz'],
35
- [7n, 'yedi'],
36
- [6n, 'altı'],
37
- [5n, 'beş'],
38
- [4n, 'dört'],
39
- [3n, 'üç'],
40
- [2n, 'iki'],
41
- [1n, 'bir'],
42
- [0n, 'sıfır']
43
- ]
44
-
45
- constructor (options = {}) {
46
- super()
47
-
48
- this.setOptions({
49
- dropSpaces: false
50
- }, options)
51
-
52
- if (this.options.dropSpaces) {
53
- this.wordSeparator = ''
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]
54
124
  }
125
+
126
+ return result
55
127
  }
128
+
129
+ // For numbers >= 1,000,000, use scale decomposition
130
+ return buildLargeNumberWords(n, options)
56
131
  }
132
+
133
+ /**
134
+ * Builds words for numbers >= 1,000,000.
135
+ *
136
+ * @param {bigint} n - Number >= 1,000,000
137
+ * @param {Object} options - Conversion options
138
+ * @returns {string} Turkish words
139
+ */
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
+ }
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)
219
+ }
220
+
221
+ return result
222
+ }
223
+
224
+ /**
225
+ * Converts a numeric value to Turkish words.
226
+ *
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
233
+ *
234
+ * @example
235
+ * toWords(21) // 'yirmi bir'
236
+ * toWords(21, { dropSpaces: true }) // 'yirmibir'
237
+ * toWords(1000) // 'bin'
238
+ */
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
257
+ }
258
+
259
+ // ============================================================================
260
+ // Public API
261
+ // ============================================================================
262
+
263
+ export { toWords }
@@ -1,85 +1,11 @@
1
1
  /**
2
- * Ukrainian language converter.
2
+ * Converts a numeric value to Ukrainian words.
3
3
  *
4
- * Supports:
5
- * - Three-form pluralization (one/few/many)
6
- * - Gender agreement (один/одна, два/дві)
7
- * - Ukrainian orthography and phonology
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
8
  */
9
- export class Ukrainian extends SlavicLanguage {
10
- onesWords: {
11
- 1: string;
12
- 2: string;
13
- 3: string;
14
- 4: string;
15
- 5: string;
16
- 6: string;
17
- 7: string;
18
- 8: string;
19
- 9: string;
20
- };
21
- onesFeminineWords: {
22
- 1: string;
23
- 2: string;
24
- 3: string;
25
- 4: string;
26
- 5: string;
27
- 6: string;
28
- 7: string;
29
- 8: string;
30
- 9: string;
31
- };
32
- teensWords: {
33
- 0: string;
34
- 1: string;
35
- 2: string;
36
- 3: string;
37
- 4: string;
38
- 5: string;
39
- 6: string;
40
- 7: string;
41
- 8: string;
42
- 9: string;
43
- };
44
- twentiesWords: {
45
- 2: string;
46
- 3: string;
47
- 4: string;
48
- 5: string;
49
- 6: string;
50
- 7: string;
51
- 8: string;
52
- 9: string;
53
- };
54
- hundredsWords: {
55
- 1: string;
56
- 2: string;
57
- 3: string;
58
- 4: string;
59
- 5: string;
60
- 6: string;
61
- 7: string;
62
- 8: string;
63
- 9: string;
64
- };
65
- pluralForms: {
66
- 1: string[];
67
- 2: string[];
68
- 3: string[];
69
- 4: string[];
70
- 5: string[];
71
- 6: string[];
72
- 7: string[];
73
- 8: string[];
74
- 9: string[];
75
- 10: string[];
76
- };
77
- /**
78
- * Ukrainian thousands (тисяча) are feminine, requiring одна/двi forms.
79
- * Other scales (million, billion, etc.) are masculine.
80
- */
81
- scaleGenders: {
82
- 1: boolean;
83
- };
84
- }
85
- import { SlavicLanguage } from '../classes/slavic-language.js';
9
+ export function toWords(value: number | string | bigint, options?: {
10
+ gender?: "masculine" | "feminine" | undefined;
11
+ }): string;