n2words 3.1.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (486) hide show
  1. package/CHANGELOG.md +51 -40
  2. package/LICENSE +1 -1
  3. package/README.md +64 -184
  4. package/dist/am-ET.js +2 -0
  5. package/dist/am-ET.umd.js +2 -0
  6. package/dist/am-Latn-ET.js +2 -0
  7. package/dist/am-Latn-ET.umd.js +2 -0
  8. package/dist/ar-SA.js +2 -0
  9. package/dist/ar-SA.umd.js +2 -0
  10. package/dist/az-AZ.js +2 -0
  11. package/dist/az-AZ.umd.js +2 -0
  12. package/dist/bn-BD.js +2 -0
  13. package/dist/bn-BD.umd.js +2 -0
  14. package/dist/cs-CZ.js +2 -0
  15. package/dist/cs-CZ.umd.js +2 -0
  16. package/dist/da-DK.js +2 -0
  17. package/dist/da-DK.umd.js +2 -0
  18. package/dist/de-DE.js +2 -0
  19. package/dist/de-DE.umd.js +2 -0
  20. package/dist/el-GR.js +2 -0
  21. package/dist/el-GR.umd.js +2 -0
  22. package/dist/en-AU.js +2 -0
  23. package/dist/en-AU.umd.js +2 -0
  24. package/dist/en-BD.js +2 -0
  25. package/dist/en-BD.umd.js +2 -0
  26. package/dist/en-CA.js +2 -0
  27. package/dist/en-CA.umd.js +2 -0
  28. package/dist/en-GB.js +2 -0
  29. package/dist/en-GB.umd.js +2 -0
  30. package/dist/en-GH.js +2 -0
  31. package/dist/en-GH.umd.js +2 -0
  32. package/dist/en-IE.js +2 -0
  33. package/dist/en-IE.umd.js +2 -0
  34. package/dist/en-IN.js +2 -0
  35. package/dist/en-IN.umd.js +2 -0
  36. package/dist/en-KE.js +2 -0
  37. package/dist/en-KE.umd.js +2 -0
  38. package/dist/en-MY.js +2 -0
  39. package/dist/en-MY.umd.js +2 -0
  40. package/dist/en-NG.js +2 -0
  41. package/dist/en-NG.umd.js +2 -0
  42. package/dist/en-NZ.js +2 -0
  43. package/dist/en-NZ.umd.js +2 -0
  44. package/dist/en-PH.js +2 -0
  45. package/dist/en-PH.umd.js +2 -0
  46. package/dist/en-PK.js +2 -0
  47. package/dist/en-PK.umd.js +2 -0
  48. package/dist/en-SG.js +2 -0
  49. package/dist/en-SG.umd.js +2 -0
  50. package/dist/en-US.js +2 -0
  51. package/dist/en-US.umd.js +2 -0
  52. package/dist/en-ZA.js +2 -0
  53. package/dist/en-ZA.umd.js +2 -0
  54. package/dist/es-ES.js +2 -0
  55. package/dist/es-ES.umd.js +2 -0
  56. package/dist/es-MX.js +2 -0
  57. package/dist/es-MX.umd.js +2 -0
  58. package/dist/es-US.js +2 -0
  59. package/dist/es-US.umd.js +2 -0
  60. package/dist/fa-IR.js +2 -0
  61. package/dist/fa-IR.umd.js +2 -0
  62. package/dist/fi-FI.js +2 -0
  63. package/dist/fi-FI.umd.js +2 -0
  64. package/dist/fil-PH.js +2 -0
  65. package/dist/fil-PH.umd.js +2 -0
  66. package/dist/fr-BE.js +2 -0
  67. package/dist/fr-BE.umd.js +2 -0
  68. package/dist/fr-FR.js +2 -0
  69. package/dist/fr-FR.umd.js +2 -0
  70. package/dist/gu-IN.js +2 -0
  71. package/dist/gu-IN.umd.js +2 -0
  72. package/dist/ha-NG.js +2 -0
  73. package/dist/ha-NG.umd.js +2 -0
  74. package/dist/hbo-IL.js +2 -0
  75. package/dist/hbo-IL.umd.js +2 -0
  76. package/dist/he-IL.js +2 -0
  77. package/dist/he-IL.umd.js +2 -0
  78. package/dist/hi-IN.js +2 -0
  79. package/dist/hi-IN.umd.js +2 -0
  80. package/dist/hr-HR.js +2 -0
  81. package/dist/hr-HR.umd.js +2 -0
  82. package/dist/hu-HU.js +2 -0
  83. package/dist/hu-HU.umd.js +2 -0
  84. package/dist/id-ID.js +2 -0
  85. package/dist/id-ID.umd.js +2 -0
  86. package/dist/it-IT.js +2 -0
  87. package/dist/it-IT.umd.js +2 -0
  88. package/dist/ja-JP.js +2 -0
  89. package/dist/ja-JP.umd.js +2 -0
  90. package/dist/ka-GE.js +2 -0
  91. package/dist/ka-GE.umd.js +2 -0
  92. package/dist/kn-IN.js +2 -0
  93. package/dist/kn-IN.umd.js +2 -0
  94. package/dist/ko-KR.js +2 -0
  95. package/dist/ko-KR.umd.js +2 -0
  96. package/dist/lt-LT.js +2 -0
  97. package/dist/lt-LT.umd.js +2 -0
  98. package/dist/lv-LV.js +2 -0
  99. package/dist/lv-LV.umd.js +2 -0
  100. package/dist/mr-IN.js +2 -0
  101. package/dist/mr-IN.umd.js +2 -0
  102. package/dist/ms-MY.js +2 -0
  103. package/dist/ms-MY.umd.js +2 -0
  104. package/dist/nb-NO.js +2 -0
  105. package/dist/nb-NO.umd.js +2 -0
  106. package/dist/nl-NL.js +2 -0
  107. package/dist/nl-NL.umd.js +2 -0
  108. package/dist/pa-IN.js +2 -0
  109. package/dist/pa-IN.umd.js +2 -0
  110. package/dist/pl-PL.js +2 -0
  111. package/dist/pl-PL.umd.js +2 -0
  112. package/dist/pt-BR.js +2 -0
  113. package/dist/pt-BR.umd.js +2 -0
  114. package/dist/pt-PT.js +2 -0
  115. package/dist/pt-PT.umd.js +2 -0
  116. package/dist/ro-RO.js +2 -0
  117. package/dist/ro-RO.umd.js +2 -0
  118. package/dist/ru-RU.js +2 -0
  119. package/dist/ru-RU.umd.js +2 -0
  120. package/dist/sr-Cyrl-RS.js +2 -0
  121. package/dist/sr-Cyrl-RS.umd.js +2 -0
  122. package/dist/sr-Latn-RS.js +2 -0
  123. package/dist/sr-Latn-RS.umd.js +2 -0
  124. package/dist/sv-SE.js +2 -0
  125. package/dist/sv-SE.umd.js +2 -0
  126. package/dist/sw-KE.js +2 -0
  127. package/dist/sw-KE.umd.js +2 -0
  128. package/dist/ta-IN.js +2 -0
  129. package/dist/ta-IN.umd.js +2 -0
  130. package/dist/te-IN.js +2 -0
  131. package/dist/te-IN.umd.js +2 -0
  132. package/dist/th-TH.js +2 -0
  133. package/dist/th-TH.umd.js +2 -0
  134. package/dist/tr-TR.js +2 -0
  135. package/dist/tr-TR.umd.js +2 -0
  136. package/dist/uk-UA.js +2 -0
  137. package/dist/uk-UA.umd.js +2 -0
  138. package/dist/ur-PK.js +2 -0
  139. package/dist/ur-PK.umd.js +2 -0
  140. package/dist/vi-VN.js +2 -0
  141. package/dist/vi-VN.umd.js +2 -0
  142. package/dist/yo-NG.js +2 -0
  143. package/dist/yo-NG.umd.js +2 -0
  144. package/dist/zh-Hans-CN.js +2 -0
  145. package/dist/zh-Hans-CN.umd.js +2 -0
  146. package/dist/zh-Hant-TW.js +2 -0
  147. package/dist/zh-Hant-TW.umd.js +2 -0
  148. package/package.json +61 -88
  149. package/src/am-ET.d.ts +40 -0
  150. package/src/am-ET.js +269 -0
  151. package/src/am-Latn-ET.d.ts +35 -0
  152. package/src/am-Latn-ET.js +264 -0
  153. package/src/ar-SA.d.ts +49 -0
  154. package/{lib/languages/ar.js → src/ar-SA.js} +177 -15
  155. package/src/az-AZ.d.ts +37 -0
  156. package/src/az-AZ.js +312 -0
  157. package/src/bn-BD.d.ts +36 -0
  158. package/{lib/languages/bn.js → src/bn-BD.js} +110 -6
  159. package/src/cs-CZ.d.ts +49 -0
  160. package/{lib/languages/cs.js → src/cs-CZ.js} +240 -14
  161. package/src/da-DK.d.ts +44 -0
  162. package/{lib/languages/da.js → src/da-DK.js} +131 -11
  163. package/src/de-DE.d.ts +57 -0
  164. package/src/de-DE.js +603 -0
  165. package/src/el-GR.d.ts +40 -0
  166. package/src/el-GR.js +418 -0
  167. package/src/en-AU.d.ts +47 -0
  168. package/src/en-AU.js +423 -0
  169. package/src/en-BD.d.ts +49 -0
  170. package/src/en-BD.js +415 -0
  171. package/src/en-CA.d.ts +63 -0
  172. package/src/en-CA.js +518 -0
  173. package/src/en-GB.d.ts +56 -0
  174. package/src/en-GB.js +469 -0
  175. package/src/en-GH.d.ts +11 -0
  176. package/src/en-GH.js +345 -0
  177. package/src/en-IE.d.ts +56 -0
  178. package/src/en-IE.js +479 -0
  179. package/src/en-IN.d.ts +49 -0
  180. package/src/en-IN.js +415 -0
  181. package/src/en-KE.d.ts +11 -0
  182. package/src/en-KE.js +345 -0
  183. package/src/en-MY.d.ts +11 -0
  184. package/src/en-MY.js +347 -0
  185. package/src/en-NG.d.ts +56 -0
  186. package/src/en-NG.js +479 -0
  187. package/src/en-NZ.d.ts +11 -0
  188. package/{lib/languages/en.js → src/en-NZ.js} +164 -31
  189. package/src/en-PH.d.ts +11 -0
  190. package/src/en-PH.js +345 -0
  191. package/src/en-PK.d.ts +49 -0
  192. package/src/en-PK.js +415 -0
  193. package/src/en-SG.d.ts +11 -0
  194. package/src/en-SG.js +345 -0
  195. package/src/en-US.d.ts +63 -0
  196. package/src/en-US.js +516 -0
  197. package/src/en-ZA.d.ts +56 -0
  198. package/src/en-ZA.js +478 -0
  199. package/src/es-ES.d.ts +65 -0
  200. package/src/es-ES.js +541 -0
  201. package/src/es-MX.d.ts +58 -0
  202. package/{lib/languages/es.js → src/es-MX.js} +228 -18
  203. package/src/es-US.d.ts +58 -0
  204. package/src/es-US.js +446 -0
  205. package/src/fa-IR.d.ts +38 -0
  206. package/src/fa-IR.js +246 -0
  207. package/src/fi-FI.d.ts +46 -0
  208. package/{lib/languages/fi.js → src/fi-FI.js} +152 -11
  209. package/src/fil-PH.d.ts +37 -0
  210. package/{lib/languages/fil.js → src/fil-PH.js} +144 -8
  211. package/src/fr-BE.d.ts +49 -0
  212. package/{lib/languages → src}/fr-BE.js +175 -13
  213. package/src/fr-FR.d.ts +63 -0
  214. package/{lib/languages/fr.js → src/fr-FR.js} +182 -16
  215. package/src/gu-IN.d.ts +35 -0
  216. package/{lib/languages/gu.js → src/gu-IN.js} +115 -6
  217. package/src/ha-NG.d.ts +37 -0
  218. package/{lib/languages/ha.js → src/ha-NG.js} +107 -8
  219. package/src/hbo-IL.d.ts +39 -0
  220. package/{lib/languages/hbo.js → src/hbo-IL.js} +211 -19
  221. package/src/he-IL.d.ts +37 -0
  222. package/src/he-IL.js +537 -0
  223. package/src/hi-IN.d.ts +36 -0
  224. package/{lib/languages/hi.js → src/hi-IN.js} +116 -6
  225. package/src/hr-HR.d.ts +42 -0
  226. package/src/hr-HR.js +463 -0
  227. package/src/hu-HU.d.ts +38 -0
  228. package/{lib/languages/hu.js → src/hu-HU.js} +164 -6
  229. package/src/id-ID.d.ts +38 -0
  230. package/{lib/languages/id.js → src/id-ID.js} +99 -8
  231. package/src/it-IT.d.ts +59 -0
  232. package/{lib/languages/it.js → src/it-IT.js} +179 -15
  233. package/src/ja-JP.d.ts +49 -0
  234. package/{lib/languages/ja.js → src/ja-JP.js} +111 -12
  235. package/src/ka-GE.d.ts +44 -0
  236. package/{lib/languages/ka.js → src/ka-GE.js} +113 -11
  237. package/src/kn-IN.d.ts +35 -0
  238. package/{lib/languages/kn.js → src/kn-IN.js} +115 -6
  239. package/src/ko-KR.d.ts +45 -0
  240. package/{lib/languages/ko.js → src/ko-KR.js} +94 -12
  241. package/src/lt-LT.d.ts +49 -0
  242. package/src/lt-LT.js +543 -0
  243. package/src/lv-LV.d.ts +49 -0
  244. package/src/lv-LV.js +595 -0
  245. package/src/mr-IN.d.ts +36 -0
  246. package/{lib/languages/mr.js → src/mr-IN.js} +116 -6
  247. package/src/ms-MY.d.ts +37 -0
  248. package/{lib/languages/ms.js → src/ms-MY.js} +111 -8
  249. package/src/nb-NO.d.ts +44 -0
  250. package/{lib/languages/nb.js → src/nb-NO.js} +153 -11
  251. package/src/nl-NL.d.ts +54 -0
  252. package/{lib/languages/nl.js → src/nl-NL.js} +260 -18
  253. package/src/pa-IN.d.ts +36 -0
  254. package/{lib/languages/pa.js → src/pa-IN.js} +116 -6
  255. package/src/pl-PL.d.ts +55 -0
  256. package/src/pl-PL.js +585 -0
  257. package/src/pt-BR.d.ts +31 -0
  258. package/src/pt-BR.js +534 -0
  259. package/src/pt-PT.d.ts +45 -0
  260. package/{lib/languages/pt.js → src/pt-PT.js} +234 -12
  261. package/src/ro-RO.d.ts +44 -0
  262. package/{lib/languages/ro.js → src/ro-RO.js} +212 -18
  263. package/src/ru-RU.d.ts +50 -0
  264. package/src/ru-RU.js +535 -0
  265. package/src/sr-Cyrl-RS.d.ts +49 -0
  266. package/src/sr-Cyrl-RS.js +503 -0
  267. package/src/sr-Latn-RS.d.ts +49 -0
  268. package/src/sr-Latn-RS.js +503 -0
  269. package/src/sv-SE.d.ts +44 -0
  270. package/{lib/languages/sv.js → src/sv-SE.js} +136 -11
  271. package/src/sw-KE.d.ts +37 -0
  272. package/{lib/languages/sw.js → src/sw-KE.js} +117 -6
  273. package/src/ta-IN.d.ts +35 -0
  274. package/{lib/languages/ta.js → src/ta-IN.js} +109 -6
  275. package/src/te-IN.d.ts +35 -0
  276. package/{lib/languages/te.js → src/te-IN.js} +115 -6
  277. package/src/th-TH.d.ts +38 -0
  278. package/{lib/languages/th.js → src/th-TH.js} +99 -6
  279. package/src/tr-TR.d.ts +48 -0
  280. package/{lib/languages/tr.js → src/tr-TR.js} +168 -23
  281. package/src/uk-UA.d.ts +42 -0
  282. package/src/uk-UA.js +463 -0
  283. package/src/ur-PK.d.ts +36 -0
  284. package/{lib/languages/ur.js → src/ur-PK.js} +116 -6
  285. package/src/utils/expand-scientific.d.ts +32 -0
  286. package/src/utils/expand-scientific.js +65 -0
  287. package/src/utils/parse-cardinal.d.ts +14 -0
  288. package/{lib/utils/parse-numeric.js → src/utils/parse-cardinal.js} +14 -44
  289. package/src/utils/parse-currency.d.ts +14 -0
  290. package/src/utils/parse-currency.js +91 -0
  291. package/src/utils/parse-ordinal.d.ts +10 -0
  292. package/src/utils/parse-ordinal.js +103 -0
  293. package/src/vi-VN.d.ts +48 -0
  294. package/{lib/languages/vi.js → src/vi-VN.js} +102 -11
  295. package/src/yo-NG.d.ts +37 -0
  296. package/{lib/languages/yo.js → src/yo-NG.js} +109 -9
  297. package/src/zh-Hans-CN.d.ts +48 -0
  298. package/{lib/languages/zh-Hans.js → src/zh-Hans-CN.js} +140 -8
  299. package/src/zh-Hant-TW.d.ts +50 -0
  300. package/{lib/languages/zh-Hant.js → src/zh-Hant-TW.js} +139 -8
  301. package/dist/languages/am-Latn.js +0 -3
  302. package/dist/languages/am-Latn.js.map +0 -1
  303. package/dist/languages/am.js +0 -3
  304. package/dist/languages/am.js.map +0 -1
  305. package/dist/languages/ar.js +0 -3
  306. package/dist/languages/ar.js.map +0 -1
  307. package/dist/languages/az.js +0 -3
  308. package/dist/languages/az.js.map +0 -1
  309. package/dist/languages/bn.js +0 -3
  310. package/dist/languages/bn.js.map +0 -1
  311. package/dist/languages/cs.js +0 -3
  312. package/dist/languages/cs.js.map +0 -1
  313. package/dist/languages/da.js +0 -3
  314. package/dist/languages/da.js.map +0 -1
  315. package/dist/languages/de.js +0 -3
  316. package/dist/languages/de.js.map +0 -1
  317. package/dist/languages/el.js +0 -3
  318. package/dist/languages/el.js.map +0 -1
  319. package/dist/languages/en.js +0 -3
  320. package/dist/languages/en.js.map +0 -1
  321. package/dist/languages/es.js +0 -3
  322. package/dist/languages/es.js.map +0 -1
  323. package/dist/languages/fa.js +0 -3
  324. package/dist/languages/fa.js.map +0 -1
  325. package/dist/languages/fi.js +0 -3
  326. package/dist/languages/fi.js.map +0 -1
  327. package/dist/languages/fil.js +0 -3
  328. package/dist/languages/fil.js.map +0 -1
  329. package/dist/languages/fr-BE.js +0 -3
  330. package/dist/languages/fr-BE.js.map +0 -1
  331. package/dist/languages/fr.js +0 -3
  332. package/dist/languages/fr.js.map +0 -1
  333. package/dist/languages/gu.js +0 -3
  334. package/dist/languages/gu.js.map +0 -1
  335. package/dist/languages/ha.js +0 -3
  336. package/dist/languages/ha.js.map +0 -1
  337. package/dist/languages/hbo.js +0 -3
  338. package/dist/languages/hbo.js.map +0 -1
  339. package/dist/languages/he.js +0 -3
  340. package/dist/languages/he.js.map +0 -1
  341. package/dist/languages/hi.js +0 -3
  342. package/dist/languages/hi.js.map +0 -1
  343. package/dist/languages/hr.js +0 -3
  344. package/dist/languages/hr.js.map +0 -1
  345. package/dist/languages/hu.js +0 -3
  346. package/dist/languages/hu.js.map +0 -1
  347. package/dist/languages/id.js +0 -3
  348. package/dist/languages/id.js.map +0 -1
  349. package/dist/languages/it.js +0 -3
  350. package/dist/languages/it.js.map +0 -1
  351. package/dist/languages/ja.js +0 -3
  352. package/dist/languages/ja.js.map +0 -1
  353. package/dist/languages/ka.js +0 -3
  354. package/dist/languages/ka.js.map +0 -1
  355. package/dist/languages/kn.js +0 -3
  356. package/dist/languages/kn.js.map +0 -1
  357. package/dist/languages/ko.js +0 -3
  358. package/dist/languages/ko.js.map +0 -1
  359. package/dist/languages/lt.js +0 -3
  360. package/dist/languages/lt.js.map +0 -1
  361. package/dist/languages/lv.js +0 -3
  362. package/dist/languages/lv.js.map +0 -1
  363. package/dist/languages/mr.js +0 -3
  364. package/dist/languages/mr.js.map +0 -1
  365. package/dist/languages/ms.js +0 -3
  366. package/dist/languages/ms.js.map +0 -1
  367. package/dist/languages/nb.js +0 -3
  368. package/dist/languages/nb.js.map +0 -1
  369. package/dist/languages/nl.js +0 -3
  370. package/dist/languages/nl.js.map +0 -1
  371. package/dist/languages/pa.js +0 -3
  372. package/dist/languages/pa.js.map +0 -1
  373. package/dist/languages/pl.js +0 -3
  374. package/dist/languages/pl.js.map +0 -1
  375. package/dist/languages/pt.js +0 -3
  376. package/dist/languages/pt.js.map +0 -1
  377. package/dist/languages/ro.js +0 -3
  378. package/dist/languages/ro.js.map +0 -1
  379. package/dist/languages/ru.js +0 -3
  380. package/dist/languages/ru.js.map +0 -1
  381. package/dist/languages/sr-Cyrl.js +0 -3
  382. package/dist/languages/sr-Cyrl.js.map +0 -1
  383. package/dist/languages/sr-Latn.js +0 -3
  384. package/dist/languages/sr-Latn.js.map +0 -1
  385. package/dist/languages/sv.js +0 -3
  386. package/dist/languages/sv.js.map +0 -1
  387. package/dist/languages/sw.js +0 -3
  388. package/dist/languages/sw.js.map +0 -1
  389. package/dist/languages/ta.js +0 -3
  390. package/dist/languages/ta.js.map +0 -1
  391. package/dist/languages/te.js +0 -3
  392. package/dist/languages/te.js.map +0 -1
  393. package/dist/languages/th.js +0 -3
  394. package/dist/languages/th.js.map +0 -1
  395. package/dist/languages/tr.js +0 -3
  396. package/dist/languages/tr.js.map +0 -1
  397. package/dist/languages/uk.js +0 -3
  398. package/dist/languages/uk.js.map +0 -1
  399. package/dist/languages/ur.js +0 -3
  400. package/dist/languages/ur.js.map +0 -1
  401. package/dist/languages/vi.js +0 -3
  402. package/dist/languages/vi.js.map +0 -1
  403. package/dist/languages/yo.js +0 -3
  404. package/dist/languages/yo.js.map +0 -1
  405. package/dist/languages/zh-Hans.js +0 -3
  406. package/dist/languages/zh-Hans.js.map +0 -1
  407. package/dist/languages/zh-Hant.js +0 -3
  408. package/dist/languages/zh-Hant.js.map +0 -1
  409. package/dist/n2words.js +0 -3
  410. package/dist/n2words.js.map +0 -1
  411. package/lib/languages/am-Latn.d.ts +0 -7
  412. package/lib/languages/am-Latn.js +0 -159
  413. package/lib/languages/am.d.ts +0 -7
  414. package/lib/languages/am.js +0 -159
  415. package/lib/languages/ar.d.ts +0 -17
  416. package/lib/languages/az.d.ts +0 -7
  417. package/lib/languages/az.js +0 -171
  418. package/lib/languages/bn.d.ts +0 -7
  419. package/lib/languages/cs.d.ts +0 -18
  420. package/lib/languages/da.d.ts +0 -14
  421. package/lib/languages/de.d.ts +0 -17
  422. package/lib/languages/de.js +0 -320
  423. package/lib/languages/el.d.ts +0 -14
  424. package/lib/languages/el.js +0 -236
  425. package/lib/languages/en.d.ts +0 -17
  426. package/lib/languages/es.d.ts +0 -21
  427. package/lib/languages/fa.d.ts +0 -7
  428. package/lib/languages/fa.js +0 -134
  429. package/lib/languages/fi.d.ts +0 -14
  430. package/lib/languages/fil.d.ts +0 -7
  431. package/lib/languages/fr-BE.d.ts +0 -11
  432. package/lib/languages/fr.d.ts +0 -21
  433. package/lib/languages/gu.d.ts +0 -7
  434. package/lib/languages/ha.d.ts +0 -7
  435. package/lib/languages/hbo.d.ts +0 -13
  436. package/lib/languages/he.d.ts +0 -13
  437. package/lib/languages/he.js +0 -265
  438. package/lib/languages/hi.d.ts +0 -7
  439. package/lib/languages/hr.d.ts +0 -11
  440. package/lib/languages/hr.js +0 -224
  441. package/lib/languages/hu.d.ts +0 -7
  442. package/lib/languages/id.d.ts +0 -7
  443. package/lib/languages/it.d.ts +0 -19
  444. package/lib/languages/ja.d.ts +0 -17
  445. package/lib/languages/ka.d.ts +0 -17
  446. package/lib/languages/kn.d.ts +0 -7
  447. package/lib/languages/ko.d.ts +0 -14
  448. package/lib/languages/lt.d.ts +0 -18
  449. package/lib/languages/lt.js +0 -301
  450. package/lib/languages/lv.d.ts +0 -18
  451. package/lib/languages/lv.js +0 -312
  452. package/lib/languages/mr.d.ts +0 -7
  453. package/lib/languages/ms.d.ts +0 -7
  454. package/lib/languages/nb.d.ts +0 -14
  455. package/lib/languages/nl.d.ts +0 -26
  456. package/lib/languages/pa.d.ts +0 -7
  457. package/lib/languages/pl.d.ts +0 -22
  458. package/lib/languages/pl.js +0 -317
  459. package/lib/languages/pt.d.ts +0 -17
  460. package/lib/languages/ro.d.ts +0 -18
  461. package/lib/languages/ru.d.ts +0 -11
  462. package/lib/languages/ru.js +0 -245
  463. package/lib/languages/sr-Cyrl.d.ts +0 -11
  464. package/lib/languages/sr-Cyrl.js +0 -221
  465. package/lib/languages/sr-Latn.d.ts +0 -11
  466. package/lib/languages/sr-Latn.js +0 -221
  467. package/lib/languages/sv.d.ts +0 -14
  468. package/lib/languages/sw.d.ts +0 -7
  469. package/lib/languages/ta.d.ts +0 -7
  470. package/lib/languages/te.d.ts +0 -7
  471. package/lib/languages/th.d.ts +0 -7
  472. package/lib/languages/tr.d.ts +0 -18
  473. package/lib/languages/uk.d.ts +0 -11
  474. package/lib/languages/uk.js +0 -224
  475. package/lib/languages/ur.d.ts +0 -7
  476. package/lib/languages/vi.d.ts +0 -17
  477. package/lib/languages/yo.d.ts +0 -7
  478. package/lib/languages/zh-Hans.d.ts +0 -11
  479. package/lib/languages/zh-Hant.d.ts +0 -11
  480. package/lib/n2words.d.ts +0 -55
  481. package/lib/n2words.js +0 -126
  482. package/lib/utils/parse-numeric.d.ts +0 -17
  483. /package/{lib → src}/utils/is-plain-object.d.ts +0 -0
  484. /package/{lib → src}/utils/is-plain-object.js +0 -0
  485. /package/{lib → src}/utils/validate-options.d.ts +0 -0
  486. /package/{lib → src}/utils/validate-options.js +0 -0
