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,36 +1,18 @@
1
- import SlavicLanguage from '../classes/slavic-language.js'
2
-
3
- /**
4
- * @typedef {Object} SlavicOptions
5
- * @property {boolean} [feminine=false] Use feminine forms for numbers.
6
- */
1
+ import { SlavicLanguage } from '../classes/slavic-language.js'
7
2
 
8
3
  /**
9
4
  * Czech language converter.
10
5
  *
11
- * Implements Czech number words using the Slavic language pattern:
12
- * - Czech number words (jedna, dva, tři, čtyři, pět...)
13
- * - Slavic three-form pluralization (tisíc/tisíce/tisíc)
14
- * - Gender agreement for numbers 1-2
15
- * - Czech-specific number word endings
16
- *
17
- * Key Features:
18
- * - Three-form pluralization system shared across Slavic languages
19
- * * Form 1 (singular): 1 (e.g., "tisíc")
20
- * * Form 2 (few): 2-4, 22-24, 32-34... excluding teens (e.g., "tisíce")
21
- * * Form 3 (many): all other numbers (e.g., "tisíc")
22
- * - Chunk-based decomposition (splits into groups of 3 digits: ones, thousands, millions, etc.)
23
- * - Large number handling via thousands[] array with indexed [singular, few, many] forms
24
- *
25
- * Inherits from SlavicLanguage:
26
- * - Complex pluralization rules (one/few/many forms)
27
- * - Group-based large number handling (chunk decomposition via splitByX())
28
- * - Proper declension patterns via pluralize() method
6
+ * Supports:
7
+ * - Three-form pluralization (one/few/many)
8
+ * - Dynamic decimal separator (celá/celé/celých)
9
+ * - Gender agreement in number words
29
10
  */
