n2words 1.23.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (322) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +317 -59
  3. package/dist/ArabicConverter.js +3 -0
  4. package/dist/ArabicConverter.js.map +1 -0
  5. package/dist/AzerbaijaniConverter.js +3 -0
  6. package/dist/AzerbaijaniConverter.js.map +1 -0
  7. package/dist/BanglaConverter.js +3 -0
  8. package/dist/BanglaConverter.js.map +1 -0
  9. package/dist/BiblicalHebrewConverter.js +3 -0
  10. package/dist/BiblicalHebrewConverter.js.map +1 -0
  11. package/dist/CroatianConverter.js +3 -0
  12. package/dist/CroatianConverter.js.map +1 -0
  13. package/dist/CzechConverter.js +3 -0
  14. package/dist/CzechConverter.js.map +1 -0
  15. package/dist/DanishConverter.js +3 -0
  16. package/dist/DanishConverter.js.map +1 -0
  17. package/dist/DutchConverter.js +3 -0
  18. package/dist/DutchConverter.js.map +1 -0
  19. package/dist/EnglishConverter.js +3 -0
  20. package/dist/EnglishConverter.js.map +1 -0
  21. package/dist/FilipinoConverter.js +3 -0
  22. package/dist/FilipinoConverter.js.map +1 -0
  23. package/dist/FrenchBelgiumConverter.js +3 -0
  24. package/dist/FrenchBelgiumConverter.js.map +1 -0
  25. package/dist/FrenchConverter.js +3 -0
  26. package/dist/FrenchConverter.js.map +1 -0
  27. package/dist/GermanConverter.js +3 -0
  28. package/dist/GermanConverter.js.map +1 -0
  29. package/dist/GreekConverter.js +3 -0
  30. package/dist/GreekConverter.js.map +1 -0
  31. package/dist/GujaratiConverter.js +3 -0
  32. package/dist/GujaratiConverter.js.map +1 -0
  33. package/dist/HebrewConverter.js +3 -0
  34. package/dist/HebrewConverter.js.map +1 -0
  35. package/dist/HindiConverter.js +3 -0
  36. package/dist/HindiConverter.js.map +1 -0
  37. package/dist/HungarianConverter.js +3 -0
  38. package/dist/HungarianConverter.js.map +1 -0
  39. package/dist/IndonesianConverter.js +3 -0
  40. package/dist/IndonesianConverter.js.map +1 -0
  41. package/dist/ItalianConverter.js +3 -0
  42. package/dist/ItalianConverter.js.map +1 -0
  43. package/dist/JapaneseConverter.js +3 -0
  44. package/dist/JapaneseConverter.js.map +1 -0
  45. package/dist/KannadaConverter.js +3 -0
  46. package/dist/KannadaConverter.js.map +1 -0
  47. package/dist/KoreanConverter.js +3 -0
  48. package/dist/KoreanConverter.js.map +1 -0
  49. package/dist/LatvianConverter.js +3 -0
  50. package/dist/LatvianConverter.js.map +1 -0
  51. package/dist/LithuanianConverter.js +3 -0
  52. package/dist/LithuanianConverter.js.map +1 -0
  53. package/dist/MalayConverter.js +3 -0
  54. package/dist/MalayConverter.js.map +1 -0
  55. package/dist/MarathiConverter.js +3 -0
  56. package/dist/MarathiConverter.js.map +1 -0
  57. package/dist/NorwegianBokmalConverter.js +3 -0
  58. package/dist/NorwegianBokmalConverter.js.map +1 -0
  59. package/dist/PersianConverter.js +3 -0
  60. package/dist/PersianConverter.js.map +1 -0
  61. package/dist/PolishConverter.js +3 -0
  62. package/dist/PolishConverter.js.map +1 -0
  63. package/dist/PortugueseConverter.js +3 -0
  64. package/dist/PortugueseConverter.js.map +1 -0
  65. package/dist/PunjabiConverter.js +3 -0
  66. package/dist/PunjabiConverter.js.map +1 -0
  67. package/dist/RomanianConverter.js +3 -0
  68. package/dist/RomanianConverter.js.map +1 -0
  69. package/dist/RussianConverter.js +3 -0
  70. package/dist/RussianConverter.js.map +1 -0
  71. package/dist/SerbianCyrillicConverter.js +3 -0
  72. package/dist/SerbianCyrillicConverter.js.map +1 -0
  73. package/dist/SerbianLatinConverter.js +3 -0
  74. package/dist/SerbianLatinConverter.js.map +1 -0
  75. package/dist/SimplifiedChineseConverter.js +3 -0
  76. package/dist/SimplifiedChineseConverter.js.map +1 -0
  77. package/dist/SpanishConverter.js +3 -0
  78. package/dist/SpanishConverter.js.map +1 -0
  79. package/dist/SwahiliConverter.js +3 -0
  80. package/dist/SwahiliConverter.js.map +1 -0
  81. package/dist/SwedishConverter.js +3 -0
  82. package/dist/SwedishConverter.js.map +1 -0
  83. package/dist/TamilConverter.js +3 -0
  84. package/dist/TamilConverter.js.map +1 -0
  85. package/dist/TeluguConverter.js +3 -0
  86. package/dist/TeluguConverter.js.map +1 -0
  87. package/dist/ThaiConverter.js +3 -0
  88. package/dist/ThaiConverter.js.map +1 -0
  89. package/dist/TraditionalChineseConverter.js +3 -0
  90. package/dist/TraditionalChineseConverter.js.map +1 -0
  91. package/dist/TurkishConverter.js +3 -0
  92. package/dist/TurkishConverter.js.map +1 -0
  93. package/dist/UkrainianConverter.js +3 -0
  94. package/dist/UkrainianConverter.js.map +1 -0
  95. package/dist/UrduConverter.js +3 -0
  96. package/dist/UrduConverter.js.map +1 -0
  97. package/dist/VietnameseConverter.js +3 -0
  98. package/dist/VietnameseConverter.js.map +1 -0
  99. package/dist/n2words.js +3 -2
  100. package/dist/n2words.js.map +1 -1
  101. package/lib/classes/abstract-language.d.ts +158 -34
  102. package/lib/classes/abstract-language.js +223 -115
  103. package/lib/classes/greedy-scale-language.d.ts +109 -0
  104. package/lib/classes/greedy-scale-language.js +201 -0
  105. package/lib/classes/slavic-language.d.ts +148 -0
  106. package/lib/classes/slavic-language.js +281 -0
  107. package/lib/classes/south-asian-language.d.ts +70 -0
  108. package/lib/classes/south-asian-language.js +154 -0
  109. package/lib/classes/turkic-language.d.ts +26 -0
  110. package/lib/classes/turkic-language.js +59 -0
  111. package/lib/languages/ar.d.ts +30 -0
  112. package/lib/languages/ar.js +159 -0
  113. package/lib/languages/az.d.ts +12 -0
  114. package/lib/languages/az.js +42 -0
  115. package/lib/languages/bn.d.ts +11 -0
  116. package/lib/languages/bn.js +131 -0
  117. package/lib/languages/cs.d.ts +88 -0
  118. package/lib/languages/cs.js +143 -0
  119. package/lib/languages/da.d.ts +15 -0
  120. package/lib/languages/da.js +120 -0
  121. package/lib/languages/de.d.ts +14 -0
  122. package/lib/languages/de.js +101 -0
  123. package/lib/languages/el.d.ts +14 -0
  124. package/lib/languages/el.js +90 -0
  125. package/lib/languages/en.d.ts +16 -0
  126. package/lib/languages/en.js +86 -0
  127. package/lib/languages/es.d.ts +15 -0
  128. package/lib/languages/es.js +121 -0
  129. package/lib/languages/fa.d.ts +47 -0
  130. package/lib/languages/fa.js +144 -0
  131. package/lib/languages/fil.d.ts +16 -0
  132. package/lib/languages/fil.js +121 -0
  133. package/lib/languages/fr-BE.d.ts +11 -0
  134. package/lib/languages/fr-BE.js +25 -0
  135. package/lib/languages/fr.d.ts +15 -0
  136. package/lib/languages/fr.js +106 -0
  137. package/lib/languages/gu.d.ts +11 -0
  138. package/lib/languages/gu.js +132 -0
  139. package/lib/languages/hbo.d.ts +113 -0
  140. package/lib/languages/hbo.js +251 -0
  141. package/lib/languages/he.d.ts +80 -0
  142. package/lib/languages/he.js +206 -0
  143. package/lib/languages/hi.d.ts +11 -0
  144. package/lib/languages/hi.js +131 -0
  145. package/lib/languages/hr.d.ts +80 -0
  146. package/lib/languages/hr.js +113 -0
  147. package/lib/languages/hu.d.ts +22 -0
  148. package/lib/languages/hu.js +137 -0
  149. package/lib/languages/id.d.ts +37 -0
  150. package/lib/languages/id.js +159 -0
  151. package/lib/languages/it.d.ts +37 -0
  152. package/lib/languages/it.js +132 -0
  153. package/lib/languages/ja.d.ts +17 -0
  154. package/lib/languages/ja.js +137 -0
  155. package/lib/languages/kn.d.ts +11 -0
  156. package/lib/languages/kn.js +42 -0
  157. package/lib/languages/ko.d.ts +14 -0
  158. package/lib/languages/ko.js +55 -0
  159. package/lib/{i18n/pl.d.ts → languages/lt.d.ts} +18 -15
  160. package/lib/languages/lt.js +136 -0
  161. package/lib/{i18n/lt.d.ts → languages/lv.d.ts} +16 -14
  162. package/lib/languages/lv.js +130 -0
  163. package/lib/languages/mr.d.ts +11 -0
  164. package/lib/languages/mr.js +132 -0
  165. package/lib/languages/ms.d.ts +31 -0
  166. package/lib/languages/ms.js +150 -0
  167. package/lib/languages/nb.d.ts +12 -0
  168. package/lib/languages/nb.js +100 -0
  169. package/lib/languages/nl.d.ts +16 -0
  170. package/lib/languages/nl.js +155 -0
  171. package/lib/languages/pa.d.ts +11 -0
  172. package/lib/languages/pa.js +131 -0
  173. package/lib/{i18n/uk.d.ts → languages/pl.d.ts} +16 -14
  174. package/lib/languages/pl.js +110 -0
  175. package/lib/languages/pt.d.ts +29 -0
  176. package/lib/languages/pt.js +112 -0
  177. package/lib/languages/ro.d.ts +158 -0
  178. package/lib/languages/ro.js +273 -0
  179. package/lib/languages/ru.d.ts +85 -0
  180. package/lib/languages/ru.js +96 -0
  181. package/lib/languages/sr-Cyrl.d.ts +80 -0
  182. package/lib/languages/sr-Cyrl.js +113 -0
  183. package/lib/{i18n/cz.d.ts → languages/sr-Latn.d.ts} +26 -14
  184. package/lib/languages/sr-Latn.js +113 -0
  185. package/lib/languages/sv.d.ts +14 -0
  186. package/lib/languages/sv.js +90 -0
  187. package/lib/languages/sw.d.ts +39 -0
  188. package/lib/languages/sw.js +126 -0
  189. package/lib/languages/ta.d.ts +20 -0
  190. package/lib/languages/ta.js +226 -0
  191. package/lib/languages/te.d.ts +22 -0
  192. package/lib/languages/te.js +219 -0
  193. package/lib/languages/th.d.ts +17 -0
  194. package/lib/languages/th.js +117 -0
  195. package/lib/languages/tr.d.ts +12 -0
  196. package/lib/languages/tr.js +56 -0
  197. package/lib/languages/uk.d.ts +85 -0
  198. package/lib/{i18n → languages}/uk.js +33 -32
  199. package/lib/languages/ur.d.ts +11 -0
  200. package/lib/languages/ur.js +131 -0
  201. package/lib/{i18n → languages}/vi.d.ts +15 -13
  202. package/lib/languages/vi.js +147 -0
  203. package/lib/languages/zh-Hans.d.ts +21 -0
  204. package/lib/languages/zh-Hans.js +111 -0
  205. package/lib/languages/zh-Hant.d.ts +21 -0
  206. package/lib/languages/zh-Hant.js +111 -0
  207. package/lib/n2words.d.ts +207 -7
  208. package/lib/n2words.js +535 -81
  209. package/package.json +126 -79
  210. package/dist/ar.js +0 -2
  211. package/dist/ar.js.map +0 -1
  212. package/dist/az.js +0 -2
  213. package/dist/az.js.map +0 -1
  214. package/dist/cz.js +0 -2
  215. package/dist/cz.js.map +0 -1
  216. package/dist/de.js +0 -2
  217. package/dist/de.js.map +0 -1
  218. package/dist/dk.js +0 -2
  219. package/dist/dk.js.map +0 -1
  220. package/dist/en.js +0 -2
  221. package/dist/en.js.map +0 -1
  222. package/dist/es.js +0 -2
  223. package/dist/es.js.map +0 -1
  224. package/dist/fa.js +0 -2
  225. package/dist/fa.js.map +0 -1
  226. package/dist/fr-BE.js +0 -2
  227. package/dist/fr-BE.js.map +0 -1
  228. package/dist/fr.js +0 -2
  229. package/dist/fr.js.map +0 -1
  230. package/dist/he.js +0 -2
  231. package/dist/he.js.map +0 -1
  232. package/dist/hr.js +0 -2
  233. package/dist/hr.js.map +0 -1
  234. package/dist/hu.js +0 -2
  235. package/dist/hu.js.map +0 -1
  236. package/dist/id.js +0 -2
  237. package/dist/id.js.map +0 -1
  238. package/dist/it.js +0 -2
  239. package/dist/it.js.map +0 -1
  240. package/dist/ko.js +0 -2
  241. package/dist/ko.js.map +0 -1
  242. package/dist/lt.js +0 -2
  243. package/dist/lt.js.map +0 -1
  244. package/dist/lv.js +0 -2
  245. package/dist/lv.js.map +0 -1
  246. package/dist/n2words.d.ts +0 -2
  247. package/dist/nl.js +0 -2
  248. package/dist/nl.js.map +0 -1
  249. package/dist/no.js +0 -2
  250. package/dist/no.js.map +0 -1
  251. package/dist/pl.js +0 -2
  252. package/dist/pl.js.map +0 -1
  253. package/dist/pt.js +0 -2
  254. package/dist/pt.js.map +0 -1
  255. package/dist/ro.js +0 -2
  256. package/dist/ro.js.map +0 -1
  257. package/dist/ru.js +0 -2
  258. package/dist/ru.js.map +0 -1
  259. package/dist/sr.js +0 -2
  260. package/dist/sr.js.map +0 -1
  261. package/dist/tr.js +0 -2
  262. package/dist/tr.js.map +0 -1
  263. package/dist/uk.js +0 -2
  264. package/dist/uk.js.map +0 -1
  265. package/dist/vi.js +0 -2
  266. package/dist/vi.js.map +0 -1
  267. package/dist/zh.js +0 -2
  268. package/dist/zh.js.map +0 -1
  269. package/lib/classes/base-language.d.ts +0 -58
  270. package/lib/classes/base-language.js +0 -172
  271. package/lib/i18n/ar.d.ts +0 -41
  272. package/lib/i18n/ar.js +0 -209
  273. package/lib/i18n/az.d.ts +0 -15
  274. package/lib/i18n/az.js +0 -66
  275. package/lib/i18n/cz.js +0 -135
  276. package/lib/i18n/de.d.ts +0 -17
  277. package/lib/i18n/de.js +0 -103
  278. package/lib/i18n/dk.d.ts +0 -14
  279. package/lib/i18n/dk.js +0 -110
  280. package/lib/i18n/en.d.ts +0 -22
  281. package/lib/i18n/en.js +0 -86
  282. package/lib/i18n/es.d.ts +0 -16
  283. package/lib/i18n/es.js +0 -110
  284. package/lib/i18n/fa.d.ts +0 -54
  285. package/lib/i18n/fa.js +0 -106
  286. package/lib/i18n/fr-BE.d.ts +0 -11
  287. package/lib/i18n/fr-BE.js +0 -20
  288. package/lib/i18n/fr.d.ts +0 -15
  289. package/lib/i18n/fr.js +0 -99
  290. package/lib/i18n/he.d.ts +0 -61
  291. package/lib/i18n/he.js +0 -132
  292. package/lib/i18n/hr.d.ts +0 -68
  293. package/lib/i18n/hr.js +0 -129
  294. package/lib/i18n/hu.d.ts +0 -17
  295. package/lib/i18n/hu.js +0 -135
  296. package/lib/i18n/id.d.ts +0 -43
  297. package/lib/i18n/id.js +0 -156
  298. package/lib/i18n/it.d.ts +0 -29
  299. package/lib/i18n/it.js +0 -137
  300. package/lib/i18n/ko.d.ts +0 -15
  301. package/lib/i18n/ko.js +0 -56
  302. package/lib/i18n/lt.js +0 -138
  303. package/lib/i18n/lv.d.ts +0 -57
  304. package/lib/i18n/lv.js +0 -120
  305. package/lib/i18n/nl.d.ts +0 -20
  306. package/lib/i18n/nl.js +0 -125
  307. package/lib/i18n/no.d.ts +0 -15
  308. package/lib/i18n/no.js +0 -77
  309. package/lib/i18n/pl.js +0 -126
  310. package/lib/i18n/pt.d.ts +0 -26
  311. package/lib/i18n/pt.js +0 -118
  312. package/lib/i18n/ro.d.ts +0 -109
  313. package/lib/i18n/ro.js +0 -360
  314. package/lib/i18n/ru.d.ts +0 -30
  315. package/lib/i18n/ru.js +0 -198
  316. package/lib/i18n/sr.d.ts +0 -56
  317. package/lib/i18n/sr.js +0 -127
  318. package/lib/i18n/tr.d.ts +0 -15
  319. package/lib/i18n/tr.js +0 -64
  320. package/lib/i18n/vi.js +0 -151
  321. package/lib/i18n/zh.d.ts +0 -18
  322. package/lib/i18n/zh.js +0 -78
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Romanian language converter.
3
+ *
4
+ * Supports:
5
+ * - Gender agreement (unu/una, doi/două)
6
+ * - Complex pluralization (singular/plural forms)
7
+ * - "De" preposition insertion for groups >= 20
8
+ */
9
+ export class Romanian extends AbstractLanguage {
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
+ teensMasculineWords: {
46
+ 0: string;
47
+ 1: string;
48
+ 2: string;
49
+ 3: string;
50
+ 4: string;
51
+ 5: string;
52
+ 6: string;
53
+ 7: string;
54
+ 8: string;
55
+ 9: string;
56
+ };
57
+ twentiesWords: {
58
+ 2: string;
59
+ 3: string;
60
+ 4: string;
61
+ 5: string;
62
+ 6: string;
63
+ 7: string;
64
+ 8: string;
65
+ 9: string;
66
+ };
67
+ hundredsWords: {
68
+ 1: string;
69
+ 2: string;
70
+ 3: string;
71
+ 4: string;
72
+ 5: string;
73
+ 6: string;
74
+ 7: string;
75
+ 8: string;
76
+ 9: string;
77
+ };
78
+ /**
79
+ * Romanian big units.
80
+ * For each power group we keep: singular, plural, feminineUnits?, needsDe?
81
+ * - 10^3: mie/mii (feminine units in segment; "de" for segment >= 20)
82
+ * - 10^6: milion/milioane ("de" for segment >= 20)
83
+ * - 10^9: miliard/miliarde ("de" for segment >= 20)
84
+ */
85
+ scaleMetadata: {
86
+ 1: {
87
+ singular: string;
88
+ plural: string;
89
+ feminine: boolean;
90
+ needsDe: boolean;
91
+ };
92
+ 2: {
93
+ singular: string;
94
+ plural: string;
95
+ feminine: boolean;
96
+ needsDe: boolean;
97
+ };
98
+ 3: {
99
+ singular: string;
100
+ plural: string;
101
+ feminine: boolean;
102
+ needsDe: boolean;
103
+ };
104
+ 4: {
105
+ singular: string;
106
+ plural: string;
107
+ feminine: boolean;
108
+ needsDe: boolean;
109
+ };
110
+ 5: {
111
+ singular: string;
112
+ plural: string;
113
+ feminine: boolean;
114
+ needsDe: boolean;
115
+ };
116
+ 6: {
117
+ singular: string;
118
+ plural: string;
119
+ feminine: boolean;
120
+ needsDe: boolean;
121
+ };
122
+ 7: {
123
+ singular: string;
124
+ plural: string;
125
+ feminine: boolean;
126
+ needsDe: boolean;
127
+ };
128
+ 8: {
129
+ singular: string;
130
+ plural: string;
131
+ feminine: boolean;
132
+ needsDe: boolean;
133
+ };
134
+ 9: {
135
+ singular: string;
136
+ plural: string;
137
+ feminine: boolean;
138
+ needsDe: boolean;
139
+ };
140
+ 10: {
141
+ singular: string;
142
+ plural: string;
143
+ feminine: boolean;
144
+ needsDe: boolean;
145
+ };
146
+ };
147
+ /** Split numeric string into BigInt segments of specified size from left to right. */
148
+ splitToSegments(n: any, x: any): bigint[];
149
+ extractDigits(value: any): any;
150
+ /** Romanian pluralization & "de" rule for big units. */
151
+ romanianPluralize(segment: any, form: any): string;
152
+ spellUnder100(n: any, feminineUnits?: boolean, masculineTeens?: boolean): any;
153
+ spellUnder1000(n: any, feminineUnits?: boolean, masculineTeens?: boolean): any;
154
+ /** Decimals always use masculine forms regardless of gender option. */
155
+ decimalIntegerToWords(integerPart: any): any;
156
+ integerToWords(integerPart: any): string;
157
+ }
158
+ import { AbstractLanguage } from '../classes/abstract-language.js';
@@ -0,0 +1,273 @@
1
+ import { AbstractLanguage } from '../classes/abstract-language.js'
2
+
3
+ /**
4
+ * Romanian language converter.
5
+ *
6
+ * Supports:
7
+ * - Gender agreement (unu/una, doi/două)
8
+ * - Complex pluralization (singular/plural forms)
9
+ * - "De" preposition insertion for groups >= 20
10
+ */
11
+ export class Romanian extends AbstractLanguage {
12
+ negativeWord = 'minus'
13
+ decimalSeparatorWord = 'virgulă'
14
+ zeroWord = 'zero'
15
+
16
+ onesWords = {
17
+ 1: 'unu',
18
+ 2: 'doi',
19
+ 3: 'trei',
20
+ 4: 'patru',
21
+ 5: 'cinci',
22
+ 6: 'șase',
23
+ 7: 'șapte',
24
+ 8: 'opt',
25
+ 9: 'nouă'
26
+ }
27
+
28
+ onesFeminineWords = {
29
+ 1: 'una',
30
+ 2: 'două',
31
+ 3: 'trei',
32
+ 4: 'patru',
33
+ 5: 'cinci',
34
+ 6: 'șase',
35
+ 7: 'șapte',
36
+ 8: 'opt',
37
+ 9: 'nouă'
38
+ }
39
+
40
+ teensWords = {
41
+ 0: 'zece',
42
+ 1: 'unsprezece',
43
+ 2: 'douăsprezece',
44
+ 3: 'treisprezece',
45
+ 4: 'paisprezece',
46
+ 5: 'cincisprezece',
47
+ 6: 'șaisprezece',
48
+ 7: 'șaptesprezece',
49
+ 8: 'optsprezece',
50
+ 9: 'nouăsprezece'
51
+ }
52
+
53
+ teensMasculineWords = {
54
+ 0: 'zece',
55
+ 1: 'unsprezece',
56
+ 2: 'doisprezece',
57
+ 3: 'treisprezece',
58
+ 4: 'paisprezece',
59
+ 5: 'cincisprezece',
60
+ 6: 'șaisprezece',
61
+ 7: 'șaptesprezece',
62
+ 8: 'optsprezece',
63
+ 9: 'nouăsprezece'
64
+ }
65
+
66
+ twentiesWords = {
67
+ 2: 'douăzeci',
68
+ 3: 'treizeci',
69
+ 4: 'patruzeci',
70
+ 5: 'cincizeci',
71
+ 6: 'șaizeci',
72
+ 7: 'șaptezeci',
73
+ 8: 'optzeci',
74
+ 9: 'nouăzeci'
75
+ }
76
+
77
+ hundredsWords = {
78
+ 1: 'o sută',
79
+ 2: 'două sute',
80
+ 3: 'trei sute',
81
+ 4: 'patru sute',
82
+ 5: 'cinci sute',
83
+ 6: 'șase sute',
84
+ 7: 'șapte sute',
85
+ 8: 'opt sute',
86
+ 9: 'nouă sute'
87
+ }
88
+
89
+ /**
90
+ * Romanian big units.
91
+ * For each power group we keep: singular, plural, feminineUnits?, needsDe?
92
+ * - 10^3: mie/mii (feminine units in segment; "de" for segment >= 20)
93
+ * - 10^6: milion/milioane ("de" for segment >= 20)
94
+ * - 10^9: miliard/miliarde ("de" for segment >= 20)
95
+ */
96
+ scaleMetadata = {
97
+ 1: { singular: 'mie', plural: 'mii', feminine: true, needsDe: true }, // 10^3
98
+ 2: { singular: 'milion', plural: 'milioane', feminine: false, needsDe: true }, // 10^6
99
+ 3: { singular: 'miliard', plural: 'miliarde', feminine: false, needsDe: true }, // 10^9
100
+ 4: { singular: 'trilion', plural: 'trilioane', feminine: false, needsDe: true }, // 10^12
101
+ 5: { singular: 'cvadrilion', plural: 'cvadrilioane', feminine: false, needsDe: true }, // 10^15
102
+ 6: { singular: 'cvintilion', plural: 'cvintilioane', feminine: false, needsDe: true }, // 10^18
103
+ 7: { singular: 'sextilion', plural: 'sextilioane', feminine: false, needsDe: true }, // 10^21
104
+ 8: { singular: 'septilion', plural: 'septilioane', feminine: false, needsDe: true }, // 10^24
105
+ 9: { singular: 'octilion', plural: 'octilioane', feminine: false, needsDe: true }, // 10^27
106
+ 10: { singular: 'decilion', plural: 'decilioane', feminine: false, needsDe: true } // 10^33
107
+ }
108
+
109
+ constructor (options = {}) {
110
+ super()
111
+
112
+ this.setOptions({
113
+ gender: 'masculine'
114
+ }, options)
115
+ }
116
+
117
+ /** Split numeric string into BigInt segments of specified size from left to right. */
118
+ splitToSegments (n, x) {
119
+ const results = []
120
+ const l = n.length
121
+ let result
122
+
123
+ if (l > x) {
124
+ const start = l % x
125
+ if (start > 0) {
126
+ result = n.slice(0, start)
127
+ results.push(BigInt(result))
128
+ }
129
+ for (let index = start; index < l; index += x) {
130
+ result = n.slice(index, index + x)
131
+ results.push(BigInt(result))
132
+ }
133
+ } else {
134
+ results.push(BigInt(n))
135
+ }
136
+ return results
137
+ }
138
+
139
+ extractDigits (value) {
140
+ const stringValue = value.toString().padStart(3, '0').slice(-3)
141
+ const a = [...stringValue].toReversed()
142
+ return a.map(BigInt)
143
+ }
144
+
145
+ /** Romanian pluralization & "de" rule for big units. */
146
+ romanianPluralize (segment, form) {
147
+ const n = Number(segment)
148
+
149
+ if (n === 1) {
150
+ // article differs for feminine "mie" (o mie) vs the rest (un milion/miliard…)
151
+ const article = form.feminine ? 'o' : 'un'
152
+ return `${article} ${form.singular}`
153
+ }
154
+
155
+ // For 21 with big units, use feminine "una" with plural nouns
156
+ if (n === 21 && form.needsDe) {
157
+ return `douăzeci și una de ${form.plural}`
158
+ }
159
+
160
+ // spell the segment itself (use feminine units for big numbers)
161
+ const words = this.spellUnder1000(n, true)
162
+
163
+ // "de" after >= 20 (covers 20, 21, 100, 101, 999, etc.)
164
+ const needsDe = form.needsDe && n >= 20
165
+ const de = needsDe ? ' de ' : ' '
166
+
167
+ return `${words}${de}${form.plural}`
168
+ }
169
+
170
+ spellUnder100 (n, feminineUnits = false, masculineTeens = false) {
171
+ if (n < 10) {
172
+ return (feminineUnits ? this.onesFeminineWords : this.onesWords)[n]
173
+ }
174
+ if (n < 20) {
175
+ return (masculineTeens ? this.teensMasculineWords : this.teensWords)[n - 10]
176
+ }
177
+ const t = Math.floor(n / 10)
178
+ const u = n % 10
179
+ return u
180
+ ? `${this.twentiesWords[t]} și ${(feminineUnits ? this.onesFeminineWords : this.onesWords)[u]}`
181
+ : this.twentiesWords[t]
182
+ }
183
+
184
+ spellUnder1000 (n, feminineUnits = false, masculineTeens = false) {
185
+ if (n < 100) return this.spellUnder100(n, feminineUnits, masculineTeens)
186
+ const h = Math.floor(n / 100)
187
+ const r = n % 100
188
+ const hundredWords = this.hundredsWords[h]
189
+ if (!r) return hundredWords
190
+ // Standard readable form: "o sută unu" (for units) or "o sută cincizeci" (for tens)
191
+ const separator = ' '
192
+ return `${hundredWords}${separator}${this.spellUnder100(r, feminineUnits, masculineTeens)}`
193
+ }
194
+
195
+ /** Decimals always use masculine forms regardless of gender option. */
196
+ decimalIntegerToWords (integerPart) {
197
+ if (integerPart === 0n) return this.zeroWord
198
+ // Use spellUnder1000 with masculine forms (feminineUnits=false, masculineTeens=true)
199
+ if (integerPart < 1000n) return this.spellUnder1000(Number(integerPart), false, true)
200
+ // For larger decimals, process segments with masculine forms
201
+ const words = []
202
+ const segments = this.splitToSegments(integerPart.toString(), 3)
203
+ let index = segments.length
204
+ for (const x of segments) {
205
+ index = index - 1
206
+ if (x === 0n) continue
207
+ const [n1, n2, n3] = this.extractDigits(x)
208
+ if (n3 > 0n) words.push(this.hundredsWords[Number(n3)])
209
+ if (n2 > 1n) words.push(this.twentiesWords[Number(n2)])
210
+ if (n2 === 1n) {
211
+ words.push(this.teensMasculineWords[Number(n1)])
212
+ } else if (n1 > 0n) {
213
+ if (n2 > 1n) words.push('și')
214
+ words.push(this.onesWords[Number(n1)])
215
+ }
216
+ if (index > 0) {
217
+ const form = this.scaleMetadata[index]
218
+ if (form) {
219
+ words.push(this.romanianPluralize(x, form))
220
+ } else {
221
+ words.push(this.spellUnder1000(Number(x), false))
222
+ }
223
+ }
224
+ }
225
+ return words.join(' ').replaceAll(/\s+/g, ' ').trim()
226
+ }
227
+
228
+ integerToWords (integerPart) {
229
+ if (integerPart === 0n) {
230
+ return this.zeroWord
231
+ }
232
+ const words = []
233
+ const segments = this.splitToSegments(integerPart.toString(), 3)
234
+ let index = segments.length
235
+ for (const x of segments) {
236
+ let onesMap = []
237
+ index = index - 1
238
+ if (x === 0n) continue
239
+ const [n1, n2, n3] = this.extractDigits(x) // units, tens, hundreds (as BigInt)
240
+ // hundreds (only for the last group, not for thousands)
241
+ if (n3 > 0n && index === 0) {
242
+ words.push(this.hundredsWords[Number(n3)])
243
+ }
244
+ // tens & teens (only for the last group, not for thousands)
245
+ if (index === 0) {
246
+ if (n2 > 1n) {
247
+ words.push(this.twentiesWords[Number(n2)])
248
+ }
249
+ if (n2 === 1n) {
250
+ words.push(this.teensWords[Number(n1)])
251
+ } else if (n1 > 0n) {
252
+ // pick masculine/feminine units (only for the last group, not for thousands)
253
+ const feminineUnits = this.options.gender === 'feminine' && index === 0
254
+ onesMap = feminineUnits ? this.onesFeminineWords : this.onesWords
255
+ // if there is a twenty/treizeci/etc AND ones > 0 → add "și"
256
+ if (n2 > 1n) words.push('și')
257
+ words.push(onesMap[Number(n1)])
258
+ }
259
+ }
260
+ // big unit name (mie/mii, milion/milioane, …)
261
+ if (index > 0) {
262
+ const form = this.scaleMetadata[index]
263
+ if (form) {
264
+ words.push(this.romanianPluralize(x, form))
265
+ } else {
266
+ // For very large numbers beyond our defined units, just spell out the number
267
+ words.push(this.spellUnder1000(Number(x), true))
268
+ }
269
+ }
270
+ }
271
+ return words.join(' ').replaceAll(/\s+/g, ' ').trim()
272
+ }
273
+ }
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Russian language converter.
3
+ *
4
+ * Supports:
5
+ * - Gender agreement (masculine/feminine forms)
6
+ * - Three-form pluralization (one/few/many)
7
+ * - Large numbers up to nonillions
8
+ */
9
+ export class Russian extends SlavicLanguage {
10
+ onesWords: {
11
+ 1: string;
12
+ 2: string;
13
+ 3: string;
14
+ 4: string;
15
+ 5: string;
16
+ 6: string;
17
+ 7: string;
18
+ 8: string;
19
+ 9: string;
20
+ };
21
+ onesFeminineWords: {
22
+ 1: string;
23
+ 2: string;
24
+ 3: string;
25
+ 4: string;
26
+ 5: string;
27
+ 6: string;
28
+ 7: string;
29
+ 8: string;
30
+ 9: string;
31
+ };
32
+ teensWords: {
33
+ 0: string;
34
+ 1: string;
35
+ 2: string;
36
+ 3: string;
37
+ 4: string;
38
+ 5: string;
39
+ 6: string;
40
+ 7: string;
41
+ 8: string;
42
+ 9: string;
43
+ };
44
+ twentiesWords: {
45
+ 2: string;
46
+ 3: string;
47
+ 4: string;
48
+ 5: string;
49
+ 6: string;
50
+ 7: string;
51
+ 8: string;
52
+ 9: string;
53
+ };
54
+ hundredsWords: {
55
+ 1: string;
56
+ 2: string;
57
+ 3: string;
58
+ 4: string;
59
+ 5: string;
60
+ 6: string;
61
+ 7: string;
62
+ 8: string;
63
+ 9: string;
64
+ };
65
+ pluralForms: {
66
+ 1: string[];
67
+ 2: string[];
68
+ 3: string[];
69
+ 4: string[];
70
+ 5: string[];
71
+ 6: string[];
72
+ 7: string[];
73
+ 8: string[];
74
+ 9: string[];
75
+ 10: string[];
76
+ };
77
+ /**
78
+ * Russian thousands (тысяча) are feminine, requiring одна/две forms.
79
+ * Other scales (million, billion, etc.) are masculine.
80
+ */
81
+ scaleGenders: {
82
+ 1: boolean;
83
+ };
84
+ }
85
+ import { SlavicLanguage } from '../classes/slavic-language.js';
@@ -0,0 +1,96 @@
1
+ import { SlavicLanguage } from '../classes/slavic-language.js'
2
+
3
+ /**
4
+ * Russian language converter.
5
+ *
6
+ * Supports:
7
+ * - Gender agreement (masculine/feminine forms)
8
+ * - Three-form pluralization (one/few/many)
9
+ * - Large numbers up to nonillions
10
+ */
11
+ export class Russian extends SlavicLanguage {
12
+ negativeWord = 'минус'
13
+ decimalSeparatorWord = 'запятая'
14
+ zeroWord = 'ноль'
15
+
16
+ onesWords = {
17
+ 1: 'один',
18
+ 2: 'два',
19
+ 3: 'три',
20
+ 4: 'четыре',
21
+ 5: 'пять',
22
+ 6: 'шесть',
23
+ 7: 'семь',
24
+ 8: 'восемь',
25
+ 9: 'девять'
26
+ }
27
+
28
+ onesFeminineWords = {
29
+ 1: 'одна',
30
+ 2: 'две',
31
+ 3: 'три',
32
+ 4: 'четыре',
33
+ 5: 'пять',
34
+ 6: 'шесть',
35
+ 7: 'семь',
36
+ 8: 'восемь',
37
+ 9: 'девять'
38
+ }
39
+
40
+ teensWords = {
41
+ 0: 'десять',
42
+ 1: 'одиннадцать',
43
+ 2: 'двенадцать',
44
+ 3: 'тринадцать',
45
+ 4: 'четырнадцать',
46
+ 5: 'пятнадцать',
47
+ 6: 'шестнадцать',
48
+ 7: 'семнадцать',
49
+ 8: 'восемнадцать',
50
+ 9: 'девятнадцать'
51
+ }
52
+
53
+ twentiesWords = {
54
+ 2: 'двадцать',
55
+ 3: 'тридцать',
56
+ 4: 'сорок',
57
+ 5: 'пятьдесят',
58
+ 6: 'шестьдесят',
59
+ 7: 'семьдесят',
60
+ 8: 'восемьдесят',
61
+ 9: 'девяносто'
62
+ }
63
+
64
+ hundredsWords = {
65
+ 1: 'сто',
66
+ 2: 'двести',
67
+ 3: 'триста',
68
+ 4: 'четыреста',
69
+ 5: 'пятьсот',
70
+ 6: 'шестьсот',
71
+ 7: 'семьсот',
72
+ 8: 'восемьсот',
73
+ 9: 'девятьсот'
74
+ }
75
+
76
+ pluralForms = {
77
+ 1: ['тысяча', 'тысячи', 'тысяч'], // 10^ 3
78
+ 2: ['миллион', 'миллиона', 'миллионов'], // 10^ 6
79
+ 3: ['миллиард', 'миллиарда', 'миллиардов'], // 10^ 9
80
+ 4: ['триллион', 'триллиона', 'триллионов'], // 10^ 12
81
+ 5: ['квадриллион', 'квадриллиона', 'квадриллионов'], // 10^ 15
82
+ 6: ['квинтиллион', 'квинтиллиона', 'квинтиллионов'], // 10^ 18
83
+ 7: ['секстиллион', 'секстиллиона', 'секстиллионов'], // 10^ 21
84
+ 8: ['септиллион', 'септиллиона', 'септиллионов'], // 10^ 24
85
+ 9: ['октиллион', 'октиллиона', 'октиллионов'], // 10^ 27
86
+ 10: ['нониллион', 'нониллиона', 'нониллионов'] // 10^ 30
87
+ }
88
+
89
+ /**
90
+ * Russian thousands (тысяча) are feminine, requiring одна/две forms.
91
+ * Other scales (million, billion, etc.) are masculine.
92
+ */
93
+ scaleGenders = {
94
+ 1: true // thousands are feminine
95
+ }
96
+ }
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Serbian language converter (Cyrillic script).
3
+ *
4
+ * Supports:
5
+ * - Three-form pluralization (one/few/many)
6
+ * - Gender agreement (један/једна, два/две)
7
+ * - Cyrillic script representation
8
+ */
9
+ export class SerbianCyrillic extends SlavicLanguage {
10
+ onesWords: {
11
+ 1: string;
12
+ 2: string;
13
+ 3: string;
14
+ 4: string;
15
+ 5: string;
16
+ 6: string;
17
+ 7: string;
18
+ 8: string;
19
+ 9: string;
20
+ };
21
+ onesFeminineWords: {
22
+ 1: string;
23
+ 2: string;
24
+ 3: string;
25
+ 4: string;
26
+ 5: string;
27
+ 6: string;
28
+ 7: string;
29
+ 8: string;
30
+ 9: string;
31
+ };
32
+ teensWords: {
33
+ 0: string;
34
+ 1: string;
35
+ 2: string;
36
+ 3: string;
37
+ 4: string;
38
+ 5: string;
39
+ 6: string;
40
+ 7: string;
41
+ 8: string;
42
+ 9: string;
43
+ };
44
+ twentiesWords: {
45
+ 2: string;
46
+ 3: string;
47
+ 4: string;
48
+ 5: string;
49
+ 6: string;
50
+ 7: string;
51
+ 8: string;
52
+ 9: string;
53
+ };
54
+ hundredsWords: {
55
+ 1: string;
56
+ 2: string;
57
+ 3: string;
58
+ 4: string;
59
+ 5: string;
60
+ 6: string;
61
+ 7: string;
62
+ 8: string;
63
+ 9: string;
64
+ };
65
+ pluralForms: {
66
+ 1: string[];
67
+ 2: string[];
68
+ 3: string[];
69
+ 4: string[];
70
+ 5: string[];
71
+ 6: string[];
72
+ 7: string[];
73
+ 8: string[];
74
+ 9: string[];
75
+ 10: string[];
76
+ };
77
+ /** Selects Serbian plural form: 1 = singular, 2-4 = few, else = many. */
78
+ pluralize(n: any, forms: any): any;
79
+ }
80
+ import { SlavicLanguage } from '../classes/slavic-language.js';