n2words 2.0.0 → 3.1.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 (335) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/README.md +86 -188
  3. package/dist/languages/am-Latn.js +3 -0
  4. package/dist/languages/am-Latn.js.map +1 -0
  5. package/dist/languages/am.js +3 -0
  6. package/dist/languages/am.js.map +1 -0
  7. package/dist/languages/ar.js +3 -0
  8. package/dist/languages/ar.js.map +1 -0
  9. package/dist/languages/az.js +3 -0
  10. package/dist/languages/az.js.map +1 -0
  11. package/dist/languages/bn.js +3 -0
  12. package/dist/languages/bn.js.map +1 -0
  13. package/dist/languages/cs.js +3 -0
  14. package/dist/languages/cs.js.map +1 -0
  15. package/dist/languages/da.js +3 -0
  16. package/dist/languages/da.js.map +1 -0
  17. package/dist/languages/de.js +3 -0
  18. package/dist/languages/de.js.map +1 -0
  19. package/dist/languages/el.js +3 -0
  20. package/dist/languages/el.js.map +1 -0
  21. package/dist/languages/en.js +3 -0
  22. package/dist/languages/en.js.map +1 -0
  23. package/dist/languages/es.js +3 -0
  24. package/dist/languages/es.js.map +1 -0
  25. package/dist/languages/fa.js +3 -0
  26. package/dist/languages/fa.js.map +1 -0
  27. package/dist/languages/fi.js +3 -0
  28. package/dist/languages/fi.js.map +1 -0
  29. package/dist/languages/fil.js +3 -0
  30. package/dist/languages/fil.js.map +1 -0
  31. package/dist/languages/fr-BE.js +3 -0
  32. package/dist/languages/fr-BE.js.map +1 -0
  33. package/dist/languages/fr.js +3 -0
  34. package/dist/languages/fr.js.map +1 -0
  35. package/dist/languages/gu.js +3 -0
  36. package/dist/languages/gu.js.map +1 -0
  37. package/dist/languages/ha.js +3 -0
  38. package/dist/languages/ha.js.map +1 -0
  39. package/dist/languages/hbo.js +3 -0
  40. package/dist/languages/hbo.js.map +1 -0
  41. package/dist/languages/he.js +3 -0
  42. package/dist/languages/he.js.map +1 -0
  43. package/dist/languages/hi.js +3 -0
  44. package/dist/languages/hi.js.map +1 -0
  45. package/dist/languages/hr.js +3 -0
  46. package/dist/languages/hr.js.map +1 -0
  47. package/dist/languages/hu.js +3 -0
  48. package/dist/languages/hu.js.map +1 -0
  49. package/dist/languages/id.js +3 -0
  50. package/dist/languages/id.js.map +1 -0
  51. package/dist/languages/it.js +3 -0
  52. package/dist/languages/it.js.map +1 -0
  53. package/dist/languages/ja.js +3 -0
  54. package/dist/languages/ja.js.map +1 -0
  55. package/dist/languages/ka.js +3 -0
  56. package/dist/languages/ka.js.map +1 -0
  57. package/dist/languages/kn.js +3 -0
  58. package/dist/languages/kn.js.map +1 -0
  59. package/dist/languages/ko.js +3 -0
  60. package/dist/languages/ko.js.map +1 -0
  61. package/dist/languages/lt.js +3 -0
  62. package/dist/languages/lt.js.map +1 -0
  63. package/dist/languages/lv.js +3 -0
  64. package/dist/languages/lv.js.map +1 -0
  65. package/dist/languages/mr.js +3 -0
  66. package/dist/languages/mr.js.map +1 -0
  67. package/dist/languages/ms.js +3 -0
  68. package/dist/languages/ms.js.map +1 -0
  69. package/dist/languages/nb.js +3 -0
  70. package/dist/languages/nb.js.map +1 -0
  71. package/dist/languages/nl.js +3 -0
  72. package/dist/languages/nl.js.map +1 -0
  73. package/dist/languages/pa.js +3 -0
  74. package/dist/languages/pa.js.map +1 -0
  75. package/dist/languages/pl.js +3 -0
  76. package/dist/languages/pl.js.map +1 -0
  77. package/dist/languages/pt.js +3 -0
  78. package/dist/languages/pt.js.map +1 -0
  79. package/dist/languages/ro.js +3 -0
  80. package/dist/languages/ro.js.map +1 -0
  81. package/dist/languages/ru.js +3 -0
  82. package/dist/languages/ru.js.map +1 -0
  83. package/dist/languages/sr-Cyrl.js +3 -0
  84. package/dist/languages/sr-Cyrl.js.map +1 -0
  85. package/dist/languages/sr-Latn.js +3 -0
  86. package/dist/languages/sr-Latn.js.map +1 -0
  87. package/dist/languages/sv.js +3 -0
  88. package/dist/languages/sv.js.map +1 -0
  89. package/dist/languages/sw.js +3 -0
  90. package/dist/languages/sw.js.map +1 -0
  91. package/dist/languages/ta.js +3 -0
  92. package/dist/languages/ta.js.map +1 -0
  93. package/dist/languages/te.js +3 -0
  94. package/dist/languages/te.js.map +1 -0
  95. package/dist/languages/th.js +3 -0
  96. package/dist/languages/th.js.map +1 -0
  97. package/dist/languages/tr.js +3 -0
  98. package/dist/languages/tr.js.map +1 -0
  99. package/dist/languages/uk.js +3 -0
  100. package/dist/languages/uk.js.map +1 -0
  101. package/dist/languages/ur.js +3 -0
  102. package/dist/languages/ur.js.map +1 -0
  103. package/dist/languages/vi.js +3 -0
  104. package/dist/languages/vi.js.map +1 -0
  105. package/dist/languages/yo.js +3 -0
  106. package/dist/languages/yo.js.map +1 -0
  107. package/dist/languages/zh-Hans.js +3 -0
  108. package/dist/languages/zh-Hans.js.map +1 -0
  109. package/dist/languages/zh-Hant.js +3 -0
  110. package/dist/languages/zh-Hant.js.map +1 -0
  111. package/dist/n2words.js +2 -2
  112. package/dist/n2words.js.map +1 -1
  113. package/lib/languages/am-Latn.d.ts +7 -0
  114. package/lib/languages/am-Latn.js +159 -0
  115. package/lib/languages/am.d.ts +7 -0
  116. package/lib/languages/am.js +159 -0
  117. package/lib/languages/ar.d.ts +14 -27
  118. package/lib/languages/ar.js +175 -129
  119. package/lib/languages/az.d.ts +4 -9
  120. package/lib/languages/az.js +166 -37
  121. package/lib/languages/bn.d.ts +4 -8
  122. package/lib/languages/bn.js +159 -124
  123. package/lib/languages/cs.d.ts +15 -85
  124. package/lib/languages/cs.js +293 -114
  125. package/lib/languages/da.d.ts +11 -12
  126. package/lib/languages/da.js +269 -101
  127. package/lib/languages/de.d.ts +14 -11
  128. package/lib/languages/de.js +305 -86
  129. package/lib/languages/el.d.ts +11 -11
  130. package/lib/languages/el.js +224 -78
  131. package/lib/languages/en.d.ts +14 -13
  132. package/lib/languages/en.js +228 -72
  133. package/lib/languages/es.d.ts +18 -12
  134. package/lib/languages/es.js +297 -103
  135. package/lib/languages/fa.d.ts +4 -44
  136. package/lib/languages/fa.js +112 -122
  137. package/lib/languages/fi.d.ts +14 -0
  138. package/lib/languages/fi.js +238 -0
  139. package/lib/languages/fil.d.ts +4 -13
  140. package/lib/languages/fil.js +196 -106
  141. package/lib/languages/fr-BE.d.ts +8 -8
  142. package/lib/languages/fr-BE.js +285 -19
  143. package/lib/languages/fr.d.ts +18 -12
  144. package/lib/languages/fr.js +339 -89
  145. package/lib/languages/gu.d.ts +4 -8
  146. package/lib/languages/gu.js +143 -125
  147. package/lib/languages/ha.d.ts +7 -0
  148. package/lib/languages/ha.js +225 -0
  149. package/lib/languages/hbo.d.ts +10 -110
  150. package/lib/languages/hbo.js +245 -214
  151. package/lib/languages/he.d.ts +10 -77
  152. package/lib/languages/he.js +231 -172
  153. package/lib/languages/hi.d.ts +4 -8
  154. package/lib/languages/hi.js +163 -124
  155. package/lib/languages/hr.d.ts +8 -77
  156. package/lib/languages/hr.js +200 -89
  157. package/lib/languages/hu.d.ts +4 -19
  158. package/lib/languages/hu.js +198 -119
  159. package/lib/languages/id.d.ts +4 -34
  160. package/lib/languages/id.js +166 -129
  161. package/lib/languages/it.d.ts +16 -34
  162. package/lib/languages/it.js +307 -97
  163. package/lib/languages/ja.d.ts +14 -14
  164. package/lib/languages/ja.js +221 -111
  165. package/lib/languages/ka.d.ts +17 -0
  166. package/lib/languages/ka.js +291 -0
  167. package/lib/languages/kn.d.ts +4 -8
  168. package/lib/languages/kn.js +143 -35
  169. package/lib/languages/ko.d.ts +11 -11
  170. package/lib/languages/ko.js +250 -49
  171. package/lib/languages/lt.d.ts +15 -67
  172. package/lib/languages/lt.js +287 -122
  173. package/lib/languages/lv.d.ts +15 -67
  174. package/lib/languages/lv.js +288 -106
  175. package/lib/languages/mr.d.ts +4 -8
  176. package/lib/languages/mr.js +143 -125
  177. package/lib/languages/ms.d.ts +4 -28
  178. package/lib/languages/ms.js +166 -116
  179. package/lib/languages/nb.d.ts +11 -9
  180. package/lib/languages/nb.js +272 -87
  181. package/lib/languages/nl.d.ts +23 -13
  182. package/lib/languages/nl.js +299 -133
  183. package/lib/languages/pa.d.ts +4 -8
  184. package/lib/languages/pa.js +151 -124
  185. package/lib/languages/pl.d.ts +19 -77
  186. package/lib/languages/pl.js +294 -87
  187. package/lib/languages/pt.d.ts +14 -26
  188. package/lib/languages/pt.js +272 -92
  189. package/lib/languages/ro.d.ts +15 -155
  190. package/lib/languages/ro.js +219 -235
  191. package/lib/languages/ru.d.ts +8 -82
  192. package/lib/languages/ru.js +239 -90
  193. package/lib/languages/sr-Cyrl.d.ts +8 -77
  194. package/lib/languages/sr-Cyrl.js +197 -89
  195. package/lib/languages/sr-Latn.d.ts +8 -77
  196. package/lib/languages/sr-Latn.js +197 -89
  197. package/lib/languages/sv.d.ts +11 -11
  198. package/lib/languages/sv.js +278 -74
  199. package/lib/languages/sw.d.ts +4 -36
  200. package/lib/languages/sw.js +133 -106
  201. package/lib/languages/ta.d.ts +4 -17
  202. package/lib/languages/ta.js +143 -202
  203. package/lib/languages/te.d.ts +4 -19
  204. package/lib/languages/te.js +133 -196
  205. package/lib/languages/th.d.ts +4 -14
  206. package/lib/languages/th.js +135 -91
  207. package/lib/languages/tr.d.ts +15 -9
  208. package/lib/languages/tr.js +245 -49
  209. package/lib/languages/uk.d.ts +8 -82
  210. package/lib/languages/uk.js +206 -78
  211. package/lib/languages/ur.d.ts +4 -8
  212. package/lib/languages/ur.js +151 -124
  213. package/lib/languages/vi.d.ts +14 -69
  214. package/lib/languages/vi.js +278 -129
  215. package/lib/languages/yo.d.ts +7 -0
  216. package/lib/languages/yo.js +303 -0
  217. package/lib/languages/zh-Hans.d.ts +8 -18
  218. package/lib/languages/zh-Hans.js +163 -92
  219. package/lib/languages/zh-Hant.d.ts +8 -18
  220. package/lib/languages/zh-Hant.js +181 -90
  221. package/lib/n2words.d.ts +55 -209
  222. package/lib/n2words.js +115 -530
  223. package/lib/utils/is-plain-object.d.ts +13 -0
  224. package/lib/utils/is-plain-object.js +17 -0
  225. package/lib/utils/parse-numeric.d.ts +17 -0
  226. package/lib/utils/parse-numeric.js +108 -0
  227. package/lib/utils/validate-options.d.ts +8 -0
  228. package/lib/utils/validate-options.js +16 -0
  229. package/package.json +26 -14
  230. package/dist/ArabicConverter.js +0 -3
  231. package/dist/ArabicConverter.js.map +0 -1
  232. package/dist/AzerbaijaniConverter.js +0 -3
  233. package/dist/AzerbaijaniConverter.js.map +0 -1
  234. package/dist/BanglaConverter.js +0 -3
  235. package/dist/BanglaConverter.js.map +0 -1
  236. package/dist/BiblicalHebrewConverter.js +0 -3
  237. package/dist/BiblicalHebrewConverter.js.map +0 -1
  238. package/dist/CroatianConverter.js +0 -3
  239. package/dist/CroatianConverter.js.map +0 -1
  240. package/dist/CzechConverter.js +0 -3
  241. package/dist/CzechConverter.js.map +0 -1
  242. package/dist/DanishConverter.js +0 -3
  243. package/dist/DanishConverter.js.map +0 -1
  244. package/dist/DutchConverter.js +0 -3
  245. package/dist/DutchConverter.js.map +0 -1
  246. package/dist/EnglishConverter.js +0 -3
  247. package/dist/EnglishConverter.js.map +0 -1
  248. package/dist/FilipinoConverter.js +0 -3
  249. package/dist/FilipinoConverter.js.map +0 -1
  250. package/dist/FrenchBelgiumConverter.js +0 -3
  251. package/dist/FrenchBelgiumConverter.js.map +0 -1
  252. package/dist/FrenchConverter.js +0 -3
  253. package/dist/FrenchConverter.js.map +0 -1
  254. package/dist/GermanConverter.js +0 -3
  255. package/dist/GermanConverter.js.map +0 -1
  256. package/dist/GreekConverter.js +0 -3
  257. package/dist/GreekConverter.js.map +0 -1
  258. package/dist/GujaratiConverter.js +0 -3
  259. package/dist/GujaratiConverter.js.map +0 -1
  260. package/dist/HebrewConverter.js +0 -3
  261. package/dist/HebrewConverter.js.map +0 -1
  262. package/dist/HindiConverter.js +0 -3
  263. package/dist/HindiConverter.js.map +0 -1
  264. package/dist/HungarianConverter.js +0 -3
  265. package/dist/HungarianConverter.js.map +0 -1
  266. package/dist/IndonesianConverter.js +0 -3
  267. package/dist/IndonesianConverter.js.map +0 -1
  268. package/dist/ItalianConverter.js +0 -3
  269. package/dist/ItalianConverter.js.map +0 -1
  270. package/dist/JapaneseConverter.js +0 -3
  271. package/dist/JapaneseConverter.js.map +0 -1
  272. package/dist/KannadaConverter.js +0 -3
  273. package/dist/KannadaConverter.js.map +0 -1
  274. package/dist/KoreanConverter.js +0 -3
  275. package/dist/KoreanConverter.js.map +0 -1
  276. package/dist/LatvianConverter.js +0 -3
  277. package/dist/LatvianConverter.js.map +0 -1
  278. package/dist/LithuanianConverter.js +0 -3
  279. package/dist/LithuanianConverter.js.map +0 -1
  280. package/dist/MalayConverter.js +0 -3
  281. package/dist/MalayConverter.js.map +0 -1
  282. package/dist/MarathiConverter.js +0 -3
  283. package/dist/MarathiConverter.js.map +0 -1
  284. package/dist/NorwegianBokmalConverter.js +0 -3
  285. package/dist/NorwegianBokmalConverter.js.map +0 -1
  286. package/dist/PersianConverter.js +0 -3
  287. package/dist/PersianConverter.js.map +0 -1
  288. package/dist/PolishConverter.js +0 -3
  289. package/dist/PolishConverter.js.map +0 -1
  290. package/dist/PortugueseConverter.js +0 -3
  291. package/dist/PortugueseConverter.js.map +0 -1
  292. package/dist/PunjabiConverter.js +0 -3
  293. package/dist/PunjabiConverter.js.map +0 -1
  294. package/dist/RomanianConverter.js +0 -3
  295. package/dist/RomanianConverter.js.map +0 -1
  296. package/dist/RussianConverter.js +0 -3
  297. package/dist/RussianConverter.js.map +0 -1
  298. package/dist/SerbianCyrillicConverter.js +0 -3
  299. package/dist/SerbianCyrillicConverter.js.map +0 -1
  300. package/dist/SerbianLatinConverter.js +0 -3
  301. package/dist/SerbianLatinConverter.js.map +0 -1
  302. package/dist/SimplifiedChineseConverter.js +0 -3
  303. package/dist/SimplifiedChineseConverter.js.map +0 -1
  304. package/dist/SpanishConverter.js +0 -3
  305. package/dist/SpanishConverter.js.map +0 -1
  306. package/dist/SwahiliConverter.js +0 -3
  307. package/dist/SwahiliConverter.js.map +0 -1
  308. package/dist/SwedishConverter.js +0 -3
  309. package/dist/SwedishConverter.js.map +0 -1
  310. package/dist/TamilConverter.js +0 -3
  311. package/dist/TamilConverter.js.map +0 -1
  312. package/dist/TeluguConverter.js +0 -3
  313. package/dist/TeluguConverter.js.map +0 -1
  314. package/dist/ThaiConverter.js +0 -3
  315. package/dist/ThaiConverter.js.map +0 -1
  316. package/dist/TraditionalChineseConverter.js +0 -3
  317. package/dist/TraditionalChineseConverter.js.map +0 -1
  318. package/dist/TurkishConverter.js +0 -3
  319. package/dist/TurkishConverter.js.map +0 -1
  320. package/dist/UkrainianConverter.js +0 -3
  321. package/dist/UkrainianConverter.js.map +0 -1
  322. package/dist/UrduConverter.js +0 -3
  323. package/dist/UrduConverter.js.map +0 -1
  324. package/dist/VietnameseConverter.js +0 -3
  325. package/dist/VietnameseConverter.js.map +0 -1
  326. package/lib/classes/abstract-language.d.ts +0 -178
  327. package/lib/classes/abstract-language.js +0 -268
  328. package/lib/classes/greedy-scale-language.d.ts +0 -109
  329. package/lib/classes/greedy-scale-language.js +0 -201
  330. package/lib/classes/slavic-language.d.ts +0 -148
  331. package/lib/classes/slavic-language.js +0 -281
  332. package/lib/classes/south-asian-language.d.ts +0 -70
  333. package/lib/classes/south-asian-language.js +0 -154
  334. package/lib/classes/turkic-language.d.ts +0 -26
  335. package/lib/classes/turkic-language.js +0 -59
