n2words 1.24.0 → 3.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 (280) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/README.md +183 -156
  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 -2
  8. package/dist/languages/ar.js.map +1 -1
  9. package/dist/languages/az.js +3 -2
  10. package/dist/languages/az.js.map +1 -1
  11. package/dist/languages/bn.js +3 -2
  12. package/dist/languages/bn.js.map +1 -1
  13. package/dist/languages/cs.js +3 -2
  14. package/dist/languages/cs.js.map +1 -1
  15. package/dist/languages/da.js +3 -2
  16. package/dist/languages/da.js.map +1 -1
  17. package/dist/languages/de.js +3 -2
  18. package/dist/languages/de.js.map +1 -1
  19. package/dist/languages/el.js +3 -2
  20. package/dist/languages/el.js.map +1 -1
  21. package/dist/languages/en.js +3 -2
  22. package/dist/languages/en.js.map +1 -1
  23. package/dist/languages/es.js +3 -2
  24. package/dist/languages/es.js.map +1 -1
  25. package/dist/languages/fa.js +3 -2
  26. package/dist/languages/fa.js.map +1 -1
  27. package/dist/languages/fi.js +3 -0
  28. package/dist/languages/fi.js.map +1 -0
  29. package/dist/languages/fil.js +3 -2
  30. package/dist/languages/fil.js.map +1 -1
  31. package/dist/languages/fr-BE.js +3 -2
  32. package/dist/languages/fr-BE.js.map +1 -1
  33. package/dist/languages/fr.js +3 -2
  34. package/dist/languages/fr.js.map +1 -1
  35. package/dist/languages/gu.js +3 -2
  36. package/dist/languages/gu.js.map +1 -1
  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 -2
  42. package/dist/languages/he.js.map +1 -1
  43. package/dist/languages/hi.js +3 -2
  44. package/dist/languages/hi.js.map +1 -1
  45. package/dist/languages/hr.js +3 -2
  46. package/dist/languages/hr.js.map +1 -1
  47. package/dist/languages/hu.js +3 -2
  48. package/dist/languages/hu.js.map +1 -1
  49. package/dist/languages/id.js +3 -2
  50. package/dist/languages/id.js.map +1 -1
  51. package/dist/languages/it.js +3 -2
  52. package/dist/languages/it.js.map +1 -1
  53. package/dist/languages/ja.js +3 -2
  54. package/dist/languages/ja.js.map +1 -1
  55. package/dist/languages/kn.js +3 -2
  56. package/dist/languages/kn.js.map +1 -1
  57. package/dist/languages/ko.js +3 -2
  58. package/dist/languages/ko.js.map +1 -1
  59. package/dist/languages/lt.js +3 -2
  60. package/dist/languages/lt.js.map +1 -1
  61. package/dist/languages/lv.js +3 -2
  62. package/dist/languages/lv.js.map +1 -1
  63. package/dist/languages/mr.js +3 -2
  64. package/dist/languages/mr.js.map +1 -1
  65. package/dist/languages/ms.js +3 -2
  66. package/dist/languages/ms.js.map +1 -1
  67. package/dist/languages/nb.js +3 -2
  68. package/dist/languages/nb.js.map +1 -1
  69. package/dist/languages/nl.js +3 -2
  70. package/dist/languages/nl.js.map +1 -1
  71. package/dist/languages/pa.js +3 -0
  72. package/dist/languages/pa.js.map +1 -0
  73. package/dist/languages/pl.js +3 -2
  74. package/dist/languages/pl.js.map +1 -1
  75. package/dist/languages/pt.js +3 -2
  76. package/dist/languages/pt.js.map +1 -1
  77. package/dist/languages/ro.js +3 -2
  78. package/dist/languages/ro.js.map +1 -1
  79. package/dist/languages/ru.js +3 -2
  80. package/dist/languages/ru.js.map +1 -1
  81. package/dist/languages/sr-Cyrl.js +3 -0
  82. package/dist/languages/sr-Cyrl.js.map +1 -0
  83. package/dist/languages/sr-Latn.js +3 -2
  84. package/dist/languages/sr-Latn.js.map +1 -1
  85. package/dist/languages/sv.js +3 -2
  86. package/dist/languages/sv.js.map +1 -1
  87. package/dist/languages/sw.js +3 -2
  88. package/dist/languages/sw.js.map +1 -1
  89. package/dist/languages/ta.js +3 -2
  90. package/dist/languages/ta.js.map +1 -1
  91. package/dist/languages/te.js +3 -2
  92. package/dist/languages/te.js.map +1 -1
  93. package/dist/languages/th.js +3 -2
  94. package/dist/languages/th.js.map +1 -1
  95. package/dist/languages/tr.js +3 -2
  96. package/dist/languages/tr.js.map +1 -1
  97. package/dist/languages/uk.js +3 -2
  98. package/dist/languages/uk.js.map +1 -1
  99. package/dist/languages/ur.js +3 -2
  100. package/dist/languages/ur.js.map +1 -1
  101. package/dist/languages/vi.js +3 -2
  102. package/dist/languages/vi.js.map +1 -1
  103. package/dist/languages/zh-Hans.js +3 -2
  104. package/dist/languages/zh-Hans.js.map +1 -1
  105. package/dist/languages/zh-Hant.js +3 -0
  106. package/dist/languages/zh-Hant.js.map +1 -0
  107. package/dist/n2words.js +3 -2
  108. package/dist/n2words.js.map +1 -1
  109. package/lib/languages/am-Latn.d.ts +7 -0
  110. package/lib/languages/am-Latn.js +164 -0
  111. package/lib/languages/am.d.ts +7 -0
  112. package/lib/languages/am.js +164 -0
  113. package/lib/languages/ar.d.ts +17 -0
  114. package/lib/languages/ar.js +171 -209
  115. package/lib/languages/az.d.ts +7 -0
  116. package/lib/languages/az.js +167 -49
  117. package/lib/languages/bn.d.ts +7 -0
  118. package/lib/languages/bn.js +142 -123
  119. package/lib/languages/cs.d.ts +18 -0
  120. package/lib/languages/cs.js +303 -176
  121. package/lib/languages/da.d.ts +14 -0
  122. package/lib/languages/da.js +267 -139
  123. package/lib/languages/de.d.ts +17 -0
  124. package/lib/languages/de.js +310 -113
  125. package/lib/languages/el.d.ts +14 -0
  126. package/lib/languages/el.js +225 -98
  127. package/lib/languages/en.d.ts +17 -0
  128. package/lib/languages/en.js +235 -102
  129. package/lib/languages/es.d.ts +21 -0
  130. package/lib/languages/es.js +307 -125
  131. package/lib/languages/fa.d.ts +7 -0
  132. package/lib/languages/fa.js +115 -108
  133. package/lib/languages/fi.d.ts +14 -0
  134. package/lib/languages/fi.js +245 -0
  135. package/lib/languages/fil.d.ts +7 -0
  136. package/lib/languages/fil.js +199 -139
  137. package/lib/languages/fr-BE.d.ts +11 -0
  138. package/lib/languages/fr-BE.js +287 -48
  139. package/lib/languages/fr.d.ts +21 -0
  140. package/lib/languages/fr.js +343 -119
  141. package/lib/languages/gu.d.ts +7 -0
  142. package/lib/languages/gu.js +125 -144
  143. package/lib/languages/ha.d.ts +7 -0
  144. package/lib/languages/ha.js +230 -0
  145. package/lib/languages/hbo.d.ts +13 -0
  146. package/lib/languages/hbo.js +300 -0
  147. package/lib/languages/he.d.ts +13 -0
  148. package/lib/languages/he.js +230 -283
  149. package/lib/languages/hi.d.ts +7 -0
  150. package/lib/languages/hi.js +142 -123
  151. package/lib/languages/hr.d.ts +11 -0
  152. package/lib/languages/hr.js +190 -129
  153. package/lib/languages/hu.d.ts +7 -0
  154. package/lib/languages/hu.js +194 -133
  155. package/lib/languages/id.d.ts +7 -0
  156. package/lib/languages/id.js +167 -140
  157. package/lib/languages/it.d.ts +19 -0
  158. package/lib/languages/it.js +337 -108
  159. package/lib/languages/ja.d.ts +17 -0
  160. package/lib/languages/ja.js +224 -155
  161. package/lib/languages/kn.d.ts +7 -0
  162. package/lib/languages/kn.js +128 -62
  163. package/lib/languages/ko.d.ts +14 -0
  164. package/lib/languages/ko.js +250 -70
  165. package/lib/languages/lt.d.ts +18 -0
  166. package/lib/languages/lt.js +287 -148
  167. package/lib/languages/lv.d.ts +18 -0
  168. package/lib/languages/lv.js +291 -123
  169. package/lib/languages/mr.d.ts +7 -0
  170. package/lib/languages/mr.js +125 -144
  171. package/lib/languages/ms.d.ts +7 -0
  172. package/lib/languages/ms.js +171 -112
  173. package/lib/languages/nb.d.ts +14 -0
  174. package/lib/languages/nb.js +275 -100
  175. package/lib/languages/nl.d.ts +26 -0
  176. package/lib/languages/nl.js +307 -174
  177. package/lib/languages/pa.d.ts +7 -0
  178. package/lib/languages/pa.js +163 -0
  179. package/lib/languages/pl.d.ts +22 -0
  180. package/lib/languages/pl.js +299 -158
  181. package/lib/languages/pt.d.ts +17 -0
  182. package/lib/languages/pt.js +279 -120
  183. package/lib/languages/ro.d.ts +18 -0
  184. package/lib/languages/ro.js +214 -337
  185. package/lib/languages/ru.d.ts +11 -0
  186. package/lib/languages/ru.js +219 -95
  187. package/lib/languages/sr-Cyrl.d.ts +11 -0
  188. package/lib/languages/sr-Cyrl.js +215 -0
  189. package/lib/languages/sr-Latn.d.ts +11 -0
  190. package/lib/languages/sr-Latn.js +190 -132
  191. package/lib/languages/sv.d.ts +14 -0
  192. package/lib/languages/sv.js +280 -103
  193. package/lib/languages/sw.d.ts +7 -0
  194. package/lib/languages/sw.js +135 -103
  195. package/lib/languages/ta.d.ts +7 -0
  196. package/lib/languages/ta.js +133 -205
  197. package/lib/languages/te.d.ts +7 -0
  198. package/lib/languages/te.js +148 -213
  199. package/lib/languages/th.d.ts +7 -0
  200. package/lib/languages/th.js +139 -101
  201. package/lib/languages/tr.d.ts +18 -0
  202. package/lib/languages/tr.js +246 -66
  203. package/lib/languages/uk.d.ts +11 -0
  204. package/lib/languages/uk.js +197 -101
  205. package/lib/languages/ur.d.ts +7 -0
  206. package/lib/languages/ur.js +160 -123
  207. package/lib/languages/vi.d.ts +17 -0
  208. package/lib/languages/vi.js +287 -164
  209. package/lib/languages/zh-Hans.d.ts +11 -0
  210. package/lib/languages/zh-Hans.js +159 -142
  211. package/lib/languages/zh-Hant.d.ts +11 -0
  212. package/lib/languages/zh-Hant.js +202 -0
  213. package/lib/n2words.d.ts +53 -0
  214. package/lib/n2words.js +91 -227
  215. package/lib/utils/is-plain-object.d.ts +13 -0
  216. package/lib/utils/is-plain-object.js +17 -0
  217. package/lib/utils/parse-numeric.d.ts +17 -0
  218. package/lib/utils/parse-numeric.js +108 -0
  219. package/lib/utils/validate-options.d.ts +8 -0
  220. package/lib/utils/validate-options.js +16 -0
  221. package/package.json +118 -67
  222. package/dist/languages/pa-Guru.js +0 -2
  223. package/dist/languages/pa-Guru.js.map +0 -1
  224. package/lib/classes/abstract-language.js +0 -261
  225. package/lib/classes/greedy-scale-language.js +0 -195
  226. package/lib/classes/slavic-language.js +0 -251
  227. package/lib/classes/south-asian-language.js +0 -161
  228. package/lib/classes/turkic-language.js +0 -63
  229. package/lib/languages/pa-Guru.js +0 -126
  230. package/typings/classes/abstract-language.d.ts +0 -144
  231. package/typings/classes/greedy-scale-language.d.ts +0 -148
  232. package/typings/classes/slavic-language.d.ts +0 -145
  233. package/typings/classes/south-asian-language.d.ts +0 -101
  234. package/typings/classes/turkic-language.d.ts +0 -42
  235. package/typings/languages/ar.d.ts +0 -93
  236. package/typings/languages/az.d.ts +0 -25
  237. package/typings/languages/bn.d.ts +0 -1
  238. package/typings/languages/cs.d.ts +0 -120
  239. package/typings/languages/da.d.ts +0 -53
  240. package/typings/languages/de.d.ts +0 -26
  241. package/typings/languages/el.d.ts +0 -11
  242. package/typings/languages/en.d.ts +0 -30
  243. package/typings/languages/es.d.ts +0 -43
  244. package/typings/languages/fa.d.ts +0 -81
  245. package/typings/languages/fil.d.ts +0 -12
  246. package/typings/languages/fr-BE.d.ts +0 -41
  247. package/typings/languages/fr.d.ts +0 -43
  248. package/typings/languages/gu.d.ts +0 -12
  249. package/typings/languages/he.d.ts +0 -197
  250. package/typings/languages/hi.d.ts +0 -1
  251. package/typings/languages/hr.d.ts +0 -110
  252. package/typings/languages/hu.d.ts +0 -37
  253. package/typings/languages/id.d.ts +0 -69
  254. package/typings/languages/it.d.ts +0 -51
  255. package/typings/languages/ja.d.ts +0 -58
  256. package/typings/languages/kn.d.ts +0 -11
  257. package/typings/languages/ko.d.ts +0 -25
  258. package/typings/languages/lt.d.ts +0 -110
  259. package/typings/languages/lv.d.ts +0 -99
  260. package/typings/languages/mr.d.ts +0 -12
  261. package/typings/languages/ms.d.ts +0 -37
  262. package/typings/languages/nb.d.ts +0 -27
  263. package/typings/languages/nl.d.ts +0 -65
  264. package/typings/languages/pa-Guru.d.ts +0 -1
  265. package/typings/languages/pl.d.ts +0 -116
  266. package/typings/languages/pt.d.ts +0 -39
  267. package/typings/languages/ro.d.ts +0 -229
  268. package/typings/languages/ru.d.ts +0 -108
  269. package/typings/languages/sr-Latn.d.ts +0 -98
  270. package/typings/languages/sv.d.ts +0 -30
  271. package/typings/languages/sw.d.ts +0 -1
  272. package/typings/languages/ta.d.ts +0 -1
  273. package/typings/languages/te.d.ts +0 -1
  274. package/typings/languages/th.d.ts +0 -1
  275. package/typings/languages/tr.d.ts +0 -46
  276. package/typings/languages/uk.d.ts +0 -117
  277. package/typings/languages/ur.d.ts +0 -1
  278. package/typings/languages/vi.d.ts +0 -116
  279. package/typings/languages/zh-Hans.d.ts +0 -57
  280. package/typings/n2words.d.ts +0 -177
