n2words 2.0.0 → 3.1.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 (335) hide show
  1. package/CHANGELOG.md +64 -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/ka.js +3 -0
  56. package/dist/languages/ka.js.map +1 -0
  57. package/dist/languages/kn.js +3 -0
  58. package/dist/languages/kn.js.map +1 -0
  59. package/dist/languages/ko.js +3 -0
  60. package/dist/languages/ko.js.map +1 -0
  61. package/dist/languages/lt.js +3 -0
  62. package/dist/languages/lt.js.map +1 -0
  63. package/dist/languages/lv.js +3 -0
  64. package/dist/languages/lv.js.map +1 -0
  65. package/dist/languages/mr.js +3 -0
  66. package/dist/languages/mr.js.map +1 -0
  67. package/dist/languages/ms.js +3 -0
  68. package/dist/languages/ms.js.map +1 -0
  69. package/dist/languages/nb.js +3 -0
  70. package/dist/languages/nb.js.map +1 -0
  71. package/dist/languages/nl.js +3 -0
  72. package/dist/languages/nl.js.map +1 -0
  73. package/dist/languages/pa.js +3 -0
  74. package/dist/languages/pa.js.map +1 -0
  75. package/dist/languages/pl.js +3 -0
  76. package/dist/languages/pl.js.map +1 -0
  77. package/dist/languages/pt.js +3 -0
  78. package/dist/languages/pt.js.map +1 -0
  79. package/dist/languages/ro.js +3 -0
  80. package/dist/languages/ro.js.map +1 -0
  81. package/dist/languages/ru.js +3 -0
  82. package/dist/languages/ru.js.map +1 -0
  83. package/dist/languages/sr-Cyrl.js +3 -0
  84. package/dist/languages/sr-Cyrl.js.map +1 -0
  85. package/dist/languages/sr-Latn.js +3 -0
  86. package/dist/languages/sr-Latn.js.map +1 -0
  87. package/dist/languages/sv.js +3 -0
  88. package/dist/languages/sv.js.map +1 -0
  89. package/dist/languages/sw.js +3 -0
  90. package/dist/languages/sw.js.map +1 -0
  91. package/dist/languages/ta.js +3 -0
  92. package/dist/languages/ta.js.map +1 -0
  93. package/dist/languages/te.js +3 -0
  94. package/dist/languages/te.js.map +1 -0
  95. package/dist/languages/th.js +3 -0
  96. package/dist/languages/th.js.map +1 -0
  97. package/dist/languages/tr.js +3 -0
  98. package/dist/languages/tr.js.map +1 -0
  99. package/dist/languages/uk.js +3 -0
  100. package/dist/languages/uk.js.map +1 -0
  101. package/dist/languages/ur.js +3 -0
  102. package/dist/languages/ur.js.map +1 -0
  103. package/dist/languages/vi.js +3 -0
  104. package/dist/languages/vi.js.map +1 -0
  105. package/dist/languages/yo.js +3 -0
  106. package/dist/languages/yo.js.map +1 -0
  107. package/dist/languages/zh-Hans.js +3 -0
  108. package/dist/languages/zh-Hans.js.map +1 -0
  109. package/dist/languages/zh-Hant.js +3 -0
  110. package/dist/languages/zh-Hant.js.map +1 -0
  111. package/dist/n2words.js +2 -2
  112. package/dist/n2words.js.map +1 -1
  113. package/lib/languages/am-Latn.d.ts +7 -0
  114. package/lib/languages/am-Latn.js +159 -0
  115. package/lib/languages/am.d.ts +7 -0
  116. package/lib/languages/am.js +159 -0
  117. package/lib/languages/ar.d.ts +14 -27
  118. package/lib/languages/ar.js +175 -129
  119. package/lib/languages/az.d.ts +4 -9
  120. package/lib/languages/az.js +166 -37
  121. package/lib/languages/bn.d.ts +4 -8
  122. package/lib/languages/bn.js +159 -124
  123. package/lib/languages/cs.d.ts +15 -85
  124. package/lib/languages/cs.js +293 -114
  125. package/lib/languages/da.d.ts +11 -12
  126. package/lib/languages/da.js +269 -101
  127. package/lib/languages/de.d.ts +14 -11
  128. package/lib/languages/de.js +305 -86
  129. package/lib/languages/el.d.ts +11 -11
  130. package/lib/languages/el.js +224 -78
  131. package/lib/languages/en.d.ts +14 -13
  132. package/lib/languages/en.js +228 -72
  133. package/lib/languages/es.d.ts +18 -12
  134. package/lib/languages/es.js +297 -103
  135. package/lib/languages/fa.d.ts +4 -44
  136. package/lib/languages/fa.js +112 -122
  137. package/lib/languages/fi.d.ts +14 -0
  138. package/lib/languages/fi.js +238 -0
  139. package/lib/languages/fil.d.ts +4 -13
  140. package/lib/languages/fil.js +196 -106
  141. package/lib/languages/fr-BE.d.ts +8 -8
  142. package/lib/languages/fr-BE.js +285 -19
  143. package/lib/languages/fr.d.ts +18 -12
  144. package/lib/languages/fr.js +339 -89
  145. package/lib/languages/gu.d.ts +4 -8
  146. package/lib/languages/gu.js +143 -125
  147. package/lib/languages/ha.d.ts +7 -0
  148. package/lib/languages/ha.js +225 -0
  149. package/lib/languages/hbo.d.ts +10 -110
  150. package/lib/languages/hbo.js +245 -214
  151. package/lib/languages/he.d.ts +10 -77
  152. package/lib/languages/he.js +231 -172
  153. package/lib/languages/hi.d.ts +4 -8
  154. package/lib/languages/hi.js +163 -124
  155. package/lib/languages/hr.d.ts +8 -77
  156. package/lib/languages/hr.js +200 -89
  157. package/lib/languages/hu.d.ts +4 -19
  158. package/lib/languages/hu.js +198 -119
  159. package/lib/languages/id.d.ts +4 -34
  160. package/lib/languages/id.js +166 -129
  161. package/lib/languages/it.d.ts +16 -34
  162. package/lib/languages/it.js +307 -97
  163. package/lib/languages/ja.d.ts +14 -14
  164. package/lib/languages/ja.js +221 -111
  165. package/lib/languages/ka.d.ts +17 -0
  166. package/lib/languages/ka.js +291 -0
  167. package/lib/languages/kn.d.ts +4 -8
  168. package/lib/languages/kn.js +143 -35
  169. package/lib/languages/ko.d.ts +11 -11
  170. package/lib/languages/ko.js +250 -49
  171. package/lib/languages/lt.d.ts +15 -67
  172. package/lib/languages/lt.js +287 -122
  173. package/lib/languages/lv.d.ts +15 -67
  174. package/lib/languages/lv.js +288 -106
  175. package/lib/languages/mr.d.ts +4 -8
  176. package/lib/languages/mr.js +143 -125
  177. package/lib/languages/ms.d.ts +4 -28
  178. package/lib/languages/ms.js +166 -116
  179. package/lib/languages/nb.d.ts +11 -9
  180. package/lib/languages/nb.js +272 -87
  181. package/lib/languages/nl.d.ts +23 -13
  182. package/lib/languages/nl.js +299 -133
  183. package/lib/languages/pa.d.ts +4 -8
  184. package/lib/languages/pa.js +151 -124
  185. package/lib/languages/pl.d.ts +19 -77
  186. package/lib/languages/pl.js +294 -87
  187. package/lib/languages/pt.d.ts +14 -26
  188. package/lib/languages/pt.js +272 -92
  189. package/lib/languages/ro.d.ts +15 -155
  190. package/lib/languages/ro.js +219 -235
  191. package/lib/languages/ru.d.ts +8 -82
  192. package/lib/languages/ru.js +239 -90
  193. package/lib/languages/sr-Cyrl.d.ts +8 -77
  194. package/lib/languages/sr-Cyrl.js +197 -89
  195. package/lib/languages/sr-Latn.d.ts +8 -77
  196. package/lib/languages/sr-Latn.js +197 -89
  197. package/lib/languages/sv.d.ts +11 -11
  198. package/lib/languages/sv.js +278 -74
  199. package/lib/languages/sw.d.ts +4 -36
  200. package/lib/languages/sw.js +133 -106
  201. package/lib/languages/ta.d.ts +4 -17
  202. package/lib/languages/ta.js +143 -202
  203. package/lib/languages/te.d.ts +4 -19
  204. package/lib/languages/te.js +133 -196
  205. package/lib/languages/th.d.ts +4 -14
  206. package/lib/languages/th.js +135 -91
  207. package/lib/languages/tr.d.ts +15 -9
  208. package/lib/languages/tr.js +245 -49
  209. package/lib/languages/uk.d.ts +8 -82
  210. package/lib/languages/uk.js +206 -78
  211. package/lib/languages/ur.d.ts +4 -8
  212. package/lib/languages/ur.js +151 -124
  213. package/lib/languages/vi.d.ts +14 -69
  214. package/lib/languages/vi.js +278 -129
  215. package/lib/languages/yo.d.ts +7 -0
  216. package/lib/languages/yo.js +303 -0
  217. package/lib/languages/zh-Hans.d.ts +8 -18
  218. package/lib/languages/zh-Hans.js +163 -92
  219. package/lib/languages/zh-Hant.d.ts +8 -18
  220. package/lib/languages/zh-Hant.js +181 -90
  221. package/lib/n2words.d.ts +55 -209
  222. package/lib/n2words.js +115 -530
  223. package/lib/utils/is-plain-object.d.ts +13 -0
  224. package/lib/utils/is-plain-object.js +17 -0
  225. package/lib/utils/parse-numeric.d.ts +17 -0
  226. package/lib/utils/parse-numeric.js +108 -0
  227. package/lib/utils/validate-options.d.ts +8 -0
  228. package/lib/utils/validate-options.js +16 -0
  229. package/package.json +26 -14
  230. package/dist/ArabicConverter.js +0 -3
  231. package/dist/ArabicConverter.js.map +0 -1
  232. package/dist/AzerbaijaniConverter.js +0 -3
  233. package/dist/AzerbaijaniConverter.js.map +0 -1
  234. package/dist/BanglaConverter.js +0 -3
  235. package/dist/BanglaConverter.js.map +0 -1
  236. package/dist/BiblicalHebrewConverter.js +0 -3
  237. package/dist/BiblicalHebrewConverter.js.map +0 -1
  238. package/dist/CroatianConverter.js +0 -3
  239. package/dist/CroatianConverter.js.map +0 -1
  240. package/dist/CzechConverter.js +0 -3
  241. package/dist/CzechConverter.js.map +0 -1
  242. package/dist/DanishConverter.js +0 -3
  243. package/dist/DanishConverter.js.map +0 -1
  244. package/dist/DutchConverter.js +0 -3
  245. package/dist/DutchConverter.js.map +0 -1
  246. package/dist/EnglishConverter.js +0 -3
  247. package/dist/EnglishConverter.js.map +0 -1
  248. package/dist/FilipinoConverter.js +0 -3
  249. package/dist/FilipinoConverter.js.map +0 -1
  250. package/dist/FrenchBelgiumConverter.js +0 -3
  251. package/dist/FrenchBelgiumConverter.js.map +0 -1
  252. package/dist/FrenchConverter.js +0 -3
  253. package/dist/FrenchConverter.js.map +0 -1
  254. package/dist/GermanConverter.js +0 -3
  255. package/dist/GermanConverter.js.map +0 -1
  256. package/dist/GreekConverter.js +0 -3
  257. package/dist/GreekConverter.js.map +0 -1
  258. package/dist/GujaratiConverter.js +0 -3
  259. package/dist/GujaratiConverter.js.map +0 -1
  260. package/dist/HebrewConverter.js +0 -3
  261. package/dist/HebrewConverter.js.map +0 -1
  262. package/dist/HindiConverter.js +0 -3
  263. package/dist/HindiConverter.js.map +0 -1
  264. package/dist/HungarianConverter.js +0 -3
  265. package/dist/HungarianConverter.js.map +0 -1
  266. package/dist/IndonesianConverter.js +0 -3
  267. package/dist/IndonesianConverter.js.map +0 -1
  268. package/dist/ItalianConverter.js +0 -3
  269. package/dist/ItalianConverter.js.map +0 -1
  270. package/dist/JapaneseConverter.js +0 -3
  271. package/dist/JapaneseConverter.js.map +0 -1
  272. package/dist/KannadaConverter.js +0 -3
  273. package/dist/KannadaConverter.js.map +0 -1
  274. package/dist/KoreanConverter.js +0 -3
  275. package/dist/KoreanConverter.js.map +0 -1
  276. package/dist/LatvianConverter.js +0 -3
  277. package/dist/LatvianConverter.js.map +0 -1
  278. package/dist/LithuanianConverter.js +0 -3
  279. package/dist/LithuanianConverter.js.map +0 -1
  280. package/dist/MalayConverter.js +0 -3
  281. package/dist/MalayConverter.js.map +0 -1
  282. package/dist/MarathiConverter.js +0 -3
  283. package/dist/MarathiConverter.js.map +0 -1
  284. package/dist/NorwegianBokmalConverter.js +0 -3
  285. package/dist/NorwegianBokmalConverter.js.map +0 -1
  286. package/dist/PersianConverter.js +0 -3
  287. package/dist/PersianConverter.js.map +0 -1
  288. package/dist/PolishConverter.js +0 -3
  289. package/dist/PolishConverter.js.map +0 -1
  290. package/dist/PortugueseConverter.js +0 -3
  291. package/dist/PortugueseConverter.js.map +0 -1
  292. package/dist/PunjabiConverter.js +0 -3
  293. package/dist/PunjabiConverter.js.map +0 -1
  294. package/dist/RomanianConverter.js +0 -3
  295. package/dist/RomanianConverter.js.map +0 -1
  296. package/dist/RussianConverter.js +0 -3
  297. package/dist/RussianConverter.js.map +0 -1
  298. package/dist/SerbianCyrillicConverter.js +0 -3
  299. package/dist/SerbianCyrillicConverter.js.map +0 -1
  300. package/dist/SerbianLatinConverter.js +0 -3
  301. package/dist/SerbianLatinConverter.js.map +0 -1
  302. package/dist/SimplifiedChineseConverter.js +0 -3
  303. package/dist/SimplifiedChineseConverter.js.map +0 -1
  304. package/dist/SpanishConverter.js +0 -3
  305. package/dist/SpanishConverter.js.map +0 -1
  306. package/dist/SwahiliConverter.js +0 -3
  307. package/dist/SwahiliConverter.js.map +0 -1
  308. package/dist/SwedishConverter.js +0 -3
  309. package/dist/SwedishConverter.js.map +0 -1
  310. package/dist/TamilConverter.js +0 -3
  311. package/dist/TamilConverter.js.map +0 -1
  312. package/dist/TeluguConverter.js +0 -3
  313. package/dist/TeluguConverter.js.map +0 -1
  314. package/dist/ThaiConverter.js +0 -3
  315. package/dist/ThaiConverter.js.map +0 -1
  316. package/dist/TraditionalChineseConverter.js +0 -3
  317. package/dist/TraditionalChineseConverter.js.map +0 -1
  318. package/dist/TurkishConverter.js +0 -3
  319. package/dist/TurkishConverter.js.map +0 -1
  320. package/dist/UkrainianConverter.js +0 -3
  321. package/dist/UkrainianConverter.js.map +0 -1
  322. package/dist/UrduConverter.js +0 -3
  323. package/dist/UrduConverter.js.map +0 -1
  324. package/dist/VietnameseConverter.js +0 -3
  325. package/dist/VietnameseConverter.js.map +0 -1
  326. package/lib/classes/abstract-language.d.ts +0 -178
  327. package/lib/classes/abstract-language.js +0 -268
  328. package/lib/classes/greedy-scale-language.d.ts +0 -109
  329. package/lib/classes/greedy-scale-language.js +0 -201
  330. package/lib/classes/slavic-language.d.ts +0 -148
  331. package/lib/classes/slavic-language.js +0 -281
  332. package/lib/classes/south-asian-language.d.ts +0 -70
  333. package/lib/classes/south-asian-language.js +0 -154
  334. package/lib/classes/turkic-language.d.ts +0 -26
  335. package/lib/classes/turkic-language.js +0 -59