@@ -1,110 +1,317 @@
1
- import { SlavicLanguage } from '../classes/slavic-language.js'
2
-
3
1
  /**
4
- * Polish language converter.
2
+ * Polish language converter - Functional Implementation
3
+ *
4
+ * Self-contained module with its own input validation, ready for subpath exports.
5
5
  *
6
- * Supports:
7
- * - Three-form pluralization (one/few/many)
8
- * - Polish-specific declension patterns
9
- * - Distinctive Polish phonology and orthography
6
+ * Polish-specific rules:
7
+ * - Three-form pluralization: 1 = singular, 2-4 = few, 5+ = many
8
+ * - Gender agreement (masculine/feminine for numbers < 1000)
9
+ * - Omit "jeden" before scale words (tysiąc, milion, etc.)
10
+ * - Irregular hundreds: dwieście, trzysta, czterysta, pięćset...
11
+ * - Long scale with -ard forms: miliard, biliard, tryliard
12
+ */
13
+
14
+ import { parseNumericValue } from '../utils/parse-numeric.js'
15
+ import { validateOptions } from '../utils/validate-options.js'
16
+
17
+ // ============================================================================
18
+ // Vocabulary (module-level constants)
19
+ // ============================================================================
20
+
21
+ const ONES_MASC = ['', 'jeden', 'dwa', 'trzy', 'cztery', 'pięć', 'sześć', 'siedem', 'osiem', 'dziewięć']
22
+ const ONES_FEM = ['', 'jedna', 'dwie', 'trzy', 'cztery', 'pięć', 'sześć', 'siedem', 'osiem', 'dziewięć']
23
+
24
+ const TEENS = ['dziesięć', 'jedenaście', 'dwanaście', 'trzynaście', 'czternaście', 'piętnaście', 'szesnaście', 'siedemnaście', 'osiemnaście', 'dziewiętnaście']
25
+
26
+ const TENS = ['', '', 'dwadzieścia', 'trzydzieści', 'czterdzieści', 'pięćdziesiąt', 'sześćdziesiąt', 'siedemdziesiąt', 'osiemdziesiąt', 'dziewięćdziesiąt']
27
+
28
+ // Irregular hundreds
29
+ const HUNDREDS = ['', 'sto', 'dwieście', 'trzysta', 'czterysta', 'pięćset', 'sześćset', 'siedemset', 'osiemset', 'dziewięćset']
30
+
31
+ // Scale words: [singular, few (2-4), many (5+)]
32
+ const PLURAL_FORMS = {
33
+ 1: ['tysiąc', 'tysiące', 'tysięcy'],
34
+ 2: ['milion', 'miliony', 'milionów'],
35
+ 3: ['miliard', 'miliardy', 'miliardów'],
36
+ 4: ['bilion', 'biliony', 'bilionów'],
37
+ 5: ['biliard', 'biliardy', 'biliardów'],
38
+ 6: ['trylion', 'tryliony', 'trylionów'],
39
+ 7: ['tryliard', 'tryliardy', 'tryliardów'],
40
+ 8: ['kwadrylion', 'kwadryliony', 'kwadrylionów'],
41
+ 9: ['kwaryliard', 'kwadryliardy', 'kwadryliardów'],
42
+ 10: ['kwintylion', 'kwintyliony', 'kwintylionów']
43
+ }
44
+
45
+ const ZERO = 'zero'
46
+ const NEGATIVE = 'minus'
47
+ const DECIMAL_SEP = 'przecinek'
48
+
49
+ // ============================================================================
50
+ // Segment Building
51
+ // ============================================================================
52
+
53
+ /**
54
+ * Builds segment word for 0-999 (masculine form).
55
+ * @param {number} n - Segment value
56
+ * @returns {string} Polish word
10
57
  */