30
11
  export class Czech extends SlavicLanguage {
31
12
  negativeWord = 'mínus'
32
13
  zeroWord = 'nula'
33
- ones = {
14
+
15
+ onesWords = {
34
16
  1: 'jedna',
35
17
  2: 'dva',
36
18
  3: 'tři',
@@ -42,7 +24,19 @@ export class Czech extends SlavicLanguage {
42
24
  9: 'devět'
43
25
  }
44
26
 
45
- tens = {
27
+ onesFeminineWords = {
28
+ 1: 'jedna',
29
+ 2: 'dvě',
30
+ 3: 'tři',
31
+ 4: 'čtyři',
32
+ 5: 'pět',
33
+ 6: 'šest',
34
+ 7: 'sedm',
35
+ 8: 'osm',
36
+ 9: 'devět'
37
+ }
38
+
39
+ teensWords = {
46
40
  0: 'deset',
47
41
  1: 'jedenáct',
48
42
  2: 'dvanáct',
@@ -55,7 +49,7 @@ export class Czech extends SlavicLanguage {
55
49
  9: 'devatenáct'
56
50
  }
57
51
 
58
- twenties = {
52
+ twentiesWords = {
59
53
  2: 'dvacet',
60
54
  3: 'třicet',
61
55
  4: 'čtyřicet',
@@ -66,7 +60,7 @@ export class Czech extends SlavicLanguage {
66
60
  9: 'devadesát'
67
61
  }
68
62
 
69
- hundreds = {
63
+ hundredsWords = {
70
64
  1: 'sto',
71
65
  2: 'dvě stě',
72
66
  3: 'tři sta',
@@ -78,7 +72,7 @@ export class Czech extends SlavicLanguage {
78
72
  9: 'devět set'
79
73
  }
80
74
 
81
- thousands = {
75
+ pluralForms = {
82
76
  1: ['tisíc', 'tisíce', 'tisíc'], // 10^ 3
83
77
  2: ['milion', 'miliony', 'milionů'], // 10^ 6
84
78
  3: ['miliarda', 'miliardy', 'miliard'], // 10^ 9
@@ -92,25 +86,29 @@ export class Czech extends SlavicLanguage {
92
86
  }
93
87
 
94
88
  /**
95
- * Returns the Czech word for the decimal separator based on the whole number.
96
- *
97
- * @returns {string} The Czech word for the decimal separator.
89
+ * Czech omits "one" before scale words.
90
+ * e.g., 1000 is "tisíc" not "jedna tisíc"
98
91
  */
92
+ omitOneBeforeScale = true
93
+
94
+ /**
95
+ * Cached integer part for decimal separator word selection.
96
+ * Set by toWords() before calling super.toWords().
97
+ * @private
98
+ */
99
+ #integerPart = 0n
100
+
101
+ /** Returns decimal separator word based on integer part (celá/celé/celých). */
99
102
  get decimalSeparatorWord () {
100
- if (this.cachedWholeNumber === 0n || this.cachedWholeNumber === 1n) {
103
+ if (this.#integerPart === 0n || this.#integerPart === 1n) {
101
104
  return 'celá'
102
- } else if (this.cachedWholeNumber >= 2n && this.cachedWholeNumber <= 4n) {
105
+ } else if (this.#integerPart >= 2n && this.#integerPart <= 4n) {
103
106
  return 'celé'
104
107
  } else {
105
108
  return 'celých'
106
109
  }
107
110
  }
108
111
 
109
- /**
110
- * Initializes the Czech converter with language-specific options.
111
- *
112
- * @param {SlavicOptions} [options={}] Configuration options (inherited from SlavicLanguage).
113
- */
114
112
  constructor (options = {}) {
115
113
  super(options)
116
114
 
@@ -119,17 +117,14 @@ export class Czech extends SlavicLanguage {
119
117
  }
120
118
 
121
119
  /**
122
- * Implements Czech-specific three-form pluralization rules.
123
- *
124
- * Czech three-form system:
125
- * - Form 1 (singular): exactly n=1 (e.g., "tisíc")
126
- * - Form 2 (few): n ends in 2-4, excluding teens (22-24, 32-34...) (e.g., "tisíce")
127
- * - Form 3 (many): all other numbers (e.g., "tisíc" for 0, 5+)
128
- *
129
- * @param {bigint} n The number to classify.
130
- * @param {Array<string>} forms Array of [singular, few, many] word forms.
131
- * @returns {string} The appropriate form for the number n.
120
+ * Override toWords to cache integer part before decimal separator is accessed.
132
121
  */
122
+ toWords (isNegative, integerPart, decimalPart) {
123
+ this.#integerPart = integerPart
124
+ return super.toWords(isNegative, integerPart, decimalPart)
125
+ }
126
+
127
+ /** Selects Czech plural form: 1 = singular, 2-4 = few, else = many. */
133
128
  pluralize (n, forms) {
134
129
  if (n === 1n) {
135
130
  return forms[0]
@@ -145,68 +140,4 @@ export class Czech extends SlavicLanguage {
145
140
 
146
141
  return forms[2]
147
142
  }
148
-
149
- /**
150
- * Converts a whole number to Czech cardinal form.
151
- *
152
- * Algorithm (chunk-based decomposition):
153
- * 1. Split number into chunks of 3 digits (right-to-left): ones, thousands, millions, etc.
154
- * 2. For each non-zero chunk:
155
- * a. Extract hundreds digit (n3), tens digit (n2), ones digit (n1)
156
- * b. Add hundreds word (e.g., "sto", "dvě stě")
157
- * c. Add tens/ones (handles teens 10-19 separately from compound tens)
158
- * d. Add pluralized magnitude word (e.g., "tisíce", "miliony")
159
- * 3. Join all words with spaces
160
- *
161
- * Example: 1234 → chunks [1, 234] → "jeden tisíc dvěstěčtyřicet"
162
- * - Chunk 1 (index=1, thousands): "jeden" + "tisíc"
163
- * - Chunk 234 (index=0): "dvě stě" + "třicet" + "čtyři"
164
- *
165
- * Special case: When chunk=1 at thousands+ levels, omit the ones word to avoid
166
- * redundancy with the pluralized magnitude (e.g., just "tisíc" not "jeden tisíc").
167
- *
168
- * @param {bigint} number The whole number to convert.
169
- * @returns {string} The number expressed in Czech words.
170
- */
171
- convertWholePart (number) {
172
- if (number === 0n) {
173
- return this.zeroWord
174
- }
175
- const words = []
176
- const chunks = this.splitByX(number.toString(), 3)
177
- let index = chunks.length
178
- for (const x of chunks) {
179
- index--
180
- if (x === 0n) continue
181
- const [n1, n2, n3] = this.getDigits(x)
182
- if (n3 > 0n) {
183
- words.push(this.hundreds[n3])
184
- }
185
- if (n2 > 1n) {
186
- words.push(this.twenties[n2])
187
- }
188
- if (n2 === 1n) {
189
- words.push(this.tens[n1])
190
- } else if (n1 > 0n && !(index > 0 && x === 1n)) {
191
- words.push(this.ones[n1])
192
- }
193
- if (index > 0) {
194
- words.push(this.pluralize(x, this.thousands[index]))
195
- }
196
- }
197
- return words.join(' ')
198
- }
199
- }
200
-
201
- /**
202
- * Converts a number to Czech cardinal (written) form.
203
- *
204
- * @param {number|string|bigint} value The number to convert.
205
- * @param {SlavicOptions} [options={}] Configuration options.
206
- * @returns {string} The number expressed in Czech words.
207
- * @throws {TypeError} If value is NaN or invalid type.
208
- * @throws {Error} If value is an invalid number string.
209
- */
210
- export default function convertToWords (value, options = {}) {
211
- return new Czech(options).convertToWords(value)
212
143
  }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Danish language converter.
3
+ *
4
+ * Supports:
5
+ * - Vigesimal (base-20) number system
6
+ * - Units-before-tens ordering (e.g., "tre-og-tyve" = 23)
7
+ * - Optional ordinal numbers via ordFlag option
8
+ */
9
+ export class Danish extends GreedyScaleLanguage {
10
+ constructor(options?: {});
11
+ scaleWords: (string | bigint)[][];
12
+ /** Combines two word-sets with Danish vigesimal and reversal rules. */
13
+ combineWordSets(preceding: any, following: any): any;
14
+ }
15
+ import { GreedyScaleLanguage } from '../classes/greedy-scale-language.js';
@@ -1,31 +1,19 @@
1
- import GreedyScaleLanguage from '../classes/greedy-scale-language.js'
2
-
3
- /**
4
- * @typedef {Object} DanishOptions
5
- * @property {boolean} [ordFlag=false] Enable ordinal number conversion.
6
- */
1
+ import { GreedyScaleLanguage } from '../classes/greedy-scale-language.js'
7
2
 
8
3
  /**
9
4
  * Danish language converter.
10
5
  *
11
- * GreedyScaleLanguage with Danish-specific extensions:
12
- * - Unique vigesimal (base-20) number system for 50-90
13
- * - Special composition rules ("og" for "and" between units and tens)
14
- * - Reverse digit order (e.g., "fem-og-tyve" = five-and-twenty = 25)
15
- * - Support for ordinal numbers via ordFlag option
16
- *
17
- * Key Features:
18
- * - Vigesimal tens: halvtreds (50), treds (60), halvfjerds (70), firs (80), halvfems (90)
19
- * - Units-before-tens pattern (e.g., "tre-og-tyve" = 23)
20
- * - "et" prefix for hundreds/thousands (not "en")
21
- * - Optional ordinal number conversion via ordFlag option
22
- * - Inline merge logic tailored for Danish ordering
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
23
10
  */
24
11
  export class Danish extends GreedyScaleLanguage {
25
12
  negativeWord = 'minus'
26
13
  decimalSeparatorWord = 'komma'
27
14
  zeroWord = 'nul'
28
- scaleWordPairs = [
15
+
16
+ scaleWords = [
29
17
  [1_000_000_000_000_000_000_000_000_000n, 'quadrillarder'],
30
18
  [1_000_000_000_000_000_000_000_000n, 'quadrillioner'],
31
19
  [1_000_000_000_000_000_000_000n, 'trillarder'],
@@ -66,102 +54,67 @@ export class Danish extends GreedyScaleLanguage {
66
54
  [0n, 'nul']
67
55
  ]
68
56
 
69
- /**
70
- * Initializes the Danish converter with language-specific options.
71
- *
72
- * @param {DanishOptions} [options={}] Configuration options.
73
- */
74
- constructor ({ ordFlag = false } = {}) {
57
+ constructor (options = {}) {
75
58
  super()
76
59
 
77
- this.ordFlag = ordFlag
60
+ this.setOptions({
61
+ ordFlag: false
62
+ }, options)
78
63
  }
79
64
 
80
- /**
81
- * Merges two adjacent word-number pairs according to Danish grammar rules.
82
- * Danish uses complex vigesimal (base-20) patterns and reverse digit ordering.
83
- *
84
- * Key Danish patterns:
85
- * - Vigesimal tens: halvtreds(50), treds(60), halvfjerds(70), firs(80), halvfems(90)
86
- * - Units-before-tens order with "og" (and): "tre-og-tyve" (3 and 20 = 25)
87
- * - "et" prefix for hundreds/thousands (not "en")
88
- * - Space separators for large magnitudes (≥ millions)
89
- * - Ordinal support via this.ordFlag
90
- *
91
- * @param {Object} current The left operand as `{ word: bigint }`.
92
- * @param {Object} next The right operand as `{ word: bigint }`.
93
- * @returns {Object} Merged pair with combined word and resulting number (bigint).
94
- */
95
- mergeScales (current, next) {
96
- let cText = Object.keys(current)[0]
97
- let nText = Object.keys(next)[0]
98
- const cNumber = Object.values(current)[0] // BigInt (e.g., 1n, 100n, 1000n)
99
- const nNumber = Object.values(next)[0] // BigInt (e.g., magnitude level like 100n, 1000n)
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)
100
71
 
101
72
  // Prepend "et" to hundreds and thousands (not "en") for proper Danish form
102
- if (nNumber === 100n || nNumber === 1000n) {
103
- next = { [`et${nText}`]: nNumber }
73
+ if (followingValue === 100n || followingValue === 1000n) {
74
+ following = { [`et${followingWord}`]: followingValue }
104
75
  }
105
76
 
106
77
  // Implicit '1' handling: omit '1' before most magnitudes (except millions/ordinals)
107
- if (cNumber === 1n) {
108
- if (nNumber < 1_000_000n || this.ordFlag) {
109
- return next // Just the magnitude word (e.g., "hundrede" not "en hundrede")
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")
110
81
  }
111
- cText = 'en' // Explicit "en" (one) for millions and above
82
+ precedingWord = 'en' // Explicit "en" (one) for millions and above
112
83
  }
113
84
 
114
85
  // Multiplication across magnitude boundaries
115
- if (nNumber > cNumber) {
86
+ if (followingValue > precedingValue) {
116
87
  // Space for million+ (e.g., "en million", "to millioner")
117
- if (nNumber >= 1_000_000n) {
118
- cText += ' '
88
+ if (followingValue >= 1_000_000n) {
89
+ precedingWord += ' '
119
90
  }
120
- return { [`${cText}${nText}`]: cNumber * nNumber }
91
+ return { [`${precedingWord}${followingWord}`]: precedingValue * followingValue }
121
92
  }
122
93
 
123
94
  // Addition with separator rules:
124
95
  // "og" (and) for hundreds + smaller numbers
125
- if (cNumber >= 100n && cNumber < 1000n) {
126
- cText += ' og '
127
- } else if (cNumber >= 1000n && cNumber <= 100_000n) {
96
+ if (precedingValue >= 100n && precedingValue < 1000n) {
97
+ precedingWord += ' og '
98
+ } else if (precedingValue >= 1000n && precedingValue <= 100_000n) {
128
99
  // Special "e og" for thousands (e.g., "tusinde og tyve")
129
- cText += 'e og '
100
+ precedingWord += 'e og '
130
101
  }
131
102
 
132
103
  // Units-before-tens reversal (Danish vigesimal pattern):
133
104
  // For small units (< 10) with tens (10-99), swap order: "tre og tyve" (25)
134
- if (nNumber < 10n && cNumber > 10n && cNumber < 100n) {
135
- if (nNumber === 1n) {
136
- nText = 'en' // Convert 1 to "en" for vigesimal context
105
+ if (followingValue < 10n && precedingValue > 10n && precedingValue < 100n) {
106
+ if (followingValue === 1n) {
107
+ followingWord = 'en' // Convert 1 to "en" for vigesimal context
137
108
  }
138
109
  // Swap positions: units go after "og", tens go before
139
- const temporary = nText
140
- nText = cText
141
- cText = temporary + 'og'
142
- } else if (cNumber >= 1_000_000n) {
110
+ const temporary = followingWord
111
+ followingWord = precedingWord
112
+ precedingWord = temporary + 'og'
113
+ } else if (precedingValue >= 1_000_000n) {
143
114
  // Space for large magnitudes (millions+)
144
- cText += ' '
115
+ precedingWord += ' '
145
116
  }
146
117
 
147
- return { [`${cText}${nText}`]: cNumber + nNumber }
118
+ return { [`${precedingWord}${followingWord}`]: precedingValue + followingValue }
148
119
  }
149
120
  }
150
-
151
- /**
152
- * Converts a number to Danish cardinal (written) form.
153
- *
154
- * @param {number|string|bigint} value The number to convert.
155
- * @param {Object} [options] Conversion options (see Danish class options).
156
- * @param {boolean} [options.ordFlag=false] Enable ordinal number conversion.
157
- * @returns {string} The number expressed in Danish words.
158
- * @throws {TypeError} If value is NaN or invalid type.
159
- * @throws {Error} If value is an invalid number string.
160
- *
161
- * @example
162
- * convertToWords(25); // 'femogtyve' (five-and-twenty)
163
- * convertToWords(50); // 'halvtreds' (half-third-times-twenty)
164
- */
165
- export default function convertToWords (value, options = {}) {
166
- return new Danish(options).convertToWords(value)
167
- }
@@ -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';
@@ -1,19 +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
  * German language converter.
5
5
  *
6
- * Handles German grammatical features:
7
- * - "eins" vs "ein" and "eine" forms for 1
8
- * - Compound words without separators (e.g., "einundzwanzig" = 21)
9
- * - Million/Billion pluralization
10
- * - Special characters (e.g., "ü", "ö", "ß")
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)
11
10
  */
12
11
  export class German extends GreedyScaleLanguage {
13
12
  negativeWord = 'minus'
14
13
  decimalSeparatorWord = 'komma'
15
14
  zeroWord = 'null'
16
- scaleWordPairs = [
15
+
16
+ scaleWords = [
17
17
  [1_000_000_000_000_000_000_000_000_000n, 'Quadrilliarde'],
18
18
  [1_000_000_000_000_000_000_000_000n, 'Quadrillion'],
19
19
  [1_000_000_000_000_000_000_000n, 'Trilliarde'],
@@ -54,82 +54,48 @@ export class German extends GreedyScaleLanguage {
54
54
  [0n, 'null']
55
55
  ]
56
56
 
57
- /**
58
- * Merges two adjacent word-number pairs according to German grammar rules.
59
- *
60
- * German-specific rules:
61
- * - Implicit "eins": `mergeScales({ 'eins': 1n }, { 'hundert': 100n })` → `{ 'einhundert': 100n }`
62
- * - Compound words without separators (e.g., "einundzwanzig" = 21)
63
- * - Special handling for forms of 1 (eins/ein/eine) depending on context
64
- * - Pluralization of millions and higher: "Millionen", "Milliarden"
65
- * - Reordering of tens and units: `mergeScales({ 'zwanzig': 20n }, { 'eins': 1n })` → `{ 'einundzwanzig': 21n }`
66
- *
67
- * @param {Object} currentPair The left operand as `{ word: BigInt }`.
68
- * @param {Object} nextPair The right operand as `{ word: BigInt }`.
69
- * @returns {Object} Merged pair with combined word and resulting numeric value.
70
- *
71
- * @example
72
- * mergeScales({ 'eins': 1n }, { 'hundert': 100n }); // { 'einhundert': 100n }
73
- * mergeScales({ 'zwanzig': 20n }, { 'drei': 3n }); // { 'dreiundzwanzig': 23n }
74
- */
75
- mergeScales (currentPair, nextPair) {
76
- let currentWord = Object.keys(currentPair)[0]
77
- let nextWord = Object.keys(nextPair)[0]
78
- const currentNumber = Object.values(currentPair)[0]
79
- const nextNumber = Object.values(nextPair)[0]
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]
80
63
 
81
64
  // Handle form of 1: "eins" → "ein(e)" in certain contexts
82
- if (currentNumber === 1n) {
83
- if (nextNumber === 100n || nextNumber === 1000n) {
84
- return { [`ein${nextWord}`]: nextNumber }
65
+ if (precedingValue === 1n) {
66
+ if (followingValue === 100n || followingValue === 1000n) {
67
+ return { [`ein${followingWord}`]: followingValue }
85
68
  }
86
- if (nextNumber < 1_000_000n) {
87
- return nextPair
69
+ if (followingValue < 1_000_000n) {
70
+ return following
88
71
  }
89
- currentWord = 'eine'
72
+ precedingWord = 'eine'
90
73
  }
91
74
 
92
- if (nextNumber > currentNumber) {
75
+ if (followingValue > precedingValue) {
93
76
  // Multiply: apply pluralization rules for millions
94
- if (nextNumber >= 1_000_000n) {
95
- if (currentNumber > 1n) {
96
- nextWord += nextWord.at(-1) === 'e' ? 'n' : 'en'
77
+ if (followingValue >= 1_000_000n) {
78
+ if (precedingValue > 1n) {
79
+ followingWord += followingWord.at(-1) === 'e' ? 'n' : 'en'
97
80
  }
98
- currentWord += ' '
81
+ precedingWord += ' '
99
82
  }
100
- return { [`${currentWord}${nextWord}`]: currentNumber * nextNumber }
83
+ return { [`${precedingWord}${followingWord}`]: precedingValue * followingValue }
101
84
  }
102
85
 
103
86
  // Add: handle special case of tens + units
104
- if (nextNumber < 10n && currentNumber > 10n && currentNumber < 100n) {
87
+ if (followingValue < 10n && precedingValue > 10n && precedingValue < 100n) {
105
88
  // German reverses tens and units (einundzwanzig = one and twenty)
106
- if (nextNumber === 1n) {
107
- nextWord = 'ein'
89
+ if (followingValue === 1n) {
90
+ followingWord = 'ein'
108
91
  }
109
- const temp = nextWord
110
- nextWord = currentWord
111
- currentWord = `${temp}und`
112
- } else if (currentNumber >= 1_000_000n) {
113
- currentWord += ' '
92
+ const temp = followingWord
93
+ followingWord = precedingWord
94
+ precedingWord = `${temp}und`
95
+ } else if (precedingValue >= 1_000_000n) {
96
+ precedingWord += ' '
114
97
  }
115
98
 
116
- return { [`${currentWord}${nextWord}`]: currentNumber + nextNumber }
99
+ return { [`${precedingWord}${followingWord}`]: precedingValue + followingValue }
117
100
  }
118
101
  }
119
-
120
- /**
121
- * Converts a number to German cardinal (written) form.
122
- *
123
- * @param {number|string|bigint} value The number to convert.
124
- * @param {Object} [options] Conversion options (see German class options).
125
- * @returns {string} The number expressed in German words.
126
- * @throws {TypeError} If value is NaN or invalid type.
127
- * @throws {Error} If value is an invalid number string.
128
- *
129
- * @example
130
- * convertToWords(42); // 'zweiundvierzig'
131
- * convertToWords('1.5'); // 'eins komma fünf'
132
- */
133
- export default function convertToWords (value, options = {}) {
134
- return new German(options).convertToWords(value)
135
- }
@@ -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';