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
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Base class for Turkic languages with shared grammar patterns.
3
+ *
4
+ * This class provides a reusable implementation for Turkic languages that share:
5
+ * - Space-separated number combinations
6
+ * - Implicit 'bir' (one) before hundreds and thousands
7
+ * - Simple multiplication/addition logic
8
+ * - Consistent magnitude handling
9
+ * - Inherits decimal handling from AbstractLanguage via GreedyScaleLanguage
10
+ * (supports both grouped and per-digit modes via the `usePerDigitDecimals` class property).
11
+ *
12
+ * Used by: Turkish (TR), Azerbaijani (AZ)
13
+ *
14
+ * Subclasses MUST define (from GreedyScaleLanguage requirements):
15
+ * - `scaleWords` array of [value, word] tuples as a class property (ordered descending by value).
16
+ * Optionally, language-specific class properties (e.g., `negativeWord`, `zeroWord`, `decimalSeparatorWord`, `wordSeparator`).
17
+ *
18
+ * TurkicLanguage provides a default `combineWordSets()` implementation; subclasses may override
19
+ * if specialized combine logic is needed (unlikely for Turkic languages).
20
+ *
21
+ * @abstract
22
+ * @extends GreedyScaleLanguage
23
+ */
24
+ export class TurkicLanguage extends GreedyScaleLanguage {
25
+ }
26
+ import { GreedyScaleLanguage } from './greedy-scale-language.js';
@@ -1,10 +1,4 @@
1
- import GreedyScaleLanguage from './greedy-scale-language.js'
2
-
3
- /**
4
- * @typedef {Object} TurkicWordPair
5
- * @property {string} word - The Turkic word or phrase
6
- * @property {bigint} value - The numeric value represented by the word
7
- */
1
+ import { GreedyScaleLanguage } from './greedy-scale-language.js'
8
2
 
9
3
  /**
10
4
  * Base class for Turkic languages with shared grammar patterns.
@@ -15,49 +9,51 @@ import GreedyScaleLanguage from './greedy-scale-language.js'
15
9
  * - Simple multiplication/addition logic
16
10
  * - Consistent magnitude handling
17
11
  * - Inherits decimal handling from AbstractLanguage via GreedyScaleLanguage
18
- * (supports both grouped and per-digit modes via the `convertDecimalsPerDigit` class property).
12
+ * (supports both grouped and per-digit modes via the `usePerDigitDecimals` class property).
19
13
  *
20
14
  * Used by: Turkish (TR), Azerbaijani (AZ)
21
15
  *
22
16
  * Subclasses MUST define (from GreedyScaleLanguage requirements):
23
- * - `scaleWordPairs` array of [value, word] pairs as a class property (ordered descending by value).
17
+ * - `scaleWords` array of [value, word] tuples as a class property (ordered descending by value).
24
18
  * Optionally, language-specific class properties (e.g., `negativeWord`, `zeroWord`, `decimalSeparatorWord`, `wordSeparator`).
25
19
  *
26
- * TurkicLanguage provides a default `mergeScales()` implementation; subclasses may override
27
- * if specialized merge logic is needed (unlikely for Turkic languages).
20
+ * TurkicLanguage provides a default `combineWordSets()` implementation; subclasses may override
21
+ * if specialized combine logic is needed (unlikely for Turkic languages).
28
22
  *
29
23
  * @abstract
30
24
  * @extends GreedyScaleLanguage
31
25
  */
