n2words 1.24.0 → 2.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 (349) hide show
  1. package/README.md +285 -156
  2. package/dist/ArabicConverter.js +3 -0
  3. package/dist/ArabicConverter.js.map +1 -0
  4. package/dist/AzerbaijaniConverter.js +3 -0
  5. package/dist/AzerbaijaniConverter.js.map +1 -0
  6. package/dist/BanglaConverter.js +3 -0
  7. package/dist/BanglaConverter.js.map +1 -0
  8. package/dist/BiblicalHebrewConverter.js +3 -0
  9. package/dist/BiblicalHebrewConverter.js.map +1 -0
  10. package/dist/CroatianConverter.js +3 -0
  11. package/dist/CroatianConverter.js.map +1 -0
  12. package/dist/CzechConverter.js +3 -0
  13. package/dist/CzechConverter.js.map +1 -0
  14. package/dist/DanishConverter.js +3 -0
  15. package/dist/DanishConverter.js.map +1 -0
  16. package/dist/DutchConverter.js +3 -0
  17. package/dist/DutchConverter.js.map +1 -0
  18. package/dist/EnglishConverter.js +3 -0
  19. package/dist/EnglishConverter.js.map +1 -0
  20. package/dist/FilipinoConverter.js +3 -0
  21. package/dist/FilipinoConverter.js.map +1 -0
  22. package/dist/FrenchBelgiumConverter.js +3 -0
  23. package/dist/FrenchBelgiumConverter.js.map +1 -0
  24. package/dist/FrenchConverter.js +3 -0
  25. package/dist/FrenchConverter.js.map +1 -0
  26. package/dist/GermanConverter.js +3 -0
  27. package/dist/GermanConverter.js.map +1 -0
  28. package/dist/GreekConverter.js +3 -0
  29. package/dist/GreekConverter.js.map +1 -0
  30. package/dist/GujaratiConverter.js +3 -0
  31. package/dist/GujaratiConverter.js.map +1 -0
  32. package/dist/HebrewConverter.js +3 -0
  33. package/dist/HebrewConverter.js.map +1 -0
  34. package/dist/HindiConverter.js +3 -0
  35. package/dist/HindiConverter.js.map +1 -0
  36. package/dist/HungarianConverter.js +3 -0
  37. package/dist/HungarianConverter.js.map +1 -0
  38. package/dist/IndonesianConverter.js +3 -0
  39. package/dist/IndonesianConverter.js.map +1 -0
  40. package/dist/ItalianConverter.js +3 -0
  41. package/dist/ItalianConverter.js.map +1 -0
  42. package/dist/JapaneseConverter.js +3 -0
  43. package/dist/JapaneseConverter.js.map +1 -0
  44. package/dist/KannadaConverter.js +3 -0
  45. package/dist/KannadaConverter.js.map +1 -0
  46. package/dist/KoreanConverter.js +3 -0
  47. package/dist/KoreanConverter.js.map +1 -0
  48. package/dist/LatvianConverter.js +3 -0
  49. package/dist/LatvianConverter.js.map +1 -0
  50. package/dist/LithuanianConverter.js +3 -0
  51. package/dist/LithuanianConverter.js.map +1 -0
  52. package/dist/MalayConverter.js +3 -0
  53. package/dist/MalayConverter.js.map +1 -0
  54. package/dist/MarathiConverter.js +3 -0
  55. package/dist/MarathiConverter.js.map +1 -0
  56. package/dist/NorwegianBokmalConverter.js +3 -0
  57. package/dist/NorwegianBokmalConverter.js.map +1 -0
  58. package/dist/PersianConverter.js +3 -0
  59. package/dist/PersianConverter.js.map +1 -0
  60. package/dist/PolishConverter.js +3 -0
  61. package/dist/PolishConverter.js.map +1 -0
  62. package/dist/PortugueseConverter.js +3 -0
  63. package/dist/PortugueseConverter.js.map +1 -0
  64. package/dist/PunjabiConverter.js +3 -0
  65. package/dist/PunjabiConverter.js.map +1 -0
  66. package/dist/RomanianConverter.js +3 -0
  67. package/dist/RomanianConverter.js.map +1 -0
  68. package/dist/RussianConverter.js +3 -0
  69. package/dist/RussianConverter.js.map +1 -0
  70. package/dist/SerbianCyrillicConverter.js +3 -0
  71. package/dist/SerbianCyrillicConverter.js.map +1 -0
  72. package/dist/SerbianLatinConverter.js +3 -0
  73. package/dist/SerbianLatinConverter.js.map +1 -0
  74. package/dist/SimplifiedChineseConverter.js +3 -0
  75. package/dist/SimplifiedChineseConverter.js.map +1 -0
  76. package/dist/SpanishConverter.js +3 -0
  77. package/dist/SpanishConverter.js.map +1 -0
  78. package/dist/SwahiliConverter.js +3 -0
  79. package/dist/SwahiliConverter.js.map +1 -0
  80. package/dist/SwedishConverter.js +3 -0
  81. package/dist/SwedishConverter.js.map +1 -0
  82. package/dist/TamilConverter.js +3 -0
  83. package/dist/TamilConverter.js.map +1 -0
  84. package/dist/TeluguConverter.js +3 -0
  85. package/dist/TeluguConverter.js.map +1 -0
  86. package/dist/ThaiConverter.js +3 -0
  87. package/dist/ThaiConverter.js.map +1 -0
  88. package/dist/TraditionalChineseConverter.js +3 -0
  89. package/dist/TraditionalChineseConverter.js.map +1 -0
  90. package/dist/TurkishConverter.js +3 -0
  91. package/dist/TurkishConverter.js.map +1 -0
  92. package/dist/UkrainianConverter.js +3 -0
  93. package/dist/UkrainianConverter.js.map +1 -0
  94. package/dist/UrduConverter.js +3 -0
  95. package/dist/UrduConverter.js.map +1 -0
  96. package/dist/VietnameseConverter.js +3 -0
  97. package/dist/VietnameseConverter.js.map +1 -0
  98. package/dist/n2words.js +3 -2
  99. package/dist/n2words.js.map +1 -1
  100. package/lib/classes/abstract-language.d.ts +178 -0
  101. package/lib/classes/abstract-language.js +192 -185
  102. package/lib/classes/greedy-scale-language.d.ts +109 -0
  103. package/lib/classes/greedy-scale-language.js +96 -90
  104. package/lib/classes/slavic-language.d.ts +148 -0
  105. package/lib/classes/slavic-language.js +136 -106
  106. package/lib/classes/south-asian-language.d.ts +70 -0
  107. package/lib/classes/south-asian-language.js +58 -65
  108. package/lib/classes/turkic-language.d.ts +26 -0
  109. package/lib/classes/turkic-language.js +22 -26
  110. package/lib/languages/ar.d.ts +30 -0
  111. package/lib/languages/ar.js +49 -133
  112. package/lib/languages/az.d.ts +12 -0
  113. package/lib/languages/az.js +7 -23
  114. package/lib/languages/bn.d.ts +11 -0
  115. package/lib/languages/bn.js +12 -7
  116. package/lib/languages/cs.d.ts +88 -0
  117. package/lib/languages/cs.js +44 -113
  118. package/lib/languages/da.d.ts +15 -0
  119. package/lib/languages/da.js +40 -87
  120. package/lib/languages/de.d.ts +14 -0
  121. package/lib/languages/de.js +34 -68
  122. package/lib/languages/el.d.ts +14 -0
  123. package/lib/languages/el.js +22 -48
  124. package/lib/languages/en.d.ts +16 -0
  125. package/lib/languages/en.js +22 -59
  126. package/lib/languages/es.d.ts +15 -0
  127. package/lib/languages/es.js +49 -81
  128. package/lib/languages/fa.d.ts +47 -0
  129. package/lib/languages/fa.js +90 -73
  130. package/lib/languages/fil.d.ts +16 -0
  131. package/lib/languages/fil.js +35 -76
  132. package/lib/languages/fr-BE.d.ts +11 -0
  133. package/lib/languages/fr-BE.js +15 -51
  134. package/lib/languages/fr.d.ts +15 -0
  135. package/lib/languages/fr.js +33 -72
  136. package/lib/languages/gu.d.ts +11 -0
  137. package/lib/languages/gu.js +10 -34
  138. package/lib/languages/hbo.d.ts +113 -0
  139. package/lib/languages/hbo.js +251 -0
  140. package/lib/languages/he.d.ts +80 -0
  141. package/lib/languages/he.js +41 -164
  142. package/lib/languages/hi.d.ts +11 -0
  143. package/lib/languages/hi.js +12 -7
  144. package/lib/languages/hr.d.ts +80 -0
  145. package/lib/languages/hr.js +51 -95
  146. package/lib/languages/hu.d.ts +22 -0
  147. package/lib/languages/hu.js +35 -53
  148. package/lib/languages/id.d.ts +37 -0
  149. package/lib/languages/id.js +29 -44
  150. package/lib/languages/it.d.ts +37 -0
  151. package/lib/languages/it.js +36 -52
  152. package/lib/languages/ja.d.ts +17 -0
  153. package/lib/languages/ja.js +22 -75
  154. package/lib/languages/kn.d.ts +11 -0
  155. package/lib/languages/kn.js +10 -39
  156. package/lib/languages/ko.d.ts +14 -0
  157. package/lib/languages/ko.js +17 -45
  158. package/lib/languages/lt.d.ts +70 -0
  159. package/lib/languages/lt.js +28 -63
  160. package/lib/languages/lv.d.ts +70 -0
  161. package/lib/languages/lv.js +35 -58
  162. package/lib/languages/mr.d.ts +11 -0
  163. package/lib/languages/mr.js +10 -34
  164. package/lib/languages/ms.d.ts +31 -0
  165. package/lib/languages/ms.js +24 -20
  166. package/lib/languages/nb.d.ts +12 -0
  167. package/lib/languages/nb.js +36 -56
  168. package/lib/languages/nl.d.ts +16 -0
  169. package/lib/languages/nl.js +58 -109
  170. package/lib/languages/pa.d.ts +11 -0
  171. package/lib/languages/{pa-Guru.js → pa.js} +12 -7
  172. package/lib/languages/pl.d.ts +80 -0
  173. package/lib/languages/pl.js +26 -105
  174. package/lib/languages/pt.d.ts +29 -0
  175. package/lib/languages/pt.js +29 -64
  176. package/lib/languages/ro.d.ts +158 -0
  177. package/lib/languages/ro.js +60 -167
  178. package/lib/languages/ru.d.ts +85 -0
  179. package/lib/languages/ru.js +17 -37
  180. package/lib/languages/sr-Cyrl.d.ts +80 -0
  181. package/lib/languages/sr-Cyrl.js +113 -0
  182. package/lib/languages/sr-Latn.d.ts +80 -0
  183. package/lib/languages/sr-Latn.js +54 -98
  184. package/lib/languages/sv.d.ts +14 -0
  185. package/lib/languages/sv.js +26 -63
  186. package/lib/languages/sw.d.ts +39 -0
  187. package/lib/languages/sw.js +26 -21
  188. package/lib/languages/ta.d.ts +20 -0
  189. package/lib/languages/ta.js +26 -26
  190. package/lib/languages/te.d.ts +22 -0
  191. package/lib/languages/te.js +28 -38
  192. package/lib/languages/th.d.ts +17 -0
  193. package/lib/languages/th.js +25 -31
  194. package/lib/languages/tr.d.ts +12 -0
  195. package/lib/languages/tr.js +11 -38
  196. package/lib/languages/uk.d.ts +85 -0
  197. package/lib/languages/uk.js +18 -44
  198. package/lib/languages/ur.d.ts +11 -0
  199. package/lib/languages/ur.js +12 -7
  200. package/lib/languages/vi.d.ts +72 -0
  201. package/lib/languages/vi.js +25 -71
  202. package/lib/languages/zh-Hans.d.ts +21 -0
  203. package/lib/languages/zh-Hans.js +33 -87
  204. package/lib/languages/zh-Hant.d.ts +21 -0
  205. package/lib/languages/zh-Hant.js +111 -0
  206. package/lib/n2words.d.ts +209 -0
  207. package/lib/n2words.js +474 -191
  208. package/package.json +106 -67
  209. package/dist/languages/ar.js +0 -2
  210. package/dist/languages/ar.js.map +0 -1
  211. package/dist/languages/az.js +0 -2
  212. package/dist/languages/az.js.map +0 -1
  213. package/dist/languages/bn.js +0 -2
  214. package/dist/languages/bn.js.map +0 -1
  215. package/dist/languages/cs.js +0 -2
  216. package/dist/languages/cs.js.map +0 -1
  217. package/dist/languages/da.js +0 -2
  218. package/dist/languages/da.js.map +0 -1
  219. package/dist/languages/de.js +0 -2
  220. package/dist/languages/de.js.map +0 -1
  221. package/dist/languages/el.js +0 -2
  222. package/dist/languages/el.js.map +0 -1
  223. package/dist/languages/en.js +0 -2
  224. package/dist/languages/en.js.map +0 -1
  225. package/dist/languages/es.js +0 -2
  226. package/dist/languages/es.js.map +0 -1
  227. package/dist/languages/fa.js +0 -2
  228. package/dist/languages/fa.js.map +0 -1
  229. package/dist/languages/fil.js +0 -2
  230. package/dist/languages/fil.js.map +0 -1
  231. package/dist/languages/fr-BE.js +0 -2
  232. package/dist/languages/fr-BE.js.map +0 -1
  233. package/dist/languages/fr.js +0 -2
  234. package/dist/languages/fr.js.map +0 -1
  235. package/dist/languages/gu.js +0 -2
  236. package/dist/languages/gu.js.map +0 -1
  237. package/dist/languages/he.js +0 -2
  238. package/dist/languages/he.js.map +0 -1
  239. package/dist/languages/hi.js +0 -2
  240. package/dist/languages/hi.js.map +0 -1
  241. package/dist/languages/hr.js +0 -2
  242. package/dist/languages/hr.js.map +0 -1
  243. package/dist/languages/hu.js +0 -2
  244. package/dist/languages/hu.js.map +0 -1
  245. package/dist/languages/id.js +0 -2
  246. package/dist/languages/id.js.map +0 -1
  247. package/dist/languages/it.js +0 -2
  248. package/dist/languages/it.js.map +0 -1
  249. package/dist/languages/ja.js +0 -2
  250. package/dist/languages/ja.js.map +0 -1
  251. package/dist/languages/kn.js +0 -2
  252. package/dist/languages/kn.js.map +0 -1
  253. package/dist/languages/ko.js +0 -2
  254. package/dist/languages/ko.js.map +0 -1
  255. package/dist/languages/lt.js +0 -2
  256. package/dist/languages/lt.js.map +0 -1
  257. package/dist/languages/lv.js +0 -2
  258. package/dist/languages/lv.js.map +0 -1
  259. package/dist/languages/mr.js +0 -2
  260. package/dist/languages/mr.js.map +0 -1
  261. package/dist/languages/ms.js +0 -2
  262. package/dist/languages/ms.js.map +0 -1
  263. package/dist/languages/nb.js +0 -2
  264. package/dist/languages/nb.js.map +0 -1
  265. package/dist/languages/nl.js +0 -2
  266. package/dist/languages/nl.js.map +0 -1
  267. package/dist/languages/pa-Guru.js +0 -2
  268. package/dist/languages/pa-Guru.js.map +0 -1
  269. package/dist/languages/pl.js +0 -2
  270. package/dist/languages/pl.js.map +0 -1
  271. package/dist/languages/pt.js +0 -2
  272. package/dist/languages/pt.js.map +0 -1
  273. package/dist/languages/ro.js +0 -2
  274. package/dist/languages/ro.js.map +0 -1
  275. package/dist/languages/ru.js +0 -2
  276. package/dist/languages/ru.js.map +0 -1
  277. package/dist/languages/sr-Latn.js +0 -2
  278. package/dist/languages/sr-Latn.js.map +0 -1
  279. package/dist/languages/sv.js +0 -2
  280. package/dist/languages/sv.js.map +0 -1
  281. package/dist/languages/sw.js +0 -2
  282. package/dist/languages/sw.js.map +0 -1
  283. package/dist/languages/ta.js +0 -2
  284. package/dist/languages/ta.js.map +0 -1
  285. package/dist/languages/te.js +0 -2
  286. package/dist/languages/te.js.map +0 -1
  287. package/dist/languages/th.js +0 -2
  288. package/dist/languages/th.js.map +0 -1
  289. package/dist/languages/tr.js +0 -2
  290. package/dist/languages/tr.js.map +0 -1
  291. package/dist/languages/uk.js +0 -2
  292. package/dist/languages/uk.js.map +0 -1
  293. package/dist/languages/ur.js +0 -2
  294. package/dist/languages/ur.js.map +0 -1
  295. package/dist/languages/vi.js +0 -2
  296. package/dist/languages/vi.js.map +0 -1
  297. package/dist/languages/zh-Hans.js +0 -2
  298. package/dist/languages/zh-Hans.js.map +0 -1
  299. package/typings/classes/abstract-language.d.ts +0 -144
  300. package/typings/classes/greedy-scale-language.d.ts +0 -148
  301. package/typings/classes/slavic-language.d.ts +0 -145
  302. package/typings/classes/south-asian-language.d.ts +0 -101
  303. package/typings/classes/turkic-language.d.ts +0 -42
  304. package/typings/languages/ar.d.ts +0 -93
  305. package/typings/languages/az.d.ts +0 -25
  306. package/typings/languages/bn.d.ts +0 -1
  307. package/typings/languages/cs.d.ts +0 -120
  308. package/typings/languages/da.d.ts +0 -53
  309. package/typings/languages/de.d.ts +0 -26
  310. package/typings/languages/el.d.ts +0 -11
  311. package/typings/languages/en.d.ts +0 -30
  312. package/typings/languages/es.d.ts +0 -43
  313. package/typings/languages/fa.d.ts +0 -81
  314. package/typings/languages/fil.d.ts +0 -12
  315. package/typings/languages/fr-BE.d.ts +0 -41
  316. package/typings/languages/fr.d.ts +0 -43
  317. package/typings/languages/gu.d.ts +0 -12
  318. package/typings/languages/he.d.ts +0 -197
  319. package/typings/languages/hi.d.ts +0 -1
  320. package/typings/languages/hr.d.ts +0 -110
  321. package/typings/languages/hu.d.ts +0 -37
  322. package/typings/languages/id.d.ts +0 -69
  323. package/typings/languages/it.d.ts +0 -51
  324. package/typings/languages/ja.d.ts +0 -58
  325. package/typings/languages/kn.d.ts +0 -11
  326. package/typings/languages/ko.d.ts +0 -25
  327. package/typings/languages/lt.d.ts +0 -110
  328. package/typings/languages/lv.d.ts +0 -99
  329. package/typings/languages/mr.d.ts +0 -12
  330. package/typings/languages/ms.d.ts +0 -37
  331. package/typings/languages/nb.d.ts +0 -27
  332. package/typings/languages/nl.d.ts +0 -65
  333. package/typings/languages/pa-Guru.d.ts +0 -1
  334. package/typings/languages/pl.d.ts +0 -116
  335. package/typings/languages/pt.d.ts +0 -39
  336. package/typings/languages/ro.d.ts +0 -229
  337. package/typings/languages/ru.d.ts +0 -108
  338. package/typings/languages/sr-Latn.d.ts +0 -98
  339. package/typings/languages/sv.d.ts +0 -30
  340. package/typings/languages/sw.d.ts +0 -1
  341. package/typings/languages/ta.d.ts +0 -1
  342. package/typings/languages/te.d.ts +0 -1
  343. package/typings/languages/th.d.ts +0 -1
  344. package/typings/languages/tr.d.ts +0 -46
  345. package/typings/languages/uk.d.ts +0 -117
  346. package/typings/languages/ur.d.ts +0 -1
  347. package/typings/languages/vi.d.ts +0 -116
  348. package/typings/languages/zh-Hans.d.ts +0 -57
  349. package/typings/n2words.d.ts +0 -177
