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,136 +1,301 @@
1
- import { SlavicLanguage } from '../classes/slavic-language.js'
1
+ /**
2
+ * Lithuanian language converter - Functional Implementation
3
+ *
4
+ * Self-contained module with its own input validation, ready for subpath exports.
5
+ *
6
+ * Key features:
7
+ * - Three-form pluralization (singular/plural/genitive)
8
+ * - Gender agreement (masculine/feminine for numbers < 1000)
9
+ * - Two-form hundreds (šimtas/šimtai)
10
+ * - Long scale naming
11
+ */
12
+
13
+ import { parseNumericValue } from '../utils/parse-numeric.js'
14
+ import { validateOptions } from '../utils/validate-options.js'
15
+
16
+ // ============================================================================
17
+ // Vocabulary (module-level constants)
18
+ // ============================================================================
19
+
20
+ const ONES_MASC = ['', 'vienas', 'du', 'trys', 'keturi', 'penki', 'šeši', 'septyni', 'aštuoni', 'devyni']
21
+ const ONES_FEM = ['', 'viena', 'dvi', 'trys', 'keturios', 'penkios', 'šešios', 'septynios', 'aštuonios', 'devynios']
22
+
23
+ const TEENS = ['dešimt', 'vienuolika', 'dvylika', 'trylika', 'keturiolika', 'penkiolika', 'šešiolika', 'septyniolika', 'aštuoniolika', 'devyniolika']
24
+ const TENS = ['', '', 'dvidešimt', 'trisdešimt', 'keturiasdešimt', 'penkiasdešimt', 'šešiasdešimt', 'septyniasdešimt', 'aštuoniasdešimt', 'devyniasdešimt']
25
+
26
+ // Hundreds: šimtas (singular), šimtai (plural)
27
+ const HUNDRED_SINGULAR = 'šimtas'
28
+ const HUNDRED_PLURAL = 'šimtai'
29
+
30
+ const ZERO = 'nulis'
31
+ const NEGATIVE = 'minus'
32
+ const DECIMAL_SEP = 'kablelis'
33
+
34
+ // Scale words: [singular, plural, genitive]
35
+ const SCALE_FORMS = [
36
+ ['tūkstantis', 'tūkstančiai', 'tūkstančių'],
37
+ ['milijonas', 'milijonai', 'milijonų'],
38
+ ['milijardas', 'milijardai', 'milijardų'],
39
+ ['trilijonas', 'trilijonai', 'trilijonų'],
40
+ ['kvadrilijonas', 'kvadrilijonai', 'kvadrilijonų'],
41
+ ['kvintilijonas', 'kvintilijonai', 'kvintilijonų'],
42
+ ['sikstilijonas', 'sikstilijonai', 'sikstilijonų'],
43
+ ['septilijonas', 'septilijonai', 'septilijonų'],
44
+ ['oktilijonas', 'oktilijonai', 'oktilijonų']
45
+ ]
46
+
47
+ // ============================================================================
48
+ // Segment Building
49
+ // ============================================================================
50
+
51
+ /**
52
+ * Builds segment word for 0-999 (masculine form).
53
+ */
54
+ function buildSegment (n) {
55
+ if (n === 0) return ''
56
+
57
+ const ones = n % 10
58
+ const tens = Math.floor(n / 10) % 10
59
+ const hundreds = Math.floor(n / 100)
60
+
61
+ const parts = []
62
+
63
+ // Hundreds - Lithuanian always includes the numeral
64
+ if (hundreds > 0) {
65
+ parts.push(ONES_MASC[hundreds])
66
+ parts.push(hundreds === 1 ? HUNDRED_SINGULAR : HUNDRED_PLURAL)
67
+ }
68
+
69
+ // Tens
70
+ if (tens > 1) {
71
+ parts.push(TENS[tens])
72
+ }
73
+
74
+ // Teens or ones
75
+ if (tens === 1) {
76
+ parts.push(TEENS[ones])
77
+ } else if (ones > 0) {
78
+ parts.push(ONES_MASC[ones])
79
+ }
80
+
81
+ return parts.join(' ')
82
+ }
2
83
 