32
- class TurkicLanguage extends GreedyScaleLanguage {
26
+ export class TurkicLanguage extends GreedyScaleLanguage {
27
+ // ============================================================================
28
+ // Inherited Implementation (overrides GreedyScaleLanguage)
29
+ // ============================================================================
30
+
33
31
  /**
34
- * Merges two adjacent word-number pairs according to Turkic grammar rules.
32
+ * Combines two adjacent word-sets according to Turkic grammar rules.
35
33
  *
36
34
  * Shared Turkic patterns:
37
35
  * - Implicit 'bir' (one) before hundreds and thousands
38
36
  * - Space separator (wordSeparator property) for all combinations
39
- * - Multiplies when right > left (crossing magnitude boundary)
37
+ * - Multiplies when following > preceding (crossing magnitude boundary)
40
38
  * - Adds otherwise (combining same-magnitude components)
41
39
  *
42
- * @param {Object} leftPair The left operand as `{ word: bigint }`.
43
- * @param {Object} rightPair The right operand as `{ word: bigint }`.
44
- * @returns {Object} Merged pair with combined word and resulting number (bigint).
40
+ * @param {Object} preceding Preceding word-set as { word: bigint }.
41
+ * @param {Object} following Following word-set as { word: bigint }.
42
+ * @returns {Object} Combined word-set with merged word and resulting number.
45
43
  */
46
- mergeScales (leftPair, rightPair) {
47
- const [[leftWord, leftNumber]] = Object.entries(leftPair)
48
- const [[rightWord, rightNumber]] = Object.entries(rightPair)
44
+ combineWordSets (preceding, following) {
45
+ const [[precedingWord, precedingValue]] = Object.entries(preceding)
46
+ const [[followingWord, followingValue]] = Object.entries(following)
49
47
 
50
48
  // Implicit 'bir' (one) before certain magnitudes:
51
49
  // Omit '1' before hundreds (100n) and thousands (1000n) to form natural combinations
52
- if (leftNumber === 1n && (rightNumber <= 100n || rightNumber === 1000n)) {
53
- return rightPair // Return just the magnitude word (e.g., "yüz", not "bir yüz")
50
+ if (precedingValue === 1n && (followingValue <= 100n || followingValue === 1000n)) {
51
+ return following // Return just the magnitude word (e.g., "yüz", not "bir yüz")
54
52
  }
55
53
 
56
54
  // Combine numbers with space separator (wordSeparator from GreedyScaleLanguage):
57
55
  // Multiply when crossing magnitude boundary, add otherwise
58
- const mergedNumber = rightNumber > leftNumber ? leftNumber * rightNumber : leftNumber + rightNumber
59
- return { [`${leftWord}${this.wordSeparator}${rightWord}`]: mergedNumber }
56
+ const resultNumber = followingValue > precedingValue ? precedingValue * followingValue : precedingValue + followingValue
57
+ return { [`${precedingWord}${this.wordSeparator}${followingWord}`]: resultNumber }
60
58
  }
61
59
  }
62
-
63
- export default TurkicLanguage
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Arabic language converter.
3
+ *
4
+ * Supports:
5
+ * - Gender agreement (masculine/feminine forms)
6
+ * - Complex pluralization (singular/dual/plural)
7
+ * - Traditional Arabic number naming conventions
8
+ * - Right-to-left text orientation
9
+ */
10
+ export class Arabic extends AbstractLanguage {
11
+ constructor(options?: {});
12
+ tensWords: string[];
13
+ hundredsWords: string[];
14
+ scaleWords: string[];
15
+ scaleAppendedWords: string[];
16
+ scalePluralWords: string[];
17
+ dualWords: string[];
18
+ dualAppendedWords: string[];
19
+ ones: {
20
+ masculine: string[];
21
+ feminine: string[];
22
+ };
23
+ /** Selects masculine or feminine number forms based on options. */
24
+ get selectedOnes(): string[];
25
+ /** Converts a 3-digit segment (0-999) to Arabic words with gender/plural rules. */
26
+ segmentToWords(groupNumber: any, groupLevel: any, fullNumber: any): string;
27
+ /** Converts integer part to Arabic words by processing 3-digit groups. */
28
+ integerToWords(integerPart: any): string;
29
+ }
30
+ import { AbstractLanguage } from '../classes/abstract-language.js';
@@ -1,129 +1,63 @@
1
- import AbstractLanguage from '../classes/abstract-language.js'
2
-
3
- /**
4
- * @typedef {Object} ArabicOptions
5
- * @property {string} [negativeWord='ناقص'] Word for negative numbers (minus).
6
- * @property {boolean} [feminine=false] Use feminine forms for numbers.
7
- */
1
+ import { AbstractLanguage } from '../classes/abstract-language.js'
8
2
 
9
3
  /**
10
4
  * Arabic language converter.
11
5
  *
12
- * Converts numbers to Arabic words with full grammatical support:
6
+ * Supports:
13
7
  * - Gender agreement (masculine/feminine forms)
14
- * - Complex pluralization rules (singular, dual, plural forms)
15
- * - Special handling for hundreds, thousands, millions, etc.
16
- * - Right-to-left text orientation
8
+ * - Complex pluralization (singular/dual/plural)
17
9
  * - Traditional Arabic number naming conventions
18
- *
19
- * Key Features:
20
- * - Gender-aware number forms (واحد masculine vs واحدة feminine)
21
- * - Dual forms: اثنان/اثنتان (two masculine/feminine)
22
- * - Complex rule system for numbers 3-10 (requiring feminine when referring to countables)
23
- * - Group-based algorithm: splits number by powers of 1000 (ones, thousands, millions, billions)
24
- * - Tanween (nunation) for indefinite numbers
25
- * - Sophisticated pluralization with singular, dual, and plural forms
26
- *
27
- * Algorithm:
28
- * 1. Break number into groups of 3 digits (right to left)
29
- * 2. For each non-zero group, convert to words using gender and plural rules
30
- * 3. Append the appropriate magnitude word (ألف/مليون/مليار) with proper plural form
31
- * 4. Join all groups with spaces
32
- *
33
- * Features:
34
- * - Support for gender-aware number forms
35
- * - Proper handling of Arabic dual forms (اثنان/اثنتان)
36
- * - Complex group processing for large numbers
37
10
  * - Right-to-left text orientation
38
- * - Traditional Arabic number naming conventions
39
11
  */
40
12
  export class Arabic extends AbstractLanguage {
13
+ negativeWord = 'ناقص'
41
14
  decimalSeparatorWord = 'فاصلة'
42
15
  zeroWord = 'صفر'
43
- arabicTens = ['عشرون', 'ثلاثون', 'أربعون', 'خمسون', 'ستون', 'سبعون', 'ثمانون', 'تسعون']
44
- arabicHundreds = ['', 'مائة', 'مئتان', 'ثلاثمائة', 'أربعمائة', 'خمسمائة', 'ستمائة', 'سبعمائة', 'ثمانمائة', 'تسعمائة']
45
- arabicAppendedTwos = ['مئتا', 'ألفا', 'مليونا', 'مليارا', 'تريليونا', 'كوادريليونا', 'كوينتليونا', 'سكستيليونا']
46
- arabicTwos = ['مئتان', 'ألفان', 'مليونان', 'ملياران', 'تريليونان', 'كوادريليونان', 'كوينتليونان', 'سكستيليونان']
47
- arabicGroup = ['مائة', 'ألف', 'مليون', 'مليار', 'تريليون', 'كوادريليون', 'كوينتليون', 'سكستيليون']
48
- arabicAppendedGroup = ['', 'ألفاً', 'مليوناً', 'ملياراً', 'تريليوناً', 'كوادريليوناً', 'كوينتليوناً', 'سكستيليوناً']
49
- arabicPluralGroups = ['', 'آلاف', 'ملايين', 'مليارات', 'تريليونات', 'كوادريليونات', 'كوينتليونات', 'سكستيليونات']
16
+
17
+ tensWords = ['عشرون', 'ثلاثون', 'أربعون', 'خمسون', 'ستون', 'سبعون', 'ثمانون', 'تسعون']
18
+ hundredsWords = ['', 'مائة', 'مئتان', 'ثلاثمائة', 'أربعمائة', 'خمسمائة', 'ستمائة', 'سبعمائة', 'ثمانمائة', 'تسعمائة']
19
+
20
+ // Magnitude words with three forms: singular, appended (tanween), plural
21
+ scaleWords = ['مائة', 'ألف', 'مليون', 'مليار', 'تريليون', 'كوادريليون', 'كوينتليون', 'سكستيليون']
22
+ scaleAppendedWords = ['', 'ألفاً', 'مليوناً', 'ملياراً', 'تريليوناً', 'كوادريليوناً', 'كوينتليوناً', 'سكستيليوناً']
23
+ scalePluralWords = ['', 'آلاف', 'ملايين', 'مليارات', 'تريليونات', 'كوادريليونات', 'كوينتليونات', 'سكستيليونات']
24
+
25
+ // Dual forms (Arabic has singular, dual, plural)
26
+ dualWords = ['مئتان', 'ألفان', 'مليونان', 'ملياران', 'تريليونان', 'كوادريليونان', 'كوينتليونان', 'سكستيليونان']
27
+ dualAppendedWords = ['مئتا', 'ألفا', 'مليونا', 'مليارا', 'تريليونا', 'كوادريليونا', 'كوينتليونا', 'سكستيليونا']
28
+
29
+ // Gender-specific number words (1-19)
50
30
  ones = {
51
31
  masculine: [
52
- 'واحد',
53
- 'اثنان',
54
- 'ثلاثة',
55
- 'أربعة',
56
- 'خمسة',
57
- 'ستة',
58
- 'سبعة',
59
- 'ثمانية',
60
- 'تسعة',
61
- 'عشرة',
62
- 'أحد عشر',
63
- 'اثنا عشر',
64
- 'ثلاثة عشر',
65
- 'أربعة عشر',
66
- 'خمسة عشر',
67
- 'ستة عشر',
68
- 'سبعة عشر',
69
- 'ثمانية عشر',
70
- 'تسعة عشر'
32
+ 'واحد', 'اثنان', 'ثلاثة', 'أربعة', 'خمسة', 'ستة', 'سبعة', 'ثمانية', 'تسعة', 'عشرة',
33
+ 'أحد عشر', 'اثنا عشر', 'ثلاثة عشر', 'أربعة عشر', 'خمسة عشر', 'ستة عشر', 'سبعة عشر', 'ثمانية عشر', 'تسعة عشر'
71
34
  ],
72
35
  feminine: [
73
- 'واحدة',
74
- 'اثنتان',
75
- 'ثلاث',
76
- 'أربع',
77
- 'خمس',
78
- 'ست',
79
- 'سبع',
80
- 'ثمان',
81
- 'تسع',
82
- 'عشر',
83
- 'إحدى عشرة',
84
- 'اثنتا عشرة',
85
- 'ثلاث عشرة',
86
- 'أربع عشرة',
87
- 'خمس عشرة',
88
- 'ست عشرة',
89
- 'سبع عشرة',
90
- 'ثماني عشرة',
91
- 'تسع عشرة'
36
+ 'واحدة', 'اثنتان', 'ثلاث', 'أربع', 'خمس', 'ست', 'سبع', 'ثمان', 'تسع', 'عشر',
37
+ 'إحدى عشرة', 'اثنتا عشرة', 'ثلاث عشرة', 'أربع عشرة', 'خمس عشرة', 'ست عشرة', 'سبع عشرة', 'ثماني عشرة', 'تسع عشرة'
92
38
  ]
93
39
  }
94
40
 
95
- /**
96
- * Initializes the Arabic converter with language-specific options.
97
- *
98
- * @param {ArabicOptions} [options={}] Configuration options.
99
- */
100
- constructor ({ negativeWord = 'ناقص', feminine = false } = {}) {
41
+ constructor (options = {}) {
101
42
  super()
102
43
 
103
- this.feminine = feminine
104
- this.negativeWord = negativeWord
44
+ this.setOptions({
45
+ gender: 'masculine'
46
+ }, options)
105
47
 
106
- this.selectedOnes = this.ones[this.feminine ? 'feminine' : 'masculine']
48
+ // Allow custom negativeWord via options
49
+ if (options.negativeWord !== undefined) {
50
+ this.negativeWord = options.negativeWord
51
+ }
107
52
  }
108
53
 
109
- /**
110
- * Returns the feminine status of a given digit (1-9).
111
- *
112
- * @param {number} digit - The digit to check (1-9).
113
- * @returns {string} The word form of the digit based on feminine status.
114
- */
115
- digitFeminineStatus (digit) {
116
- return this.selectedOnes[digit - 1]
54
+ /** Selects masculine or feminine number forms based on options. */
55
+ get selectedOnes () {
56
+ return this.ones[this.options.gender === 'feminine' ? 'feminine' : 'masculine']
117
57
  }
118
58
 
119
- /**
120
- * Processes the Arabic group number and returns the corresponding Arabic representation.
121
- * @param {number} groupNumber - The number to process. (Range: 1-999)
122
- * @param {number} groupLevel - Group level to process. (See example)
123
- * @returns {string} The Arabic representation of the group number.
124
- * @example 12345678 is processed in blocks of 3: '678' (group 0), '345' (group 1), '12' (group 2).
125
- */
126
- processArabicGroup (groupNumber, groupLevel, fullNumber) {
59
+ /** Converts a 3-digit segment (0-999) to Arabic words with gender/plural rules. */
60
+ segmentToWords (groupNumber, groupLevel, fullNumber) {
127
61
  const tens = groupNumber % 100
128
62
  const hundredsRaw = groupNumber / 100
129
63
  const hundreds = Math.trunc(hundredsRaw)
@@ -132,9 +66,9 @@ export class Arabic extends AbstractLanguage {
132
66
  // Process hundreds
133
67
  if (hundreds > 0) {
134
68
  if (tens === 0 && hundreds === 2) {
135
- returnValue = this.arabicTwos[0]
69
+ returnValue = this.dualWords[0]
136
70
  } else {
137
- const hundredsWord = this.arabicHundreds[hundreds]
71
+ const hundredsWord = this.hundredsWords[hundreds]
138
72
  if (hundredsWord) {
139
73
  returnValue = hundredsWord
140
74
  if (tens !== 0) {
@@ -152,12 +86,12 @@ export class Arabic extends AbstractLanguage {
152
86
  const numValue = Number(fullNumber)
153
87
  const pow = Math.trunc(Math.log10(numValue))
154
88
  if (pow % 3 === 0 && fullNumber === BigInt(2 * Math.pow(10, pow))) {
155
- returnValue = groupNumber === 2 ? this.arabicTwos[groupLevel] : this.arabicAppendedTwos[groupLevel]
89
+ returnValue = groupNumber === 2 ? this.dualWords[groupLevel] : this.dualAppendedWords[groupLevel]
156
90
  } else {
157
- returnValue = this.arabicTwos[groupLevel]
91
+ returnValue = this.dualWords[groupLevel]
158
92
  }
159
93
  } else if (tens === 1 && groupLevel > 0) {
160
- returnValue += this.arabicGroup[groupLevel]
94
+ returnValue += this.scaleWords[groupLevel]
161
95
  } else {
162
96
  returnValue += this.selectedOnes[tens - 1]
163
97
  }
@@ -169,24 +103,19 @@ export class Arabic extends AbstractLanguage {
169
103
  returnValue += this.selectedOnes[ones - 1]
170
104
  returnValue += ' و'
171
105
  }
172
- returnValue += this.arabicTens[tensIndex]
106
+ returnValue += this.tensWords[tensIndex]
173
107
  }
174
108
  }
175
109
 
176
110
  return returnValue
177
111
  }
178
112
 
179
- /**
180
- * Converts a number to its cardinal representation in Arabic.
181
- * It process by blocks of 3 digits.
182
- * @param {bigint} number - The number to convert.
183
- * @returns {string} The cardinal representation of the number in Arabic.
184
- */
185
- convertWholePart (number) {
186
- if (number === 0n) {
113
+ /** Converts integer part to Arabic words by processing 3-digit groups. */
114
+ integerToWords (integerPart) {
115
+ if (integerPart === 0n) {
187
116
  return this.zeroWord
188
117
  }
189
- let temp = number
118
+ let temp = integerPart
190
119
  let group = 0
191
120
  let result = ''
192
121
 
@@ -196,7 +125,7 @@ export class Arabic extends AbstractLanguage {
196
125
  temp = temp / 1000n
197
126
 
198
127
  if (numberToProcess > 0) {
199
- const groupDescription = this.processArabicGroup(numberToProcess, group, number)
128
+ const groupDescription = this.segmentToWords(numberToProcess, group, integerPart)
200
129
 
201
130
  if (groupDescription) {
202
131
  // Add group name for thousands, millions, etc.
@@ -208,11 +137,11 @@ export class Arabic extends AbstractLanguage {
208
137
  if (numberToProcess > 2) {
209
138
  const remainder = numberToProcess % 100
210
139
  if (remainder === 1) {
211
- result = this.arabicGroup[group] + ' ' + result
140
+ result = this.scaleWords[group] + ' ' + result
212
141
  } else if (numberToProcess >= 3 && numberToProcess <= 10) {
213
- result = this.arabicPluralGroups[group] + ' ' + result
142
+ result = this.scalePluralWords[group] + ' ' + result
214
143
  } else {
215
- result = (result ? this.arabicAppendedGroup[group] : this.arabicGroup[group]) + ' ' + result
144
+ result = (result ? this.scaleAppendedWords[group] : this.scaleWords[group]) + ' ' + result
216
145
  }
217
146
  }
218
147
  }
@@ -228,16 +157,3 @@ export class Arabic extends AbstractLanguage {
228
157
  return result.replace(/\s+/g, ' ').trim()
229
158
  }
230
159
  }
231
-
232
- /**
233
- * Converts a number to Arabic cardinal (written) form.
234
- *
235
- * @param {number|string|bigint} value The number to convert.
236
- * @param {ArabicOptions} [options={}] Configuration options.
237
- * @returns {string} The number expressed in Arabic words.
238
- * @throws {TypeError} If value is NaN or invalid type.
239
- * @throws {Error} If value is an invalid number string.
240
- */
241
- export default function convertToWords (value, options = {}) {
242
- return new Arabic(options).convertToWords(value)
243
- }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Azerbaijani language converter.
3
+ *
4
+ * Supports:
5
+ * - Implicit "bir" (one) omission before hundreds and thousands
6
+ * - Turkic language number patterns
7
+ * - Large numbers up to quintillion
8
+ */
9
+ export class Azerbaijani extends TurkicLanguage {
10
+ scaleWords: (string | bigint)[][];
11
+ }
12
+ import { TurkicLanguage } from '../classes/turkic-language.js';
@@ -1,18 +1,19 @@
1
- import TurkicLanguage from '../classes/turkic-language.js'
1
+ import { TurkicLanguage } from '../classes/turkic-language.js'
2
2
 
3
3
  /**
4
4
  * Azerbaijani language converter.
5
5
  *
6
- * Inherits from TurkicLanguage shared patterns:
7
- * - Space-separated number combinations
8
- * - Omits '1' before hundreds and thousands
9
- * - Supports flexible word spacing configuration
6
+ * Supports:
7
+ * - Implicit "bir" (one) omission before hundreds and thousands
8
+ * - Turkic language number patterns
9
+ * - Large numbers up to quintillion
10
10
  */
11
11
  export class Azerbaijani extends TurkicLanguage {
12
12
  negativeWord = 'mənfi'
13
13
  decimalSeparatorWord = 'nöqtə'
14
14
  zeroWord = 'sıfır'
15
- scaleWordPairs = [[1_000_000_000_000_000_000n, 'kentilyon'],
15
+
16
+ scaleWords = [[1_000_000_000_000_000_000n, 'kentilyon'],
16
17
  [1_000_000_000_000_000n, 'katrilyon'],
17
18
  [1_000_000_000_000n, 'trilyon'],
18
19
  [1_000_000_000n, 'milyar'],
@@ -39,20 +40,3 @@ export class Azerbaijani extends TurkicLanguage {
39
40
  [1n, 'bir'],
40
41
  [0n, 'sıfır']]
41
42
  }
42
-
43
- /**
44
- * Converts a number to Azerbaijani cardinal (written) form.
45
- *
46
- * @param {number|string|bigint} value The number to convert.
47
- * @param {Object} [options] Conversion options (see AZ class).
48
- * @returns {string} The number expressed in Azerbaijani words.
49
- * @throws {TypeError} If value is NaN or invalid type.
50
- * @throws {Error} If value is an invalid number string.
51
- *
52
- * @example
53
- * convertToWords(42, { lang: 'az' }); // 'qırx iki'
54
- * convertToWords(1000, { lang: 'az' }); // 'min'
55
- */
56
- export default function convertToWords (value, options = {}) {
57
- return new Azerbaijani(options).convertToWords(value)
58
- }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Bangla language converter.
3
+ *
4
+ * Supports:
5
+ * - Indian numbering system (হাজার, লাখ, কোটি)
6
+ * - Bangla script (Bengali)
7
+ * - Complete word forms for 0-99
8
+ */
9
+ export class Bangla extends SouthAsianLanguage {
10
+ }
11
+ import { SouthAsianLanguage } from '../classes/south-asian-language.js';
@@ -1,11 +1,20 @@
1
- import SouthAsianLanguage from '../classes/south-asian-language.js'
1
+ import { SouthAsianLanguage } from '../classes/south-asian-language.js'
2
2
 
3
- class Bengali extends SouthAsianLanguage {
3
+ /**
4
+ * Bangla language converter.
5
+ *
6
+ * Supports:
7
+ * - Indian numbering system (হাজার, লাখ, কোটি)
8
+ * - Bangla script (Bengali)
9
+ * - Complete word forms for 0-99
10
+ */
11
+ export class Bangla extends SouthAsianLanguage {
4
12
  negativeWord = 'মাইনাস'
5
13
  decimalSeparatorWord = 'দশমিক'
6
14
  zeroWord = 'শূন্য'
7
15
  hundredWord = 'শত'
8
- belowHundred = [
16
+
17
+ belowHundredWords = [
9
18
  'শূন্য',
10
19
  'এক',
11
20
  'দুই',
@@ -120,7 +129,3 @@ class Bengali extends SouthAsianLanguage {
120
129
  'শঙ্খ'
121
130
  ]
122
131
  }
123
-
124
- export default function convertToWords (value, options = {}) {
125
- return new Bengali(options).convertToWords(value)
126
- }
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Czech language converter.
3
+ *
4
+ * Supports:
5
+ * - Three-form pluralization (one/few/many)
6
+ * - Dynamic decimal separator (celá/celé/celých)
7
+ * - Gender agreement in number words
8
+ */
9
+ export class Czech extends SlavicLanguage {
10
+ constructor(options?: {});
11
+ onesWords: {
12
+ 1: string;
13
+ 2: string;
14
+ 3: string;
15
+ 4: string;
16
+ 5: string;
17
+ 6: string;
18
+ 7: string;
19
+ 8: string;
20
+ 9: string;
21
+ };
22
+ onesFeminineWords: {
23
+ 1: string;
24
+ 2: string;
25
+ 3: string;
26
+ 4: string;
27
+ 5: string;
28
+ 6: string;
29
+ 7: string;
30
+ 8: string;
31
+ 9: string;
32
+ };
33
+ teensWords: {
34
+ 0: string;
35
+ 1: string;
36
+ 2: string;
37
+ 3: string;
38
+ 4: string;
39
+ 5: string;
40
+ 6: string;
41
+ 7: string;
42
+ 8: string;
43
+ 9: string;
44
+ };
45
+ twentiesWords: {
46
+ 2: string;
47
+ 3: string;
48
+ 4: string;
49
+ 5: string;
50
+ 6: string;
51
+ 7: string;
52
+ 8: string;
53
+ 9: string;
54
+ };
55
+ hundredsWords: {
56
+ 1: string;
57
+ 2: string;
58
+ 3: string;
59
+ 4: string;
60
+ 5: string;
61
+ 6: string;
62
+ 7: string;
63
+ 8: string;
64
+ 9: string;
65
+ };
66
+ pluralForms: {
67
+ 1: string[];
68
+ 2: string[];
69
+ 3: string[];
70
+ 4: string[];
71
+ 5: string[];
72
+ 6: string[];
73
+ 7: string[];
74
+ 8: string[];
75
+ 9: string[];
76
+ 10: string[];
77
+ };
78
+ /** Returns decimal separator word based on integer part (celá/celé/celých). */
79
+ get decimalSeparatorWord(): "celá" | "celé" | "celých";
80
+ /**
81
+ * Override toWords to cache integer part before decimal separator is accessed.
82
+ */
83
+ toWords(isNegative: any, integerPart: any, decimalPart: any): string;
84
+ /** Selects Czech plural form: 1 = singular, 2-4 = few, else = many. */
85
+ pluralize(n: any, forms: any): any;
86
+ #private;
87
+ }
88
+ import { SlavicLanguage } from '../classes/slavic-language.js';