n2words 1.23.1 → 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 (322) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +317 -59
  3. package/dist/ArabicConverter.js +3 -0
  4. package/dist/ArabicConverter.js.map +1 -0
  5. package/dist/AzerbaijaniConverter.js +3 -0
  6. package/dist/AzerbaijaniConverter.js.map +1 -0
  7. package/dist/BanglaConverter.js +3 -0
  8. package/dist/BanglaConverter.js.map +1 -0
  9. package/dist/BiblicalHebrewConverter.js +3 -0
  10. package/dist/BiblicalHebrewConverter.js.map +1 -0
  11. package/dist/CroatianConverter.js +3 -0
  12. package/dist/CroatianConverter.js.map +1 -0
  13. package/dist/CzechConverter.js +3 -0
  14. package/dist/CzechConverter.js.map +1 -0
  15. package/dist/DanishConverter.js +3 -0
  16. package/dist/DanishConverter.js.map +1 -0
  17. package/dist/DutchConverter.js +3 -0
  18. package/dist/DutchConverter.js.map +1 -0
  19. package/dist/EnglishConverter.js +3 -0
  20. package/dist/EnglishConverter.js.map +1 -0
  21. package/dist/FilipinoConverter.js +3 -0
  22. package/dist/FilipinoConverter.js.map +1 -0
  23. package/dist/FrenchBelgiumConverter.js +3 -0
  24. package/dist/FrenchBelgiumConverter.js.map +1 -0
  25. package/dist/FrenchConverter.js +3 -0
  26. package/dist/FrenchConverter.js.map +1 -0
  27. package/dist/GermanConverter.js +3 -0
  28. package/dist/GermanConverter.js.map +1 -0
  29. package/dist/GreekConverter.js +3 -0
  30. package/dist/GreekConverter.js.map +1 -0
  31. package/dist/GujaratiConverter.js +3 -0
  32. package/dist/GujaratiConverter.js.map +1 -0
  33. package/dist/HebrewConverter.js +3 -0
  34. package/dist/HebrewConverter.js.map +1 -0
  35. package/dist/HindiConverter.js +3 -0
  36. package/dist/HindiConverter.js.map +1 -0
  37. package/dist/HungarianConverter.js +3 -0
  38. package/dist/HungarianConverter.js.map +1 -0
  39. package/dist/IndonesianConverter.js +3 -0
  40. package/dist/IndonesianConverter.js.map +1 -0
  41. package/dist/ItalianConverter.js +3 -0
  42. package/dist/ItalianConverter.js.map +1 -0
  43. package/dist/JapaneseConverter.js +3 -0
  44. package/dist/JapaneseConverter.js.map +1 -0
  45. package/dist/KannadaConverter.js +3 -0
  46. package/dist/KannadaConverter.js.map +1 -0
  47. package/dist/KoreanConverter.js +3 -0
  48. package/dist/KoreanConverter.js.map +1 -0
  49. package/dist/LatvianConverter.js +3 -0
  50. package/dist/LatvianConverter.js.map +1 -0
  51. package/dist/LithuanianConverter.js +3 -0
  52. package/dist/LithuanianConverter.js.map +1 -0
  53. package/dist/MalayConverter.js +3 -0
  54. package/dist/MalayConverter.js.map +1 -0
  55. package/dist/MarathiConverter.js +3 -0
  56. package/dist/MarathiConverter.js.map +1 -0
  57. package/dist/NorwegianBokmalConverter.js +3 -0
  58. package/dist/NorwegianBokmalConverter.js.map +1 -0
  59. package/dist/PersianConverter.js +3 -0
  60. package/dist/PersianConverter.js.map +1 -0
  61. package/dist/PolishConverter.js +3 -0
  62. package/dist/PolishConverter.js.map +1 -0
  63. package/dist/PortugueseConverter.js +3 -0
  64. package/dist/PortugueseConverter.js.map +1 -0
  65. package/dist/PunjabiConverter.js +3 -0
  66. package/dist/PunjabiConverter.js.map +1 -0
  67. package/dist/RomanianConverter.js +3 -0
  68. package/dist/RomanianConverter.js.map +1 -0
  69. package/dist/RussianConverter.js +3 -0
  70. package/dist/RussianConverter.js.map +1 -0
  71. package/dist/SerbianCyrillicConverter.js +3 -0
  72. package/dist/SerbianCyrillicConverter.js.map +1 -0
  73. package/dist/SerbianLatinConverter.js +3 -0
  74. package/dist/SerbianLatinConverter.js.map +1 -0
  75. package/dist/SimplifiedChineseConverter.js +3 -0
  76. package/dist/SimplifiedChineseConverter.js.map +1 -0
  77. package/dist/SpanishConverter.js +3 -0
  78. package/dist/SpanishConverter.js.map +1 -0
  79. package/dist/SwahiliConverter.js +3 -0
  80. package/dist/SwahiliConverter.js.map +1 -0
  81. package/dist/SwedishConverter.js +3 -0
  82. package/dist/SwedishConverter.js.map +1 -0
  83. package/dist/TamilConverter.js +3 -0
  84. package/dist/TamilConverter.js.map +1 -0
  85. package/dist/TeluguConverter.js +3 -0
  86. package/dist/TeluguConverter.js.map +1 -0
  87. package/dist/ThaiConverter.js +3 -0
  88. package/dist/ThaiConverter.js.map +1 -0
  89. package/dist/TraditionalChineseConverter.js +3 -0
  90. package/dist/TraditionalChineseConverter.js.map +1 -0
  91. package/dist/TurkishConverter.js +3 -0
  92. package/dist/TurkishConverter.js.map +1 -0
  93. package/dist/UkrainianConverter.js +3 -0
  94. package/dist/UkrainianConverter.js.map +1 -0
  95. package/dist/UrduConverter.js +3 -0
  96. package/dist/UrduConverter.js.map +1 -0
  97. package/dist/VietnameseConverter.js +3 -0
  98. package/dist/VietnameseConverter.js.map +1 -0
  99. package/dist/n2words.js +3 -2
  100. package/dist/n2words.js.map +1 -1
  101. package/lib/classes/abstract-language.d.ts +158 -34
  102. package/lib/classes/abstract-language.js +223 -115
  103. package/lib/classes/greedy-scale-language.d.ts +109 -0
  104. package/lib/classes/greedy-scale-language.js +201 -0
  105. package/lib/classes/slavic-language.d.ts +148 -0
  106. package/lib/classes/slavic-language.js +281 -0
  107. package/lib/classes/south-asian-language.d.ts +70 -0
  108. package/lib/classes/south-asian-language.js +154 -0
  109. package/lib/classes/turkic-language.d.ts +26 -0
  110. package/lib/classes/turkic-language.js +59 -0
  111. package/lib/languages/ar.d.ts +30 -0
  112. package/lib/languages/ar.js +159 -0
  113. package/lib/languages/az.d.ts +12 -0
  114. package/lib/languages/az.js +42 -0
  115. package/lib/languages/bn.d.ts +11 -0
  116. package/lib/languages/bn.js +131 -0
  117. package/lib/languages/cs.d.ts +88 -0
  118. package/lib/languages/cs.js +143 -0
  119. package/lib/languages/da.d.ts +15 -0
  120. package/lib/languages/da.js +120 -0
  121. package/lib/languages/de.d.ts +14 -0
  122. package/lib/languages/de.js +101 -0
  123. package/lib/languages/el.d.ts +14 -0
  124. package/lib/languages/el.js +90 -0
  125. package/lib/languages/en.d.ts +16 -0
  126. package/lib/languages/en.js +86 -0
  127. package/lib/languages/es.d.ts +15 -0
  128. package/lib/languages/es.js +121 -0
  129. package/lib/languages/fa.d.ts +47 -0
  130. package/lib/languages/fa.js +144 -0
  131. package/lib/languages/fil.d.ts +16 -0
  132. package/lib/languages/fil.js +121 -0
  133. package/lib/languages/fr-BE.d.ts +11 -0
  134. package/lib/languages/fr-BE.js +25 -0
  135. package/lib/languages/fr.d.ts +15 -0
  136. package/lib/languages/fr.js +106 -0
  137. package/lib/languages/gu.d.ts +11 -0
  138. package/lib/languages/gu.js +132 -0
  139. package/lib/languages/hbo.d.ts +113 -0
  140. package/lib/languages/hbo.js +251 -0
  141. package/lib/languages/he.d.ts +80 -0
  142. package/lib/languages/he.js +206 -0
  143. package/lib/languages/hi.d.ts +11 -0
  144. package/lib/languages/hi.js +131 -0
  145. package/lib/languages/hr.d.ts +80 -0
  146. package/lib/languages/hr.js +113 -0
  147. package/lib/languages/hu.d.ts +22 -0
  148. package/lib/languages/hu.js +137 -0
  149. package/lib/languages/id.d.ts +37 -0
  150. package/lib/languages/id.js +159 -0
  151. package/lib/languages/it.d.ts +37 -0
  152. package/lib/languages/it.js +132 -0
  153. package/lib/languages/ja.d.ts +17 -0
  154. package/lib/languages/ja.js +137 -0
  155. package/lib/languages/kn.d.ts +11 -0
  156. package/lib/languages/kn.js +42 -0
  157. package/lib/languages/ko.d.ts +14 -0
  158. package/lib/languages/ko.js +55 -0
  159. package/lib/{i18n/pl.d.ts → languages/lt.d.ts} +18 -15
  160. package/lib/languages/lt.js +136 -0
  161. package/lib/{i18n/lt.d.ts → languages/lv.d.ts} +16 -14
  162. package/lib/languages/lv.js +130 -0
  163. package/lib/languages/mr.d.ts +11 -0
  164. package/lib/languages/mr.js +132 -0
  165. package/lib/languages/ms.d.ts +31 -0
  166. package/lib/languages/ms.js +150 -0
  167. package/lib/languages/nb.d.ts +12 -0
  168. package/lib/languages/nb.js +100 -0
  169. package/lib/languages/nl.d.ts +16 -0
  170. package/lib/languages/nl.js +155 -0
  171. package/lib/languages/pa.d.ts +11 -0
  172. package/lib/languages/pa.js +131 -0
  173. package/lib/{i18n/uk.d.ts → languages/pl.d.ts} +16 -14
  174. package/lib/languages/pl.js +110 -0
  175. package/lib/languages/pt.d.ts +29 -0
  176. package/lib/languages/pt.js +112 -0
  177. package/lib/languages/ro.d.ts +158 -0
  178. package/lib/languages/ro.js +273 -0
  179. package/lib/languages/ru.d.ts +85 -0
  180. package/lib/languages/ru.js +96 -0
  181. package/lib/languages/sr-Cyrl.d.ts +80 -0
  182. package/lib/languages/sr-Cyrl.js +113 -0
  183. package/lib/{i18n/cz.d.ts → languages/sr-Latn.d.ts} +26 -14
  184. package/lib/languages/sr-Latn.js +113 -0
  185. package/lib/languages/sv.d.ts +14 -0
  186. package/lib/languages/sv.js +90 -0
  187. package/lib/languages/sw.d.ts +39 -0
  188. package/lib/languages/sw.js +126 -0
  189. package/lib/languages/ta.d.ts +20 -0
  190. package/lib/languages/ta.js +226 -0
  191. package/lib/languages/te.d.ts +22 -0
  192. package/lib/languages/te.js +219 -0
  193. package/lib/languages/th.d.ts +17 -0
  194. package/lib/languages/th.js +117 -0
  195. package/lib/languages/tr.d.ts +12 -0
  196. package/lib/languages/tr.js +56 -0
  197. package/lib/languages/uk.d.ts +85 -0
  198. package/lib/{i18n → languages}/uk.js +33 -32
  199. package/lib/languages/ur.d.ts +11 -0
  200. package/lib/languages/ur.js +131 -0
  201. package/lib/{i18n → languages}/vi.d.ts +15 -13
  202. package/lib/languages/vi.js +147 -0
  203. package/lib/languages/zh-Hans.d.ts +21 -0
  204. package/lib/languages/zh-Hans.js +111 -0
  205. package/lib/languages/zh-Hant.d.ts +21 -0
  206. package/lib/languages/zh-Hant.js +111 -0
  207. package/lib/n2words.d.ts +207 -7
  208. package/lib/n2words.js +535 -81
  209. package/package.json +126 -79
  210. package/dist/ar.js +0 -2
  211. package/dist/ar.js.map +0 -1
  212. package/dist/az.js +0 -2
  213. package/dist/az.js.map +0 -1
  214. package/dist/cz.js +0 -2
  215. package/dist/cz.js.map +0 -1
  216. package/dist/de.js +0 -2
  217. package/dist/de.js.map +0 -1
  218. package/dist/dk.js +0 -2
  219. package/dist/dk.js.map +0 -1
  220. package/dist/en.js +0 -2
  221. package/dist/en.js.map +0 -1
  222. package/dist/es.js +0 -2
  223. package/dist/es.js.map +0 -1
  224. package/dist/fa.js +0 -2
  225. package/dist/fa.js.map +0 -1
  226. package/dist/fr-BE.js +0 -2
  227. package/dist/fr-BE.js.map +0 -1
  228. package/dist/fr.js +0 -2
  229. package/dist/fr.js.map +0 -1
  230. package/dist/he.js +0 -2
  231. package/dist/he.js.map +0 -1
  232. package/dist/hr.js +0 -2
  233. package/dist/hr.js.map +0 -1
  234. package/dist/hu.js +0 -2
  235. package/dist/hu.js.map +0 -1
  236. package/dist/id.js +0 -2
  237. package/dist/id.js.map +0 -1
  238. package/dist/it.js +0 -2
  239. package/dist/it.js.map +0 -1
  240. package/dist/ko.js +0 -2
  241. package/dist/ko.js.map +0 -1
  242. package/dist/lt.js +0 -2
  243. package/dist/lt.js.map +0 -1
  244. package/dist/lv.js +0 -2
  245. package/dist/lv.js.map +0 -1
  246. package/dist/n2words.d.ts +0 -2
  247. package/dist/nl.js +0 -2
  248. package/dist/nl.js.map +0 -1
  249. package/dist/no.js +0 -2
  250. package/dist/no.js.map +0 -1
  251. package/dist/pl.js +0 -2
  252. package/dist/pl.js.map +0 -1
  253. package/dist/pt.js +0 -2
  254. package/dist/pt.js.map +0 -1
  255. package/dist/ro.js +0 -2
  256. package/dist/ro.js.map +0 -1
  257. package/dist/ru.js +0 -2
  258. package/dist/ru.js.map +0 -1
  259. package/dist/sr.js +0 -2
  260. package/dist/sr.js.map +0 -1
  261. package/dist/tr.js +0 -2
  262. package/dist/tr.js.map +0 -1
  263. package/dist/uk.js +0 -2
  264. package/dist/uk.js.map +0 -1
  265. package/dist/vi.js +0 -2
  266. package/dist/vi.js.map +0 -1
  267. package/dist/zh.js +0 -2
  268. package/dist/zh.js.map +0 -1
  269. package/lib/classes/base-language.d.ts +0 -58
  270. package/lib/classes/base-language.js +0 -172
  271. package/lib/i18n/ar.d.ts +0 -41
  272. package/lib/i18n/ar.js +0 -209
  273. package/lib/i18n/az.d.ts +0 -15
  274. package/lib/i18n/az.js +0 -66
  275. package/lib/i18n/cz.js +0 -135
  276. package/lib/i18n/de.d.ts +0 -17
  277. package/lib/i18n/de.js +0 -103
  278. package/lib/i18n/dk.d.ts +0 -14
  279. package/lib/i18n/dk.js +0 -110
  280. package/lib/i18n/en.d.ts +0 -22
  281. package/lib/i18n/en.js +0 -86
  282. package/lib/i18n/es.d.ts +0 -16
  283. package/lib/i18n/es.js +0 -110
  284. package/lib/i18n/fa.d.ts +0 -54
  285. package/lib/i18n/fa.js +0 -106
  286. package/lib/i18n/fr-BE.d.ts +0 -11
  287. package/lib/i18n/fr-BE.js +0 -20
  288. package/lib/i18n/fr.d.ts +0 -15
  289. package/lib/i18n/fr.js +0 -99
  290. package/lib/i18n/he.d.ts +0 -61
  291. package/lib/i18n/he.js +0 -132
  292. package/lib/i18n/hr.d.ts +0 -68
  293. package/lib/i18n/hr.js +0 -129
  294. package/lib/i18n/hu.d.ts +0 -17
  295. package/lib/i18n/hu.js +0 -135
  296. package/lib/i18n/id.d.ts +0 -43
  297. package/lib/i18n/id.js +0 -156
  298. package/lib/i18n/it.d.ts +0 -29
  299. package/lib/i18n/it.js +0 -137
  300. package/lib/i18n/ko.d.ts +0 -15
  301. package/lib/i18n/ko.js +0 -56
  302. package/lib/i18n/lt.js +0 -138
  303. package/lib/i18n/lv.d.ts +0 -57
  304. package/lib/i18n/lv.js +0 -120
  305. package/lib/i18n/nl.d.ts +0 -20
  306. package/lib/i18n/nl.js +0 -125
  307. package/lib/i18n/no.d.ts +0 -15
  308. package/lib/i18n/no.js +0 -77
  309. package/lib/i18n/pl.js +0 -126
  310. package/lib/i18n/pt.d.ts +0 -26
  311. package/lib/i18n/pt.js +0 -118
  312. package/lib/i18n/ro.d.ts +0 -109
  313. package/lib/i18n/ro.js +0 -360
  314. package/lib/i18n/ru.d.ts +0 -30
  315. package/lib/i18n/ru.js +0 -198
  316. package/lib/i18n/sr.d.ts +0 -56
  317. package/lib/i18n/sr.js +0 -127
  318. package/lib/i18n/tr.d.ts +0 -15
  319. package/lib/i18n/tr.js +0 -64
  320. package/lib/i18n/vi.js +0 -151
  321. package/lib/i18n/zh.d.ts +0 -18
  322. package/lib/i18n/zh.js +0 -78
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Croatian language converter.
3
+ *
4
+ * Supports:
5
+ * - Three-form pluralization (one/few/many)
6
+ * - Gender agreement (jedan/jedna, dva/dvije)
7
+ * - Croatian-specific declension endings
8
+ */
9
+ export class Croatian 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: {
55
+ 1: string;
56
+ 2: string;
57
+ 3: string;
58
+ 4: string;
59
+ 5: string;
60
+ 6: string;
61
+ 7: string;
62
+ 8: string;
63
+ 9: string;
64
+ };
65
+ pluralForms: {
66
+ 1: string[];
67
+ 2: string[];
68
+ 3: string[];
69
+ 4: string[];
70
+ 5: string[];
71
+ 6: string[];
72
+ 7: string[];
73
+ 8: string[];
74
+ 9: string[];
75
+ 10: string[];
76
+ };
77
+ /** Selects Croatian plural form: 1 = singular, 2-4 = few, else = many. */
78
+ pluralize(n: any, forms: any): any;
79
+ }
80
+ import { SlavicLanguage } from '../classes/slavic-language.js';
@@ -0,0 +1,113 @@
1
+ import { SlavicLanguage } from '../classes/slavic-language.js'
2
+
3
+ /**
4
+ * Croatian language converter.
5
+ *
6
+ * Supports:
7
+ * - Three-form pluralization (one/few/many)
8
+ * - Gender agreement (jedan/jedna, dva/dvije)
9
+ * - Croatian-specific declension endings
10
+ */
11
+ export class Croatian extends SlavicLanguage {
12
+ negativeWord = 'minus'
13
+ decimalSeparatorWord = 'zarez'
14
+ zeroWord = 'nula'
15
+
16
+ onesWords = {
17
+ 1: 'jedan',
18
+ 2: 'dva',
19
+ 3: 'tri',
20
+ 4: 'četiri',
21
+ 5: 'pet',
22
+ 6: 'šest',
23
+ 7: 'sedam',
24
+ 8: 'osam',
25
+ 9: 'devet'
26
+ }
27
+
28
+ onesFeminineWords = {
29
+ 1: 'jedna',
30
+ 2: 'dvije',
31
+ 3: 'tri',
32
+ 4: 'četiri',
33
+ 5: 'pet',
34
+ 6: 'šest',
35
+ 7: 'sedam',
36
+ 8: 'osam',
37
+ 9: 'devet'
38
+ }
39
+
40
+ teensWords = {
41
+ 0: 'deset',
42
+ 1: 'jedanaest',
43
+ 2: 'dvanaest',
44
+ 3: 'trinaest',
45
+ 4: 'četrnaest',
46
+ 5: 'petnaest',
47
+ 6: 'šesnaest',
48
+ 7: 'sedamnaest',
49
+ 8: 'osamnaest',
50
+ 9: 'devetnaest'
51
+ }
52
+
53
+ twentiesWords = {
54
+ 2: 'dvadeset',
55
+ 3: 'trideset',
56
+ 4: 'četrdeset',
57
+ 5: 'pedeset',
58
+ 6: 'šezdeset',
59
+ 7: 'sedamdeset',
60
+ 8: 'osamdeset',
61
+ 9: 'devedeset'
62
+ }
63
+
64
+ hundredsWords = {
65
+ 1: 'sto',
66
+ 2: 'dvjesto',
67
+ 3: 'tristo',
68
+ 4: 'četiristo',
69
+ 5: 'petsto',
70
+ 6: 'šesto',
71
+ 7: 'sedamsto',
72
+ 8: 'osamsto',
73
+ 9: 'devetsto'
74
+ }
75
+
76
+ pluralForms = {
77
+ 1: ['tisuća', 'tisuće', 'tisuća'], // 10 ^ 3
78
+ 2: ['milijun', 'milijuna', 'milijuna'], // 10 ^ 6
79
+ 3: ['milijarda', 'milijarde', 'milijarda'], // 10 ^ 9
80
+ 4: ['bilijun', 'bilijuna', 'bilijuna'], // 10 ^ 12
81
+ 5: ['bilijarda', 'bilijarde', 'bilijarda'], // 10 ^ 15
82
+ 6: ['trilijun', 'trilijuna', 'trilijuna'], // 10 ^ 18
83
+ 7: ['trilijarda', 'trilijarde', 'trilijarda'], // 10 ^ 21
84
+ 8: ['kvadrilijun', 'kvadrilijuna', 'kvadrilijuna'], // 10 ^ 24
85
+ 9: ['kvadrilijarda', 'kvadrilijarde', 'kvadrilijarda'], // 10 ^ 27
86
+ 10: ['kvintilijun', 'kvintilijuna', 'kvintilijuna'] // 10 ^ 30
87
+ }
88
+
89
+ /**
90
+ * Maps segment indices to whether they are grammatically feminine.
91
+ * In Croatian, thousands (index 1) are feminine, others are masculine.
92
+ * @type {Object.<number, boolean>}
93
+ */
94
+ scaleGenders = {
95
+ 1: true // thousands are feminine (others default to false)
96
+ }
97
+
98
+ /** Selects Croatian plural form: 1 = singular, 2-4 = few, else = many. */
99
+ pluralize (n, forms) {
100
+ const lastDigit = n % 10n
101
+ const lastTwoDigits = n % 100n
102
+
103
+ if ((lastTwoDigits < 10n || lastTwoDigits > 20n) && lastDigit === 1n) {
104
+ return forms[0]
105
+ }
106
+
107
+ if ((lastTwoDigits < 10n || lastTwoDigits > 20n) && lastDigit > 1n && lastDigit < 5n) {
108
+ return forms[1]
109
+ }
110
+
111
+ return forms[2]
112
+ }
113
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Hungarian language converter.
3
+ *
4
+ * Supports:
5
+ * - Agglutinative structure (no spaces between compound parts)
6
+ * - Special handling for "egy" (one) omission
7
+ * - Pre-composed twenties (huszonegy through huszonkilenc)
8
+ */
9
+ export class Hungarian extends GreedyScaleLanguage {
10
+ scaleWords: (string | bigint)[][];
11
+ /** Converts tens (30-99) with agglutinative composition. */
12
+ tensToCardinal(number: any): string | undefined;
13
+ /** Converts hundreds (100-999) with "száz" composition. */
14
+ hundredsToCardinal(number: any): string;
15
+ /** Converts thousands (1000-999999) with "ezer" composition. */
16
+ thousandsToCardinal(number: any): string;
17
+ /** Converts large numbers (millions and above) with scale words. */
18
+ bigNumberToCardinal(number: any): string;
19
+ /** Converts integer part using Hungarian agglutinative rules. */
20
+ integerToWords(integerPart: any, zeroWord?: string): string;
21
+ }
22
+ import { GreedyScaleLanguage } from '../classes/greedy-scale-language.js';
@@ -0,0 +1,137 @@
1
+ import { GreedyScaleLanguage } from '../classes/greedy-scale-language.js'
2
+
3
+ /**
4
+ * Hungarian language converter.
5
+ *
6
+ * Supports:
7
+ * - Agglutinative structure (no spaces between compound parts)
8
+ * - Special handling for "egy" (one) omission
9
+ * - Pre-composed twenties (huszonegy through huszonkilenc)
10
+ */
11
+ export class Hungarian extends GreedyScaleLanguage {
12
+ negativeWord = 'mínusz'
13
+ decimalSeparatorWord = 'egész'
14
+ zeroWord = 'nulla'
15
+
16
+ scaleWords = [
17
+ [1_000_000_000_000_000_000_000_000_000n, 'quadrilliárd'],
18
+ [1_000_000_000_000_000_000_000_000n, 'quadrillió'],
19
+ [1_000_000_000_000_000_000_000n, 'trilliárd'],
20
+ [1_000_000_000_000_000_000n, 'trillió'],
21
+ [1_000_000_000_000_000n, 'billiárd'],
22
+ [1_000_000_000_000n, 'billió'],
23
+ [1_000_000_000n, 'milliárd'],
24
+ [1_000_000n, 'millió'],
25
+ [1000n, 'ezer'],
26
+ [100n, 'száz'],
27
+ [90n, 'kilencven'],
28
+ [80n, 'nyolcvan'],
29
+ [70n, 'hetven'],
30
+ [60n, 'hatvan'],
31
+ [50n, 'ötven'],
32
+ [40n, 'negyven'],
33
+ [30n, 'harminc'],
34
+ [29n, 'huszonkilenc'],
35
+ [28n, 'huszonnyolc'],
36
+ [27n, 'huszonhét'],
37
+ [26n, 'huszonhat'],
38
+ [25n, 'huszonöt'],
39
+ [24n, 'huszonnégy'],
40
+ [23n, 'huszonhárom'],
41
+ [22n, 'huszonkettő'],
42
+ [21n, 'huszonegy'],
43
+ [20n, 'húsz'],
44
+ [19n, 'tizenkilenc'],
45
+ [18n, 'tizennyolc'],
46
+ [17n, 'tizenhét'],
47
+ [16n, 'tizenhat'],
48
+ [15n, 'tizenöt'],
49
+ [14n, 'tizennégy'],
50
+ [13n, 'tizenhárom'],
51
+ [12n, 'tizenkettő'],
52
+ [11n, 'tizenegy'],
53
+ [10n, 'tíz'],
54
+ [9n, 'kilenc'],
55
+ [8n, 'nyolc'],
56
+ [7n, 'hét'],
57
+ [6n, 'hat'],
58
+ [5n, 'öt'],
59
+ [4n, 'négy'],
60
+ [3n, 'három'],
61
+ [2n, 'kettő'],
62
+ [1n, 'egy'],
63
+ [0n, 'nulla']
64
+ ]
65
+
66
+ /** Converts tens (30-99) with agglutinative composition. */
67
+ tensToCardinal (number) {
68
+ // Expecting `number` as bigint when called from integerToWords
69
+ if (this.wordForScale(number)) {
70
+ return this.wordForScale(number)
71
+ } else {
72
+ const tens = number / 10n
73
+ const units = number % 10n
74
+ return this.wordForScale(tens * 10n) + this.integerToWords(units)
75
+ }
76
+ }
77
+
78
+ /** Converts hundreds (100-999) with "száz" composition. */
79
+ hundredsToCardinal (number) {
80
+ const hundreds = number / 100n
81
+ let prefix = 'száz'
82
+ if (hundreds !== 1n) {
83
+ prefix = this.integerToWords(hundreds, '') + prefix
84
+ }
85
+ const postfix = this.integerToWords(number % 100n, '')
86
+ return prefix + postfix
87
+ }
88
+
89
+ /** Converts thousands (1000-999999) with "ezer" composition. */
90
+ thousandsToCardinal (number) {
91
+ const thousands = number / 1000n
92
+ let prefix = 'ezer'
93
+ if (thousands !== 1n) {
94
+ prefix = this.integerToWords(thousands, '') + prefix
95
+ }
96
+ const postfix = this.integerToWords(number % 1000n, '')
97
+ const middle = (number <= 2000n || postfix === '') ? '' : '-'
98
+ return prefix + middle + postfix
99
+ }
100
+
101
+ /** Converts large numbers (millions and above) with scale words. */
102
+ bigNumberToCardinal (number) {
103
+ const numberLength = number.toString().length
104
+ const digits = (numberLength % 3 === 0) ? numberLength - 2 : numberLength
105
+ const exp = 10 ** (Math.floor(digits / 3) * 3)
106
+ const prefix = this.integerToWords(number / BigInt(exp), '')
107
+ const rest = this.integerToWords(number % BigInt(exp), '')
108
+ const postfix = (rest === '') ? '' : ('-' + rest)
109
+ return prefix + this.wordForScale(BigInt(exp)) + postfix
110
+ }
111
+
112
+ /** Converts integer part using Hungarian agglutinative rules. */
113
+ integerToWords (integerPart, zeroWord = this.zeroWord) {
114
+ let words = ''
115
+
116
+ // Normalize to BigInt for consistent comparisons
117
+ if (typeof integerPart !== 'bigint') integerPart = BigInt(integerPart)
118
+
119
+ if (integerPart === 0n) {
120
+ words = zeroWord
121
+ } else if (zeroWord === '' && integerPart === 2n) {
122
+ words = 'két'
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)
131
+ } else {
132
+ words = this.bigNumberToCardinal(integerPart)
133
+ }
134
+
135
+ return words
136
+ }
137
+ }
@@ -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';
@@ -0,0 +1,159 @@
1
+ import { AbstractLanguage } from '../classes/abstract-language.js'
2
+
3
+ /**
4
+ * Indonesian language converter.
5
+ *
6
+ * Supports:
7
+ * - "Se-" prefix for one (seratus, seribu, sejuta)
8
+ * - Regular patterns (puluh for tens, ratus for hundreds)
9
+ * - Space-separated number components
10
+ */
11
+ export class Indonesian extends AbstractLanguage {
12
+ negativeWord = 'min'
13
+ decimalSeparatorWord = 'koma'
14
+ zeroWord = 'nol'
15
+
16
+ /**
17
+ * Word forms for digits 0-9.
18
+ * @type {Object.<number, string[]>}
19
+ */
20
+ digitWords = {
21
+ 0: [],
22
+ 1: ['satu'],
23
+ 2: ['dua'],
24
+ 3: ['tiga'],
25
+ 4: ['empat'],
26
+ 5: ['lima'],
27
+ 6: ['enam'],
28
+ 7: ['tujuh'],
29
+ 8: ['delapan'],
30
+ 9: ['sembilan']
31
+ }
32
+
33
+ /**
34
+ * Scale magnitude words keyed by exponent (10^n).
35
+ * @type {Object.<number, string>}
36
+ */
37
+ scaleWords = {
38
+ 3: 'ribu', // 10^3
39
+ 6: 'juta', // 10^6
40
+ 9: 'miliar', // 10^9
41
+ 12: 'triliun',
42
+ 15: 'kuadriliun',
43
+ 18: 'kuantiliun',
44
+ 21: 'sekstiliun',
45
+ 24: 'septiliun',
46
+ 27: 'oktiliun',
47
+ 30: 'noniliun',
48
+ 33: 'desiliun'
49
+ }
50
+
51
+ /** Splits number into groups of 3 digits. */
52
+ splitBy3 (number) {
53
+ // Split to groups of 3 numbers: 1234567 -> [['1'], ['234'], ['567']]
54
+ const blocks = []
55
+ const stringNumber = number.toString()
56
+ const length = stringNumber.length
57
+ let firstBlock
58
+
59
+ if (length < 3) {
60
+ blocks.push([stringNumber])
61
+ } else {
62
+ const firstBlockLength = length % 3
63
+
64
+ if (firstBlockLength > 0) {
65
+ firstBlock = [stringNumber.slice(0, firstBlockLength)]
66
+ blocks.push(firstBlock)
67
+ }
68
+
69
+ for (let index = firstBlockLength; index < length; index += 3) {
70
+ const nextBlock = [stringNumber.slice(index, index + 3)]
71
+ blocks.push(nextBlock)
72
+ }
73
+ }
74
+ return blocks
75
+ }
76
+
77
+ /** Converts digit blocks to Indonesian words. */
78
+ spell (blocks) {
79
+ let wordBlocks = []
80
+ let spelling
81
+ const firstBlock = blocks[0]
82
+ if (firstBlock[0].length === 1) {
83
+ spelling = firstBlock[0] === '0' ? ['nol'] : this.digitWords[Math.trunc(firstBlock[0])]
84
+ } else if (firstBlock[0].length === 2) {
85
+ spelling = this.getTens(firstBlock[0])
86
+ } else {
87
+ spelling = [...this.getHundreds(firstBlock[0][0]), ...this.getTens(firstBlock[0].slice(1, 3))]
88
+ }
89
+ wordBlocks = [...wordBlocks, [firstBlock[0], spelling]]
90
+ for (let index = 1; index < blocks.length; index++) {
91
+ let block = blocks[index]
92
+ spelling = [...this.getHundreds(block[0][0]), ...this.getTens(block[0].slice(1, 3))]
93
+ block = [...block, spelling]
94
+ wordBlocks = [...wordBlocks, block]
95
+ }
96
+ return wordBlocks
97
+ }
98
+
99
+ /** Converts hundreds digit with "seratus" or "ratus" suffix. */
100
+ getHundreds (number) {
101
+ if (number === '1') {
102
+ return ['seratus']
103
+ } else if (number === '0') {
104
+ return []
105
+ } else {
106
+ return [...this.digitWords[Math.trunc(number)], 'ratus']
107
+ }
108
+ }
109
+
110
+ /** Converts tens and units digits with "puluh" or "belas" suffix. */
111
+ getTens (number) {
112
+ if (number[0] === '1') {
113
+ if (number[1] === '0') {
114
+ return ['sepuluh']
115
+ } else if (number[1] === '1') {
116
+ return ['sebelas']
117
+ }
118
+ return [...this.digitWords[Math.trunc(number[1])], 'belas']
119
+ }
120
+
121
+ if (number[0] === '0') {
122
+ return this.digitWords[Math.trunc(number[1])]
123
+ }
124
+
125
+ return [...this.digitWords[Math.trunc(number[0])], 'puluh', ...this.digitWords[Math.trunc(number[1])]]
126
+ }
127
+
128
+ /** Joins word blocks with magnitude scale words. */
129
+ join (wordBlocks) {
130
+ let wordList = []
131
+ const length = wordBlocks.length - 1
132
+ const firstBlock = [wordBlocks[0]]
133
+ let start = 0
134
+ if (length === 1 && firstBlock[0][0] === '1') {
135
+ wordList.push('seribu')
136
+ start = 1
137
+ }
138
+ for (let index = start; index < length + 1; index++) {
139
+ wordList = [...wordList, ...wordBlocks[index][1]]
140
+ if (wordBlocks[index][1].length === 0) {
141
+ continue
142
+ }
143
+ if (index === length) {
144
+ break
145
+ }
146
+ wordList = [...wordList, this.scaleWords[(length - index) * 3]]
147
+ }
148
+ return wordList.join(' ')
149
+ }
150
+
151
+ /** Converts integer part using Indonesian group-based conversion. */
152
+ integerToWords (integerPart) {
153
+ return this.join(
154
+ this.spell(
155
+ this.splitBy3(integerPart)
156
+ )
157
+ ).trim()
158
+ }
159
+ }
@@ -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';