@@ -1,17 +1,20 @@
1
1
  /**
2
- * Portuguese language converter - Functional Implementation
2
+ * Portuguese (Portugal) language converter
3
3
  *
4
- * Self-contained module with its own input validation, ready for subpath exports.
4
+ * CLDR: pt-PT | European Portuguese as used in Portugal
5
5
  *
6
6
  * Portuguese-specific rules:
7
7
  * - "e" conjunction everywhere: vinte e um, cento e um, mil e um
8
8
  * - "cem" for exact 100, "cento" for 100+ remainder
9
9
  * - Irregular hundreds: duzentos, trezentos, quatrocentos, etc.
10
- * - Compound scale: milhão (10^6), mil milhões (10^9), bilião (10^12)
10
+ * - Long scale: milhão (10^6), mil milhões (10^9), bilião (10^12)
11
11
  * - Omit "um" before "mil"
12
12
  */
13
13
 
14
- import { parseNumericValue } from '../utils/parse-numeric.js'
14
+ import { parseCardinalValue } from './utils/parse-cardinal.js'
15
+ import { parseCurrencyValue } from './utils/parse-currency.js'
16
+ import { parseOrdinalValue } from './utils/parse-ordinal.js'
17
+ import { validateOptions } from './utils/validate-options.js'
15
18
 