3
84
  /**
4
- * Lithuanian language converter.
85
+ * Builds segment word for 0-999 (feminine form - only differs in ones).
86
+ */
87
+ function buildSegmentFeminine (n) {
88
+ if (n === 0) return ''
89
+
90
+ const ones = n % 10
91
+ const tens = Math.floor(n / 10) % 10
92
+ const hundreds = Math.floor(n / 100)
93
+
94
+ const parts = []
95
+
96
+ // Hundreds - always masculine
97
+ if (hundreds > 0) {
98
+ parts.push(ONES_MASC[hundreds])
99
+ parts.push(hundreds === 1 ? HUNDRED_SINGULAR : HUNDRED_PLURAL)
100
+ }
101
+
102
+ // Tens
103
+ if (tens > 1) {
104
+ parts.push(TENS[tens])
105
+ }
106
+
107
+ // Teens or ones - feminine for ones only
108
+ if (tens === 1) {
109
+ parts.push(TEENS[ones])
110
+ } else if (ones > 0) {
111
+ parts.push(ONES_FEM[ones])
112
+ }
113
+
114
+ return parts.join(' ')
115
+ }
116
+
117
+ // ============================================================================
118
+ // Pluralization
119
+ // ============================================================================
120
+
121
+ /**
122
+ * Lithuanian pluralization rules.
123
+ * - Singular: ends in 1 (except 11)
124
+ * - Plural: ends in 2-9 (except 12-19)
125
+ * - Genitive: 0, 10-19, or ends in 0
5
126
  *
6
- * Supports:
7
- * - Three-form pluralization (one/few/many)
8
- * - Gender agreement (vienas/viena, du/dvi)
9
- * - Baltic declension patterns
127
+ * @param {number} n - The segment value
128
+ * @param {string[]} forms - [singular, plural, genitive]
129
+ * @returns {string} The appropriate form
10
130
  */
