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,120 @@
1
+ import { GreedyScaleLanguage } from '../classes/greedy-scale-language.js'
2
+
3
+ /**
4
+ * Danish language converter.
5
+ *
6
+ * Supports:
7
+ * - Vigesimal (base-20) number system
8
+ * - Units-before-tens ordering (e.g., "tre-og-tyve" = 23)
9
+ * - Optional ordinal numbers via ordFlag option
10
+ */
11
+ export class Danish extends GreedyScaleLanguage {
12
+ negativeWord = 'minus'
13
+ decimalSeparatorWord = 'komma'
14
+ zeroWord = 'nul'
15
+
16
+ scaleWords = [
17
+ [1_000_000_000_000_000_000_000_000_000n, 'quadrillarder'],
18
+ [1_000_000_000_000_000_000_000_000n, 'quadrillioner'],
19
+ [1_000_000_000_000_000_000_000n, 'trillarder'],
20
+ [1_000_000_000_000_000_000n, 'trillioner'],
21
+ [1_000_000_000_000_000n, 'billarder'],
22
+ [1_000_000_000_000n, 'billioner'],
23
+ [1_000_000_000n, 'millarder'],
24
+ [1_000_000n, 'millioner'],
25
+ [1000n, 'tusind'],
26
+ [100n, 'hundrede'],
27
+ [90n, 'halvfems'],
28
+ [80n, 'firs'],
29
+ [70n, 'halvfjerds'],
30
+ [60n, 'treds'],
31
+ [50n, 'halvtreds'],
32
+ [40n, 'fyrre'],
33
+ [30n, 'tredive'],
34
+ [20n, 'tyve'],
35
+ [19n, 'nitten'],
36
+ [18n, 'atten'],
37
+ [17n, 'sytten'],
38
+ [16n, 'seksten'],
39
+ [15n, 'femten'],
40
+ [14n, 'fjorten'],
41
+ [13n, 'tretten'],
42
+ [12n, 'tolv'],
43
+ [11n, 'elleve'],
44
+ [10n, 'ti'],
45
+ [9n, 'ni'],
46
+ [8n, 'otte'],
47
+ [7n, 'syv'],
48
+ [6n, 'seks'],
49
+ [5n, 'fem'],
50
+ [4n, 'fire'],
51
+ [3n, 'tre'],
52
+ [2n, 'to'],
53
+ [1n, 'et'],
54
+ [0n, 'nul']
55
+ ]
56
+
57
+ constructor (options = {}) {
58
+ super()
59
+
60
+ this.setOptions({
61
+ ordFlag: false
62
+ }, options)
63
+ }
64
+
65
+ /** Combines two word-sets with Danish vigesimal and reversal rules. */
66
+ combineWordSets (preceding, following) {
67
+ let precedingWord = Object.keys(preceding)[0]
68
+ let followingWord = Object.keys(following)[0]
69
+ const precedingValue = Object.values(preceding)[0] // BigInt (e.g., 1n, 100n, 1000n)
70
+ const followingValue = Object.values(following)[0] // BigInt (e.g., magnitude level like 100n, 1000n)
71
+
72
+ // Prepend "et" to hundreds and thousands (not "en") for proper Danish form
73
+ if (followingValue === 100n || followingValue === 1000n) {
74
+ following = { [`et${followingWord}`]: followingValue }
75
+ }
76
+
77
+ // Implicit '1' handling: omit '1' before most magnitudes (except millions/ordinals)
78
+ if (precedingValue === 1n) {
79
+ if (followingValue < 1_000_000n || this.options.ordFlag) {
80
+ return following // Just the magnitude word (e.g., "hundrede" not "en hundrede")
81
+ }
82
+ precedingWord = 'en' // Explicit "en" (one) for millions and above
83
+ }
84
+
85
+ // Multiplication across magnitude boundaries
86
+ if (followingValue > precedingValue) {
87
+ // Space for million+ (e.g., "en million", "to millioner")
88
+ if (followingValue >= 1_000_000n) {
89
+ precedingWord += ' '
90
+ }
91
+ return { [`${precedingWord}${followingWord}`]: precedingValue * followingValue }
92
+ }
93
+
94
+ // Addition with separator rules:
95
+ // "og" (and) for hundreds + smaller numbers
96
+ if (precedingValue >= 100n && precedingValue < 1000n) {
97
+ precedingWord += ' og '
98
+ } else if (precedingValue >= 1000n && precedingValue <= 100_000n) {
99
+ // Special "e og" for thousands (e.g., "tusinde og tyve")
100
+ precedingWord += 'e og '
101
+ }
102
+
103
+ // Units-before-tens reversal (Danish vigesimal pattern):
104
+ // For small units (< 10) with tens (10-99), swap order: "tre og tyve" (25)
105
+ if (followingValue < 10n && precedingValue > 10n && precedingValue < 100n) {
106
+ if (followingValue === 1n) {
107
+ followingWord = 'en' // Convert 1 to "en" for vigesimal context
108
+ }
109
+ // Swap positions: units go after "og", tens go before
110
+ const temporary = followingWord
111
+ followingWord = precedingWord
112
+ precedingWord = temporary + 'og'
113
+ } else if (precedingValue >= 1_000_000n) {
114
+ // Space for large magnitudes (millions+)
115
+ precedingWord += ' '
116
+ }
117
+
118
+ return { [`${precedingWord}${followingWord}`]: precedingValue + followingValue }
119
+ }
120
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * German language converter.
3
+ *
4
+ * Supports:
5
+ * - Compound formation (no separators between words)
6
+ * - Three forms of 1 (eins/ein/eine)
7
+ * - Units-before-tens ordering (einundzwanzig = one and twenty)
8
+ */
9
+ export class German extends GreedyScaleLanguage {
10
+ scaleWords: (string | bigint)[][];
11
+ /** Combines two word-sets with German compound formation and reversal rules. */
12
+ combineWordSets(preceding: any, following: any): any;
13
+ }
14
+ import { GreedyScaleLanguage } from '../classes/greedy-scale-language.js';
@@ -0,0 +1,101 @@
1
+ import { GreedyScaleLanguage } from '../classes/greedy-scale-language.js'
2
+
3
+ /**
4
+ * German language converter.
5
+ *
6
+ * Supports:
7
+ * - Compound formation (no separators between words)
8
+ * - Three forms of 1 (eins/ein/eine)
9
+ * - Units-before-tens ordering (einundzwanzig = one and twenty)
10
+ */
11
+ export class German extends GreedyScaleLanguage {
12
+ negativeWord = 'minus'
13
+ decimalSeparatorWord = 'komma'
14
+ zeroWord = 'null'
15
+
16
+ scaleWords = [
17
+ [1_000_000_000_000_000_000_000_000_000n, 'Quadrilliarde'],
18
+ [1_000_000_000_000_000_000_000_000n, 'Quadrillion'],
19
+ [1_000_000_000_000_000_000_000n, 'Trilliarde'],
20
+ [1_000_000_000_000_000_000n, 'Trillion'],
21
+ [1_000_000_000_000_000n, 'Billiarde'],
22
+ [1_000_000_000_000n, 'Billion'],
23
+ [1_000_000_000n, 'Milliarde'],
24
+ [1_000_000n, 'Million'],
25
+ [1000n, 'tausend'],
26
+ [100n, 'hundert'],
27
+ [90n, 'neunzig'],
28
+ [80n, 'achtzig'],
29
+ [70n, 'siebzig'],
30
+ [60n, 'sechzig'],
31
+ [50n, 'fünfzig'],
32
+ [40n, 'vierzig'],
33
+ [30n, 'dreißig'],
34
+ [20n, 'zwanzig'],
35
+ [19n, 'neunzehn'],
36
+ [18n, 'achtzehn'],
37
+ [17n, 'siebzehn'],
38
+ [16n, 'sechzehn'],
39
+ [15n, 'fünfzehn'],
40
+ [14n, 'vierzehn'],
41
+ [13n, 'dreizehn'],
42
+ [12n, 'zwölf'],
43
+ [11n, 'elf'],
44
+ [10n, 'zehn'],
45
+ [9n, 'neun'],
46
+ [8n, 'acht'],
47
+ [7n, 'sieben'],
48
+ [6n, 'sechs'],
49
+ [5n, 'fünf'],
50
+ [4n, 'vier'],
51
+ [3n, 'drei'],
52
+ [2n, 'zwei'],
53
+ [1n, 'eins'],
54
+ [0n, 'null']
55
+ ]
56
+
57
+ /** Combines two word-sets with German compound formation and reversal rules. */
58
+ combineWordSets (preceding, following) {
59
+ let precedingWord = Object.keys(preceding)[0]
60
+ let followingWord = Object.keys(following)[0]
61
+ const precedingValue = Object.values(preceding)[0]
62
+ const followingValue = Object.values(following)[0]
63
+
64
+ // Handle form of 1: "eins" → "ein(e)" in certain contexts
65
+ if (precedingValue === 1n) {
66
+ if (followingValue === 100n || followingValue === 1000n) {
67
+ return { [`ein${followingWord}`]: followingValue }
68
+ }
69
+ if (followingValue < 1_000_000n) {
70
+ return following
71
+ }
72
+ precedingWord = 'eine'
73
+ }
74
+
75
+ if (followingValue > precedingValue) {
76
+ // Multiply: apply pluralization rules for millions
77
+ if (followingValue >= 1_000_000n) {
78
+ if (precedingValue > 1n) {
79
+ followingWord += followingWord.at(-1) === 'e' ? 'n' : 'en'
80
+ }
81
+ precedingWord += ' '
82
+ }
83
+ return { [`${precedingWord}${followingWord}`]: precedingValue * followingValue }
84
+ }
85
+
86
+ // Add: handle special case of tens + units
87
+ if (followingValue < 10n && precedingValue > 10n && precedingValue < 100n) {
88
+ // German reverses tens and units (einundzwanzig = one and twenty)
89
+ if (followingValue === 1n) {
90
+ followingWord = 'ein'
91
+ }
92
+ const temp = followingWord
93
+ followingWord = precedingWord
94
+ precedingWord = `${temp}und`
95
+ } else if (precedingValue >= 1_000_000n) {
96
+ precedingWord += ' '
97
+ }
98
+
99
+ return { [`${precedingWord}${followingWord}`]: precedingValue + followingValue }
100
+ }
101
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Greek language converter.
3
+ *
4
+ * Supports:
5
+ * - Space-separated number composition
6
+ * - Implicit "one" (ένα) omission before scale words
7
+ * - Digit-by-digit decimal reading
8
+ */
9
+ export class Greek extends GreedyScaleLanguage {
10
+ scaleWords: (string | bigint)[][];
11
+ /** Combines two word-sets with Greek space-separation rules. */
12
+ combineWordSets(preceding: any, following: any): any;
13
+ }
14
+ import { GreedyScaleLanguage } from '../classes/greedy-scale-language.js';
@@ -0,0 +1,90 @@
1
+ import { GreedyScaleLanguage } from '../classes/greedy-scale-language.js'
2
+
3
+ /**
4
+ * Greek language converter.
5
+ *
6
+ * Supports:
7
+ * - Space-separated number composition
8
+ * - Implicit "one" (ένα) omission before scale words
9
+ * - Digit-by-digit decimal reading
10
+ */
11
+ export class Greek extends GreedyScaleLanguage {
12
+ negativeWord = 'μείον'
13
+ decimalSeparatorWord = 'κόμμα'
14
+ zeroWord = 'μηδέν'
15
+ usePerDigitDecimals = true
16
+
17
+ scaleWords = [
18
+ // Large numbers (limited set for now)
19
+ [1_000_000_000n, 'δισεκατομμύριο'],
20
+ [1_000_000n, 'εκατομμύριο'],
21
+ [1000n, 'χίλια'],
22
+
23
+ // Hundreds
24
+ [900n, 'εννιακόσια'],
25
+ [800n, 'οκτακόσια'],
26
+ [700n, 'επτακόσια'],
27
+ [600n, 'εξακόσια'],
28
+ [500n, 'πεντακόσια'],
29
+ [400n, 'τετρακόσια'],
30
+ [300n, 'τριακόσια'],
31
+ [200n, 'διακόσια'],
32
+ [100n, 'εκατό'],
33
+
34
+ // Tens
35
+ [90n, 'ενενήντα'],
36
+ [80n, 'ογδόντα'],
37
+ [70n, 'εβδομήντα'],
38
+ [60n, 'εξήντα'],
39
+ [50n, 'πενήντα'],
40
+ [40n, 'σαράντα'],
41
+ [30n, 'τριάντα'],
42
+ [20n, 'είκοσι'],
43
+ [19n, 'δεκαεννέα'],
44
+ [18n, 'δεκαοκτώ'],
45
+ [17n, 'δεκαεπτά'],
46
+ [16n, 'δεκαέξι'],
47
+ [15n, 'δεκαπέντε'],
48
+ [14n, 'δεκατέσσερα'],
49
+ [13n, 'δεκατρία'],
50
+ [12n, 'δώδεκα'],
51
+ [11n, 'έντεκα'],
52
+ [10n, 'δέκα'],
53
+
54
+ // Singles
55
+ [9n, 'εννέα'],
56
+ [8n, 'οκτώ'],
57
+ [7n, 'επτά'],
58
+ [6n, 'έξι'],
59
+ [5n, 'πέντε'],
60
+ [4n, 'τέσσερα'],
61
+ [3n, 'τρία'],
62
+ [2n, 'δύο'],
63
+ [1n, 'ένα'],
64
+ [0n, 'μηδέν']
65
+ ]
66
+
67
+ /** Combines two word-sets with Greek space-separation rules. */
68
+ combineWordSets (preceding, following) {
69
+ const precedingWord = Object.keys(preceding)[0]
70
+ const precedingValue = Object.values(preceding)[0]
71
+ const followingWord = Object.keys(following)[0]
72
+ const followingValue = Object.values(following)[0]
73
+
74
+ // Implicit one: omit "ένα" before any following value (> 0)
75
+ if (precedingValue === 1n) {
76
+ return following
77
+ }
78
+
79
+ // No special handling needed for trailing 'ένα';
80
+ // nested merge will first collapse {1, 'ένα'} -> 'ένα'.
81
+
82
+ // Multiplication: larger following scale multiplied by preceding number
83
+ if (followingValue > precedingValue) {
84
+ return { [`${precedingWord} ${followingWord}`]: precedingValue * followingValue }
85
+ }
86
+
87
+ // Addition: smaller numbers added together
88
+ return { [`${precedingWord} ${followingWord}`]: precedingValue + followingValue }
89
+ }
90
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * English language converter.
3
+ *
4
+ * Supports:
5
+ * - Hyphenated compounds (e.g., "twenty-three")
6
+ * - "and" after hundreds (e.g., "one hundred and one")
7
+ * - Numbers up to octillions
8
+ */
9
+ export class English extends GreedyScaleLanguage {
10
+ scaleWords: (string | bigint)[][];
11
+ /** Combines two word-sets with English hyphenation and "and" rules. */
12
+ combineWordSets(preceding: any, following: any): {
13
+ [x: string]: any;
14
+ };
15
+ }
16
+ import { GreedyScaleLanguage } from '../classes/greedy-scale-language.js';
@@ -0,0 +1,86 @@
1
+ import { GreedyScaleLanguage } from '../classes/greedy-scale-language.js'
2
+
3
+ /**
4
+ * English language converter.
5
+ *
6
+ * Supports:
7
+ * - Hyphenated compounds (e.g., "twenty-three")
8
+ * - "and" after hundreds (e.g., "one hundred and one")
9
+ * - Numbers up to octillions
10
+ */
11
+ export class English extends GreedyScaleLanguage {
12
+ negativeWord = 'minus'
13
+ decimalSeparatorWord = 'point'
14
+ zeroWord = 'zero'
15
+
16
+ scaleWords = [
17
+ [1_000_000_000_000_000_000_000_000_000n, 'octillion'],
18
+ [1_000_000_000_000_000_000_000_000n, 'septillion'],
19
+ [1_000_000_000_000_000_000_000n, 'sextillion'],
20
+ [1_000_000_000_000_000_000n, 'quintillion'],
21
+ [1_000_000_000_000_000n, 'quadrillion'],
22
+ [1_000_000_000_000n, 'trillion'],
23
+ [1_000_000_000n, 'billion'],
24
+ [1_000_000n, 'million'],
25
+ [1000n, 'thousand'],
26
+ [100n, 'hundred'],
27
+ [90n, 'ninety'],
28
+ [80n, 'eighty'],
29
+ [70n, 'seventy'],
30
+ [60n, 'sixty'],
31
+ [50n, 'fifty'],
32
+ [40n, 'forty'],
33
+ [30n, 'thirty'],
34
+ [20n, 'twenty'],
35
+ [19n, 'nineteen'],
36
+ [18n, 'eighteen'],
37
+ [17n, 'seventeen'],
38
+ [16n, 'sixteen'],
39
+ [15n, 'fifteen'],
40
+ [14n, 'fourteen'],
41
+ [13n, 'thirteen'],
42
+ [12n, 'twelve'],
43
+ [11n, 'eleven'],
44
+ [10n, 'ten'],
45
+ [9n, 'nine'],
46
+ [8n, 'eight'],
47
+ [7n, 'seven'],
48
+ [6n, 'six'],
49
+ [5n, 'five'],
50
+ [4n, 'four'],
51
+ [3n, 'three'],
52
+ [2n, 'two'],
53
+ [1n, 'one'],
54
+ [0n, 'zero']
55
+ ]
56
+
57
+ /** Combines two word-sets with English hyphenation and "and" rules. */
58
+ combineWordSets (preceding, following) {
59
+ const precedingWord = Object.keys(preceding)[0]
60
+ const precedingValue = Object.values(preceding)[0]
61
+ const followingWord = Object.keys(following)[0]
62
+ const followingValue = Object.values(following)[0]
63
+
64
+ // Rule 1: Implicit "one" - omit when multiplying ("one hundred" → "hundred")
65
+ if (precedingValue === 1n && followingValue < 100n) {
66
+ return { [followingWord]: followingValue }
67
+ }
68
+
69
+ // Rule 2: Hyphenate compounds under 100 ("twenty-three")
70
+ if (precedingValue < 100n && precedingValue > followingValue) {
71
+ return { [`${precedingWord}-${followingWord}`]: precedingValue + followingValue }
72
+ }
73
+
74
+ // Rule 3: Add "and" before units after hundreds ("one hundred and one")
75
+ if (precedingValue >= 100n && followingValue < 100n) {
76
+ return { [`${precedingWord} and ${followingWord}`]: precedingValue + followingValue }
77
+ }
78
+
79
+ // Rule 4: Multiply when following > preceding ("one thousand")
80
+ if (followingValue > precedingValue) {
81
+ return { [`${precedingWord} ${followingWord}`]: precedingValue * followingValue }
82
+ }
83
+
84
+ return { [`${precedingWord} ${followingWord}`]: precedingValue + followingValue }
85
+ }
86
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Spanish language converter.
3
+ *
4
+ * Supports:
5
+ * - Gender agreement (masculine/feminine via genderStem option)
6
+ * - "y" conjunction between tens and units
7
+ * - Special hundred forms (cien/ciento)
8
+ */
9
+ export class Spanish extends GreedyScaleLanguage {
10
+ constructor(options?: {});
11
+ scaleWords: (string | bigint)[][];
12
+ /** Combines two word-sets with Spanish gender and conjunction rules. */
13
+ combineWordSets(preceding: any, following: any): any;
14
+ }
15
+ import { GreedyScaleLanguage } from '../classes/greedy-scale-language.js';
@@ -0,0 +1,121 @@
1
+ import { GreedyScaleLanguage } from '../classes/greedy-scale-language.js'
2
+
3
+ /**
4
+ * Spanish language converter.
5
+ *
6
+ * Supports:
7
+ * - Gender agreement (masculine/feminine via genderStem option)
8
+ * - "y" conjunction between tens and units
9
+ * - Special hundred forms (cien/ciento)
10
+ */
11
+ export class Spanish extends GreedyScaleLanguage {
12
+ negativeWord = 'menos'
13
+ decimalSeparatorWord = 'punto'
14
+ zeroWord = 'cero'
15
+
16
+ scaleWords = [
17
+ [1_000_000_000_000_000_000_000_000n, 'cuatrillón'],
18
+ [1_000_000_000_000_000_000n, 'trillón'],
19
+ [1_000_000_000_000n, 'billón'],
20
+ [1_000_000n, 'millón'],
21
+ [1000n, 'mil'],
22
+ [100n, 'cien'],
23
+ [90n, 'noventa'],
24
+ [80n, 'ochenta'],
25
+ [70n, 'setenta'],
26
+ [60n, 'sesenta'],
27
+ [50n, 'cincuenta'],
28
+ [40n, 'cuarenta'],
29
+ [30n, 'treinta'],
30
+ [29n, 'veintinueve'],
31
+ [28n, 'veintiocho'],
32
+ [27n, 'veintisiete'],
33
+ [26n, 'veintiséis'],
34
+ [25n, 'veinticinco'],
35
+ [24n, 'veinticuatro'],
36
+ [23n, 'veintitrés'],
37
+ [22n, 'veintidós'],
38
+ [21n, 'veintiuno'],
39
+ [20n, 'veinte'],
40
+ [19n, 'diecinueve'],
41
+ [18n, 'dieciocho'],
42
+ [17n, 'diecisiete'],
43
+ [16n, 'dieciseis'],
44
+ [15n, 'quince'],
45
+ [14n, 'catorce'],
46
+ [13n, 'trece'],
47
+ [12n, 'doce'],
48
+ [11n, 'once'],
49
+ [10n, 'diez'],
50
+ [9n, 'nueve'],
51
+ [8n, 'ocho'],
52
+ [7n, 'siete'],
53
+ [6n, 'seis'],
54
+ [5n, 'cinco'],
55
+ [4n, 'cuatro'],
56
+ [3n, 'tres'],
57
+ [2n, 'dos'],
58
+ [1n, 'uno'],
59
+ [0n, 'cero']
60
+ ]
61
+
62
+ constructor (options = {}) {
63
+ super()
64
+
65
+ this.setOptions({
66
+ gender: 'masculine'
67
+ }, options)
68
+
69
+ // Apply gender agreement to scale words if feminine
70
+ if (this.options.gender === 'feminine') {
71
+ this.scaleWords = this.scaleWords.map(([value, word]) => {
72
+ if (word === 'veintiuno') return [value, 'veintiuna']
73
+ if (word === 'uno') return [value, 'una']
74
+ return [value, word]
75
+ })
76
+ }
77
+ }
78
+
79
+ /** Combines two word-sets with Spanish gender and conjunction rules. */
80
+ combineWordSets (preceding, following) {
81
+ let precedingWord = Object.keys(preceding)[0]
82
+ let followingWord = Object.keys(following)[0]
83
+ const precedingValue = Object.values(preceding)[0]
84
+ const followingValue = Object.values(following)[0]
85
+ const genderStem = this.options.gender === 'feminine' ? 'a' : 'o'
86
+
87
+ if (precedingValue === 1n) {
88
+ if (followingValue < 1_000_000n) return following
89
+ precedingWord = 'un'
90
+ } else if (precedingValue === 100n && followingValue % 1000n !== 0n) {
91
+ precedingWord += 't' + genderStem
92
+ }
93
+
94
+ if (followingValue < precedingValue) {
95
+ if (precedingValue < 100n) {
96
+ return { [`${precedingWord} y ${followingWord}`]: precedingValue + followingValue }
97
+ }
98
+ return { [`${precedingWord} ${followingWord}`]: precedingValue + followingValue }
99
+ }
100
+
101
+ if (followingValue % 1_000_000n === 0n && precedingValue > 1n) {
102
+ followingWord = followingWord.slice(0, -3) + 'lones'
103
+ }
104
+
105
+ if (followingValue === 100n) {
106
+ if (precedingValue === 5n) {
107
+ precedingWord = 'quinien'
108
+ followingWord = ''
109
+ } else if (precedingValue === 7n) {
110
+ precedingWord = 'sete'
111
+ } else if (precedingValue === 9n) {
112
+ precedingWord = 'nove'
113
+ }
114
+ followingWord += 't' + genderStem + 's'
115
+ } else {
116
+ followingWord = ' ' + followingWord
117
+ }
118
+
119
+ return { [`${precedingWord}${followingWord}`]: precedingValue * followingValue }
120
+ }
121
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Persian language converter.
3
+ *
4
+ * Supports:
5
+ * - "و" (and) conjunction for compound numbers
6
+ * - Recursive conversion for larger numbers
7
+ */
8
+ export class Persian extends AbstractLanguage {
9
+ /**
10
+ * Words for digits 1-9.
11
+ * @type {Object.<number, string>}
12
+ */
13
+ onesWords: {
14
+ [x: number]: string;
15
+ };
16
+ /**
17
+ * Words for teen numbers (10-19).
18
+ * @type {Object.<number, string>}
19
+ */
20
+ teensWords: {
21
+ [x: number]: string;
22
+ };
23
+ /**
24
+ * Words for multiples of ten (20-90).
25
+ * @type {Object.<number, string>}
26
+ */
27
+ tensWords: {
28
+ [x: number]: string;
29
+ };
30
+ /**
31
+ * Words for hundreds (100-900).
32
+ * @type {Object.<number, string>}
33
+ */
34
+ hundredsWords: {
35
+ [x: number]: string;
36
+ };
37
+ /**
38
+ * Scale magnitude words.
39
+ * @type {Object.<number, string>}
40
+ */
41
+ scaleWords: {
42
+ [x: number]: string;
43
+ };
44
+ /** Converts integer part using categorized word tables. */
45
+ integerToWords(integerPart: any): any;
46
+ }
47
+ import { AbstractLanguage } from '../classes/abstract-language.js';