@@ -1,156 +1,137 @@
1
1
  /**
2
- * Gujarati language implementation for n2words
2
+ * Gujarati language converter - Functional Implementation
3
3
  *
4
- * Gujarati uses Indian-style number grouping (3 digits, then 2-2 from right).
5
- * Numbers: શૂન્ય (0), એક (1), બે (2), ત્રણ (3), ચાર (4), પાંચ (5)...
4
+ * Self-contained converter for South Asian numbering.
6
5
  *
7
- * @module lib/languages/gu
8
- * @example
9
- * import gu from './lib/languages/gu.js'
10
- * gu(42) // 'બેતાળીસ'
11
- * gu(1000) // 'એક હજાર'
6
+ * Key features:
7
+ * - Indian numbering system (હજાર, લાખ, કરોડ)
8
+ * - Gujarati script
9
+ * - 3-2-2 grouping pattern (last 3 digits, then groups of 2)
10
+ * - Complete word forms for 0-99
11
+ * - Per-digit decimal reading
12
12
  */
13
13
 
14
- import SouthAsianLanguage from '../classes/south-asian-language.js'
14
+ import { parseNumericValue } from '../utils/parse-numeric.js'
15
15
 
16
- /**
17
- * Gujarati language implementation
18
- * Extends SouthAsianLanguage for Indian-style grouping
19
- */
20
- class GujaratiLanguage extends SouthAsianLanguage {
21
- negativeWord = 'ઋણ'
22
- decimalSeparatorWord = 'દશાંશ'
23
- zeroWord = 'શૂન્ય'
24
- hundredWord = 'સો'
25
- convertDecimalsPerDigit = true
26
-
27
- belowHundred = [
28
- 'શૂન્ય',
29
- 'એક',
30
- 'બે',
31
- 'ત્રણ',
32
- 'ચાર',
33
- 'પાંચ',
34
- '',
35
- 'સાત',
36
- 'આઠ',
37
- 'નવ',
38
- 'દસ',
39
- 'અગિયાર',
40
- 'બાર',
41
- 'તેર',
42
- 'ચૌદ',
43
- 'પંદર',
44
- 'સોળ',
45
- 'સત્તર',
46
- 'અઢાર',
47
- 'ઓગણીસ',
48
- 'વીસ',
49
- 'એકવીસ',
50
- 'બાવીસ',
51
- 'ત્રેવીસ',
52
- 'ચોવીસ',
53
- 'પચીસ',
54
- 'છવ્વીસ',
55
- 'સત્તાવીસ',
56
- 'અઠ્ઠાવીસ',
57
- 'ઓગણત્રીસ',
58
- 'ત્રીસ',
59
- 'એકત્રીસ',
60
- 'બત્રીસ',
61
- 'તેત્રીસ',
62
- 'ચોત્રીસ',
63
- 'પાંત્રીસ',
64
- 'છત્રીસ',
65
- 'સાડત્રીસ',
66
- 'અડત્રીસ',
67
- 'ઓગણચાલીસ',
68
- 'ચાલીસ',
69
- 'એકતાલીસ',
70
- 'બેતાળીસ',
71
- 'ત્રેતાળીસ',
72
- 'ચુંમાલીસ',
73
- 'પિસ્તાલીસ',
74
- 'છેતાળીસ',
75
- 'સુડતાળીસ',
76
- 'અડતાળીસ',
77
- 'ઓગણપચાસ',
78
- 'પચાસ',
79
- 'એકાવન',
80
- 'બાવન',
81
- 'ત્રેપન',
82
- 'ચોપન',
83
- 'પંચાવન',
84
- 'છપ્પન',
85
- 'સત્તાવન',
86
- 'અઠ્ઠાવન',
87
- 'ઓગણસાઠ',
88
- 'સાઠ',
89
- 'એકસઠ',
90
- 'બાસઠ',
91
- 'ત્રેસઠ',
92
- 'ચોસઠ',
93
- 'પાંસઠ',
94
- 'છાસઠ',
95
- 'સડસઠ',
96
- 'અડસઠ',
97
- 'અગણોસિત્તેર',
98
- 'સિત્તેર',
99
- 'એકોતેર',
100
- 'બોતેર',
101
- 'તોતેર',
102
- 'ચુમોતેર',
103
- 'પંચોતેર',
104
- 'છોતેર',
105
- 'સિત્યોતેર',
106
- 'ઇઠ્યોતેર',
107
- 'ઓગણાએંસી',
108
- 'એંસી',
109
- 'એક્યાસી',
110
- 'બ્યાસી',
111
- 'ત્યાસી',
112
- 'ચોર્યાસી',
113
- 'પંચાસી',
114
- 'છ્યાસી',
115
- 'સિત્યાસી',
116
- 'અઠ્યાસી',
117
- 'નેવ્યાસી',
118
- 'નેવું',
119
- 'એકાણું',
120
- 'બાણું',
121
- 'ત્રાણું',
122
- 'ચોરાણું',
123
- 'પંચાણું',
124
- 'છન્નું',
125
- 'સત્તાણું',
126
- 'અઠ્ઠાણું',
127
- 'નવ્વાણું'
128
- ]
129
-
130
- scaleWords = [
131
- '',
132
- 'હજાર',
133
- 'લાખ',
134
- 'કરોડ',
135
- 'અબજ',
136
- 'ખરબ',
137
- 'નીલ',
138
- 'પદ્મ',
139
- 'શંખ'
140
- ]
16
+ // ============================================================================
17
+ // Vocabulary
18
+ // ============================================================================
19
+
20
+ const ZERO = 'શૂન્ય'
21
+ const NEGATIVE = 'ઋણ'
22
+ const DECIMAL_SEP = 'દશાંશ'
23
+ const HUNDRED = 'સો'
24
+
25
+ const BELOW_HUNDRED = [
26
+ 'શૂન્ય', 'એક', 'બે', 'ત્રણ', 'ચાર', 'પાંચ', 'છ', 'સાત', 'આઠ', 'નવ',
27
+ 'દસ', 'અગિયાર', 'બાર', 'તેર', 'ચૌદ', 'પંદર', 'સોળ', 'સત્તર', 'અઢાર', 'ઓગણીસ',
28
+ 'વીસ', 'એકવીસ', 'બાવીસ', 'ત્રેવીસ', 'ચોવીસ', 'પચીસ', 'છવ્વીસ', 'સત્તાવીસ', 'અઠ્ઠાવીસ', 'ઓગણત્રીસ',
29
+ 'ત્રીસ', 'એકત્રીસ', 'બત્રીસ', 'તેત્રીસ', 'ચોત્રીસ', 'પાંત્રીસ', 'છત્રીસ', 'સાડત્રીસ', 'અડત્રીસ', 'ઓગણચાલીસ',
30
+ 'ચાલીસ', 'એકતાલીસ', 'બેતાળીસ', 'ત્રેતાળીસ', 'ચુંમાલીસ', 'પિસ્તાલીસ', 'છેતાળીસ', 'સુડતાળીસ', 'અડતાળીસ', 'ઓગણપચાસ',
31
+ 'પચાસ', 'એકાવન', 'બાવન', 'ત્રેપન', 'ચોપન', 'પંચાવન', 'છપ્પન', 'સત્તાવન', 'અઠ્ઠાવન', 'ઓગણસાઠ',
32
+ 'સાઠ', 'એકસઠ', 'બાસઠ', 'ત્રેસઠ', 'ચોસઠ', 'પાંસઠ', 'છાસઠ', 'સડસઠ', 'અડસઠ', 'અગણોસિત્તેર',
33
+ 'સિત્તેર', 'એકોતેર', 'બોતેર', 'તોતેર', 'ચુમોતેર', 'પંચોતેર', 'છોતેર', 'સિત્યોતેર', 'ઇઠ્યોતેર', 'ઓગણાએંસી',
34
+ 'એંસી', 'એક્યાસી', 'બ્યાસી', 'ત્યાસી', 'ચોર્યાસી', 'પંચાસી', 'છ્યાસી', 'સિત્યાસી', 'અઠ્યાસી', 'નેવ્યાસી',
35
+ 'નેવું', 'એકાણું', 'બાણું', 'ત્રાણું', 'ચોરાણું', 'પંચાણું', 'છન્નું', 'સત્તાણું', 'અઠ્ઠાણું', 'નવ્વાણું'
36
+ ]
37
+
38
+ // Scale words: index 0 = units (empty), 1 = thousand, 2 = lakh, 3 = crore, etc.
39
+ const SCALE_WORDS = ['', 'હજાર', 'લાખ', 'કરોડ', 'અબજ', 'ખરબ', 'નીલ', 'પદ્મ', 'શંખ']
40
+
41
+ // ============================================================================
42
+ // Segment Splitting (inlined for performance)
43
+ // ============================================================================
44
+
45
+ function groupByThreeThenTwos (n) {
46
+ const numStr = n.toString()
47
+ if (numStr.length <= 3) return [Number(numStr)]
48
+
49
+ const segments = []
50
+ segments.unshift(Number(numStr.slice(-3)))
51
+
52
+ let remaining = numStr.slice(0, -3)
53
+ while (remaining.length > 0) {
54
+ segments.unshift(Number(remaining.slice(-2)))
55
+ remaining = remaining.slice(0, -2)
56
+ }
57
+
58
+ return segments
59
+ }
60
+
61
+ function segmentToWords (n) {
62
+ if (n === 0) return ''
63
+ if (n < 100) return BELOW_HUNDRED[n]
64
+
65
+ const hundreds = Math.trunc(n / 100)
66
+ const remainder = n % 100
67
+
68
+ if (remainder === 0) {
69
+ return BELOW_HUNDRED[hundreds] + ' ' + HUNDRED
70
+ }
71
+ return BELOW_HUNDRED[hundreds] + ' ' + HUNDRED + ' ' + BELOW_HUNDRED[remainder]
72
+ }
73
+
74
+ // ============================================================================
75
+ // Conversion Functions
76
+ // ============================================================================
77
+
78
+ function integerToWords (n) {
79
+ if (n === 0n) return ZERO
80
+
81
+ const segments = groupByThreeThenTwos(n)
82
+ const segmentCount = segments.length
83
+ const words = []
84
+
85
+ for (let i = 0; i < segmentCount; i++) {
86
+ const segmentValue = segments[i]
87
+ if (segmentValue === 0) continue
88
+
89
+ const scaleIndex = segmentCount - i - 1
90
+ words.push(segmentToWords(segmentValue))
91
+ if (scaleIndex > 0 && SCALE_WORDS[scaleIndex]) {
92
+ words.push(SCALE_WORDS[scaleIndex])
93
+ }
94
+ }
95
+
96
+ return words.join(' ').trim()
97
+ }
98
+
99
+ function decimalPartToWords (decimalPart) {
100
+ // Per-digit decimal reading
101
+ const digits = []
102
+ for (const char of decimalPart) {
103
+ const d = parseInt(char, 10)
104
+ digits.push(d === 0 ? ZERO : BELOW_HUNDRED[d])
105
+ }
106
+ return digits.join(' ')
141
107
  }
142
108
 
143
109
  /**
144
- * Convert a number to Gujarati words
110
+ * Converts a numeric value to Gujarati words.
145
111
  *
146
- * @param {number|string|bigint} value - The number to convert
147
- * @param {Object} [options={}] - Conversion options
148
- * @returns {string} The Gujarati word representation
149
- * @example
150
- * convertToWords(42) // 'બેતાળીસ'
151
- * convertToWords(1000) // 'એક હજાર'
152
- * convertToWords(100000) // 'એક લાખ'
112
+ * @param {number | string | bigint} value - The numeric value to convert
113
+ * @returns {string} The number in Gujarati words
153
114
  */
154
- export default function convertToWords (value, options = {}) {
155
- return new GujaratiLanguage(options).convertToWords(value)
115
+ function toWords (value) {
116
+ const { isNegative, integerPart, decimalPart } = parseNumericValue(value)
117
+
118
+ let result = ''
119
+
120
+ if (isNegative) {
121
+ result = NEGATIVE + ' '
122
+ }
123
+
124
+ result += integerToWords(integerPart)
125
+
126
+ if (decimalPart) {
127
+ result += ' ' + DECIMAL_SEP + ' ' + decimalPartToWords(decimalPart)
128
+ }
129
+
130
+ return result
156
131
  }
132
+
133
+ // ============================================================================
134
+ // Exports
135
+ // ============================================================================
136
+
137
+ export { toWords }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Converts a numeric value to Hausa words.
3
+ *
4
+ * @param {number | string | bigint} value - The numeric value to convert
5
+ * @returns {string} The number in Hausa words
6
+ */
7
+ export function toWords(value: number | string | bigint): string;
@@ -0,0 +1,230 @@
1
+ /**
2
+ * Hausa language converter - Functional Implementation
3
+ *
4
+ * Self-contained converter with precomputed lookup tables.
5
+ *
6
+ * Key features:
7
+ * - Authentic Boko orthography with ɗ (hooked d) and ' (glottal stop)
8
+ * - Teens with "sha" prefix (sha ɗaya = 11)
9
+ * - Compound numbers with "da" connector (ashirin da ɗaya = 21)
10
+ * - Arabic loanwords for tens (ashirin, talatin, arba'in, etc.)
11
+ * - Reversed multiplier order: "biyu ɗari" (200), "biyu dubu" (2000)
12
+ * - Implicit one before ɗari and dubu
13
+ * - Per-digit decimal reading
14
+ */
15
+
16
+ import { parseNumericValue } from '../utils/parse-numeric.js'
17
+
18
+ // ============================================================================
19
+ // Vocabulary
20
+ // ============================================================================
21
+
22
+ const ONES = ['', 'ɗaya', 'biyu', 'uku', 'huɗu', 'biyar', 'shida', 'bakwai', 'takwas', 'tara']
23
+ const TEENS = ['goma', 'sha ɗaya', 'sha biyu', 'sha uku', 'sha huɗu', 'sha biyar', 'sha shida', 'sha bakwai', 'sha takwas', 'sha tara']
24
+ // Arabic loanwords for tens
25
+ const TENS = ['', '', 'ashirin', 'talatin', "arba'in", 'hamsin', 'sittin', "saba'in", 'tamanin', "tis'in"]
26
+
27
+ const HUNDRED = 'ɗari'
28
+ const THOUSAND = 'dubu'
29
+
30
+ const ZERO = 'sifiri'
31
+ const NEGATIVE = 'babu'
32
+ const DECIMAL_SEP = 'digo'
33
+
34
+ // Short scale
35
+ const SCALE_WORDS = ['', THOUSAND, 'miliyan', 'biliyan']
36
+
37
+ // ============================================================================
38
+ // Precomputed Lookup Table
39
+ // ============================================================================
40
+
41
+ /**
42
+ * Build segment for 0-999 with Hausa patterns.
43
+ * Hausa uses reversed order for hundreds: "biyu ɗari" (200)
44
+ * And "da" connector for ones: "ashirin da ɗaya" (21)
45
+ */
46
+ function buildSegment (n) {
47
+ if (n === 0) return ''
48
+
49
+ const ones = n % 10
50
+ const tensDigit = Math.floor(n / 10) % 10
51
+ const hundredsDigit = Math.floor(n / 100)
52
+
53
+ const parts = []
54
+
55
+ // Hundreds: implicit one, or "biyu ɗari" (reversed order)
56
+ if (hundredsDigit > 0) {
57
+ if (hundredsDigit === 1) {
58
+ parts.push(HUNDRED)
59
+ } else {
60
+ // Reversed: multiplier + hundredWord
61
+ parts.push(ONES[hundredsDigit] + ' ' + HUNDRED)
62
+ }
63
+ }
64
+
65
+ // Tens and ones
66
+ const tensOnes = n % 100
67
+
68
+ if (tensOnes === 0) {
69
+ // Just hundreds
70
+ } else if (tensOnes < 10) {
71
+ // Single digit - with "da" connector if after hundreds
72
+ if (hundredsDigit > 0) {
73
+ parts.push('da ' + ONES[ones])
74
+ } else {
75
+ parts.push(ONES[ones])
76
+ }
77
+ } else if (tensOnes < 20) {
78
+ // Teens (10-19): "sha X"
79
+ parts.push(TEENS[ones])
80
+ } else if (ones === 0) {
81
+ // Even tens (20, 30, 40, etc.)
82
+ parts.push(TENS[tensDigit])
83
+ } else {
84
+ // Tens + ones with "da" connector
85
+ parts.push(TENS[tensDigit] + ' da ' + ONES[ones])
86
+ }
87
+
88
+ return parts.join(' ')
89
+ }
90
+
91
+ const SEGMENTS = new Array(1000)
92
+ for (let i = 0; i < 1000; i++) {
93
+ SEGMENTS[i] = buildSegment(i)
94
+ }
95
+
96
+ // ============================================================================
97
+ // Conversion Functions
98
+ // ============================================================================
99
+
100
+ function integerToWords (n) {
101
+ if (n === 0n) return ZERO
102
+
103
+ if (n < 1000n) {
104
+ return SEGMENTS[Number(n)]
105
+ }
106
+
107
+ return buildLargeNumberWords(n)
108
+ }
109
+
110
+ /**
111
+ * Checks if a word is a single digit (1-9).
112
+ */
113
+ function isSingleDigit (word) {
114
+ return ONES.slice(1).includes(word)
115
+ }
116
+
117
+ function buildLargeNumberWords (n) {
118
+ const numStr = n.toString()
119
+ const len = numStr.length
120
+
121
+ const segments = []
122
+ const segmentSize = 3
123
+
124
+ const remainderLen = len % segmentSize
125
+ let pos = 0
126
+ if (remainderLen > 0) {
127
+ segments.push(Number(numStr.slice(0, remainderLen)))
128
+ pos = remainderLen
129
+ }
130
+ while (pos < len) {
131
+ segments.push(Number(numStr.slice(pos, pos + segmentSize)))
132
+ pos += segmentSize
133
+ }
134
+
135
+ // Build raw parts (segment words and scale words)
136
+ const rawParts = []
137
+ let scaleIndex = segments.length - 1
138
+
139
+ for (let i = 0; i < segments.length; i++) {
140
+ const segment = segments[i]
141
+
142
+ if (segment !== 0) {
143
+ const scaleWord = SCALE_WORDS[scaleIndex] || ''
144
+
145
+ if (scaleIndex === 0) {
146
+ rawParts.push(SEGMENTS[segment])
147
+ } else {
148
+ rawParts.push(SEGMENTS[segment])
149
+ rawParts.push(scaleWord)
150
+ }
151
+ }
152
+
153
+ scaleIndex--
154
+ }
155
+
156
+ // Filter out implicit "ɗaya" before ɗari or dubu
157
+ const filtered = []
158
+ for (let i = 0; i < rawParts.length; i++) {
159
+ const part = rawParts[i]
160
+ const nextPart = rawParts[i + 1]
161
+
162
+ // Skip "ɗaya" before ɗari or dubu (implicit one)
163
+ if (part === 'ɗaya' && nextPart && (nextPart === HUNDRED || nextPart === THOUSAND)) {
164
+ continue
165
+ }
166
+
167
+ filtered.push(part)
168
+ }
169
+
170
+ // Join with correct separators
171
+ const result = []
172
+ for (let i = 0; i < filtered.length; i++) {
173
+ const part = filtered[i]
174
+ const prevPart = i > 0 ? filtered[i - 1] : null
175
+
176
+ // Determine if we need "da" connector
177
+ // Use "da" when current is a single digit following a scale word
178
+ if (prevPart && isSingleDigit(part) &&
179
+ (prevPart === THOUSAND || prevPart === HUNDRED ||
180
+ SCALE_WORDS.includes(prevPart))) {
181
+ result.push(' da ')
182
+ } else if (i > 0) {
183
+ result.push(' ')
184
+ }
185
+
186
+ result.push(part)
187
+ }
188
+
189
+ return result.join('')
190
+ }
191
+
192
+ function decimalPartToWords (decimalPart) {
193
+ // Per-digit decimal reading
194
+ const digits = []
195
+ for (const char of decimalPart) {
196
+ const d = parseInt(char, 10)
197
+ digits.push(d === 0 ? ZERO : ONES[d])
198
+ }
199
+ return digits.join(' ')
200
+ }
201
+
202
+ /**
203
+ * Converts a numeric value to Hausa words.
204
+ *
205
+ * @param {number | string | bigint} value - The numeric value to convert
206
+ * @returns {string} The number in Hausa words
207
+ */
208
+ function toWords (value) {
209
+ const { isNegative, integerPart, decimalPart } = parseNumericValue(value)
210
+
211
+ let result = ''
212
+
213
+ if (isNegative) {
214
+ result = NEGATIVE + ' '
215
+ }
216
+
217
+ result += integerToWords(integerPart)
218
+
219
+ if (decimalPart) {
220
+ result += ' ' + DECIMAL_SEP + ' ' + decimalPartToWords(decimalPart)
221
+ }
222
+
223
+ return result
224
+ }
225
+
226
+ // ============================================================================
227
+ // Exports
228
+ // ============================================================================
229
+
230
+ export { toWords }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Converts a numeric value to Biblical Hebrew words.
3
+ *
4
+ * @param {number | string | bigint} value - The numeric value to convert
5
+ * @param {Object} [options] - Optional configuration
6
+ * @param {('masculine'|'feminine')} [options.gender='masculine'] - Grammatical gender
7
+ * @param {string} [options.andWord] - Custom conjunction word
8
+ * @returns {string} The number in Biblical Hebrew words
9
+ */
10
+ export function toWords(value: number | string | bigint, options?: {
11
+ gender?: "masculine" | "feminine" | undefined;
12
+ andWord?: string | undefined;
13
+ }): string;