11
- export class Lithuanian extends SlavicLanguage {
12
- negativeWord = 'minus'
13
- decimalSeparatorWord = 'kablelis'
14
- zeroWord = 'nulis'
15
-
16
- onesWords = {
17
- 1: 'vienas',
18
- 2: 'du',
19
- 3: 'trys',
20
- 4: 'keturi',
21
- 5: 'penki',
22
- 6: 'šeši',
23
- 7: 'septyni',
24
- 8: 'aštuoni',
25
- 9: 'devyni'
26
- }
27
-
28
- onesFeminineWords = {
29
- 1: 'viena',
30
- 2: 'dvi',
31
- 3: 'trys',
32
- 4: 'keturios',
33
- 5: 'penkios',
34
- 6: 'šešios',
35
- 7: 'septynios',
36
- 8: 'aštuonios',
37
- 9: 'devynios'
38
- }
39
-
40
- teensWords = {
41
- 0: 'dešimt',
42
- 1: 'vienuolika',
43
- 2: 'dvylika',
44
- 3: 'trylika',
45
- 4: 'keturiolika',
46
- 5: 'penkiolika',
47
- 6: 'šešiolika',
48
- 7: 'septyniolika',
49
- 8: 'aštuoniolika',
50
- 9: 'devyniolika'
51
- }
52
-
53
- twentiesWords = {
54
- 2: 'dvidešimt',
55
- 3: 'trisdešimt',
56
- 4: 'keturiasdešimt',
57
- 5: 'penkiasdešimt',
58
- 6: 'šešiasdešimt',
59
- 7: 'septyniasdešimt',
60
- 8: 'aštuoniasdešimt',
61
- 9: 'devyniasdešimt'
62
- }
63
-
64
- hundredsWords = ['šimtas', 'šimtai']
65
-
66
- pluralForms = {
67
- 1: ['tūkstantis', 'tūkstančiai', 'tūkstančių'],
68
- 2: ['milijonas', 'milijonai', 'milijonų'],
69
- 3: ['milijardas', 'milijardai', 'milijardų'],
70
- 4: ['trilijonas', 'trilijonai', 'trilijonų'],
71
- 5: ['kvadrilijonas', 'kvadrilijonai', 'kvadrilijonų'],
72
- 6: ['kvintilijonas', 'kvintilijonai', 'kvintilijonų'],
73
- 7: ['sikstilijonas', 'sikstilijonai', 'sikstilijonų'],
74
- 8: ['septilijonas', 'septilijonai', 'septilijonų'],
75
- 9: ['oktilijonas', 'oktilijonai', 'oktilijonų'],
76
- 10: ['naintilijonas', 'naintilijonai', 'naintilijonų']
77
- }
78
-
79
- pluralize (n, forms) {
80
- if (n === 0n) {
81
- return forms[2]
82
- }
131
+ function pluralize (n, forms) {
132
+ if (n === 0) return forms[2]
83
133
 
84
- const [n1, n2] = this.extractDigits(n)
134
+ const lastDigit = n % 10
135
+ const lastTwoDigits = n % 100
85
136
 
86
- if (n2 === 1n || n1 === 0n) {
87
- return forms[2]
88
- }
137
+ // 10-19 always use genitive
138
+ if (lastTwoDigits >= 10 && lastTwoDigits <= 19) {
139
+ return forms[2]
140
+ }
89
141
 
90
- if (n1 === 1n) {
91
- return forms[0]
92
- }
142
+ // Ends in 0 → genitive
143
+ if (lastDigit === 0) {
144
+ return forms[2]
145
+ }
93
146
 
94
- return forms[1]
147
+ // Ends in 1 → singular
148
+ if (lastDigit === 1) {
149
+ return forms[0]
95
150
  }
96
151
 
97
- integerToWords (integerPart) {
98
- if (integerPart === 0n) {
99
- return this.zeroWord
100
- }
101
- const words = []
102
- const segments = this.splitToSegments(integerPart.toString(), 3)
103
- let index = segments.length
104
- for (const x of segments) {
105
- index = index - 1
106
- if (x === 0n) {
107
- continue
108
- }
109
- const [n1, n2, n3] = this.extractDigits(x)
110
- if (n3 > 0n) {
111
- words.push(this.onesWords[n3])
112
- if (n3 > 1n) {
113
- words.push(this.hundredsWords[1])
114
- } else {
115
- words.push(this.hundredsWords[0])
116
- }
117
- }
118
- if (n2 > 1n) {
119
- words.push(this.twentiesWords[n2])
120
- }
121
- if (n2 === 1n) {
122
- words.push(this.teensWords[n1])
123
- } else if (n1 > 0n) {
124
- if ((index === 1 || (this.options.gender === 'feminine' && index === 0)) && integerPart < 1000n) {
125
- words.push(this.onesFeminineWords[n1])
126
- } else {
127
- words.push(this.onesWords[n1])
128
- }
129
- }
130
- if (index > 0) {
131
- words.push(this.pluralize(x, this.pluralForms[index]))
152
+ // Ends in 2-9 → plural
153
+ return forms[1]
154
+ }
155
+
156
+ // ============================================================================
157
+ // Conversion Functions
158
+ // ============================================================================
159
+
160
+ /**
161
+ * Converts a non-negative integer to Lithuanian words.
162
+ *
163
+ * @param {bigint} n - Non-negative integer to convert
164
+ * @param {Object} options - Conversion options
165
+ * @returns {string} Lithuanian words
166
+ */
167
+ function integerToWords (n, options = {}) {
168
+ if (n === 0n) return ZERO
169
+
170
+ // Fast path: numbers < 1000
171
+ if (n < 1000n) {
172
+ const num = Number(n)
173
+ return options.gender === 'feminine' ? buildSegmentFeminine(num) : buildSegment(num)
174
+ }
175
+
176
+ // For numbers >= 1000, feminine only applies to final segment if < 1000
177
+ // But the fixture shows feminine NOT applying for n >= 1000
178
+ // So we use masculine for all segments when n >= 1000
179
+ return buildLargeNumberWords(n, options)
180
+ }
181
+
182
+ /**
183
+ * Builds words for numbers >= 1000.
184
+ *
185
+ * @param {bigint} n - Number >= 1000
186
+ * @param {Object} options - Conversion options
187
+ * @returns {string} Lithuanian words
188
+ */
189
+ function buildLargeNumberWords (n, options) {
190
+ const numStr = n.toString()
191
+ const len = numStr.length
192
+
193
+ // Build segments of 3 digits from right to left
194
+ const segments = []
195
+ const segmentSize = 3
196
+
197
+ const remainderLen = len % segmentSize
198
+ let pos = 0
199
+ if (remainderLen > 0) {
200
+ segments.push(Number(numStr.slice(0, remainderLen)))
201
+ pos = remainderLen
202
+ }
203
+ while (pos < len) {
204
+ segments.push(Number(numStr.slice(pos, pos + segmentSize)))
205
+ pos += segmentSize
206
+ }
207
+
208
+ // Convert segments to words
209
+ const parts = []
210
+ let scaleIndex = segments.length - 1
211
+
212
+ for (let i = 0; i < segments.length; i++) {
213
+ const segment = segments[i]
214
+
215
+ if (segment !== 0) {
216
+ const segmentWord = buildSegment(segment)
217
+
218
+ if (scaleIndex === 0) {
219
+ // Units segment - use masculine (feminine doesn't apply when n >= 1000)
220
+ parts.push(segmentWord)
221
+ } else {
222
+ // Segment with scale word
223
+ const scaleForms = SCALE_FORMS[scaleIndex - 1]
224
+ const scaleWord = pluralize(segment, scaleForms)
225
+ parts.push(segmentWord + ' ' + scaleWord)
132
226
  }
133
227
  }
134
- return words.join(' ')
228
+
229
+ scaleIndex--
135
230
  }
231
+
232
+ return parts.join(' ')
136
233
  }
234
+
235
+ /**
236
+ * Converts decimal digits to Lithuanian words.
237
+ *
238
+ * @param {string} decimalPart - Decimal digits (without the point)
239
+ * @param {Object} options - Conversion options
240
+ * @returns {string} Lithuanian words for decimal part
241
+ */
242
+ function decimalPartToWords (decimalPart, options) {
243
+ let result = ''
244
+
245
+ // Handle leading zeros
246
+ let i = 0
247
+ while (i < decimalPart.length && decimalPart[i] === '0') {
248
+ if (result) result += ' '
249
+ result += ZERO
250
+ i++
251
+ }
252
+
253
+ // Convert remainder as a single number
254
+ const remainder = decimalPart.slice(i)
255
+ if (remainder) {
256
+ if (result) result += ' '
257
+ result += integerToWords(BigInt(remainder), options)
258
+ }
259
+
260
+ return result
261
+ }
262
+
263
+ /**
264
+ * Converts a numeric value to Lithuanian words.
265
+ *
266
+ * @param {number | string | bigint} value - The numeric value to convert
267
+ * @param {Object} [options] - Conversion options
268
+ * @param {string} [options.gender='masculine'] - Gender for numbers < 1000
269
+ * @returns {string} The number in Lithuanian words
270
+ * @throws {TypeError} If value is not a valid numeric type
271
+ * @throws {Error} If value is not a valid number format
272
+ *
273
+ * @example
274
+ * toWords(42) // 'keturiasdešimt du'
275
+ * toWords(1, { gender: 'feminine' }) // 'viena'
276
+ * toWords(1000000) // 'vienas milijonas'
277
+ */
278
+ function toWords (value, options) {
279
+ options = validateOptions(options)
280
+ const { isNegative, integerPart, decimalPart } = parseNumericValue(value)
281
+
282
+ let result = ''
283
+
284
+ if (isNegative) {
285
+ result = NEGATIVE + ' '
286
+ }
287
+
288
+ result += integerToWords(integerPart, options)
289
+
290
+ if (decimalPart) {
291
+ result += ' ' + DECIMAL_SEP + ' ' + decimalPartToWords(decimalPart, options)
292
+ }
293
+
294
+ return result
295
+ }
296
+
297
+ // ============================================================================
298
+ // Public API
299
+ // ============================================================================
300
+
301
+ export { toWords }
@@ -1,70 +1,18 @@
1
1
  /**
2
- * Latvian language converter.
2
+ * Converts a numeric value to Latvian words.
3
3
  *
4
- * Supports:
5
- * - Three-form pluralization (one/few/many)
6
- * - Latvian diacritical marks (ī, ā, ē, ū)
7
- * - Compound number formation (divdesmit, trīsdesmit)
4
+ * @param {number | string | bigint} value - The numeric value to convert
5
+ * @param {Object} [options] - Conversion options
6
+ * @param {string} [options.gender='masculine'] - Gender for numbers < 1000
7
+ * @returns {string} The number in Latvian 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(42) // 'četrdesmit divi'
13
+ * toWords(1, { gender: 'feminine' }) // 'viena'
14
+ * toWords(1000) // 'tūkstotis'
8
15
  */
9
- export class Latvian 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: string[];
55
- pluralForms: {
56
- 1: string[];
57
- 2: string[];
58
- 3: string[];
59
- 4: string[];
60
- 5: string[];
61
- 6: string[];
62
- 7: string[];
63
- 8: string[];
64
- 9: string[];
65
- 10: string[];
66
- };
67
- pluralize(n: any, forms: any): any;
68
- integerToWords(integerPart: any): string;
69
- }
70
- import { SlavicLanguage } from '../classes/slavic-language.js';
16
+ export function toWords(value: number | string | bigint, options?: {
17
+ gender?: string | undefined;
18
+ }): string;