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,21 +1,20 @@
1
- /**
2
- * Converts numbers to their word representation in Greek (Ελληνικά).
3
- * @module languages/el
4
- */
5
-
6
- import GreedyScaleLanguage from '../classes/greedy-scale-language.js'
1
+ import { GreedyScaleLanguage } from '../classes/greedy-scale-language.js'
7
2
 
8
3
  /**
9
- * Greek language implementation using scale-based number conversion.
10
- * @extends GreedyScaleLanguage
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
11
10
  */
12
- class GreekLanguage extends GreedyScaleLanguage {
11
+ export class Greek extends GreedyScaleLanguage {
13
12
  negativeWord = 'μείον'
14
13
  decimalSeparatorWord = 'κόμμα'
15
14
  zeroWord = 'μηδέν'
16
- convertDecimalsPerDigit = true
15
+ usePerDigitDecimals = true
17
16
 
18
- scaleWordPairs = [
17
+ scaleWords = [
19
18
  // Large numbers (limited set for now)
20
19
  [1_000_000_000n, 'δισεκατομμύριο'],
21
20
  [1_000_000n, 'εκατομμύριο'],
@@ -65,52 +64,27 @@ class GreekLanguage extends GreedyScaleLanguage {
65
64
  [0n, 'μηδέν']
66
65
  ]
67
66
 
68
- /**
69
- * Merges two adjacent word-number pairs according to Greek grammar rules.
70
- *
71
- * Greek-specific rules:
72
- * - Implicit "one": χίλια (thousand), not ένα χίλια
73
- * - Space-separated composites
74
- * - Multiplication for scales (e.g., δύο χίλια = two thousand)
75
- *
76
- * @param {Object} leftPair - Left word-number pair (e.g., { 'δύο': 2n })
77
- * @param {Object} rightPair - Right word-number pair (e.g., { 'χίλια': 1000n })
78
- * @returns {Object} Merged word-number pair
79
- */
80
- mergeScales (leftPair, rightPair) {
81
- const leftWord = Object.keys(leftPair)[0]
82
- const leftNumber = Object.values(leftPair)[0]
83
- const rightWord = Object.keys(rightPair)[0]
84
- const rightNumber = Object.values(rightPair)[0]
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]
85
73
 
86
74
  // Implicit one: omit "ένα" before any following value (> 0)
87
- if (leftNumber === 1n) {
88
- return rightPair
75
+ if (precedingValue === 1n) {
76
+ return following
89
77
  }
90
78
 
91
79
  // No special handling needed for trailing 'ένα';
92
80
  // nested merge will first collapse {1, 'ένα'} -> 'ένα'.
93
81
 
94
- // Multiplication: larger right scale multiplied by left number
95
- if (rightNumber > leftNumber) {
96
- return { [`${leftWord} ${rightWord}`]: leftNumber * rightNumber }
82
+ // Multiplication: larger following scale multiplied by preceding number
83
+ if (followingValue > precedingValue) {
84
+ return { [`${precedingWord} ${followingWord}`]: precedingValue * followingValue }
97
85
  }
98
86
 
99
87
  // Addition: smaller numbers added together
100
- return { [`${leftWord} ${rightWord}`]: leftNumber + rightNumber }
88
+ return { [`${precedingWord} ${followingWord}`]: precedingValue + followingValue }
101
89
  }
102
90
  }
103
-
104
- /**
105
- * Converts a number to its word representation in Greek.
106
- * @param {number|string|bigint} value - The number to convert
107
- * @param {Object} [options={}] - Conversion options
108
- * @returns {string} The word representation of the number
109
- * @example
110
- * convertToWords(42) // 'σαράντα δύο'
111
- * convertToWords(1000) // 'χίλια'
112
- * convertToWords(2000) // 'δύο χίλια'
113
- */
114
- export default function convertToWords (value, options = {}) {
115
- return new GreekLanguage(options).convertToWords(value)
116
- }
@@ -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';
@@ -1,23 +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
  * English language converter.
5
5
  *
6
- * Converts numbers to English words, supporting:
7
- * - Negative numbers (prepended with "minus")
8
- * - Decimal numbers (word "point" between whole and fractional parts)
9
- * - Numbers up to octillions
10
- *
11
- * Merge rules:
12
- * - Hyphenated for compound tens (e.g., "twenty-three")
6
+ * Supports:
7
+ * - Hyphenated compounds (e.g., "twenty-three")
13
8
  * - "and" after hundreds (e.g., "one hundred and one")
14
- * - Space-separated for larger composites (e.g., "one thousand twenty-three")
9
+ * - Numbers up to octillions
15
10
  */
16
11
  export class English extends GreedyScaleLanguage {
17
12
  negativeWord = 'minus'
18
13
  decimalSeparatorWord = 'point'
19
14
  zeroWord = 'zero'
20
- scaleWordPairs = [
15
+
16
+ scaleWords = [
21
17
  [1_000_000_000_000_000_000_000_000_000n, 'octillion'],
22
18
  [1_000_000_000_000_000_000_000_000n, 'septillion'],
23
19
  [1_000_000_000_000_000_000_000n, 'sextillion'],
@@ -58,66 +54,33 @@ export class English extends GreedyScaleLanguage {
58
54
  [0n, 'zero']
59
55
  ]
60
56
 
61
- /**
62
- * Merges two adjacent word-number pairs according to English grammar rules.
63
- *
64
- * English-specific rules:
65
- * - Implicit "one": `mergeScales({ 'one': 1n }, { 'hundred': 100n })` → `{ 'one hundred': 100n }`
66
- * - Hyphenated compounds: `mergeScales({ 'twenty': 20n }, { 'three': 3n })` → `{ 'twenty-three': 23n }`
67
- * - "and" after hundreds: `mergeScales({ 'one hundred': 100n }, { 'one': 1n })` → `{ 'one hundred and one': 101n }`
68
- * - Multiplication: `mergeScales({ 'one': 1n }, { 'thousand': 1000n })` → `{ 'one thousand': 1000n }`
69
- *
70
- * @param {Object} leftPair Left word-set as `{ word: BigInt }`.
71
- * @param {Object} rightPair Right word-set as `{ word: BigInt }`.
72
- * @returns {Object} Merged pair with combined word and resulting numeric value.
73
- *
74
- * @example
75
- * mergeScales({ 'one': 1n }, { 'hundred': 100n }); // { 'one hundred': 100n }
76
- * mergeScales({ 'twenty': 20n }, { 'three': 3n }); // { 'twenty-three': 23n }
77
- */
78
- mergeScales (leftPair, rightPair) {
79
- const leftWord = Object.keys(leftPair)[0]
80
- const leftNumber = Object.values(leftPair)[0]
81
- const rightWord = Object.keys(rightPair)[0]
82
- const rightNumber = Object.values(rightPair)[0]
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]
83
63
 
84
64
  // Rule 1: Implicit "one" - omit when multiplying ("one hundred" → "hundred")
85
- if (leftNumber === 1n && rightNumber < 100n) {
86
- return { [rightWord]: rightNumber }
65
+ if (precedingValue === 1n && followingValue < 100n) {
66
+ return { [followingWord]: followingValue }
87
67
  }
88
68
 
89
69
  // Rule 2: Hyphenate compounds under 100 ("twenty-three")
90
- if (leftNumber < 100n && leftNumber > rightNumber) {
91
- return { [`${leftWord}-${rightWord}`]: leftNumber + rightNumber }
70
+ if (precedingValue < 100n && precedingValue > followingValue) {
71
+ return { [`${precedingWord}-${followingWord}`]: precedingValue + followingValue }
92
72
  }
93
73
 
94
74
  // Rule 3: Add "and" before units after hundreds ("one hundred and one")
95
- if (leftNumber >= 100n && rightNumber < 100n) {
96
- return { [`${leftWord} and ${rightWord}`]: leftNumber + rightNumber }
75
+ if (precedingValue >= 100n && followingValue < 100n) {
76
+ return { [`${precedingWord} and ${followingWord}`]: precedingValue + followingValue }
97
77
  }
98
78
 
99
- // Rule 4: Multiply when right > left ("one thousand")
100
- if (rightNumber > leftNumber) {
101
- return { [`${leftWord} ${rightWord}`]: leftNumber * rightNumber }
79
+ // Rule 4: Multiply when following > preceding ("one thousand")
80
+ if (followingValue > precedingValue) {
81
+ return { [`${precedingWord} ${followingWord}`]: precedingValue * followingValue }
102
82
  }
103
83
 
104
- return { [`${leftWord} ${rightWord}`]: leftNumber + rightNumber }
84
+ return { [`${precedingWord} ${followingWord}`]: precedingValue + followingValue }
105
85
  }
106
86
  }
107
-
108
- /**
109
- * Converts a number to English cardinal (written) form.
110
- *
111
- * @param {number|string|bigint} value The number to convert.
112
- * @param {Object} [options] Conversion options (see English class options).
113
- * @returns {string} The number expressed in English words.
114
- * @throws {TypeError} If value is NaN or invalid type.
115
- * @throws {Error} If value is an invalid number string.
116
- *
117
- * @example
118
- * convertToWords(42); // 'forty-two'
119
- * convertToWords('1.5'); // 'one point five'
120
- */
121
- export default function convertToWords (value, options = {}) {
122
- return new English(options).convertToWords(value)
123
- }
@@ -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';
@@ -1,24 +1,19 @@
1
- import GreedyScaleLanguage from '../classes/greedy-scale-language.js'
2
-
3
- /**
4
- * @typedef {Object} SpanishOptions
5
- * @property {string} [genderStem='o'] Masculine 'o' or feminine 'a' ending.
6
- */
1
+ import { GreedyScaleLanguage } from '../classes/greedy-scale-language.js'
7
2
 
8
3
  /**
9
4
  * Spanish language converter.
10
5
  *
11
- * Handles Spanish grammatical features:
12
- * - Gender agreement for numbers (masculine by default, feminine via `genderStem`)
13
- * - "y" (and) between tens and units (e.g., "veinte y uno")
14
- * - Special forms for hundreds (e.g., "cien", "ciento", "doscientos")
15
- * - Million pluralization
6
+ * Supports:
7
+ * - Gender agreement (masculine/feminine via genderStem option)
8
+ * - "y" conjunction between tens and units
9
+ * - Special hundred forms (cien/ciento)
16
10
  */
17
11
  export class Spanish extends GreedyScaleLanguage {
18
12
  negativeWord = 'menos'
19
13
  decimalSeparatorWord = 'punto'
20
14
  zeroWord = 'cero'
21
- scaleWordPairs = [
15
+
16
+ scaleWords = [
22
17
  [1_000_000_000_000_000_000_000_000n, 'cuatrillón'],
23
18
  [1_000_000_000_000_000_000n, 'trillón'],
24
19
  [1_000_000_000_000n, 'billón'],
@@ -64,90 +59,63 @@ export class Spanish extends GreedyScaleLanguage {
64
59
  [0n, 'cero']
65
60
  ]
66
61
 
67
- /**
68
- * Initializes the Spanish converter.
69
- *
70
- * @param {SpanishOptions} [options={}] Configuration options.
71
- */
72
- constructor ({ genderStem = 'o' } = {}) {
62
+ constructor (options = {}) {
73
63
  super()
74
64
 
75
- this.genderStem = genderStem
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
+ }
76
77
  }
77
78
 
78
- /**
79
- * Merges two adjacent word-number pairs according to Spanish grammar rules.
80
- *
81
- * Spanish-specific rules:
82
- * - Implicit "uno": `mergeScales({ 'uno': 1n }, { 'mil': 1000n })` → `{ 'mil': 1000n }`
83
- * - "y" (and) between tens and units: `mergeScales({ 'veinte': 20n }, { 'uno': 1n })` → `{ 'veinte y uno': 21n }`
84
- * - Gender agreement for hundreds: "cien" + suffix based on genderStem
85
- * - Special forms for hundreds (cien/ciento/quinientos/setecientos/novecientos)
86
- * - Million pluralization when coefficient > 1: "millones" instead of "millón"
87
- *
88
- * @param {Object} currentPair The left operand as `{ word: BigInt }`.
89
- * @param {Object} nextPair The right operand as `{ word: BigInt }`.
90
- * @returns {Object} Merged pair with combined word and resulting numeric value.
91
- *
92
- * @example
93
- * mergeScales({ 'uno': 1n }, { 'mil': 1000n }); // { 'mil': 1000n }
94
- * mergeScales({ 'veinte': 20n }, { 'tres': 3n }); // { 'veinte y tres': 23n }
95
- */
96
- mergeScales (currentPair, nextPair) {
97
- let currentWord = Object.keys(currentPair)[0]
98
- let nextWord = Object.keys(nextPair)[0]
99
- const currentNumber = Object.values(currentPair)[0]
100
- const nextNumber = Object.values(nextPair)[0]
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'
101
86
 
102
- if (currentNumber === 1n) {
103
- if (nextNumber < 1_000_000n) return nextPair
104
- currentWord = 'un'
105
- } else if (currentNumber === 100n && nextNumber % 1000n !== 0n) {
106
- currentWord += 't' + this.genderStem
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
107
92
  }
108
93
 
109
- if (nextNumber < currentNumber) {
110
- if (currentNumber < 100n) {
111
- return { [`${currentWord} y ${nextWord}`]: currentNumber + nextNumber }
94
+ if (followingValue < precedingValue) {
95
+ if (precedingValue < 100n) {
96
+ return { [`${precedingWord} y ${followingWord}`]: precedingValue + followingValue }
112
97
  }
113
- return { [`${currentWord} ${nextWord}`]: currentNumber + nextNumber }
98
+ return { [`${precedingWord} ${followingWord}`]: precedingValue + followingValue }
114
99
  }
115
100
 
116
- if (nextNumber % 1_000_000n === 0n && currentNumber > 1n) {
117
- nextWord = nextWord.slice(0, -3) + 'lones'
101
+ if (followingValue % 1_000_000n === 0n && precedingValue > 1n) {
102
+ followingWord = followingWord.slice(0, -3) + 'lones'
118
103
  }
119
104
 
120
- if (nextNumber === 100n) {
121
- if (currentNumber === 5n) {
122
- currentWord = 'quinien'
123
- nextWord = ''
124
- } else if (currentNumber === 7n) {
125
- currentWord = 'sete'
126
- } else if (currentNumber === 9n) {
127
- currentWord = 'nove'
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'
128
113
  }
129
- nextWord += 't' + this.genderStem + 's'
114
+ followingWord += 't' + genderStem + 's'
130
115
  } else {
131
- nextWord = ' ' + nextWord
116
+ followingWord = ' ' + followingWord
132
117
  }
133
118
 
134
- return { [`${currentWord}${nextWord}`]: currentNumber * nextNumber }
119
+ return { [`${precedingWord}${followingWord}`]: precedingValue * followingValue }
135
120
  }
136
121
  }
137
-
138
- /**
139
- * Converts a number to Spanish cardinal (written) form.
140
- *
141
- * @param {number|string|bigint} value The number to convert.
142
- * @param {Object} [options] Conversion options (see ES class).
143
- * @returns {string} The number expressed in Spanish words.
144
- * @throws {TypeError} If value is NaN or invalid type.
145
- * @throws {Error} If value is an invalid number string.
146
- *
147
- * @example
148
- * convertToWords(42, { lang: 'es' }); // 'cuarenta y dos'
149
- * convertToWords(100, { lang: 'es' }); // 'cien'
150
- */
151
- export default function convertToWords (value, options = {}) {
152
- return new Spanish(options).convertToWords(value)
153
- }
@@ -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';