11
- export class Polish extends SlavicLanguage {
12
- negativeWord = 'minus'
13
- decimalSeparatorWord = 'przecinek'
14
- zeroWord = 'zero'
15
-
16
- onesWords = {
17
- 1: 'jeden',
18
- 2: 'dwa',
19
- 3: 'trzy',
20
- 4: 'cztery',
21
- 5: 'pięć',
22
- 6: 'sześć',
23
- 7: 'siedem',
24
- 8: 'osiem',
25
- 9: 'dziewięć'
58
+ function buildSegment (n) {
59
+ if (n === 0) return ''
60
+
61
+ const ones = n % 10
62
+ const tens = Math.floor(n / 10) % 10
63
+ const hundreds = Math.floor(n / 100)
64
+
65
+ const parts = []
66
+
67
+ // Hundreds
68
+ if (hundreds > 0) {
69
+ parts.push(HUNDREDS[hundreds])
26
70
  }
27
71
 
28
- onesFeminineWords = {
29
- 1: 'jedna',
30
- 2: 'dwie',
31
- 3: 'trzy',
32
- 4: 'cztery',
33
- 5: 'pięć',
34
- 6: 'sześć',
35
- 7: 'siedem',
36
- 8: 'osiem',
37
- 9: 'dziewięć'
72
+ // Tens and ones
73
+ if (tens === 1) {
74
+ // Teens (10-19)
75
+ parts.push(TEENS[ones])
76
+ } else {
77
+ if (tens >= 2) {
78
+ parts.push(TENS[tens])
79
+ }
80
+ if (ones > 0) {
81
+ parts.push(ONES_MASC[ones])
82
+ }
38
83
  }
39
84
 
40
- teensWords = {
41
- 0: 'dziesięć',
42
- 1: 'jedenaście',
43
- 2: 'dwanaście',
44
- 3: 'trzynaście',
45
- 4: 'czternaście',
46
- 5: 'piętnaście',
47
- 6: 'szesnaście',
48
- 7: 'siedemnaście',
49
- 8: 'osiemnaście',
50
- 9: 'dziewiętnaście'
85
+ return parts.join(' ')
86
+ }
87
+
88
+ /**
89
+ * Builds segment word for 0-999 (feminine form - only differs in ones).
90
+ * @param {number} n - Segment value
91
+ * @returns {string} Polish word
92
+ */
93
+ function buildSegmentFeminine (n) {
94
+ if (n === 0) return ''
95
+
96
+ const ones = n % 10
97
+ const tens = Math.floor(n / 10) % 10
98
+ const hundreds = Math.floor(n / 100)
99
+
100
+ const parts = []
101
+
102
+ // Hundreds
103
+ if (hundreds > 0) {
104
+ parts.push(HUNDREDS[hundreds])
51
105
  }
52
106
 
53
- twentiesWords = {
54
- 2: 'dwadzieścia',
55
- 3: 'trzydzieści',
56
- 4: 'czterdzieści',
57
- 5: 'pięćdziesiąt',
58
- 6: 'sześćdziesiąt',
59
- 7: 'siedemdziesiąt',
60
- 8: 'osiemdziesiąt',
61
- 9: 'dziewięćdziesiąt'
107
+ // Tens and ones - feminine for ones only
108
+ if (tens === 1) {
109
+ parts.push(TEENS[ones])
110
+ } else {
111
+ if (tens >= 2) {
112
+ parts.push(TENS[tens])
113
+ }
114
+ if (ones > 0) {
115
+ parts.push(ONES_FEM[ones])
116
+ }
62
117
  }
63
118
 
64
- hundredsWords = {
65
- 1: 'sto',
66
- 2: 'dwieście',
67
- 3: 'trzysta',
68
- 4: 'czterysta',
69
- 5: 'pięćset',
70
- 6: 'sześćset',
71
- 7: 'siedemset',
72
- 8: 'osiemset',
73
- 9: 'dziewięćset'
119
+ return parts.join(' ')
120
+ }
121
+
122
+ // ============================================================================
123
+ // Helper Functions
124
+ // ============================================================================
125
+
126
+ /**
127
+ * Polish pluralization: 1 = singular, 2-4 = few, else = many.
128
+ * Special case: 11-19 always use many form.
129
+ *
130
+ * @param {bigint} n - Number to pluralize
131
+ * @param {string[]} forms - [singular, few, many]
132
+ * @returns {string} Correct plural form
133
+ */
134
+ function pluralize (n, forms) {
135
+ if (n === 1n) {
136
+ return forms[0]
74
137
  }
75
138
 
76
- pluralForms = {
77
- 1: ['tysiąc', 'tysiące', 'tysięcy'], // 10^ 3
78
- 2: ['milion', 'miliony', 'milionów'], // 10^ 6
79
- 3: ['miliard', 'miliardy', 'miliardów'], // 10^ 9
80
- 4: ['bilion', 'biliony', 'bilionów'], // 10^ 12
81
- 5: ['biliard', 'biliardy', 'biliardów'], // 10^ 15
82
- 6: ['trylion', 'tryliony', 'trylionów'], // 10^ 18
83
- 7: ['tryliard', 'tryliardy', 'tryliardów'], // 10^ 21
84
- 8: ['kwadrylion', 'kwadryliony', 'kwadrylionów'], // 10^ 24
85
- 9: ['kwaryliard', 'kwadryliardy', 'kwadryliardów'], // 10^ 27
86
- 10: ['kwintylion', 'kwintyliony', 'kwintylionów'] // 10^ 30
139
+ const lastDigit = n % 10n
140
+ const lastTwoDigits = n % 100n
141
+
142
+ // Teens (11-19) always use many form
143
+ // 2-4 use few form (but not 12-14)
144
+ if (lastDigit >= 2n && lastDigit <= 4n && (lastTwoDigits < 10n || lastTwoDigits > 20n)) {
145
+ return forms[1]
87
146
  }
88
147
 
89
- /**
90
- * Polish omits "one" before scale words.
91
- * e.g., 1000 is "tysiąc" not "jeden tysiąc"
92
- */
93
- omitOneBeforeScale = true
148
+ return forms[2]
149
+ }
150
+
151
+ // ============================================================================
152
+ // Conversion Functions
153
+ // ============================================================================
154
+
155
+ /**
156
+ * Converts a non-negative integer to Polish words.
157
+ *
158
+ * @param {bigint} n - Non-negative integer to convert
159
+ * @param {Object} options - Conversion options
160
+ * @returns {string} Polish words
161
+ */
162
+ function integerToWords (n, options = {}) {
163
+ if (n === 0n) return ZERO
164
+
165
+ // Fast path: numbers < 1000
166
+ if (n < 1000n) {
167
+ return options.gender === 'feminine' ? buildSegmentFeminine(Number(n)) : buildSegment(Number(n))
168
+ }
94
169
 
95
- /** Implements Polish-specific three-form pluralization rules. */
96
- pluralize (n, forms) {
97
- if (n === 1n) {
98
- return forms[0]
170
+ // Fast path: numbers < 1,000,000 (thousands)
171
+ if (n < 1_000_000n) {
172
+ const thousands = Number(n / 1000n)
173
+ const remainder = Number(n % 1000n)
174
+
175
+ const scaleWord = pluralize(BigInt(thousands), PLURAL_FORMS[1])
176
+
177
+ let result
178
+ if (thousands === 1) {
179
+ // Omit "jeden" before tysiąc
180
+ result = scaleWord
181
+ } else {
182
+ result = buildSegment(thousands) + ' ' + scaleWord
183
+ }
184
+
185
+ if (remainder > 0) {
186
+ result += ' ' + buildSegment(remainder)
99
187
  }
100
188
 
101
- const lastDigit = n % 10n
102
- const lastTwoDigits = n % 100n
189
+ return result
190
+ }
191
+
192
+ // For numbers >= 1,000,000, use scale decomposition
193
+ return buildLargeNumberWords(n, options)
194
+ }
195
+
196
+ /**
197
+ * Builds words for numbers >= 1,000,000.
198
+ * Uses BigInt division for faster segment extraction.
199
+ *
200
+ * @param {bigint} n - Number >= 1,000,000
201
+ * @param {Object} options - Conversion options
202
+ * @returns {string} Polish words
203
+ */
204
+ function buildLargeNumberWords (n, options) {
205
+ // Extract segments using BigInt division (faster than string slicing)
206
+ // Segments stored least-significant first (index 0 = ones, 1 = thousands, etc.)
207
+ const segmentValues = []
208
+ let temp = n
209
+ while (temp > 0n) {
210
+ segmentValues.push(temp % 1000n)
211
+ temp = temp / 1000n
212
+ }
213
+
214
+ // Build result string directly
215
+ let result = ''
216
+
217
+ for (let i = segmentValues.length - 1; i >= 0; i--) {
218
+ const segment = segmentValues[i]
219
+ if (segment === 0n) continue
220
+
221
+ const segmentWord = buildSegment(Number(segment))
222
+
223
+ if (result) result += ' '
224
+
225
+ if (i === 0) {
226
+ // Units segment
227
+ result += segmentWord
228
+ } else {
229
+ // Scale word needed
230
+ const forms = PLURAL_FORMS[i]
231
+ if (forms) {
232
+ const scaleWord = pluralize(segment, forms)
103
233
 
104
- if (lastDigit < 5n && lastDigit > 1n && (lastTwoDigits < 10n || lastTwoDigits > 20n)) {
105
- return forms[1]
234
+ if (segment === 1n) {
235
+ // Omit "jeden" before scale words
236
+ result += scaleWord
237
+ } else {
238
+ result += segmentWord + ' ' + scaleWord
239
+ }
240
+ }
106
241
  }
242
+ }
243
+
244
+ return result
245
+ }
107
246
 
108
- return forms[2]
247
+ /**
248
+ * Converts decimal digits to Polish words.
249
+ *
250
+ * @param {string} decimalPart - Decimal digits (without the point)
251
+ * @param {Object} options - Conversion options
252
+ * @returns {string} Polish words for decimal part
253
+ */
254
+ function decimalPartToWords (decimalPart, options) {
255
+ let result = ''
256
+
257
+ // Handle leading zeros
258
+ let i = 0
259
+ while (i < decimalPart.length && decimalPart[i] === '0') {
260
+ if (result) result += ' '
261
+ result += ZERO
262
+ i++
263
+ }
264
+
265
+ // Convert remainder as a single number
266
+ const remainder = decimalPart.slice(i)
267
+ if (remainder) {
268
+ if (result) result += ' '
269
+ result += integerToWords(BigInt(remainder), options)
109
270
  }
271
+
272
+ return result
110
273
  }
274
+
275
+ /**
276
+ * Converts a numeric value to Polish words.
277
+ *
278
+ * This is the main public API. It accepts any valid numeric input
279
+ * (number, string, or bigint) and handles parsing internally.
280
+ *
281
+ * @param {number | string | bigint} value - The numeric value to convert
282
+ * @param {Object} [options] - Conversion options
283
+ * @param {string} [options.gender='masculine'] - Gender for numbers < 1000
284
+ * @returns {string} The number in Polish words
285
+ * @throws {TypeError} If value is not a valid numeric type
286
+ * @throws {Error} If value is not a valid number format
287
+ *
288
+ * @example
289
+ * toWords(1) // 'jeden'
290
+ * toWords(1, { gender: 'feminine' }) // 'jedna'
291
+ * toWords(1000) // 'tysiąc'
292
+ * toWords(2000) // 'dwa tysiące'
293
+ */
294
+ function toWords (value, options) {
295
+ options = validateOptions(options)
296
+ const { isNegative, integerPart, decimalPart } = parseNumericValue(value)
297
+
298
+ let result = ''
299
+
300
+ if (isNegative) {
301
+ result = NEGATIVE + ' '
302
+ }
303
+
304
+ result += integerToWords(integerPart, options)
305
+
306
+ if (decimalPart) {
307
+ result += ' ' + DECIMAL_SEP + ' ' + decimalPartToWords(decimalPart, options)
308
+ }
309
+
310
+ return result
311
+ }
312
+
313
+ // ============================================================================
314
+ // Public API
315
+ // ============================================================================
316
+
317
+ export { toWords }
@@ -1,29 +1,17 @@
1
1
  /**
2
- * (European) Portuguese language converter.
2
+ * Converts a numeric value to Portuguese words.
3
3
  *
4
- * Supports:
5
- * - Gender-aware hundreds (duzentos, trezentos)
6
- * - "e" (and) conjunction for number combinations
7
- * - Post-processing to normalize word flow
4
+ * This is the main public API. It accepts any valid numeric input
5
+ * (number, string, or bigint) and handles parsing internally.
6
+ *
7
+ * @param {number | string | bigint} value - The numeric value to convert
8
+ * @returns {string} The number in Portuguese words
9
+ * @throws {TypeError} If value is not a valid numeric type
10
+ * @throws {Error} If value is not a valid number format
11
+ *
12
+ * @example
13
+ * toWords(21) // 'vinte e um'
14
+ * toWords(100) // 'cem'
15
+ * toWords(1000000) // 'um milhão'
8
16
  */
9
- export class Portuguese extends GreedyScaleLanguage {
10
- static POSTCLEAN_REGEX: RegExp;
11
- scaleWords: (string | bigint)[][];
12
- hundredsWords: {
13
- 1: string;
14
- 2: string;
15
- 3: string;
16
- 4: string;
17
- 5: string;
18
- 6: string;
19
- 7: string;
20
- 8: string;
21
- 9: string;
22
- };
23
- finalizeWords(words: any): any;
24
- /** Combines two word-sets according to Portuguese grammar rules. */
25
- combineWordSets(preceding: any, following: any): {
26
- [x: string]: any;
27
- };
28
- }
29
- import { GreedyScaleLanguage } from '../classes/greedy-scale-language.js';
17
+ export function toWords(value: number | string | bigint): string;