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,42 +1,150 @@
1
- import { SouthAsianLanguage } from '../classes/south-asian-language.js'
2
-
3
1
  /**
4
- * Kannada language converter.
2
+ * Kannada 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
  * - Indian numbering system (ಸಾವಿರ, ಲಕ್ಷ, ಕೋಟಿ)
8
8
  * - Kannada script
9
+ * - 3-2-2 grouping pattern (last 3 digits, then groups of 2)
9
10
  * - Complete word forms for 0-99
11
+ * - Per-digit decimal reading
12
+ */
13
+
14
+ import { parseNumericValue } from '../utils/parse-numeric.js'
15
+
16
+ // ============================================================================
17
+ // Vocabulary
18
+ // ============================================================================
19
+
20
+ const ZERO = 'ಸೊನ್ನೆ'
21
+ const NEGATIVE = 'ಋಣಾತ್ಮಕ'
22
+ const DECIMAL_SEP = 'ದಶಮಾಂಶ'
23
+ const HUNDRED = 'ನೂರು'
24
+
25
+ const BELOW_HUNDRED = [
26
+ 'ಸೊನ್ನೆ', 'ಒಂದು', 'ಎರಡು', 'ಮೂರು', 'ನಾಲ್ಕು', 'ಐದು', 'ಆರು', 'ಏಳು', 'ಎಂಟು', 'ಒಂಬತ್ತು',
27
+ 'ಹತ್ತು', 'ಹನ್ನೊಂದು', 'ಹನ್ನೆರಡು', 'ಹದಿಮೂರು', 'ಹದಿನಾಲ್ಕು', 'ಹದಿನೈದು', 'ಹದಿನಾರು', 'ಹದಿನೇಳು', 'ಹದಿನೆಂಟು', 'ಹತ್ತೊಂಬತ್ತು',
28
+ 'ಇಪ್ಪತ್ತು', 'ಇಪ್ಪತ್ತೊಂದು', 'ಇಪ್ಪತ್ತೆರಡು', 'ಇಪ್ಪತ್ತಮೂರು', 'ಇಪ್ಪತ್ತನಾಲ್ಕು', 'ಇಪ್ಪತ್ತೈದು', 'ಇಪ್ಪತ್ತಾರು', 'ಇಪ್ಪತ್ತೇಳು', 'ಇಪ್ಪತ್ತೆಂಟು', 'ಇಪ್ಪತ್ತೊಂಬತ್ತು',
29
+ 'ಮೂವತ್ತು', 'ಮೂವತ್ತೊಂದು', 'ಮೂವತ್ತೆರಡು', 'ಮೂವತ್ತಮೂರು', 'ಮೂವತ್ತನಾಲ್ಕು', 'ಮೂವತ್ತೈದು', 'ಮೂವತ್ತಾರು', 'ಮೂವತ್ತೇಳು', 'ಮೂವತ್ತೆಂಟು', 'ಮೂವತ್ತೊಂಬತ್ತು',
30
+ 'ನಲವತ್ತು', 'ನಲವತ್ತೊಂದು', 'ನಲವತ್ತೆರಡು', 'ನಲವತ್ತಮೂರು', 'ನಲವತ್ತನಾಲ್ಕು', 'ನಲವತ್ತೈದು', 'ನಲವತ್ತಾರು', 'ನಲವತ್ತೇಳು', 'ನಲವತ್ತೆಂಟು', 'ನಲವತ್ತೊಂಬತ್ತು',
31
+ 'ಐವತ್ತು', 'ಐವತ್ತೊಂದು', 'ಐವತ್ತೆರಡು', 'ಐವತ್ತಮೂರು', 'ಐವತ್ತನಾಲ್ಕು', 'ಐವತ್ತೈದು', 'ಐವತ್ತಾರು', 'ಐವತ್ತೇಳು', 'ಐವತ್ತೆಂಟು', 'ಐವತ್ತೊಂಬತ್ತು',
32
+ 'ಅರವತ್ತು', 'ಅರವತ್ತೊಂದು', 'ಅರವತ್ತೆರಡು', 'ಅರವತ್ತಮೂರು', 'ಅರವತ್ತನಾಲ್ಕು', 'ಅರವತ್ತೈದು', 'ಅರವತ್ತಾರು', 'ಅರವತ್ತೇಳು', 'ಅರವತ್ತೆಂಟು', 'ಅರವತ್ತೊಂಬತ್ತು',
33
+ 'ಎಪ್ಪತ್ತು', 'ಎಪ್ಪತ್ತೊಂದು', 'ಎಪ್ಪತ್ತೆರಡು', 'ಎಪ್ಪತ್ತಮೂರು', 'ಎಪ್ಪತ್ತನಾಲ್ಕು', 'ಎಪ್ಪತ್ತೈದು', 'ಎಪ್ಪತ್ತಾರು', 'ಎಪ್ಪತ್ತೇಳು', 'ಎಪ್ಪತ್ತೆಂಟು', 'ಎಪ್ಪತ್ತೊಂಬತ್ತು',
34
+ 'ಎಂಬತ್ತು', 'ಎಂಬತ್ತೊಂದು', 'ಎಂಬತ್ತೆರಡು', 'ಎಂಬತ್ತಮೂರು', 'ಎಂಬತ್ತನಾಲ್ಕು', 'ಎಂಬತ್ತೈದು', 'ಎಂಬತ್ತಾರು', 'ಎಂಬತ್ತೇಳು', 'ಎಂಬತ್ತೆಂಟು', 'ಎಂಬತ್ತೊಂಬತ್ತು',
35
+ 'ತೊಂಬತ್ತು', 'ತೊಂಬತ್ತೊಂದು', 'ತೊಂಬತ್ತೆರಡು', 'ತೊಂಬತ್ತಮೂರು', 'ತೊಂಬತ್ತನಾಲ್ಕು', 'ತೊಂಬತ್ತೈದು', 'ತೊಂಬತ್ತಾರು', 'ತೊಂಬತ್ತೇಳು', 'ತೊಂಬತ್ತೆಂಟು', 'ತೊಂಬತ್ತೊಂಬತ್ತು'
36
+ ]
37
+
38
+ // Scale words: index 0 = units (empty), 1 = thousand, 2 = lakh, 3 = crore, etc.
39
+ const SCALE_WORDS = ['', 'ಸಾವಿರ', 'ಲಕ್ಷ', 'ಕೋಟಿ', 'ಅಬ್ಜ', 'ಖರ್ವ', 'ನೀಲ', 'ಪದ್ಮ', 'ಶಂಖ']
40
+
41
+ // ============================================================================
42
+ // Segment Building
43
+ // ============================================================================
44
+
45
+ /**
46
+ * Builds words for a 0-999 segment.
10
47
  */
