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,132 @@
1
+ import { AbstractLanguage } from '../classes/abstract-language.js'
2
+
3
+ /**
4
+ * Italian language converter.
5
+ *
6
+ * Supports:
7
+ * - Phonetic contractions (vowel elision: "ventotto" not "ventiotto")
8
+ * - Accentuation rules for "tre" in compounds ("ventitré")
9
+ * - Custom word construction for irregular patterns
10
+ */
11
+ export class Italian extends AbstractLanguage {
12
+ negativeWord = 'meno'
13
+ decimalSeparatorWord = 'virgola'
14
+ zeroWord = 'zero'
15
+
16
+ onesWords = [
17
+ this.zeroWord, 'uno', 'due', 'tre', 'quattro', 'cinque', 'sei', 'sette', 'otto',
18
+ 'nove', 'dieci', 'undici', 'dodici', 'tredici', 'quattordici', 'quindici',
19
+ 'sedici', 'diciassette', 'diciotto', 'diciannove'
20
+ ]
21
+
22
+ tensWords = { 2: 'venti', 3: 'trenta', 4: 'quaranta', 6: 'sessanta' }
23
+
24
+ exponentPrefixes = [this.zeroWord, 'm', 'b', 'tr', 'quadr', 'quint', 'sest', 'sett', 'ott', 'nov', 'dec']
25
+
26
+ /** Adds accent to final "tre" in compound words (ventitré). */
27
+ accentuate (string) {
28
+ const splittedString = string.split(' ')
29
+
30
+ const result = splittedString.map(word => {
31
+ return word.slice(-3) === 'tre' && word.length > 3 ? word.replaceAll('tré', 'tre').slice(0, -3) + 'tré' : word.replaceAll('tré', 'tre')
32
+ })
33
+ return result.join(' ')
34
+ }
35
+
36
+ /** Omits word if it represents zero. */
37
+ omitIfZero (numberToString) {
38
+ return numberToString === this.zeroWord ? '' : numberToString
39
+ }
40
+
41
+ /** Removes duplicate vowels for phonetic contractions. */
42
+ phoneticContraction (string) {
43
+ return string.replaceAll('oo', 'o').replaceAll('ao', 'o').replaceAll('io', 'o').replaceAll('au', 'u').replaceAll('iu', 'u')
44
+ }
45
+
46
+ /** Converts tens (20-99) with phonetic contractions. */
47
+ tensToCardinal (number) {
48
+ const tens = Math.floor(number / 10)
49
+ const units = number % 10
50
+ const prefix = Object.prototype.hasOwnProperty.call(this.tensWords, tens) ? this.tensWords[tens] : this.onesWords[tens].slice(0, -1) + 'anta'
51
+ const postfix = this.omitIfZero(this.onesWords[units])
52
+ return this.phoneticContraction(prefix + postfix)
53
+ }
54
+
55
+ /** Converts hundreds (100-999) with "cento" composition. */
56
+ hundredsToCardinal (number) {
57
+ const hundreds = Math.floor(number / 100)
58
+ let prefix = 'cento'
59
+ if (hundreds !== 1) {
60
+ prefix = this.onesWords[hundreds] + prefix
61
+ }
62
+ const postfix = this.omitIfZero(this.integerToWords(number % 100))
63
+ return this.phoneticContraction(prefix + postfix)
64
+ }
65
+
66
+ /** Converts thousands (1000-999999) with "mille/mila" composition. */
67
+ thousandsToCardinal (number) {
68
+ const thousands = Math.floor(number / 1000)
69
+ const prefix = thousands === 1 ? 'mille' : this.integerToWords(thousands) + 'mila'
70
+ const postfix = this.omitIfZero(this.integerToWords(number % 1000))
71
+ return prefix + postfix
72
+ }
73
+
74
+ /** Converts exponent length to Italian scale word (milione, miliardo, etc.). */
75
+ exponentLengthToString (exponentLength) {
76
+ const prefix = this.exponentPrefixes[Math.floor(exponentLength / 6)]
77
+ return exponentLength % 6 === 0 ? prefix + 'ilione' : prefix + 'iliardo'
78
+ }
79
+
80
+ /** Converts large numbers (millions and above) with exponent-based naming. */
81
+ bigNumberToCardinal (number) {
82
+ const digits = [...number.toString()]
83
+
84
+ let preDigits = digits.length % 3
85
+ if (preDigits === 0) {
86
+ preDigits = 3
87
+ }
88
+
89
+ const multiplier = digits.slice(0, preDigits) // first `preDigits` elements
90
+ const exponent = digits.slice(preDigits) // without the first `preDigits` elements
91
+
92
+ let prefix, postfix
93
+ let infix = this.exponentLengthToString(exponent.length)
94
+
95
+ if (multiplier.join('') === '1') {
96
+ prefix = 'un '
97
+ } else {
98
+ prefix = this.integerToWords(Math.trunc(Number(multiplier.join(''))))
99
+ infix = ' ' + infix.slice(0, -1) + 'i' // without last element
100
+ }
101
+
102
+ const isSetsEqual = (a, b) => a.size === b.size && [...a].every(value => b.has(value))
103
+ if (isSetsEqual(new Set(exponent), new Set(['0']))) {
104
+ postfix = ''
105
+ } else {
106
+ postfix = this.integerToWords(Math.trunc(exponent.join('')))
107
+
108
+ infix += (postfix.includes(' e ') ? ', ' : ' e ')
109
+ }
110
+
111
+ return prefix + infix + postfix
112
+ }
113
+
114
+ /** Converts integer part using Italian custom algorithm with accentuation. */
115
+ integerToWords (integerPart) {
116
+ let words = ''
117
+
118
+ if (integerPart < 20) {
119
+ words = this.onesWords[integerPart]
120
+ } else if (integerPart < 100) {
121
+ words = this.tensToCardinal(Number(integerPart))
122
+ } else if (integerPart < 1000) {
123
+ words = this.hundredsToCardinal(Number(integerPart))
124
+ } else if (integerPart < 1_000_000) {
125
+ words = this.thousandsToCardinal(Number(integerPart))
126
+ } else {
127
+ words = this.bigNumberToCardinal(integerPart)
128
+ }
129
+
130
+ return this.accentuate(words)
131
+ }
132
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Japanese language converter.
3
+ *
4
+ * Supports:
5
+ * - Kanji numerals (一, 二, 三, etc.)
6
+ * - Grouping by 万 (10,000) instead of 1,000
7
+ * - Special 一 (one) omission rules (十, 百, 千 but 一万, 一億)
8
+ */
9
+ export class Japanese extends AbstractLanguage {
10
+ onesWords: string[];
11
+ scaleWords: string[];
12
+ /** Converts a segment of up to 4 digits to Japanese kanji with 一 omission rules. */
13
+ segmentToWords(num: any): string;
14
+ /** Converts integer part using Japanese 万-based grouping system. */
15
+ integerToWords(integerPart: any): string;
16
+ }
17
+ import { AbstractLanguage } from '../classes/abstract-language.js';
@@ -0,0 +1,137 @@
1
+ import { AbstractLanguage } from '../classes/abstract-language.js'
2
+
3
+ /**
4
+ * Japanese language converter.
5
+ *
6
+ * Supports:
7
+ * - Kanji numerals (一, 二, 三, etc.)
8
+ * - Grouping by 万 (10,000) instead of 1,000
9
+ * - Special 一 (one) omission rules (十, 百, 千 but 一万, 一億)
10
+ */
11
+ export class Japanese extends AbstractLanguage {
12
+ negativeWord = 'マイナス'
13
+ decimalSeparatorWord = '点'
14
+ zeroWord = '零'
15
+ wordSeparator = '' // Japanese doesn't use spaces between characters
16
+ usePerDigitDecimals = true // Enable digit-by-digit decimal conversion
17
+
18
+ // Ones words used for group conversion (1-9)
19
+ onesWords = ['一', '二', '三', '四', '五', '六', '七', '八', '九']
20
+
21
+ // Scale words for grouping by 10^4
22
+ scaleWords = [
23
+ '', // 10^0 (ones)
24
+ '万', // 10^4 (man)
25
+ '億', // 10^8 (oku)
26
+ '兆', // 10^12 (chō)
27
+ '京', // 10^16 (kei)
28
+ '垓', // 10^20 (gai)
29
+ '秭', // 10^24 (jo/shi)
30
+ '穣', // 10^28 (jō)
31
+ '溝', // 10^32 (kō)
32
+ '澗', // 10^36 (kan)
33
+ '正', // 10^40 (sei)
34
+ '載', // 10^44 (sai)
35
+ '極', // 10^48 (goku)
36
+ '恒河沙', // 10^52 (gōgasha)
37
+ '阿僧祇', // 10^56 (asōgi)
38
+ '那由他', // 10^60 (nayuta)
39
+ '不可思議', // 10^64 (fukashigi)
40
+ '無量大数' // 10^68 (muryōtaisū)
41
+ ]
42
+
43
+ /** Converts a segment of up to 4 digits to Japanese kanji with 一 omission rules. */
44
+ segmentToWords (num) {
45
+ if (num === 0n) return ''
46
+
47
+ const thousands = num / 1000n
48
+ const hundreds = (num % 1000n) / 100n
49
+ const tens = (num % 100n) / 10n
50
+ const ones = num % 10n
51
+
52
+ let result = ''
53
+
54
+ // Thousands (千)
55
+ if (thousands > 0n) {
56
+ // Always omit 一 before 千 when thousands === 1
57
+ if (thousands === 1n) {
58
+ result += '千'
59
+ } else {
60
+ result += this.onesWords[Number(thousands) - 1] + '千'
61
+ }
62
+ }
63
+
64
+ // Hundreds (百)
65
+ if (hundreds > 0n) {
66
+ // Always omit 一 before 百 when hundreds === 1
67
+ if (hundreds === 1n) {
68
+ result += '百'
69
+ } else {
70
+ result += this.onesWords[Number(hundreds) - 1] + '百'
71
+ }
72
+ }
73
+
74
+ // Tens (十)
75
+ if (tens > 0n) {
76
+ // Always omit 一 before 十 when tens === 1
77
+ if (tens === 1n) {
78
+ result += '十'
79
+ } else {
80
+ result += this.onesWords[Number(tens) - 1] + '十'
81
+ }
82
+ }
83
+
84
+ // Ones
85
+ if (ones > 0n) {
86
+ result += this.onesWords[Number(ones) - 1]
87
+ }
88
+
89
+ return result
90
+ }
91
+
92
+ /** Converts integer part using Japanese 万-based grouping system. */
93
+ integerToWords (integerPart) {
94
+ if (integerPart === 0n) {
95
+ return this.zeroWord
96
+ }
97
+
98
+ let temp = integerPart
99
+ let scaleIndex = 0
100
+ const groups = []
101
+
102
+ // Split into groups of 4 digits (万-based system)
103
+ while (temp > 0n) {
104
+ const group = temp % 10000n
105
+ if (group > 0n) {
106
+ groups.push({ value: group, scale: scaleIndex })
107
+ }
108
+ temp = temp / 10000n
109
+ scaleIndex++
110
+ }
111
+
112
+ // Reverse to process from highest to lowest
113
+ groups.reverse()
114
+
115
+ let result = ''
116
+
117
+ for (let i = 0; i < groups.length; i++) {
118
+ const { value, scale } = groups[i]
119
+
120
+ const groupStr = this.segmentToWords(value)
121
+
122
+ // For scales >= 1 (万 and above), always add the scale word
123
+ if (scale >= 1) {
124
+ // Special case: if group is 1 and scale >= 1, we need 一 before the scale
125
+ if (value === 1n) {
126
+ result += '一' + this.scaleWords[scale]
127
+ } else {
128
+ result += groupStr + this.scaleWords[scale]
129
+ }
130
+ } else {
131
+ result += groupStr
132
+ }
133
+ }
134
+
135
+ return result
136
+ }
137
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Kannada language converter.
3
+ *
4
+ * Supports:
5
+ * - Indian numbering system (ಸಾವಿರ, ಲಕ್ಷ, ಕೋಟಿ)
6
+ * - Kannada script
7
+ * - Complete word forms for 0-99
8
+ */
9
+ export class Kannada extends SouthAsianLanguage {
10
+ }
11
+ import { SouthAsianLanguage } from '../classes/south-asian-language.js';
@@ -0,0 +1,42 @@
1
+ import { SouthAsianLanguage } from '../classes/south-asian-language.js'
2
+
3
+ /**
4
+ * Kannada language converter.
5
+ *
6
+ * Supports:
7
+ * - Indian numbering system (ಸಾವಿರ, ಲಕ್ಷ, ಕೋಟಿ)
8
+ * - Kannada script
9
+ * - Complete word forms for 0-99
10
+ */
11
+ export class Kannada extends SouthAsianLanguage {
12
+ negativeWord = 'ಋಣಾತ್ಮಕ'
13
+ decimalSeparatorWord = 'ದಶಮಾಂಶ'
14
+ zeroWord = 'ಸೊನ್ನೆ'
15
+ hundredWord = 'ನೂರು'
16
+ usePerDigitDecimals = true
17
+
18
+ belowHundredWords = [
19
+ 'ಸೊನ್ನೆ', 'ಒಂದು', 'ಎರಡು', 'ಮೂರು', 'ನಾಲ್ಕು', 'ಐದು', 'ಆರು', 'ಏಳು', 'ಎಂಟು', 'ಒಂಬತ್ತು',
20
+ 'ಹತ್ತು', 'ಹನ್ನೊಂದು', 'ಹನ್ನೆರಡು', 'ಹದಿಮೂರು', 'ಹದಿನಾಲ್ಕು', 'ಹದಿನೈದು', 'ಹದಿನಾರು', 'ಹದಿನೇಳು', 'ಹದಿನೆಂಟು', 'ಹತ್ತೊಂಬತ್ತು',
21
+ 'ಇಪ್ಪತ್ತು', 'ಇಪ್ಪತ್ತೊಂದು', 'ಇಪ್ಪತ್ತೆರಡು', 'ಇಪ್ಪತ್ತಮೂರು', 'ಇಪ್ಪತ್ತನಾಲ್ಕು', 'ಇಪ್ಪತ್ತೈದು', 'ಇಪ್ಪತ್ತಾರು', 'ಇಪ್ಪತ್ತೇಳು', 'ಇಪ್ಪತ್ತೆಂಟು', 'ಇಪ್ಪತ್ತೊಂಬತ್ತು',
22
+ 'ಮೂವತ್ತು', 'ಮೂವತ್ತೊಂದು', 'ಮೂವತ್ತೆರಡು', 'ಮೂವತ್ತಮೂರು', 'ಮೂವತ್ತನಾಲ್ಕು', 'ಮೂವತ್ತೈದು', 'ಮೂವತ್ತಾರು', 'ಮೂವತ್ತೇಳು', 'ಮೂವತ್ತೆಂಟು', 'ಮೂವತ್ತೊಂಬತ್ತು',
23
+ 'ನಲವತ್ತು', 'ನಲವತ್ತೊಂದು', 'ನಲವತ್ತೆರಡು', 'ನಲವತ್ತಮೂರು', 'ನಲವತ್ತನಾಲ್ಕು', 'ನಲವತ್ತೈದು', 'ನಲವತ್ತಾರು', 'ನಲವತ್ತೇಳು', 'ನಲವತ್ತೆಂಟು', 'ನಲವತ್ತೊಂಬತ್ತು',
24
+ 'ಐವತ್ತು', 'ಐವತ್ತೊಂದು', 'ಐವತ್ತೆರಡು', 'ಐವತ್ತಮೂರು', 'ಐವತ್ತನಾಲ್ಕು', 'ಐವತ್ತೈದು', 'ಐವತ್ತಾರು', 'ಐವತ್ತೇಳು', 'ಐವತ್ತೆಂಟು', 'ಐವತ್ತೊಂಬತ್ತು',
25
+ 'ಅರವತ್ತು', 'ಅರವತ್ತೊಂದು', 'ಅರವತ್ತೆರಡು', 'ಅರವತ್ತಮೂರು', 'ಅರವತ್ತನಾಲ್ಕು', 'ಅರವತ್ತೈದು', 'ಅರವತ್ತಾರು', 'ಅರವತ್ತೇಳು', 'ಅರವತ್ತೆಂಟು', 'ಅರವತ್ತೊಂಬತ್ತು',
26
+ 'ಎಪ್ಪತ್ತು', 'ಎಪ್ಪತ್ತೊಂದು', 'ಎಪ್ಪತ್ತೆರಡು', 'ಎಪ್ಪತ್ತಮೂರು', 'ಎಪ್ಪತ್ತನಾಲ್ಕು', 'ಎಪ್ಪತ್ತೈದು', 'ಎಪ್ಪತ್ತಾರು', 'ಎಪ್ಪತ್ತೇಳು', 'ಎಪ್ಪತ್ತೆಂಟು', 'ಎಪ್ಪತ್ತೊಂಬತ್ತು',
27
+ 'ಎಂಬತ್ತು', 'ಎಂಬತ್ತೊಂದು', 'ಎಂಬತ್ತೆರಡು', 'ಎಂಬತ್ತಮೂರು', 'ಎಂಬತ್ತನಾಲ್ಕು', 'ಎಂಬತ್ತೈದು', 'ಎಂಬತ್ತಾರು', 'ಎಂಬತ್ತೇಳು', 'ಎಂಬತ್ತೆಂಟು', 'ಎಂಬತ್ತೊಂಬತ್ತು',
28
+ 'ತೊಂಬತ್ತು', 'ತೊಂಬತ್ತೊಂದು', 'ತೊಂಬತ್ತೆರಡು', 'ತೊಂಬತ್ತಮೂರು', 'ತೊಂಬತ್ತನಾಲ್ಕು', 'ತೊಂಬತ್ತೈದು', 'ತೊಂಬತ್ತಾರು', 'ತೊಂಬತ್ತೇಳು', 'ತೊಂಬತ್ತೆಂಟು', 'ತೊಂಬತ್ತೊಂಬತ್ತು'
29
+ ]
30
+
31
+ scaleWords = [
32
+ '', // units
33
+ 'ಸಾವಿರ', // thousand (1,000)
34
+ 'ಲಕ್ಷ', // lakh (100,000)
35
+ 'ಕೋಟಿ', // crore (10,000,000)
36
+ 'ಅಬ್ಜ', // arab (1,000,000,000)
37
+ 'ಖರ್ವ', // kharab (100,000,000,000)
38
+ 'ನೀಲ', // neel (10,000,000,000,000)
39
+ 'ಪದ್ಮ', // padma (1,000,000,000,000,000)
40
+ 'ಶಂಖ' // shankh (100,000,000,000,000,000)
41
+ ]
42
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Korean language converter.
3
+ *
4
+ * Supports:
5
+ * - Hangul numerals (일, 이, 삼, etc.)
6
+ * - Grouping by 만 (10,000) system
7
+ * - Implicit '일' (one) omission before multipliers
8
+ */
9
+ export class Korean extends GreedyScaleLanguage {
10
+ scaleWords: (string | bigint)[][];
11
+ /** Combines two word-sets according to Korean grammar rules. */
12
+ combineWordSets(preceding: any, following: any): any;
13
+ }
14
+ import { GreedyScaleLanguage } from '../classes/greedy-scale-language.js';
@@ -0,0 +1,55 @@
1
+ import { GreedyScaleLanguage } from '../classes/greedy-scale-language.js'
2
+
3
+ /**
4
+ * Korean language converter.
5
+ *
6
+ * Supports:
7
+ * - Hangul numerals (일, 이, 삼, etc.)
8
+ * - Grouping by 만 (10,000) system
9
+ * - Implicit '일' (one) omission before multipliers
10
+ */
11
+ export class Korean extends GreedyScaleLanguage {
12
+ negativeWord = '마이너스'
13
+ decimalSeparatorWord = '점'
14
+ zeroWord = '영'
15
+
16
+ scaleWords = [
17
+ [10_000_000_000_000_000_000_000_000_000n, '양'],
18
+ [1_000_000_000_000_000_000_000_000n, '자'],
19
+ [100_000_000_000_000_000_000n, '해'],
20
+ [10_000_000_000_000_000n, '경'],
21
+ [1_000_000_000_000n, '조'],
22
+ [100_000_000n, '억'],
23
+ [10_000n, '만'],
24
+ [1000n, '천'],
25
+ [100n, '백'],
26
+ [10n, '십'],
27
+ [9n, '구'],
28
+ [8n, '팔'],
29
+ [7n, '칠'],
30
+ [6n, '육'],
31
+ [5n, '오'],
32
+ [4n, '사'],
33
+ [3n, '삼'],
34
+ [2n, '이'],
35
+ [1n, '일'],
36
+ [0n, '영']
37
+ ]
38
+
39
+ /** Combines two word-sets according to Korean grammar rules. */
40
+ combineWordSets (preceding, following) {
41
+ const precedingWord = Object.keys(preceding)[0]
42
+ const followingWord = Object.keys(following)[0]
43
+ const precedingValue = Object.values(preceding)[0] // BigInt
44
+ const followingValue = Object.values(following)[0] // BigInt
45
+
46
+ // Implicit "일": omit 1 before multipliers up to 만 (10,000)
47
+ if (precedingValue === 1n && followingValue <= 10_000n) return following
48
+ // Concatenate (no space) for small numbers less than 만
49
+ if (precedingValue < 10_000n && precedingValue > followingValue) return { [`${precedingWord}${followingWord}`]: precedingValue + followingValue }
50
+ // Space-separate for large numbers (>= 만) when adding
51
+ if (precedingValue >= 10_000n && precedingValue > followingValue) return { [`${precedingWord} ${followingWord}`]: precedingValue + followingValue }
52
+ // Multiply for all scale combinations
53
+ return { [`${precedingWord}${followingWord}`]: precedingValue * followingValue }
54
+ }
55
+ }
@@ -1,13 +1,13 @@
1
1
  /**
2
- * Converts a value to cardinal (written) form.
3
- * @param {number|string|bigint} value Number to be convert.
4
- * @param {object} [options] Options for class.
5
- * @returns {string} Value in cardinal (written) format.
6
- * @throws {Error} Value cannot be invalid.
2
+ * Lithuanian language converter.
3
+ *
4
+ * Supports:
5
+ * - Three-form pluralization (one/few/many)
6
+ * - Gender agreement (vienas/viena, du/dvi)
7
+ * - Baltic declension patterns
7
8
  */
8
- export default function floatToCardinal(value: number | string | bigint, options?: object): string;
9
- export class N2WordsPL extends N2WordsRU {
10
- ones: {
9
+ export class Lithuanian extends SlavicLanguage {
10
+ onesWords: {
11
11
  1: string;
12
12
  2: string;
13
13
  3: string;
@@ -18,8 +18,7 @@ export class N2WordsPL extends N2WordsRU {
18
18
  8: string;
19
19
  9: string;
20
20
  };
21
- tens: {
22
- 0: string;
21
+ onesFeminineWords: {
23
22
  1: string;
24
23
  2: string;
25
24
  3: string;
@@ -30,7 +29,9 @@ export class N2WordsPL extends N2WordsRU {
30
29
  8: string;
31
30
  9: string;
32
31
  };
33
- twenties: {
32
+ teensWords: {
33
+ 0: string;
34
+ 1: string;
34
35
  2: string;
35
36
  3: string;
36
37
  4: string;
@@ -40,8 +41,7 @@ export class N2WordsPL extends N2WordsRU {
40
41
  8: string;
41
42
  9: string;
42
43
  };
43
- hundreds: {
44
- 1: string;
44
+ twentiesWords: {
45
45
  2: string;
46
46
  3: string;
47
47
  4: string;
@@ -51,7 +51,8 @@ export class N2WordsPL extends N2WordsRU {
51
51
  8: string;
52
52
  9: string;
53
53
  };
54
- thousands: {
54
+ hundredsWords: string[];
55
+ pluralForms: {
55
56
  1: string[];
56
57
  2: string[];
57
58
  3: string[];
@@ -63,5 +64,7 @@ export class N2WordsPL extends N2WordsRU {
63
64
  9: string[];
64
65
  10: string[];
65
66
  };
67
+ pluralize(n: any, forms: any): any;
68
+ integerToWords(integerPart: any): string;
66
69
  }
67
- import { N2WordsRU } from './ru.js';
70
+ import { SlavicLanguage } from '../classes/slavic-language.js';
@@ -0,0 +1,136 @@
1
+ import { SlavicLanguage } from '../classes/slavic-language.js'
2
+
3
+ /**
4
+ * Lithuanian language converter.
5
+ *
6
+ * Supports:
7
+ * - Three-form pluralization (one/few/many)
8
+ * - Gender agreement (vienas/viena, du/dvi)
9
+ * - Baltic declension patterns
10
+ */
11
+ export class Lithuanian extends SlavicLanguage {
12
+ negativeWord = 'minus'
13
+ decimalSeparatorWord = 'kablelis'
14
+ zeroWord = 'nulis'
15
+
16
+ onesWords = {
17
+ 1: 'vienas',
18
+ 2: 'du',
19
+ 3: 'trys',
20
+ 4: 'keturi',
21
+ 5: 'penki',
22
+ 6: 'šeši',
23
+ 7: 'septyni',
24
+ 8: 'aštuoni',
25
+ 9: 'devyni'
26
+ }
27
+
28
+ onesFeminineWords = {
29
+ 1: 'viena',
30
+ 2: 'dvi',
31
+ 3: 'trys',
32
+ 4: 'keturios',
33
+ 5: 'penkios',
34
+ 6: 'šešios',
35
+ 7: 'septynios',
36
+ 8: 'aštuonios',
37
+ 9: 'devynios'
38
+ }
39
+
40
+ teensWords = {
41
+ 0: 'dešimt',
42
+ 1: 'vienuolika',
43
+ 2: 'dvylika',
44
+ 3: 'trylika',
45
+ 4: 'keturiolika',
46
+ 5: 'penkiolika',
47
+ 6: 'šešiolika',
48
+ 7: 'septyniolika',
49
+ 8: 'aštuoniolika',
50
+ 9: 'devyniolika'
51
+ }
52
+
53
+ twentiesWords = {
54
+ 2: 'dvidešimt',
55
+ 3: 'trisdešimt',
56
+ 4: 'keturiasdešimt',
57
+ 5: 'penkiasdešimt',
58
+ 6: 'šešiasdešimt',
59
+ 7: 'septyniasdešimt',
60
+ 8: 'aštuoniasdešimt',
61
+ 9: 'devyniasdešimt'
62
+ }
63
+
64
+ hundredsWords = ['šimtas', 'šimtai']
65
+
66
+ pluralForms = {
67
+ 1: ['tūkstantis', 'tūkstančiai', 'tūkstančių'],
68
+ 2: ['milijonas', 'milijonai', 'milijonų'],
69
+ 3: ['milijardas', 'milijardai', 'milijardų'],
70
+ 4: ['trilijonas', 'trilijonai', 'trilijonų'],
71
+ 5: ['kvadrilijonas', 'kvadrilijonai', 'kvadrilijonų'],
72
+ 6: ['kvintilijonas', 'kvintilijonai', 'kvintilijonų'],
73
+ 7: ['sikstilijonas', 'sikstilijonai', 'sikstilijonų'],
74
+ 8: ['septilijonas', 'septilijonai', 'septilijonų'],
75
+ 9: ['oktilijonas', 'oktilijonai', 'oktilijonų'],
76
+ 10: ['naintilijonas', 'naintilijonai', 'naintilijonų']
77
+ }
78
+
79
+ pluralize (n, forms) {
80
+ if (n === 0n) {
81
+ return forms[2]
82
+ }
83
+
84
+ const [n1, n2] = this.extractDigits(n)
85
+
86
+ if (n2 === 1n || n1 === 0n) {
87
+ return forms[2]
88
+ }
89
+
90
+ if (n1 === 1n) {
91
+ return forms[0]
92
+ }
93
+
94
+ return forms[1]
95
+ }
96
+
97
+ integerToWords (integerPart) {
98
+ if (integerPart === 0n) {
99
+ return this.zeroWord
100
+ }
101
+ const words = []
102
+ const segments = this.splitToSegments(integerPart.toString(), 3)
103
+ let index = segments.length
104
+ for (const x of segments) {
105
+ index = index - 1
106
+ if (x === 0n) {
107
+ continue
108
+ }
109
+ const [n1, n2, n3] = this.extractDigits(x)
110
+ if (n3 > 0n) {
111
+ words.push(this.onesWords[n3])
112
+ if (n3 > 1n) {
113
+ words.push(this.hundredsWords[1])
114
+ } else {
115
+ words.push(this.hundredsWords[0])
116
+ }
117
+ }
118
+ if (n2 > 1n) {
119
+ words.push(this.twentiesWords[n2])
120
+ }
121
+ if (n2 === 1n) {
122
+ words.push(this.teensWords[n1])
123
+ } else if (n1 > 0n) {
124
+ if ((index === 1 || (this.options.gender === 'feminine' && index === 0)) && integerPart < 1000n) {
125
+ words.push(this.onesFeminineWords[n1])
126
+ } else {
127
+ words.push(this.onesWords[n1])
128
+ }
129
+ }
130
+ if (index > 0) {
131
+ words.push(this.pluralize(x, this.pluralForms[index]))
132
+ }
133
+ }
134
+ return words.join(' ')
135
+ }
136
+ }