@@ -1,25 +1,19 @@
1
- import GreedyScaleLanguage from '../classes/greedy-scale-language.js'
1
+ import { GreedyScaleLanguage } from '../classes/greedy-scale-language.js'
2
2
 
3
3
  /**
4
4
  * Hungarian language converter.
5
5
  *
6
- * Converts numbers to Hungarian words following Hungarian conventions:
7
- * - Agglutinative structure for compound numbers
8
- * - No spaces between tens and units (e.g., "huszonegy" = twenty-one)
9
- * - Special handling for "egy" (one) - often omitted as multiplier
10
- * - Vowel harmony in compound words
11
- *
12
- * Features:
13
- * - Compact number representations (húsz, harminc, negyven)
6
+ * Supports:
7
+ * - Agglutinative structure (no spaces between compound parts)
8
+ * - Special handling for "egy" (one) omission
14
9
  * - Pre-composed twenties (huszonegy through huszonkilenc)
15
- * - "egész" as decimal separator (meaning "whole")
16
- * - Support for very large numbers (up to quadrilliards)
17
10
  */
18
11
  export class Hungarian extends GreedyScaleLanguage {
19
12
  negativeWord = 'mínusz'
20
13
  decimalSeparatorWord = 'egész'
21
14
  zeroWord = 'nulla'
22
- scaleWordPairs = [
15
+
16
+ scaleWords = [
23
17
  [1_000_000_000_000_000_000_000_000_000n, 'quadrilliárd'],
24
18
  [1_000_000_000_000_000_000_000_000n, 'quadrillió'],
25
19
  [1_000_000_000_000_000_000_000n, 'trilliárd'],
@@ -69,87 +63,75 @@ export class Hungarian extends GreedyScaleLanguage {
69
63
  [0n, 'nulla']
70
64
  ]
71
65
 
66
+ /** Converts tens (30-99) with agglutinative composition. */
72
67
  tensToCardinal (number) {
73
- // Expecting `number` as bigint when called from convertWholePart
74
- if (this.getScaleWord(number)) {
75
- return this.getScaleWord(number)
68
+ // Expecting `number` as bigint when called from integerToWords
69
+ if (this.wordForScale(number)) {
70
+ return this.wordForScale(number)
76
71
  } else {
77
72
  const tens = number / 10n
78
73
  const units = number % 10n
79
- return this.getScaleWord(tens * 10n) + this.convertWholePart(units)
74
+ return this.wordForScale(tens * 10n) + this.integerToWords(units)
80
75
  }
81
76
  }
82
77
 
78
+ /** Converts hundreds (100-999) with "száz" composition. */
83
79
  hundredsToCardinal (number) {
84
80
  const hundreds = number / 100n
85
81
  let prefix = 'száz'
86
82
  if (hundreds !== 1n) {
87
- prefix = this.convertWholePart(hundreds, '') + prefix
83
+ prefix = this.integerToWords(hundreds, '') + prefix
88
84
  }
89
- const postfix = this.convertWholePart(number % 100n, '')
85
+ const postfix = this.integerToWords(number % 100n, '')
90
86
  return prefix + postfix
91
87
  }
92
88
 
89
+ /** Converts thousands (1000-999999) with "ezer" composition. */
93
90
  thousandsToCardinal (number) {
94
91
  const thousands = number / 1000n
95
92
  let prefix = 'ezer'
96
93
  if (thousands !== 1n) {
97
- prefix = this.convertWholePart(thousands, '') + prefix
94
+ prefix = this.integerToWords(thousands, '') + prefix
98
95
  }
99
- const postfix = this.convertWholePart(number % 1000n, '')
96
+ const postfix = this.integerToWords(number % 1000n, '')
100
97
  const middle = (number <= 2000n || postfix === '') ? '' : '-'
101
98
  return prefix + middle + postfix
102
99
  }
103
100
 
101
+ /** Converts large numbers (millions and above) with scale words. */
104
102
  bigNumberToCardinal (number) {
105
103
  const numberLength = number.toString().length
106
104
  const digits = (numberLength % 3 === 0) ? numberLength - 2 : numberLength
107
105
  const exp = 10 ** (Math.floor(digits / 3) * 3)
108
- const prefix = this.convertWholePart(number / BigInt(exp), '')
109
- const rest = this.convertWholePart(number % BigInt(exp), '')
106
+ const prefix = this.integerToWords(number / BigInt(exp), '')
107
+ const rest = this.integerToWords(number % BigInt(exp), '')
110
108
  const postfix = (rest === '') ? '' : ('-' + rest)
111
- return prefix + this.getScaleWord(BigInt(exp)) + postfix
109
+ return prefix + this.wordForScale(BigInt(exp)) + postfix
112
110
  }
113
111
 
114
- convertWholePart (number, zeroWord = this.zeroWord) {
112
+ /** Converts integer part using Hungarian agglutinative rules. */
113
+ integerToWords (integerPart, zeroWord = this.zeroWord) {
115
114
  let words = ''
116
115
 
117
116
  // Normalize to BigInt for consistent comparisons
118
- if (typeof number !== 'bigint') number = BigInt(number)
117
+ if (typeof integerPart !== 'bigint') integerPart = BigInt(integerPart)
119
118
 
120
- if (number === 0n) {
119
+ if (integerPart === 0n) {
121
120
  words = zeroWord
122
- } else if (zeroWord === '' && number === 2n) {
121
+ } else if (zeroWord === '' && integerPart === 2n) {
123
122
  words = 'két'
124
- } else if (number < 30n) {
125
- words = this.getScaleWord(number)
126
- } else if (number < 100n) {
127
- words = this.tensToCardinal(number)
128
- } else if (number < 1000n) {
129
- words = this.hundredsToCardinal(number)
130
- } else if (number < 1_000_000n) {
131
- words = this.thousandsToCardinal(number)
123
+ } else if (integerPart < 30n) {
124
+ words = this.wordForScale(integerPart)
125
+ } else if (integerPart < 100n) {
126
+ words = this.tensToCardinal(integerPart)
127
+ } else if (integerPart < 1000n) {
128
+ words = this.hundredsToCardinal(integerPart)
129
+ } else if (integerPart < 1_000_000n) {
130
+ words = this.thousandsToCardinal(integerPart)
132
131
  } else {
133
- words = this.bigNumberToCardinal(number)
132
+ words = this.bigNumberToCardinal(integerPart)
134
133
  }
135
134
 
136
135
  return words
137
136
  }
138
137
  }
139
-
140
- /**
141
- * Converts a number to Hungarian cardinal (written) form.
142
- *
143
- * @param {number|string|bigint} value The number to convert.
144
- * @param {Object} [options] Conversion options (see Hungarian class options).
145
- * @returns {string} The number expressed in Hungarian words.
146
- * @throws {TypeError} If value is NaN or invalid type.
147
- * @throws {Error} If value is an invalid number string.
148
- *
149
- * @example
150
- * convertToWords(42); // 'negyvenkettő'
151
- * convertToWords(21); // 'huszonegy'
152
- */
153
- export default function convertToWords (value, options = {}) {
154
- return new Hungarian(options).convertToWords(value)
155
- }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Indonesian language converter.
3
+ *
4
+ * Supports:
5
+ * - "Se-" prefix for one (seratus, seribu, sejuta)
6
+ * - Regular patterns (puluh for tens, ratus for hundreds)
7
+ * - Space-separated number components
8
+ */
9
+ export class Indonesian extends AbstractLanguage {
10
+ /**
11
+ * Word forms for digits 0-9.
12
+ * @type {Object.<number, string[]>}
13
+ */
14
+ digitWords: {
15
+ [x: number]: string[];
16
+ };
17
+ /**
18
+ * Scale magnitude words keyed by exponent (10^n).
19
+ * @type {Object.<number, string>}
20
+ */
21
+ scaleWords: {
22
+ [x: number]: string;
23
+ };
24
+ /** Splits number into groups of 3 digits. */
25
+ splitBy3(number: any): any[][];
26
+ /** Converts digit blocks to Indonesian words. */
27
+ spell(blocks: any): any[];
28
+ /** Converts hundreds digit with "seratus" or "ratus" suffix. */
29
+ getHundreds(number: any): string[];
30
+ /** Converts tens and units digits with "puluh" or "belas" suffix. */
31
+ getTens(number: any): string[];
32
+ /** Joins word blocks with magnitude scale words. */
33
+ join(wordBlocks: any): string;
34
+ /** Converts integer part using Indonesian group-based conversion. */
35
+ integerToWords(integerPart: any): string;
36
+ }
37
+ import { AbstractLanguage } from '../classes/abstract-language.js';
@@ -1,35 +1,23 @@
1
- import AbstractLanguage from '../classes/abstract-language.js'
1
+ import { AbstractLanguage } from '../classes/abstract-language.js'
2
2
 
3
3
  /**
4
4
  * Indonesian language converter.
5
5
  *
6
- * Converts numbers to Indonesian words following Indonesian conventions:
7
- * - Simple base-10 structure
8
- * - "Se-" prefix for one (e.g., "seratus" = one hundred, "seribu" = one thousand)
6
+ * Supports:
7
+ * - "Se-" prefix for one (seratus, seribu, sejuta)
8
+ * - Regular patterns (puluh for tens, ratus for hundreds)
9
9
  * - Space-separated number components
10
- * - Straightforward grouping by thousands
11
- *
12
- * Key Features:
13
- * - Base number mapping (base) for single digits 0-9
14
- * - Magnitude scale (thousands) mapping powers of 10 to Indonesian words
15
- * - Group-based algorithm:
16
- * 1. Split number into groups of 3 digits
17
- * 2. For each group, convert ones/tens/hundreds using base and naming rules
18
- * 3. Apply "se-" prefix for 1 (seratus, seribu, sejuta)
19
- * 4. Combine with magnitude words
20
- * 5. Join all parts with spaces
21
- * - Regular patterns (puluh for tens, ratus for hundreds, ribu for thousands)
22
- * - Clear grouping: ribu (10³), juta (10⁶), miliar (10⁹), triliun (10¹²)
23
- *
24
- * Features:
25
- * - "Se-" prefix usage for singular units
26
- * - Support for very large numbers (up to decillions)
27
10
  */
28
11
  export class Indonesian extends AbstractLanguage {
29
12
  negativeWord = 'min'
30
13
  decimalSeparatorWord = 'koma'
31
14
  zeroWord = 'nol'
32
- base = {
15
+
16
+ /**
17
+ * Word forms for digits 0-9.
18
+ * @type {Object.<number, string[]>}
19
+ */
20
+ digitWords = {
33
21
  0: [],
34
22
  1: ['satu'],
35
23
  2: ['dua'],
@@ -42,7 +30,11 @@ export class Indonesian extends AbstractLanguage {
42
30
  9: ['sembilan']
43
31
  }
44
32
 
45
- thousands = {
33
+ /**
34
+ * Scale magnitude words keyed by exponent (10^n).
35
+ * @type {Object.<number, string>}
36
+ */
37
+ scaleWords = {
46
38
  3: 'ribu', // 10^3
47
39
  6: 'juta', // 10^6
48
40
  9: 'miliar', // 10^9
@@ -56,6 +48,7 @@ export class Indonesian extends AbstractLanguage {
56
48
  33: 'desiliun'
57
49
  }
58
50
 
51
+ /** Splits number into groups of 3 digits. */
59
52
  splitBy3 (number) {
60
53
  // Split to groups of 3 numbers: 1234567 -> [['1'], ['234'], ['567']]
61
54
  const blocks = []
@@ -81,12 +74,13 @@ export class Indonesian extends AbstractLanguage {
81
74
  return blocks
82
75
  }
83
76
 
77
+ /** Converts digit blocks to Indonesian words. */
84
78
  spell (blocks) {
85
79
  let wordBlocks = []
86
80
  let spelling
87
81
  const firstBlock = blocks[0]
88
82
  if (firstBlock[0].length === 1) {
89
- spelling = firstBlock[0] === '0' ? ['nol'] : this.base[Math.trunc(firstBlock[0])]
83
+ spelling = firstBlock[0] === '0' ? ['nol'] : this.digitWords[Math.trunc(firstBlock[0])]
90
84
  } else if (firstBlock[0].length === 2) {
91
85
  spelling = this.getTens(firstBlock[0])
92
86
  } else {
@@ -102,16 +96,18 @@ export class Indonesian extends AbstractLanguage {
102
96
  return wordBlocks
103
97
  }
104
98
 
99
+ /** Converts hundreds digit with "seratus" or "ratus" suffix. */
105
100
  getHundreds (number) {
106
101
  if (number === '1') {
107
102
  return ['seratus']
108
103
  } else if (number === '0') {
109
104
  return []
110
105
  } else {
111
- return [...this.base[Math.trunc(number)], 'ratus']
106
+ return [...this.digitWords[Math.trunc(number)], 'ratus']
112
107
  }
113
108
  }
114
109
 
110
+ /** Converts tens and units digits with "puluh" or "belas" suffix. */
115
111
  getTens (number) {
116
112
  if (number[0] === '1') {
117
113
  if (number[1] === '0') {
@@ -119,16 +115,17 @@ export class Indonesian extends AbstractLanguage {
119
115
  } else if (number[1] === '1') {
120
116
  return ['sebelas']
121
117
  }
122
- return [...this.base[Math.trunc(number[1])], 'belas']
118
+ return [...this.digitWords[Math.trunc(number[1])], 'belas']
123
119
  }
124
120
 
125
121
  if (number[0] === '0') {
126
- return this.base[Math.trunc(number[1])]
122
+ return this.digitWords[Math.trunc(number[1])]
127
123
  }
128
124
 
129
- return [...this.base[Math.trunc(number[0])], 'puluh', ...this.base[Math.trunc(number[1])]]
125
+ return [...this.digitWords[Math.trunc(number[0])], 'puluh', ...this.digitWords[Math.trunc(number[1])]]
130
126
  }
131
127
 
128
+ /** Joins word blocks with magnitude scale words. */
132
129
  join (wordBlocks) {
133
130
  let wordList = []
134
131
  const length = wordBlocks.length - 1
@@ -146,29 +143,17 @@ export class Indonesian extends AbstractLanguage {
146
143
  if (index === length) {
147
144
  break
148
145
  }
149
- wordList = [...wordList, this.thousands[(length - index) * 3]]
146
+ wordList = [...wordList, this.scaleWords[(length - index) * 3]]
150
147
  }
151
148
  return wordList.join(' ')
152
149
  }
153
150
 
154
- convertWholePart (number) {
151
+ /** Converts integer part using Indonesian group-based conversion. */
152
+ integerToWords (integerPart) {
155
153
  return this.join(
156
154
  this.spell(
157
- this.splitBy3(number)
155
+ this.splitBy3(integerPart)
158
156
  )
159
157
  ).trim()
160
158
  }
161
159
  }
162
-
163
- /**
164
- * Converts a number to Indonesian cardinal (written) form.
165
- *
166
- * @param {number|string|bigint} value The number to convert.
167
- * @param {Object} [options={}] Configuration options.
168
- * @returns {string} The number expressed in Indonesian words.
169
- * @throws {TypeError} If value is NaN or invalid type.
170
- * @throws {Error} If value is an invalid number string.
171
- */
172
- export default function convertToWords (value, options = {}) {
173
- return new Indonesian(options).convertToWords(value)
174
- }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Italian language converter.
3
+ *
4
+ * Supports:
5
+ * - Phonetic contractions (vowel elision: "ventotto" not "ventiotto")
6
+ * - Accentuation rules for "tre" in compounds ("ventitré")
7
+ * - Custom word construction for irregular patterns
8
+ */
9
+ export class Italian extends AbstractLanguage {
10
+ onesWords: string[];
11
+ tensWords: {
12
+ 2: string;
13
+ 3: string;
14
+ 4: string;
15
+ 6: string;
16
+ };
17
+ exponentPrefixes: string[];
18
+ /** Adds accent to final "tre" in compound words (ventitré). */
19
+ accentuate(string: any): any;
20
+ /** Omits word if it represents zero. */
21
+ omitIfZero(numberToString: any): any;
22
+ /** Removes duplicate vowels for phonetic contractions. */
23
+ phoneticContraction(string: any): any;
24
+ /** Converts tens (20-99) with phonetic contractions. */
25
+ tensToCardinal(number: any): any;
26
+ /** Converts hundreds (100-999) with "cento" composition. */
27
+ hundredsToCardinal(number: any): any;
28
+ /** Converts thousands (1000-999999) with "mille/mila" composition. */
29
+ thousandsToCardinal(number: any): string;
30
+ /** Converts exponent length to Italian scale word (milione, miliardo, etc.). */
31
+ exponentLengthToString(exponentLength: any): string;
32
+ /** Converts large numbers (millions and above) with exponent-based naming. */
33
+ bigNumberToCardinal(number: any): string;
34
+ /** Converts integer part using Italian custom algorithm with accentuation. */
35
+ integerToWords(integerPart: any): any;
36
+ }
37
+ import { AbstractLanguage } from '../classes/abstract-language.js';
@@ -1,40 +1,29 @@
1
- import GreedyScaleLanguage from '../classes/greedy-scale-language.js'
1
+ import { AbstractLanguage } from '../classes/abstract-language.js'
2
2
 
3
3
  /**
4
4
  * Italian language converter.
5
5
  *
6
- * Converts numbers to Italian words following Italian conventions:
7
- * - Phonetic contractions (removes duplicate vowels: "ventotto" not "ventiotto")
8
- * - Accentuation rules for "tre" in compounds ("ventitré" not "ventitre")
9
- * - Special handling for "uno" and vowel agreement
10
- * - Complex composition patterns for large numbers
11
- *
12
- * Architecture Note:
13
- * Unlike other GreedyScaleLanguage subclasses, Italian uses a custom algorithm
14
- * rather than the standard highest-matching-scale approach. This is necessary
15
- * because Italian's word formation rules are irregular and context-dependent.
16
- * See tensToCardinal(), hundredsToCardinal(), and bigNumberToCardinal().
17
- *
18
- * Features:
19
- * - Vowel elision (e.g., "ventotto" not "ventiotto")
20
- * - Accentuation of final "tre" (ventitré, trentacinque - note: accent on compound tres)
21
- * - Exponent-based large number naming (milione, miliardo, trilione)
22
- * - Custom word construction for hundreds and thousands
6
+ * Supports:
7
+ * - Phonetic contractions (vowel elision: "ventotto" not "ventiotto")
8
+ * - Accentuation rules for "tre" in compounds ("ventitré")
9
+ * - Custom word construction for irregular patterns
23
10
  */
24
- export class Italian extends GreedyScaleLanguage {
11
+ export class Italian extends AbstractLanguage {
25
12
  negativeWord = 'meno'
26
13
  decimalSeparatorWord = 'virgola'
27
14
  zeroWord = 'zero'
28
- cardinalWords = [
15
+
16
+ onesWords = [
29
17
  this.zeroWord, 'uno', 'due', 'tre', 'quattro', 'cinque', 'sei', 'sette', 'otto',
30
18
  'nove', 'dieci', 'undici', 'dodici', 'tredici', 'quattordici', 'quindici',
31
19
  'sedici', 'diciassette', 'diciotto', 'diciannove'
32
20
  ]
33
21
 
34
- strTens = { 2: 'venti', 3: 'trenta', 4: 'quaranta', 6: 'sessanta' }
22
+ tensWords = { 2: 'venti', 3: 'trenta', 4: 'quaranta', 6: 'sessanta' }
35
23
 
36
24
  exponentPrefixes = [this.zeroWord, 'm', 'b', 'tr', 'quadr', 'quint', 'sest', 'sett', 'ott', 'nov', 'dec']
37
25
 
26
+ /** Adds accent to final "tre" in compound words (ventitré). */
38
27
  accentuate (string) {
39
28
  const splittedString = string.split(' ')
40
29
 
@@ -44,44 +33,51 @@ export class Italian extends GreedyScaleLanguage {
44
33
  return result.join(' ')
45
34
  }
46
35
 
36
+ /** Omits word if it represents zero. */
47
37
  omitIfZero (numberToString) {
48
38
  return numberToString === this.zeroWord ? '' : numberToString
49
39
  }
50
40
 
41
+ /** Removes duplicate vowels for phonetic contractions. */
51
42
  phoneticContraction (string) {
52
43
  return string.replaceAll('oo', 'o').replaceAll('ao', 'o').replaceAll('io', 'o').replaceAll('au', 'u').replaceAll('iu', 'u')
53
44
  }
54
45
 
46
+ /** Converts tens (20-99) with phonetic contractions. */
55
47
  tensToCardinal (number) {
56
48
  const tens = Math.floor(number / 10)
57
49
  const units = number % 10
58
- const prefix = Object.prototype.hasOwnProperty.call(this.strTens, tens) ? this.strTens[tens] : this.cardinalWords[tens].slice(0, -1) + 'anta'
59
- const postfix = this.omitIfZero(this.cardinalWords[units])
50
+ const prefix = Object.prototype.hasOwnProperty.call(this.tensWords, tens) ? this.tensWords[tens] : this.onesWords[tens].slice(0, -1) + 'anta'
51
+ const postfix = this.omitIfZero(this.onesWords[units])
60
52
  return this.phoneticContraction(prefix + postfix)
61
53
  }
62
54
 
55
+ /** Converts hundreds (100-999) with "cento" composition. */
63
56
  hundredsToCardinal (number) {
64
57
  const hundreds = Math.floor(number / 100)
65
58
  let prefix = 'cento'
66
59
  if (hundreds !== 1) {
67
- prefix = this.cardinalWords[hundreds] + prefix
60
+ prefix = this.onesWords[hundreds] + prefix
68
61
  }
69
- const postfix = this.omitIfZero(this.convertWholePart(number % 100))
62
+ const postfix = this.omitIfZero(this.integerToWords(number % 100))
70
63
  return this.phoneticContraction(prefix + postfix)
71
64
  }
72
65
 
66
+ /** Converts thousands (1000-999999) with "mille/mila" composition. */
73
67
  thousandsToCardinal (number) {
74
68
  const thousands = Math.floor(number / 1000)
75
- const prefix = thousands === 1 ? 'mille' : this.convertWholePart(thousands) + 'mila'
76
- const postfix = this.omitIfZero(this.convertWholePart(number % 1000))
69
+ const prefix = thousands === 1 ? 'mille' : this.integerToWords(thousands) + 'mila'
70
+ const postfix = this.omitIfZero(this.integerToWords(number % 1000))
77
71
  return prefix + postfix
78
72
  }
79
73
 
74
+ /** Converts exponent length to Italian scale word (milione, miliardo, etc.). */
80
75
  exponentLengthToString (exponentLength) {
81
76
  const prefix = this.exponentPrefixes[Math.floor(exponentLength / 6)]
82
77
  return exponentLength % 6 === 0 ? prefix + 'ilione' : prefix + 'iliardo'
83
78
  }
84
79
 
80
+ /** Converts large numbers (millions and above) with exponent-based naming. */
85
81
  bigNumberToCardinal (number) {
86
82
  const digits = [...number.toString()]
87
83
 
@@ -99,7 +95,7 @@ export class Italian extends GreedyScaleLanguage {
99
95
  if (multiplier.join('') === '1') {
100
96
  prefix = 'un '
101
97
  } else {
102
- prefix = this.convertWholePart(Math.trunc(Number(multiplier.join(''))))
98
+ prefix = this.integerToWords(Math.trunc(Number(multiplier.join(''))))
103
99
  infix = ' ' + infix.slice(0, -1) + 'i' // without last element
104
100
  }
105
101
 
@@ -107,7 +103,7 @@ export class Italian extends GreedyScaleLanguage {
107
103
  if (isSetsEqual(new Set(exponent), new Set(['0']))) {
108
104
  postfix = ''
109
105
  } else {
110
- postfix = this.convertWholePart(Math.trunc(exponent.join('')))
106
+ postfix = this.integerToWords(Math.trunc(exponent.join('')))
111
107
 
112
108
  infix += (postfix.includes(' e ') ? ', ' : ' e ')
113
109
  }
@@ -115,34 +111,22 @@ export class Italian extends GreedyScaleLanguage {
115
111
  return prefix + infix + postfix
116
112
  }
117
113
 
118
- convertWholePart (number) {
114
+ /** Converts integer part using Italian custom algorithm with accentuation. */
115
+ integerToWords (integerPart) {
119
116
  let words = ''
120
117
 
121
- if (number < 20) {
122
- words = this.cardinalWords[number]
123
- } else if (number < 100) {
124
- words = this.tensToCardinal(Number(number))
125
- } else if (number < 1000) {
126
- words = this.hundredsToCardinal(Number(number))
127
- } else if (number < 1_000_000) {
128
- words = this.thousandsToCardinal(Number(number))
118
+ if (integerPart < 20) {
119
+ words = this.onesWords[integerPart]
120
+ } else if (integerPart < 100) {
121
+ words = this.tensToCardinal(Number(integerPart))
122
+ } else if (integerPart < 1000) {
123
+ words = this.hundredsToCardinal(Number(integerPart))
124
+ } else if (integerPart < 1_000_000) {
125
+ words = this.thousandsToCardinal(Number(integerPart))
129
126
  } else {
130
- words = this.bigNumberToCardinal(number)
127
+ words = this.bigNumberToCardinal(integerPart)
131
128
  }
132
129
 
133
130
  return this.accentuate(words)
134
131
  }
135
132
  }
136
-
137
- /**
138
- * Converts a number to Italian cardinal (written) form.
139
- *
140
- * @param {number|string|bigint} value The number to convert.
141
- * @param {Object} [options={}] Configuration options.
142
- * @returns {string} The number expressed in Italian words.
143
- * @throws {TypeError} If value is NaN or invalid type.
144
- * @throws {Error} If value is an invalid number string.
145
- */
146
- export default function convertToWords (value, options = {}) {
147
- return new Italian(options).convertToWords(value)
148
- }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Japanese language converter.
3
+ *
4
+ * Supports:
5
+ * - Kanji numerals (一, 二, 三, etc.)
6
+ * - Grouping by 万 (10,000) instead of 1,000
7
+ * - Special 一 (one) omission rules (十, 百, 千 but 一万, 一億)
8
+ */
9
+ export class Japanese extends AbstractLanguage {
10
+ onesWords: string[];
11
+ scaleWords: string[];
12
+ /** Converts a segment of up to 4 digits to Japanese kanji with 一 omission rules. */
13
+ segmentToWords(num: any): string;
14
+ /** Converts integer part using Japanese 万-based grouping system. */
15
+ integerToWords(integerPart: any): string;
16
+ }
17
+ import { AbstractLanguage } from '../classes/abstract-language.js';