@@ -1,113 +1,224 @@
1
- import { SlavicLanguage } from '../classes/slavic-language.js'
2
-
3
1
  /**
4
- * Croatian language converter.
2
+ * Croatian language converter - Functional Implementation
3
+ *
4
+ * Self-contained module with its own input validation, ready for subpath exports.
5
5
  *
6
- * Supports:
6
+ * Key features:
7
7
  * - Three-form pluralization (one/few/many)
8
- * - Gender agreement (jedan/jedna, dva/dvije)
9
- * - Croatian-specific declension endings
8
+ * - Gender: thousands are feminine, millions+ are masculine
9
+ * - Irregular hundreds (dvjesto, tristo, etc.)
10
+ * - Long scale naming with -ard forms
10
11
  */
11
- export class Croatian extends SlavicLanguage {
12
- negativeWord = 'minus'
13
- decimalSeparatorWord = 'zarez'
14
- zeroWord = 'nula'
15
-
16
- onesWords = {
17
- 1: 'jedan',
18
- 2: 'dva',
19
- 3: 'tri',
20
- 4: 'četiri',
21
- 5: 'pet',
22
- 6: 'šest',
23
- 7: 'sedam',
24
- 8: 'osam',
25
- 9: 'devet'
12
+
13
+ import { parseNumericValue } from '../utils/parse-numeric.js'
14
+ import { validateOptions } from '../utils/validate-options.js'
15
+
16
+ // ============================================================================
17
+ // Vocabulary
18
+ // ============================================================================
19
+
20
+ const ONES_MASC = ['', 'jedan', 'dva', 'tri', 'četiri', 'pet', 'šest', 'sedam', 'osam', 'devet']
21
+ const ONES_FEM = ['', 'jedna', 'dvije', 'tri', 'četiri', 'pet', 'šest', 'sedam', 'osam', 'devet']
22
+
23
+ const TEENS = ['deset', 'jedanaest', 'dvanaest', 'trinaest', 'četrnaest', 'petnaest', 'šesnaest', 'sedamnaest', 'osamnaest', 'devetnaest']
24
+ const TENS = ['', '', 'dvadeset', 'trideset', 'četrdeset', 'pedeset', 'šezdeset', 'sedamdeset', 'osamdeset', 'devedeset']
25
+
26
+ // Croatian has irregular hundreds
27
+ const HUNDREDS = ['', 'sto', 'dvjesto', 'tristo', 'četiristo', 'petsto', 'šesto', 'sedamsto', 'osamsto', 'devetsto']
28
+
29
+ const ZERO = 'nula'
30
+ const NEGATIVE = 'minus'
31
+ const DECIMAL_SEP = 'zarez'
32
+
33
+ // Scale words: [singular, few, many]
34
+ // Thousands (index 0) are feminine, rest are masculine
35
+ const SCALE_FORMS = [
36
+ ['tisuća', 'tisuće', 'tisuća'],
37
+ ['milijun', 'milijuna', 'milijuna'],
38
+ ['milijarda', 'milijarde', 'milijarda'],
39
+ ['bilijun', 'bilijuna', 'bilijuna'],
40
+ ['bilijarda', 'bilijarde', 'bilijarda'],
41
+ ['trilijun', 'trilijuna', 'trilijuna'],
42
+ ['trilijarda', 'trilijarde', 'trilijarda'],
43
+ ['kvadrilijun', 'kvadrilijuna', 'kvadrilijuna'],
44
+ ['kvadrilijarda', 'kvadrilijarde', 'kvadrilijarda']
45
+ ]
46
+
47
+ // ============================================================================
48
+ // Segment Building
49
+ // ============================================================================
50
+
51
+ function pluralize (n, forms) {
52
+ const num = typeof n === 'bigint' ? Number(n) : n
53
+ const lastDigit = num % 10
54
+ const lastTwoDigits = num % 100
55
+
56
+ if (lastTwoDigits >= 11 && lastTwoDigits <= 19) {
57
+ return forms[2]
26
58
  }
27
59
 
28
- onesFeminineWords = {
29
- 1: 'jedna',
30
- 2: 'dvije',
31
- 3: 'tri',
32
- 4: 'četiri',
33
- 5: 'pet',
34
- 6: 'šest',
35
- 7: 'sedam',
36
- 8: 'osam',
37
- 9: 'devet'
60
+ if (lastDigit === 1) return forms[0]
61
+ if (lastDigit >= 2 && lastDigit <= 4) return forms[1]
62
+ return forms[2]
63
+ }
64
+
65
+ function buildSegmentMasc (n) {
66
+ if (n === 0) return ''
67
+
68
+ const onesDigit = n % 10
69
+ const tensDigit = Math.floor(n / 10) % 10
70
+ const hundredsDigit = Math.floor(n / 100)
71
+
72
+ const parts = []
73
+
74
+ if (hundredsDigit > 0) {
75
+ parts.push(HUNDREDS[hundredsDigit])
38
76
  }
39
77
 
40
- teensWords = {
41
- 0: 'deset',
42
- 1: 'jedanaest',
43
- 2: 'dvanaest',
44
- 3: 'trinaest',
45
- 4: 'četrnaest',
46
- 5: 'petnaest',
47
- 6: 'šesnaest',
48
- 7: 'sedamnaest',
49
- 8: 'osamnaest',
50
- 9: 'devetnaest'
78
+ if (tensDigit > 1) {
79
+ parts.push(TENS[tensDigit])
51
80
  }
52
81
 
53
- twentiesWords = {
54
- 2: 'dvadeset',
55
- 3: 'trideset',
56
- 4: 'četrdeset',
57
- 5: 'pedeset',
58
- 6: 'šezdeset',
59
- 7: 'sedamdeset',
60
- 8: 'osamdeset',
61
- 9: 'devedeset'
82
+ if (tensDigit === 1) {
83
+ parts.push(TEENS[onesDigit])
84
+ } else if (onesDigit > 0) {
85
+ parts.push(ONES_MASC[onesDigit])
62
86
  }
63
87
 
64
- hundredsWords = {
65
- 1: 'sto',
66
- 2: 'dvjesto',
67
- 3: 'tristo',
68
- 4: 'četiristo',
69
- 5: 'petsto',
70
- 6: 'šesto',
71
- 7: 'sedamsto',
72
- 8: 'osamsto',
73
- 9: 'devetsto'
88
+ return parts.join(' ')
89
+ }
90
+
91
+ function buildSegmentFem (n) {
92
+ if (n === 0) return ''
93
+
94
+ const onesDigit = n % 10
95
+ const tensDigit = Math.floor(n / 10) % 10
96
+ const hundredsDigit = Math.floor(n / 100)
97
+
98
+ const parts = []
99
+
100
+ if (hundredsDigit > 0) {
101
+ parts.push(HUNDREDS[hundredsDigit])
74
102
  }
75
103
 
76
- pluralForms = {
77
- 1: ['tisuća', 'tisuće', 'tisuća'], // 10 ^ 3
78
- 2: ['milijun', 'milijuna', 'milijuna'], // 10 ^ 6
79
- 3: ['milijarda', 'milijarde', 'milijarda'], // 10 ^ 9
80
- 4: ['bilijun', 'bilijuna', 'bilijuna'], // 10 ^ 12
81
- 5: ['bilijarda', 'bilijarde', 'bilijarda'], // 10 ^ 15
82
- 6: ['trilijun', 'trilijuna', 'trilijuna'], // 10 ^ 18
83
- 7: ['trilijarda', 'trilijarde', 'trilijarda'], // 10 ^ 21
84
- 8: ['kvadrilijun', 'kvadrilijuna', 'kvadrilijuna'], // 10 ^ 24
85
- 9: ['kvadrilijarda', 'kvadrilijarde', 'kvadrilijarda'], // 10 ^ 27
86
- 10: ['kvintilijun', 'kvintilijuna', 'kvintilijuna'] // 10 ^ 30
104
+ if (tensDigit > 1) {
105
+ parts.push(TENS[tensDigit])
87
106
  }
88
107
 
89
- /**
90
- * Maps segment indices to whether they are grammatically feminine.
91
- * In Croatian, thousands (index 1) are feminine, others are masculine.
92
- * @type {Object.<number, boolean>}
93
- */
94
- scaleGenders = {
95
- 1: true // thousands are feminine (others default to false)
108
+ if (tensDigit === 1) {
109
+ parts.push(TEENS[onesDigit])
110
+ } else if (onesDigit > 0) {
111
+ parts.push(ONES_FEM[onesDigit])
96
112
  }
97
113
 
98
- /** Selects Croatian plural form: 1 = singular, 2-4 = few, else = many. */
99
- pluralize (n, forms) {
100
- const lastDigit = n % 10n
101
- const lastTwoDigits = n % 100n
114
+ return parts.join(' ')
115
+ }
102
116
 
103
- if ((lastTwoDigits < 10n || lastTwoDigits > 20n) && lastDigit === 1n) {
104
- return forms[0]
105
- }
117
+ // ============================================================================
118
+ // Conversion Functions
119
+ // ============================================================================
120
+
121
+ function integerToWords (n, options = {}) {
122
+ if (n === 0n) return ZERO
123
+
124
+ if (n < 1000n) {
125
+ return options.gender === 'feminine' ? buildSegmentFem(Number(n)) : buildSegmentMasc(Number(n))
126
+ }
127
+
128
+ return buildLargeNumberWords(n, options)
129
+ }
106
130
 
107
- if ((lastTwoDigits < 10n || lastTwoDigits > 20n) && lastDigit > 1n && lastDigit < 5n) {
108
- return forms[1]
131
+ function buildLargeNumberWords (n, options) {
132
+ const numStr = n.toString()
133
+ const len = numStr.length
134
+
135
+ const segments = []
136
+ const segmentSize = 3
137
+
138
+ const remainderLen = len % segmentSize
139
+ let pos = 0
140
+ if (remainderLen > 0) {
141
+ segments.push(Number(numStr.slice(0, remainderLen)))
142
+ pos = remainderLen
143
+ }
144
+ while (pos < len) {
145
+ segments.push(Number(numStr.slice(pos, pos + segmentSize)))
146
+ pos += segmentSize
147
+ }
148
+
149
+ const parts = []
150
+ let scaleIndex = segments.length - 1
151
+
152
+ for (let i = 0; i < segments.length; i++) {
153
+ const segment = segments[i]
154
+
155
+ if (segment !== 0) {
156
+ if (scaleIndex === 0) {
157
+ parts.push(options.gender === 'feminine' ? buildSegmentFem(segment) : buildSegmentMasc(segment))
158
+ } else {
159
+ const scaleForms = SCALE_FORMS[scaleIndex - 1]
160
+ const scaleWord = pluralize(segment, scaleForms)
161
+ // Thousands (scaleIndex=1) are feminine, others masculine
162
+ const isFeminine = scaleIndex === 1
163
+ const segmentWord = isFeminine ? buildSegmentFem(segment) : buildSegmentMasc(segment)
164
+ parts.push(segmentWord + ' ' + scaleWord)
165
+ }
109
166
  }
110
167
 
111
- return forms[2]
168
+ scaleIndex--
169
+ }
170
+
171
+ return parts.join(' ')
172
+ }
173
+
174
+ function decimalPartToWords (decimalPart, options) {
175
+ let result = ''
176
+ let i = 0
177
+
178
+ while (i < decimalPart.length && decimalPart[i] === '0') {
179
+ if (result) result += ' '
180
+ result += ZERO
181
+ i++
182
+ }
183
+
184
+ const remainder = decimalPart.slice(i)
185
+ if (remainder) {
186
+ if (result) result += ' '
187
+ result += integerToWords(BigInt(remainder), options)
112
188
  }
189
+
190
+ return result
113
191
  }
192
+
193
+ /**
194
+ * Converts a numeric value to Croatian words.
195
+ *
196
+ * @param {number | string | bigint} value - The numeric value to convert
197
+ * @param {Object} [options] - Optional configuration
198
+ * @param {('masculine'|'feminine')} [options.gender='masculine'] - Grammatical gender
199
+ * @returns {string} The number in Croatian words
200
+ */
201
+ function toWords (value, options) {
202
+ options = validateOptions(options)
203
+ const { isNegative, integerPart, decimalPart } = parseNumericValue(value)
204
+
205
+ let result = ''
206
+
207
+ if (isNegative) {
208
+ result = NEGATIVE + ' '
209
+ }
210
+
211
+ result += integerToWords(integerPart, options)
212
+
213
+ if (decimalPart) {
214
+ result += ' ' + DECIMAL_SEP + ' ' + decimalPartToWords(decimalPart, options)
215
+ }
216
+
217
+ return result
218
+ }
219
+
220
+ // ============================================================================
221
+ // Exports
222
+ // ============================================================================
223
+
224
+ export { toWords }
@@ -1,22 +1,7 @@
1
1
  /**
2
- * Hungarian language converter.
2
+ * Converts a numeric value to Hungarian words.
3
3
  *
4
- * Supports:
5
- * - Agglutinative structure (no spaces between compound parts)
6
- * - Special handling for "egy" (one) omission
7
- * - Pre-composed twenties (huszonegy through huszonkilenc)
4
+ * @param {number | string | bigint} value - The numeric value to convert
5
+ * @returns {string} The number in Hungarian words
8
6
  */
9
- export class Hungarian extends GreedyScaleLanguage {
10
- scaleWords: (string | bigint)[][];
11
- /** Converts tens (30-99) with agglutinative composition. */
12
- tensToCardinal(number: any): string | undefined;
13
- /** Converts hundreds (100-999) with "száz" composition. */
14
- hundredsToCardinal(number: any): string;
15
- /** Converts thousands (1000-999999) with "ezer" composition. */
16
- thousandsToCardinal(number: any): string;
17
- /** Converts large numbers (millions and above) with scale words. */
18
- bigNumberToCardinal(number: any): string;
19
- /** Converts integer part using Hungarian agglutinative rules. */
20
- integerToWords(integerPart: any, zeroWord?: string): string;
21
- }
22
- import { GreedyScaleLanguage } from '../classes/greedy-scale-language.js';
7
+ export function toWords(value: number | string | bigint): string;