16
19
  // ============================================================================
17
20
  // Vocabulary (module-level constants)
@@ -29,6 +32,18 @@ const ZERO = 'zero'
29
32
  const NEGATIVE = 'menos'
30
33
  const DECIMAL_SEP = 'vírgula'
31
34
 
35
+ // Ordinal vocabulary
36
+ const ORDINAL_ONES = ['', 'primeiro', 'segundo', 'terceiro', 'quarto', 'quinto', 'sexto', 'sétimo', 'oitavo', 'nono']
37
+ const ORDINAL_TEENS = ['décimo', 'décimo primeiro', 'décimo segundo', 'décimo terceiro', 'décimo quarto', 'décimo quinto', 'décimo sexto', 'décimo sétimo', 'décimo oitavo', 'décimo nono']
38
+ const ORDINAL_TENS = ['', '', 'vigésimo', 'trigésimo', 'quadragésimo', 'quinquagésimo', 'sexagésimo', 'septuagésimo', 'octogésimo', 'nonagésimo']
39
+ const ORDINAL_HUNDREDS = ['', 'centésimo', 'ducentésimo', 'tricentésimo', 'quadringentésimo', 'quingentésimo', 'sexcentésimo', 'septingentésimo', 'octingentésimo', 'nongentésimo']
40
+
41
+ // Currency vocabulary (Euro)
42
+ const EURO = 'euro'
43
+ const EUROS = 'euros'
44
+ const CENTIMO = 'cêntimo'
45
+ const CENTIMOS = 'cêntimos'
46
+
32
47
  // ============================================================================