11
- export class Kannada extends SouthAsianLanguage {
12
- negativeWord = 'ಋಣಾತ್ಮಕ'
13
- decimalSeparatorWord = 'ದಶಮಾಂಶ'
14
- zeroWord = 'ಸೊನ್ನೆ'
15
- hundredWord = 'ನೂರು'
16
- usePerDigitDecimals = true
17
-
18
- belowHundredWords = [
19
- 'ಸೊನ್ನೆ', 'ಒಂದು', 'ಎರಡು', 'ಮೂರು', 'ನಾಲ್ಕು', 'ಐದು', 'ಆರು', 'ಏಳು', 'ಎಂಟು', 'ಒಂಬತ್ತು',
20
- 'ಹತ್ತು', 'ಹನ್ನೊಂದು', 'ಹನ್ನೆರಡು', 'ಹದಿಮೂರು', 'ಹದಿನಾಲ್ಕು', 'ಹದಿನೈದು', 'ಹದಿನಾರು', 'ಹದಿನೇಳು', 'ಹದಿನೆಂಟು', 'ಹತ್ತೊಂಬತ್ತು',
21
- 'ಇಪ್ಪತ್ತು', 'ಇಪ್ಪತ್ತೊಂದು', 'ಇಪ್ಪತ್ತೆರಡು', 'ಇಪ್ಪತ್ತಮೂರು', 'ಇಪ್ಪತ್ತನಾಲ್ಕು', 'ಇಪ್ಪತ್ತೈದು', 'ಇಪ್ಪತ್ತಾರು', 'ಇಪ್ಪತ್ತೇಳು', 'ಇಪ್ಪತ್ತೆಂಟು', 'ಇಪ್ಪತ್ತೊಂಬತ್ತು',
22
- 'ಮೂವತ್ತು', 'ಮೂವತ್ತೊಂದು', 'ಮೂವತ್ತೆರಡು', 'ಮೂವತ್ತಮೂರು', 'ಮೂವತ್ತನಾಲ್ಕು', 'ಮೂವತ್ತೈದು', 'ಮೂವತ್ತಾರು', 'ಮೂವತ್ತೇಳು', 'ಮೂವತ್ತೆಂಟು', 'ಮೂವತ್ತೊಂಬತ್ತು',
23
- 'ನಲವತ್ತು', 'ನಲವತ್ತೊಂದು', 'ನಲವತ್ತೆರಡು', 'ನಲವತ್ತಮೂರು', 'ನಲವತ್ತನಾಲ್ಕು', 'ನಲವತ್ತೈದು', 'ನಲವತ್ತಾರು', 'ನಲವತ್ತೇಳು', 'ನಲವತ್ತೆಂಟು', 'ನಲವತ್ತೊಂಬತ್ತು',
24
- 'ಐವತ್ತು', 'ಐವತ್ತೊಂದು', 'ಐವತ್ತೆರಡು', 'ಐವತ್ತಮೂರು', 'ಐವತ್ತನಾಲ್ಕು', 'ಐವತ್ತೈದು', 'ಐವತ್ತಾರು', 'ಐವತ್ತೇಳು', 'ಐವತ್ತೆಂಟು', 'ಐವತ್ತೊಂಬತ್ತು',
25
- 'ಅರವತ್ತು', 'ಅರವತ್ತೊಂದು', 'ಅರವತ್ತೆರಡು', 'ಅರವತ್ತಮೂರು', 'ಅರವತ್ತನಾಲ್ಕು', 'ಅರವತ್ತೈದು', 'ಅರವತ್ತಾರು', 'ಅರವತ್ತೇಳು', 'ಅರವತ್ತೆಂಟು', 'ಅರವತ್ತೊಂಬತ್ತು',
26
- 'ಎಪ್ಪತ್ತು', 'ಎಪ್ಪತ್ತೊಂದು', 'ಎಪ್ಪತ್ತೆರಡು', 'ಎಪ್ಪತ್ತಮೂರು', 'ಎಪ್ಪತ್ತನಾಲ್ಕು', 'ಎಪ್ಪತ್ತೈದು', 'ಎಪ್ಪತ್ತಾರು', 'ಎಪ್ಪತ್ತೇಳು', 'ಎಪ್ಪತ್ತೆಂಟು', 'ಎಪ್ಪತ್ತೊಂಬತ್ತು',
27
- 'ಎಂಬತ್ತು', 'ಎಂಬತ್ತೊಂದು', 'ಎಂಬತ್ತೆರಡು', 'ಎಂಬತ್ತಮೂರು', 'ಎಂಬತ್ತನಾಲ್ಕು', 'ಎಂಬತ್ತೈದು', 'ಎಂಬತ್ತಾರು', 'ಎಂಬತ್ತೇಳು', 'ಎಂಬತ್ತೆಂಟು', 'ಎಂಬತ್ತೊಂಬತ್ತು',
28
- 'ತೊಂಬತ್ತು', 'ತೊಂಬತ್ತೊಂದು', 'ತೊಂಬತ್ತೆರಡು', 'ತೊಂಬತ್ತಮೂರು', 'ತೊಂಬತ್ತನಾಲ್ಕು', 'ತೊಂಬತ್ತೈದು', 'ತೊಂಬತ್ತಾರು', 'ತೊಂಬತ್ತೇಳು', 'ತೊಂಬತ್ತೆಂಟು', 'ತೊಂಬತ್ತೊಂಬತ್ತು'
29
- ]
30
-
31
- scaleWords = [
32
- '', // units
33
- 'ಸಾವಿರ', // thousand (1,000)
34
- 'ಲಕ್ಷ', // lakh (100,000)
35
- 'ಕೋಟಿ', // crore (10,000,000)
36
- 'ಅಬ್ಜ', // arab (1,000,000,000)
37
- 'ಖರ್ವ', // kharab (100,000,000,000)
38
- 'ನೀಲ', // neel (10,000,000,000,000)
39
- 'ಪದ್ಮ', // padma (1,000,000,000,000,000)
40
- 'ಶಂಖ' // shankh (100,000,000,000,000,000)
41
- ]
48
+ function buildSegment (n) {
49
+ if (n === 0) return ''
50
+ if (n < 100) return BELOW_HUNDRED[n]
51
+
52
+ const hundreds = Math.trunc(n / 100)
53
+ const remainder = n % 100
54
+
55
+ if (remainder === 0) {
56
+ return BELOW_HUNDRED[hundreds] + ' ' + HUNDRED
57
+ }
58
+ return BELOW_HUNDRED[hundreds] + ' ' + HUNDRED + ' ' + BELOW_HUNDRED[remainder]
42
59
  }
60
+
61
+ // ============================================================================
62
+ // Conversion Functions
63
+ // ============================================================================
64
+
65
+ /**
66
+ * Converts a non-negative integer to Kannada words.
67
+ *
68
+ * Uses BigInt modulo for segment extraction (faster than string slicing).
69
+ * South Asian 3-2-2 grouping: first 3 digits, then groups of 2.
70
+ *
71
+ * @param {bigint} n - Non-negative integer to convert
72
+ * @returns {string} Kannada words
73
+ */
74
+ function integerToWords (n) {
75
+ if (n === 0n) return ZERO
76
+
77
+ // Fast path: numbers < 1000 (direct lookup)
78
+ if (n < 1000n) {
79
+ return buildSegment(Number(n))
80
+ }
81
+
82
+ // Extract segments using BigInt modulo
83
+ const segments = []
84
+ segments.push(Number(n % 1000n))
85
+ let temp = n / 1000n
86
+
87
+ while (temp > 0n) {
88
+ segments.push(Number(temp % 100n))
89
+ temp = temp / 100n
90
+ }
91
+
92
+ // Build result string (process from most-significant to least)
93
+ const words = []
94
+ for (let i = segments.length - 1; i >= 0; i--) {
95
+ const segment = segments[i]
96
+ if (segment === 0) continue
97
+
98
+ if (i === 0) {
99
+ words.push(buildSegment(segment))
100
+ } else {
101
+ words.push(BELOW_HUNDRED[segment])
102
+ }
103
+
104
+ if (i > 0 && SCALE_WORDS[i]) {
105
+ words.push(SCALE_WORDS[i])
106
+ }
107
+ }
108
+
109
+ return words.join(' ')
110
+ }
111
+
112
+ function decimalPartToWords (decimalPart) {
113
+ // Per-digit decimal reading
114
+ const digits = []
115
+ for (const char of decimalPart) {
116
+ const d = parseInt(char, 10)
117
+ digits.push(d === 0 ? ZERO : BELOW_HUNDRED[d])
118
+ }
119
+ return digits.join(' ')
120
+ }
121
+
122
+ /**
123
+ * Converts a numeric value to Kannada words.
124
+ *
125
+ * @param {number | string | bigint} value - The numeric value to convert
126
+ * @returns {string} The number in Kannada words
127
+ */
128
+ function toWords (value) {
129
+ const { isNegative, integerPart, decimalPart } = parseNumericValue(value)
130
+
131
+ let result = ''
132
+
133
+ if (isNegative) {
134
+ result = NEGATIVE + ' '
135
+ }
136
+
137
+ result += integerToWords(integerPart)
138
+
139
+ if (decimalPart) {
140
+ result += ' ' + DECIMAL_SEP + ' ' + decimalPartToWords(decimalPart)
141
+ }
142
+
143
+ return result
144
+ }
145
+
146
+ // ============================================================================
147
+ // Exports
148
+ // ============================================================================
149
+
150
+ export { toWords }
@@ -1,14 +1,14 @@
1
1
  /**
2
- * Korean language converter.
2
+ * Converts a numeric value to Korean words.
3
3
  *
4
- * Supports:
5
- * - Hangul numerals (일, 이, 삼, etc.)
6
- * - Grouping by (10,000) system
7
- * - Implicit '일' (one) omission before multipliers
4
+ * @param {number | string | bigint} value - The numeric value to convert
5
+ * @returns {string} The number in Korean words
6
+ * @throws {TypeError} If value is not a valid numeric type
7
+ * @throws {Error} If value is not a valid number format
8
+ *
9
+ * @example
10
+ * toWords(21) // '이십일'
11
+ * toWords(10000) // '만'
12
+ * toWords(1000000) // '백만'
8
13
  */
9
- export class Korean extends GreedyScaleLanguage {
10
- scaleWords: (string | bigint)[][];
11
- /** Combines two word-sets according to Korean grammar rules. */
12
- combineWordSets(preceding: any, following: any): any;
13
- }
14
- import { GreedyScaleLanguage } from '../classes/greedy-scale-language.js';
14
+ export function toWords(value: number | string | bigint): string;
@@ -1,55 +1,256 @@
1
- import { GreedyScaleLanguage } from '../classes/greedy-scale-language.js'
1
+ /**
2
+ * Korean language converter - Functional Implementation
3
+ *
4
+ * Self-contained module with its own input validation, ready for subpath exports.
5
+ *
6
+ * Key features:
7
+ * - Myriad-based (만) grouping - 4 digits
8
+ * - Implicit '일' (one) omission before scale words
9
+ * - Space separation after 만+ scales
10
+ * - Hangul numerals
11
+ */
12
+
13
+ import { parseNumericValue } from '../utils/parse-numeric.js'
14
+
15
+ // ============================================================================
16
+ // Vocabulary (module-level constants)
17
+ // ============================================================================
18
+
19
+ const ONES = ['', '일', '이', '삼', '사', '오', '육', '칠', '팔', '구']
20
+
21
+ const TEN = '십'
22
+ const HUNDRED = '백'
23
+ const THOUSAND = '천'
24
+
25
+ const ZERO = '영'
26
+ const NEGATIVE = '마이너스'
27
+ const DECIMAL_SEP = '점'
28
+
29
+ // Myriad scale words (powers of 10,000)
30
+ // 만 (10^4), 억 (10^8), 조 (10^12), 경 (10^16), etc.
31
+ const SCALES = ['만', '억', '조', '경', '해', '자', '양']
32
+
33
+ // ============================================================================
34
+ // Segment Building
35
+ // ============================================================================
2
36
 
3
37
  /**
4
- * Korean language converter.
38
+ * Builds segment word for 0-9999 (4-digit myriad segment).
39
+ * Korean omits "일" before 십, 백, 천.
40
+ */
41
+ function buildSegment (n) {
42
+ if (n === 0) return ''
43
+
44
+ const ones = n % 10
45
+ const tens = Math.floor(n / 10) % 10
46
+ const hundreds = Math.floor(n / 100) % 10
47
+ const thousands = Math.floor(n / 1000)
48
+
49
+ let result = ''
50
+
51
+ // Thousands
52
+ if (thousands > 0) {
53
+ if (thousands === 1) {
54
+ result += THOUSAND
55
+ } else {
56
+ result += ONES[thousands] + THOUSAND
57
+ }
58
+ }
59
+
60
+ // Hundreds
61
+ if (hundreds > 0) {
62
+ if (hundreds === 1) {
63
+ result += HUNDRED
64
+ } else {
65
+ result += ONES[hundreds] + HUNDRED
66
+ }
67
+ }
68
+
69
+ // Tens
70
+ if (tens > 0) {
71
+ if (tens === 1) {
72
+ result += TEN
73
+ } else {
74
+ result += ONES[tens] + TEN
75
+ }
76
+ }
77
+
78
+ // Ones
79
+ if (ones > 0) {
80
+ result += ONES[ones]
81
+ }
82
+
83
+ return result
84
+ }
85
+
86
+ // ============================================================================
87
+ // Conversion Functions
88
+ // ============================================================================
89
+
90
+ /**
91
+ * Converts a non-negative integer to Korean words.
5
92
  *
6
- * Supports:
7
- * - Hangul numerals (일, 이, 삼, etc.)
8
- * - Grouping by 만 (10,000) system
9
- * - Implicit '일' (one) omission before multipliers
93
+ * @param {bigint} n - Non-negative integer to convert
94
+ * @returns {string} Korean words
10
95
  */
11
- export class Korean extends GreedyScaleLanguage {
12
- negativeWord = '마이너스'
13
- decimalSeparatorWord = '점'
14
- zeroWord = '영'
15
-
16
- scaleWords = [
17
- [10_000_000_000_000_000_000_000_000_000n, '양'],
18
- [1_000_000_000_000_000_000_000_000n, '자'],
19
- [100_000_000_000_000_000_000n, '해'],
20
- [10_000_000_000_000_000n, '경'],
21
- [1_000_000_000_000n, '조'],
22
- [100_000_000n, '억'],
23
- [10_000n, '만'],
24
- [1000n, '천'],
25
- [100n, '백'],
26
- [10n, '십'],
27
- [9n, '구'],
28
- [8n, '팔'],
29
- [7n, '칠'],
30
- [6n, '육'],
31
- [5n, '오'],
32
- [4n, '사'],
33
- [3n, '삼'],
34
- [2n, '이'],
35
- [1n, '일'],
36
- [0n, '영']
37
- ]
38
-
39
- /** Combines two word-sets according to Korean grammar rules. */
40
- combineWordSets (preceding, following) {
41
- const precedingWord = Object.keys(preceding)[0]
42
- const followingWord = Object.keys(following)[0]
43
- const precedingValue = Object.values(preceding)[0] // BigInt
44
- const followingValue = Object.values(following)[0] // BigInt
45
-
46
- // Implicit "일": omit 1 before multipliers up to 만 (10,000)
47
- if (precedingValue === 1n && followingValue <= 10_000n) return following
48
- // Concatenate (no space) for small numbers less than 만
49
- if (precedingValue < 10_000n && precedingValue > followingValue) return { [`${precedingWord}${followingWord}`]: precedingValue + followingValue }
50
- // Space-separate for large numbers (>= 만) when adding
51
- if (precedingValue >= 10_000n && precedingValue > followingValue) return { [`${precedingWord} ${followingWord}`]: precedingValue + followingValue }
52
- // Multiply for all scale combinations
53
- return { [`${precedingWord}${followingWord}`]: precedingValue * followingValue }
96
+ function integerToWords (n) {
97
+ if (n === 0n) return ZERO
98
+
99
+ // Fast path: numbers < 10000
100
+ if (n < 10000n) {
101
+ return buildSegment(Number(n))
54
102
  }
103
+
104
+ // For numbers >= 10000, use myriad decomposition
105
+ return buildLargeNumberWords(n)
55
106
  }
107
+
108
+ /**
109
+ * Builds words for numbers >= 10000.
110
+ * Uses myriad (만) grouping - 4 digits per segment.
111
+ *
112
+ * @param {bigint} n - Number >= 10000
113
+ * @returns {string} Korean words
114
+ */
115
+ function buildLargeNumberWords (n) {
116
+ const numStr = n.toString()
117
+ const len = numStr.length
118
+
119
+ // Build segments of 4 digits from right to left
120
+ const segments = []
121
+ const segmentSize = 4
122
+
123
+ const remainderLen = len % segmentSize
124
+ let pos = 0
125
+ if (remainderLen > 0) {
126
+ segments.push(Number(numStr.slice(0, remainderLen)))
127
+ pos = remainderLen
128
+ }
129
+ while (pos < len) {
130
+ segments.push(Number(numStr.slice(pos, pos + segmentSize)))
131
+ pos += segmentSize
132
+ }
133
+
134
+ // Convert segments to words
135
+ const parts = []
136
+ let scaleIndex = segments.length - 1
137
+
138
+ for (let i = 0; i < segments.length; i++) {
139
+ const segment = segments[i]
140
+
141
+ if (segment !== 0) {
142
+ if (scaleIndex === 0) {
143
+ // Units segment (no scale word)
144
+ parts.push({ word: buildSegment(segment), isScale: false })
145
+ } else {
146
+ // Segment with scale word
147
+ const scaleWord = SCALES[scaleIndex - 1]
148
+
149
+ // Korean omits segment when it's 1 before scale words
150
+ if (segment === 1) {
151
+ parts.push({ word: scaleWord, isScale: true })
152
+ } else {
153
+ parts.push({ word: buildSegment(segment), isScale: false })
154
+ parts.push({ word: scaleWord, isScale: true })
155
+ }
156
+ }
157
+ }
158
+
159
+ scaleIndex--
160
+ }
161
+
162
+ // Join with Korean spacing rules
163
+ return joinKoreanParts(parts)
164
+ }
165
+
166
+ /**
167
+ * Joins parts with Korean spacing rules.
168
+ * - Concatenate without spaces within segments
169
+ * - Space after scale words before next number
170
+ *
171
+ * @param {Array} parts - Parts with isScale metadata
172
+ * @returns {string} Joined string
173
+ */
174
+ function joinKoreanParts (parts) {
175
+ if (parts.length === 0) return ZERO
176
+ if (parts.length === 1) return parts[0].word
177
+
178
+ const result = []
179
+
180
+ for (let i = 0; i < parts.length; i++) {
181
+ const part = parts[i]
182
+ const prevPart = i > 0 ? parts[i - 1] : null
183
+
184
+ // Add space after scale words before next number
185
+ if (prevPart && prevPart.isScale && !part.isScale) {
186
+ result.push(' ')
187
+ }
188
+
189
+ result.push(part.word)
190
+ }
191
+
192
+ return result.join('')
193
+ }
194
+
195
+ /**
196
+ * Converts decimal digits to Korean words.
197
+ *
198
+ * @param {string} decimalPart - Decimal digits (without the point)
199
+ * @returns {string} Korean words for decimal part (space-separated)
200
+ */
201
+ function decimalPartToWords (decimalPart) {
202
+ const parts = []
203
+
204
+ // Handle leading zeros
205
+ let i = 0
206
+ while (i < decimalPart.length && decimalPart[i] === '0') {
207
+ parts.push(ZERO)
208
+ i++
209
+ }
210
+
211
+ // Convert remainder as a single number
212
+ const remainder = decimalPart.slice(i)
213
+ if (remainder) {
214
+ parts.push(integerToWords(BigInt(remainder)))
215
+ }
216
+
217
+ return parts.join(' ')
218
+ }
219
+
220
+ /**
221
+ * Converts a numeric value to Korean words.
222
+ *
223
+ * @param {number | string | bigint} value - The numeric value to convert
224
+ * @returns {string} The number in Korean words
225
+ * @throws {TypeError} If value is not a valid numeric type
226
+ * @throws {Error} If value is not a valid number format
227
+ *
228
+ * @example
229
+ * toWords(21) // '이십일'
230
+ * toWords(10000) // '만'
231
+ * toWords(1000000) // '백만'
232
+ */
233
+ function toWords (value) {
234
+ const { isNegative, integerPart, decimalPart } = parseNumericValue(value)
235
+
236
+ const parts = []
237
+
238
+ if (isNegative) {
239
+ parts.push(NEGATIVE)
240
+ }
241
+
242
+ parts.push(integerToWords(integerPart))
243
+
244
+ if (decimalPart) {
245
+ parts.push(DECIMAL_SEP)
246
+ parts.push(decimalPartToWords(decimalPart))
247
+ }
248
+
249
+ return parts.join(' ')
250
+ }
251
+
252
+ // ============================================================================
253
+ // Public API
254
+ // ============================================================================
255
+
256
+ export { toWords }
@@ -1,70 +1,18 @@
1
1
  /**
2
- * Lithuanian language converter.
2
+ * Converts a numeric value to Lithuanian words.
3
3
  *
4
- * Supports:
5
- * - Three-form pluralization (one/few/many)
6
- * - Gender agreement (vienas/viena, du/dvi)
7
- * - Baltic declension patterns
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 Lithuanian 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) // 'keturiasdešimt du'
13
+ * toWords(1, { gender: 'feminine' }) // 'viena'
14
+ * toWords(1000000) // 'vienas milijonas'
8
15
  */
9
- export class Lithuanian 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;