33
48
  // Segment Building
34
49
  // ============================================================================
@@ -44,8 +59,8 @@ function buildSegment (n) {
44
59
  if (n === 100) return { word: 'cem', isExactHundred: true }
45
60
 
46
61
  const ones = n % 10
47
- const tens = Math.floor(n / 10) % 10
48
- const hundreds = Math.floor(n / 100)
62
+ const tens = Math.trunc(n / 10) % 10
63
+ const hundreds = Math.trunc(n / 100)
49
64
 
50
65
  const parts = []
51
66
 
@@ -263,12 +278,12 @@ function decimalPartToWords (decimalPart) {
263
278
  * @throws {Error} If value is not a valid number format
264
279
  *
265
280
  * @example
266
- * toWords(21) // 'vinte e um'
267
- * toWords(100) // 'cem'
268
- * toWords(1000000) // 'um milhão'
281
+ * toCardinal(21) // 'vinte e um'
282
+ * toCardinal(100) // 'cem'
283
+ * toCardinal(1000000) // 'um milhão'
269
284
  */
270
- function toWords (value) {
271
- const { isNegative, integerPart, decimalPart } = parseNumericValue(value)
285
+ function toCardinal (value) {
286
+ const { isNegative, integerPart, decimalPart } = parseCardinalValue(value)
272
287
 
273
288
  let result = ''
274
289
 
@@ -285,8 +300,215 @@ function toWords (value) {
285
300
  return result
286
301
  }
287
302
 
303
+ // ============================================================================
304
+ // Ordinal Functions
305
+ // ============================================================================
306
+
307
+ /**
308
+ * Builds ordinal words for 0-999.
309
+ *
310
+ * @param {number} n - Number 0-999
311
+ * @returns {string} Portuguese ordinal words
312
+ */
313
+ function buildOrdinalSegment (n) {
314
+ if (n === 0) return ''
315
+
316
+ const ones = n % 10
317
+ const tens = Math.trunc(n / 10) % 10
318
+ const hundreds = Math.trunc(n / 100)
319
+
320
+ const parts = []
321
+
322
+ // Hundreds ordinal
323
+ if (hundreds > 0) {
324
+ parts.push(ORDINAL_HUNDREDS[hundreds])
325
+ }
326
+
327
+ // Tens and ones
328
+ if (tens === 1) {
329
+ // 10-19: use teens array (décimo, décimo primeiro, etc.)
330
+ parts.push(ORDINAL_TEENS[ones])
331
+ } else if (tens >= 2) {
332
+ parts.push(ORDINAL_TENS[tens])
333
+ if (ones > 0) {
334
+ parts.push(ORDINAL_ONES[ones])
335
+ }
336
+ } else if (ones > 0) {
337
+ parts.push(ORDINAL_ONES[ones])
338
+ }
339
+
340
+ return parts.join(' ')
341
+ }
342
+
343
+ /**
344
+ * Builds ordinal words for large numbers.
345
+ *
346
+ * @param {bigint} n - Non-negative integer
347
+ * @returns {string} Portuguese ordinal words
348
+ */
349
+ function buildLargeOrdinal (n) {
350
+ // Extract segments
351
+ const segments = []
352
+ let temp = n
353
+ while (temp > 0n) {
354
+ segments.push(Number(temp % 1000n))
355
+ temp = temp / 1000n
356
+ }
357
+
358
+ // Find the lowest non-zero segment (index 0 = units, lowest scale)
359
+ let lowestNonZeroIdx = 0
360
+ for (let i = 0; i < segments.length; i++) {
361
+ if (segments[i] !== 0) {
362
+ lowestNonZeroIdx = i
363
+ break
364
+ }
365
+ }
366
+
367
+ // Scale ordinal words (singular forms)
368
+ const SCALE_ORDINAL = ['', 'milésimo', 'milionésimo', 'mil milionésimo', 'bilionésimo', 'mil bilionésimo', 'trilionésimo']
369
+
370
+ let result = ''
371
+
372
+ for (let i = segments.length - 1; i >= 0; i--) {
373
+ const segment = segments[i]
374
+ if (segment === 0) continue
375
+
376
+ if (result) result += ' '
377
+
378
+ if (i === lowestNonZeroIdx) {
379
+ // Last non-zero segment gets ordinal form
380
+ if (i === 0) {
381
+ // Units: just ordinal
382
+ result += buildOrdinalSegment(segment)
383
+ } else if (segment === 1 && i > 0) {
384
+ // Exact scale: "milésimo", "milionésimo", etc.
385
+ result += SCALE_ORDINAL[i]
386
+ } else {
387
+ // Segment + scale ordinal
388
+ result += buildOrdinalSegment(segment) + ' ' + SCALE_ORDINAL[i]
389
+ }
390
+ } else {
391
+ // Higher segments use cardinal form
392
+ if (i === 0) {
393
+ result += buildSegment(segment).word
394
+ } else if (i === 1) {
395
+ if (segment === 1) {
396
+ result += THOUSAND
397
+ } else {
398
+ result += buildSegment(segment).word + ' ' + THOUSAND
399
+ }
400
+ } else {
401
+ const scaleWord = segment === 1 ? SCALE_WORDS_SINGULAR[i] : SCALE_WORDS_PLURAL[i]
402
+ if (segment === 1) {
403
+ result += 'um ' + scaleWord
404
+ } else {
405
+ result += buildSegment(segment).word + ' ' + scaleWord
406
+ }
407
+ }
408
+ }
409
+ }
410
+
411
+ return result
412
+ }
413
+
414
+ /**
415
+ * Converts a number to Portuguese ordinal words.
416
+ *
417
+ * @param {number | string | bigint} value - The number to convert
418
+ * @returns {string} Portuguese ordinal words
419
+ *
420
+ * @example
421
+ * toOrdinal(1) // 'primeiro'
422
+ * toOrdinal(21) // 'vigésimo primeiro'
423
+ * toOrdinal(100) // 'centésimo'
424
+ */
425
+ function toOrdinal (value) {
426
+ const n = parseOrdinalValue(value)
427
+
428
+ // Fast path: 1-9
429
+ if (n < 10n) {
430
+ return ORDINAL_ONES[Number(n)]
431
+ }
432
+
433
+ // Fast path: 10-19
434
+ if (n < 20n) {
435
+ return ORDINAL_TEENS[Number(n) - 10]
436
+ }
437
+
438
+ // Fast path: 20-99
439
+ if (n < 100n) {
440
+ const ones = Number(n % 10n)
441
+ const tens = Number(n / 10n)
442
+ if (ones === 0) {
443
+ return ORDINAL_TENS[tens]
444
+ }
445
+ return ORDINAL_TENS[tens] + ' ' + ORDINAL_ONES[ones]
446
+ }
447
+
448
+ // Fast path: 100-999
449
+ if (n < 1000n) {
450
+ return buildOrdinalSegment(Number(n))
451
+ }
452
+
453
+ // Large numbers
454
+ return buildLargeOrdinal(n)
455
+ }
456
+
457
+ // ============================================================================
458
+ // Currency Functions
459
+ // ============================================================================
460
+
461
+ /**
462
+ * Converts a number to Portuguese currency words (Euro).
463
+ *
464
+ * @param {number | string | bigint} value - The amount to convert
465
+ * @param {Object} [options]
466
+ * @param {boolean} [options.and=true] - Include "e" between euros and cents
467
+ * @returns {string} Portuguese currency words
468
+ *
469
+ * @example
470
+ * toCurrency(42.50) // 'quarenta e dois euros e cinquenta cêntimos'
471
+ * toCurrency(1) // 'um euro'
472
+ * toCurrency(0.01) // 'um cêntimo'
473
+ */
474
+ function toCurrency (value, options) {
475
+ options = validateOptions(options)
476
+ const { isNegative, dollars: euros, cents } = parseCurrencyValue(value)
477
+ const { and = true } = options
478
+
479
+ let result = ''
480
+
481
+ if (isNegative) {
482
+ result = NEGATIVE + ' '
483
+ }
484
+
485
+ const hasEuros = euros > 0n
486
+ const hasCents = cents > 0n
487
+
488
+ if (!hasEuros && !hasCents) {
489
+ return ZERO + ' ' + EUROS
490
+ }
491
+
492
+ if (hasEuros) {
493
+ const euroWords = integerToWords(euros)
494
+ const euroUnit = euros === 1n ? EURO : EUROS
495
+ result += euroWords + ' ' + euroUnit
496
+ }
497
+
498
+ if (hasCents) {
499
+ if (hasEuros) {
500
+ result += and ? ' e ' : ' '
501
+ }
502
+ const centWords = integerToWords(cents)
503
+ const centUnit = cents === 1n ? CENTIMO : CENTIMOS
504
+ result += centWords + ' ' + centUnit
505
+ }
506
+
507
+ return result
508
+ }
509
+
288
510
  // ============================================================================
289
511
  // Public API
290
512
  // ============================================================================
291
513
 
292
- export { toWords }
514
+ export { toCardinal, toOrdinal, toCurrency }
package/src/ro-RO.d.ts ADDED
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Converts a numeric value to Romanian words.
3
+ *
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
7
+ * @returns {string} The number in Romanian 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
+ * toCardinal(21) // 'douăzeci și unu'
13
+ * toCardinal(1, { gender: 'feminine' }) // 'una'
14
+ * toCardinal(1000) // 'o mie'
15
+ */
16
+ export function toCardinal(value: number | string | bigint, options?: {
17
+ gender?: string | undefined;
18
+ }): string;
19
+ /**
20
+ * Converts a numeric value to Romanian ordinal words.
21
+ *
22
+ * @param {number | string | bigint} value - The numeric value to convert
23
+ * @returns {string} The ordinal in Romanian words
24
+ * @throws {TypeError} If value is not a valid numeric type
25
+ * @throws {Error} If value is not a positive integer
26
+ *
27
+ * @example
28
+ * toOrdinal(1) // 'primul'
29
+ * toOrdinal(21) // 'douăzeci și primul'
30
+ */
31
+ export function toOrdinal(value: number | string | bigint): string;
32
+ /**
33
+ * Converts a numeric value to Romanian Leu currency words.
34
+ *
35
+ * @param {number | string | bigint} value - The numeric value to convert
36
+ * @returns {string} The currency in Romanian words
37
+ * @throws {TypeError} If value is not a valid numeric type
38
+ * @throws {Error} If value is not a valid number format
39
+ *
40
+ * @example
41
+ * toCurrency(1) // 'un leu'
42
+ * toCurrency(2.50) // 'doi lei cincizeci de bani'
43
+ */
44
+ export function toCurrency(value: number | string | bigint): string;
@@ -1,7 +1,7 @@
1
1
  /**
2
- * Romanian language converter - Functional Implementation
2
+ * Romanian (Romania) language converter
3
3
  *
4
- * A performance-optimized number-to-words converter using precomputed lookup tables.
4
+ * CLDR: ro-RO | Romanian as used in Romania
5
5
  *
6
6
  * Key features:
7
7
  * - Gender agreement (unu/una, doi/două)
@@ -10,8 +10,10 @@
10
10
  * - Feminine units for thousands
11
11
  */
12
12
 
13
- import { parseNumericValue } from '../utils/parse-numeric.js'
14
- import { validateOptions } from '../utils/validate-options.js'
13
+ import { parseCardinalValue } from './utils/parse-cardinal.js'
14
+ import { parseCurrencyValue } from './utils/parse-currency.js'
15
+ import { parseOrdinalValue } from './utils/parse-ordinal.js'
16
+ import { validateOptions } from './utils/validate-options.js'
15
17
 
16
18
  // ============================================================================
17
19
  // Vocabulary (module-level constants)
@@ -31,6 +33,20 @@ const ZERO = 'zero'
31
33
  const NEGATIVE = 'minus'
32
34
  const DECIMAL_SEP = 'virgulă'
33
35
 
36
+ // Ordinal vocabulary (masculine forms)
37
+ const ORDINAL_ONES = ['', 'primul', 'al doilea', 'al treilea', 'al patrulea', 'al cincilea', 'al șaselea', 'al șaptelea', 'al optulea', 'al nouălea']
38
+ const ORDINAL_TEENS = ['al zecelea', 'al unsprezecelea', 'al doisprezecelea', 'al treisprezecelea', 'al paisprezecelea', 'al cincisprezecelea', 'al șaisprezecelea', 'al șaptesprezecelea', 'al optsprezecelea', 'al nouăsprezecelea']
39
+ const ORDINAL_TENS = ['', '', 'al douăzecilea', 'al treizecilea', 'al patruzecilea', 'al cincizecilea', 'al șaizecilea', 'al șaptezecilea', 'al optzecilea', 'al nouăzecilea']
40
+ const ORDINAL_HUNDRED = 'al sutălea'
41
+ const ORDINAL_THOUSAND = 'al miilea'
42
+ const ORDINAL_MILLION = 'al milionulea'
43
+
44
+ // Currency (Romanian Leu)
45
+ const LEU_SINGULAR = 'leu'
46
+ const LEU_PLURAL = 'lei'
47
+ const BAN_SINGULAR = 'ban'
48
+ const BAN_PLURAL = 'bani'
49
+
34
50
  // Scale metadata: [singular, plural, article, feminine, needsDe]
35
51
  // - singular: form for 1
36
52
  // - plural: form for 2+
@@ -64,7 +80,7 @@ function spellUnder100 (n, feminine = false, masculineTeens = false) {
64
80
  if (n < 20) {
65
81
  return masculineTeens ? TEENS_MASC[n - 10] : TEENS[n - 10]
66
82
  }
67
- const t = Math.floor(n / 10)
83
+ const t = Math.trunc(n / 10)
68
84
  const u = n % 10
69
85
  if (u === 0) {
70
86
  return TWENTIES[t]
@@ -80,7 +96,7 @@ function spellUnder1000 (n, feminine = false, masculineTeens = false) {
80
96
  if (n === 0) return ''
81
97
  if (n < 100) return spellUnder100(n, feminine, masculineTeens)
82
98
 
83
- const h = Math.floor(n / 100)
99
+ const h = Math.trunc(n / 100)
84
100
  const r = n % 100
85
101
  const hundredWord = HUNDREDS[h]
86
102
 
@@ -126,16 +142,16 @@ function buildScalePhrase (segment, scaleIndex) {
126
142
  * @param {Object} options - Conversion options
127
143
  * @returns {string} Romanian words
128
144
  */
129
- function integerToWords (n, options = {}) {
145
+ function integerToWords (n, gender) {
130
146
  if (n === 0n) return ZERO
131
147
 
132
148
  // Fast path: numbers < 1000
133
149
  if (n < 1000n) {
134
- const feminine = options.gender === 'feminine'
150
+ const feminine = gender === 'feminine'
135
151
  return spellUnder1000(Number(n), feminine)
136
152
  }
137
153
 
138
- return buildLargeNumberWords(n, options)
154
+ return buildLargeNumberWords(n, gender)
139
155
  }
140
156
 
141
157
  /**
@@ -146,7 +162,7 @@ function integerToWords (n, options = {}) {
146
162
  * @param {Object} options - Conversion options
147
163
  * @returns {string} Romanian words
148
164
  */
149
- function buildLargeNumberWords (n, options) {
165
+ function buildLargeNumberWords (n, gender) {
150
166
  // Extract segments using BigInt division (faster than string slicing)
151
167
  // Segments stored least-significant first (index 0 = ones, 1 = thousands, etc.)
152
168
  const segmentValues = []
@@ -166,7 +182,7 @@ function buildLargeNumberWords (n, options) {
166
182
  let segmentWords
167
183
  if (i === 0) {
168
184
  // Units segment - use gender from options
169
- const feminine = options.gender === 'feminine'
185
+ const feminine = gender === 'feminine'
170
186
  segmentWords = spellUnder1000(segment, feminine)
171
187
  } else {
172
188
  // Scale segment
@@ -227,13 +243,16 @@ function decimalPartToWords (decimalPart) {
227
243
  * @throws {Error} If value is not a valid number format
228
244
  *
229
245
  * @example
230
- * toWords(21) // 'douăzeci și unu'
231
- * toWords(1, { gender: 'feminine' }) // 'una'
232
- * toWords(1000) // 'o mie'
246
+ * toCardinal(21) // 'douăzeci și unu'
247
+ * toCardinal(1, { gender: 'feminine' }) // 'una'
248
+ * toCardinal(1000) // 'o mie'
233
249
  */
234
- function toWords (value, options) {
250
+ function toCardinal (value, options) {
235
251
  options = validateOptions(options)
236
- const { isNegative, integerPart, decimalPart } = parseNumericValue(value)
252
+ const { isNegative, integerPart, decimalPart } = parseCardinalValue(value)
253
+
254
+ // Apply option defaults
255
+ const { gender = 'masculine' } = options
237
256
 
238
257
  let result = ''
239
258
 
@@ -241,7 +260,7 @@ function toWords (value, options) {
241
260
  result = NEGATIVE + ' '
242
261
  }
243
262
 
244
- result += integerToWords(integerPart, options)
263
+ result += integerToWords(integerPart, gender)
245
264
 
246
265
  if (decimalPart) {
247
266
  result += ' ' + DECIMAL_SEP + ' ' + decimalPartToWords(decimalPart)
@@ -250,8 +269,183 @@ function toWords (value, options) {
250
269
  return result
251
270
  }
252
271
 
272
+ // ============================================================================
273
+ // Ordinal Functions
274
+ // ============================================================================
275
+
276
+ /**
277
+ * Builds ordinal for tens and ones (0-99).
278
+ *
279
+ * @param {number} n - Number 0-99
280
+ * @returns {string} Ordinal word
281
+ */
282
+ function buildOrdinalTensOnes (n) {
283
+ if (n === 0) return ''
284
+ if (n < 10) return ORDINAL_ONES[n]
285
+ if (n < 20) return ORDINAL_TEENS[n - 10]
286
+
287
+ const ones = n % 10
288
+ const tens = Math.trunc(n / 10)
289
+
290
+ if (ones === 0) {
291
+ return ORDINAL_TENS[tens]
292
+ }
293
+ // Compound: cardinal tens + ordinal ones (only last is ordinal)
294
+ return TWENTIES[tens] + ' și ' + ORDINAL_ONES[ones]
295
+ }
296
+
297
+ /**
298
+ * Converts a non-negative integer to Romanian ordinal words.
299
+ *
300
+ * @param {bigint} n - Non-negative integer to convert
301
+ * @returns {string} Romanian ordinal words
302
+ */
303
+ function integerToOrdinal (n) {
304
+ if (n === 0n) return ''
305
+ if (n === 1n) return ORDINAL_ONES[1]
306
+
307
+ // Numbers < 100
308
+ if (n < 100n) {
309
+ return buildOrdinalTensOnes(Number(n))
310
+ }
311
+
312
+ // Numbers < 1000
313
+ if (n < 1000n) {
314
+ const hundreds = Number(n / 100n)
315
+ const remainder = Number(n % 100n)
316
+
317
+ if (remainder === 0) {
318
+ return ORDINAL_HUNDRED
319
+ }
320
+ return HUNDREDS[hundreds] + ' ' + buildOrdinalTensOnes(remainder)
321
+ }
322
+
323
+ // Numbers < 1,000,000
324
+ if (n < 1_000_000n) {
325
+ const thousands = Number(n / 1000n)
326
+ const remainder = Number(n % 1000n)
327
+
328
+ if (remainder === 0) {
329
+ if (thousands === 1) {
330
+ return ORDINAL_THOUSAND
331
+ }
332
+ return buildScalePhrase(thousands, 1) + ' ' + ORDINAL_THOUSAND
333
+ }
334
+
335
+ // Cardinal thousands + ordinal remainder
336
+ let result
337
+ if (thousands === 1) {
338
+ result = 'o mie'
339
+ } else {
340
+ result = buildScalePhrase(thousands, 1)
341
+ }
342
+
343
+ if (remainder < 100) {
344
+ return result + ' ' + buildOrdinalTensOnes(remainder)
345
+ }
346
+
347
+ const remHundreds = Math.trunc(remainder / 100)
348
+ const remTensOnes = remainder % 100
349
+
350
+ if (remTensOnes === 0) {
351
+ return result + ' ' + ORDINAL_HUNDRED
352
+ }
353
+ return result + ' ' + HUNDREDS[remHundreds] + ' ' + buildOrdinalTensOnes(remTensOnes)
354
+ }
355
+
356
+ // Numbers >= 1,000,000
357
+ const millions = Number(n / 1_000_000n)
358
+ const remainder = n % 1_000_000n
359
+
360
+ if (remainder === 0n) {
361
+ if (millions === 1) {
362
+ return ORDINAL_MILLION
363
+ }
364
+ return buildScalePhrase(millions, 2) + ' ' + ORDINAL_MILLION
365
+ }
366
+
367
+ // Cardinal millions + ordinal remainder
368
+ let result
369
+ if (millions === 1) {
370
+ result = 'un milion'
371
+ } else {
372
+ result = buildScalePhrase(millions, 2)
373
+ }
374
+
375
+ return result + ' ' + integerToOrdinal(remainder)
376
+ }
377
+
378
+ /**
379
+ * Converts a numeric value to Romanian ordinal words.
380
+ *
381
+ * @param {number | string | bigint} value - The numeric value to convert
382
+ * @returns {string} The ordinal in Romanian words
383
+ * @throws {TypeError} If value is not a valid numeric type
384
+ * @throws {Error} If value is not a positive integer
385
+ *
386
+ * @example
387
+ * toOrdinal(1) // 'primul'
388
+ * toOrdinal(21) // 'douăzeci și primul'
389
+ */
390
+ function toOrdinal (value) {
391
+ const n = parseOrdinalValue(value)
392
+ return integerToOrdinal(n)
393
+ }
394
+
395
+ // ============================================================================
396
+ // Currency Functions
397
+ // ============================================================================
398
+
399
+ /**
400
+ * Converts a numeric value to Romanian Leu currency words.
401
+ *
402
+ * @param {number | string | bigint} value - The numeric value to convert
403
+ * @returns {string} The currency in Romanian words
404
+ * @throws {TypeError} If value is not a valid numeric type
405
+ * @throws {Error} If value is not a valid number format
406
+ *
407
+ * @example
408
+ * toCurrency(1) // 'un leu'
409
+ * toCurrency(2.50) // 'doi lei cincizeci de bani'
410
+ */
411
+ function toCurrency (value) {
412
+ const { isNegative, dollars, cents } = parseCurrencyValue(value)
413
+
414
+ const parts = []
415
+
416
+ if (isNegative) {
417
+ parts.push(NEGATIVE)
418
+ }
419
+
420
+ // Lei (masculine)
421
+ if (dollars > 0n || cents === 0n) {
422
+ if (dollars === 1n) {
423
+ parts.push('un ' + LEU_SINGULAR)
424
+ } else {
425
+ const leuWord = integerToWords(dollars, 'masculine')
426
+ parts.push(leuWord + ' ' + LEU_PLURAL)
427
+ }
428
+ }
429
+
430
+ // Bani (masculine)
431
+ if (cents > 0n) {
432
+ const centNum = Number(cents)
433
+ if (centNum === 1) {
434
+ parts.push('un ' + BAN_SINGULAR)
435
+ } else if (centNum >= 20) {
436
+ const banWord = spellUnder100(centNum, false)
437
+ parts.push(banWord + ' de ' + BAN_PLURAL)
438
+ } else {
439
+ const banWord = spellUnder100(centNum, false)
440
+ parts.push(banWord + ' ' + BAN_PLURAL)
441
+ }
442
+ }
443
+
444
+ return parts.join(' ')
445
+ }
446
+
253
447
  // ============================================================================
254
448
  // Public API
255
449
  // ============================================================================
256
450
 
257
- export { toWords }
451
+ export { toCardinal, toOrdinal, toCurrency }
package/src/ru-RU.d.ts ADDED
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Converts a numeric value to Russian words.
3
+ *
4
+ * @param {number | string | bigint} value - The numeric value to convert
5
+ * @param {Object} [options] - Optional configuration
6
+ * @param {('masculine'|'feminine')} [options.gender='masculine'] - Grammatical gender
7
+ * @returns {string} The number in Russian words
8
+ */
9
+ export function toCardinal(value: number | string | bigint, options?: {
10
+ gender?: "masculine" | "feminine" | undefined;
11
+ }): string;
12
+ /**
13
+ * Converts a numeric value to Russian ordinal words (masculine nominative).
14
+ *
15
+ * @param {number | string | bigint} value - The numeric value to convert (must be a positive integer)
16
+ * @returns {string} The number as ordinal words (e.g., "первый", "сорок второй")
17
+ * @throws {TypeError} If value is not a valid numeric type
18
+ * @throws {RangeError} If value is negative, zero, or has a decimal part
19
+ *
20
+ * @example
21
+ * toOrdinal(1) // 'первый'
22
+ * toOrdinal(2) // 'второй'
23
+ * toOrdinal(3) // 'третий'
24
+ * toOrdinal(21) // 'двадцать первый'
25
+ * toOrdinal(42) // 'сорок второй'
26
+ * toOrdinal(100) // 'сотый'
27
+ * toOrdinal(101) // 'сто первый'
28
+ * toOrdinal(1000) // 'тысячный'
29
+ */
30
+ export function toOrdinal(value: number | string | bigint): string;
31
+ /**
32
+ * Converts a numeric value to Russian currency words (Russian Ruble).
33
+ *
34
+ * @param {number | string | bigint} value - The currency amount to convert
35
+ * @param {Object} [options] - Optional configuration
36
+ * @param {boolean} [options.and=true] - Use "и" between rubles and kopecks
37
+ * @returns {string} The amount in Russian currency words
38
+ * @throws {TypeError} If value is not a valid numeric type
39
+ * @throws {Error} If value is not a valid number format
40
+ *
41
+ * @example
42
+ * toCurrency(42.50) // 'сорок два рубля и пятьдесят копеек'
43
+ * toCurrency(1) // 'один рубль'
44
+ * toCurrency(0.99) // 'девяносто девять копеек'
45
+ * toCurrency(0.01) // 'одна копейка'
46
+ * toCurrency(42.50, { and: false }) // 'сорок два рубля пятьдесят копеек'
47
+ */
48
+ export function toCurrency(value: number | string | bigint, options?: {
49
+ and?: boolean | undefined;
50
+ }): string;