n2words 3.1.0 → 5.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.
- package/CHANGELOG.md +51 -40
- package/LICENSE +1 -1
- package/README.md +64 -184
- package/dist/am-ET.js +2 -0
- package/dist/am-ET.umd.js +2 -0
- package/dist/am-Latn-ET.js +2 -0
- package/dist/am-Latn-ET.umd.js +2 -0
- package/dist/ar-SA.js +2 -0
- package/dist/ar-SA.umd.js +2 -0
- package/dist/az-AZ.js +2 -0
- package/dist/az-AZ.umd.js +2 -0
- package/dist/bn-BD.js +2 -0
- package/dist/bn-BD.umd.js +2 -0
- package/dist/cs-CZ.js +2 -0
- package/dist/cs-CZ.umd.js +2 -0
- package/dist/da-DK.js +2 -0
- package/dist/da-DK.umd.js +2 -0
- package/dist/de-DE.js +2 -0
- package/dist/de-DE.umd.js +2 -0
- package/dist/el-GR.js +2 -0
- package/dist/el-GR.umd.js +2 -0
- package/dist/en-AU.js +2 -0
- package/dist/en-AU.umd.js +2 -0
- package/dist/en-BD.js +2 -0
- package/dist/en-BD.umd.js +2 -0
- package/dist/en-CA.js +2 -0
- package/dist/en-CA.umd.js +2 -0
- package/dist/en-GB.js +2 -0
- package/dist/en-GB.umd.js +2 -0
- package/dist/en-GH.js +2 -0
- package/dist/en-GH.umd.js +2 -0
- package/dist/en-IE.js +2 -0
- package/dist/en-IE.umd.js +2 -0
- package/dist/en-IN.js +2 -0
- package/dist/en-IN.umd.js +2 -0
- package/dist/en-KE.js +2 -0
- package/dist/en-KE.umd.js +2 -0
- package/dist/en-MY.js +2 -0
- package/dist/en-MY.umd.js +2 -0
- package/dist/en-NG.js +2 -0
- package/dist/en-NG.umd.js +2 -0
- package/dist/en-NZ.js +2 -0
- package/dist/en-NZ.umd.js +2 -0
- package/dist/en-PH.js +2 -0
- package/dist/en-PH.umd.js +2 -0
- package/dist/en-PK.js +2 -0
- package/dist/en-PK.umd.js +2 -0
- package/dist/en-SG.js +2 -0
- package/dist/en-SG.umd.js +2 -0
- package/dist/en-US.js +2 -0
- package/dist/en-US.umd.js +2 -0
- package/dist/en-ZA.js +2 -0
- package/dist/en-ZA.umd.js +2 -0
- package/dist/es-ES.js +2 -0
- package/dist/es-ES.umd.js +2 -0
- package/dist/es-MX.js +2 -0
- package/dist/es-MX.umd.js +2 -0
- package/dist/es-US.js +2 -0
- package/dist/es-US.umd.js +2 -0
- package/dist/fa-IR.js +2 -0
- package/dist/fa-IR.umd.js +2 -0
- package/dist/fi-FI.js +2 -0
- package/dist/fi-FI.umd.js +2 -0
- package/dist/fil-PH.js +2 -0
- package/dist/fil-PH.umd.js +2 -0
- package/dist/fr-BE.js +2 -0
- package/dist/fr-BE.umd.js +2 -0
- package/dist/fr-FR.js +2 -0
- package/dist/fr-FR.umd.js +2 -0
- package/dist/gu-IN.js +2 -0
- package/dist/gu-IN.umd.js +2 -0
- package/dist/ha-NG.js +2 -0
- package/dist/ha-NG.umd.js +2 -0
- package/dist/hbo-IL.js +2 -0
- package/dist/hbo-IL.umd.js +2 -0
- package/dist/he-IL.js +2 -0
- package/dist/he-IL.umd.js +2 -0
- package/dist/hi-IN.js +2 -0
- package/dist/hi-IN.umd.js +2 -0
- package/dist/hr-HR.js +2 -0
- package/dist/hr-HR.umd.js +2 -0
- package/dist/hu-HU.js +2 -0
- package/dist/hu-HU.umd.js +2 -0
- package/dist/id-ID.js +2 -0
- package/dist/id-ID.umd.js +2 -0
- package/dist/it-IT.js +2 -0
- package/dist/it-IT.umd.js +2 -0
- package/dist/ja-JP.js +2 -0
- package/dist/ja-JP.umd.js +2 -0
- package/dist/ka-GE.js +2 -0
- package/dist/ka-GE.umd.js +2 -0
- package/dist/kn-IN.js +2 -0
- package/dist/kn-IN.umd.js +2 -0
- package/dist/ko-KR.js +2 -0
- package/dist/ko-KR.umd.js +2 -0
- package/dist/lt-LT.js +2 -0
- package/dist/lt-LT.umd.js +2 -0
- package/dist/lv-LV.js +2 -0
- package/dist/lv-LV.umd.js +2 -0
- package/dist/mr-IN.js +2 -0
- package/dist/mr-IN.umd.js +2 -0
- package/dist/ms-MY.js +2 -0
- package/dist/ms-MY.umd.js +2 -0
- package/dist/nb-NO.js +2 -0
- package/dist/nb-NO.umd.js +2 -0
- package/dist/nl-NL.js +2 -0
- package/dist/nl-NL.umd.js +2 -0
- package/dist/pa-IN.js +2 -0
- package/dist/pa-IN.umd.js +2 -0
- package/dist/pl-PL.js +2 -0
- package/dist/pl-PL.umd.js +2 -0
- package/dist/pt-BR.js +2 -0
- package/dist/pt-BR.umd.js +2 -0
- package/dist/pt-PT.js +2 -0
- package/dist/pt-PT.umd.js +2 -0
- package/dist/ro-RO.js +2 -0
- package/dist/ro-RO.umd.js +2 -0
- package/dist/ru-RU.js +2 -0
- package/dist/ru-RU.umd.js +2 -0
- package/dist/sr-Cyrl-RS.js +2 -0
- package/dist/sr-Cyrl-RS.umd.js +2 -0
- package/dist/sr-Latn-RS.js +2 -0
- package/dist/sr-Latn-RS.umd.js +2 -0
- package/dist/sv-SE.js +2 -0
- package/dist/sv-SE.umd.js +2 -0
- package/dist/sw-KE.js +2 -0
- package/dist/sw-KE.umd.js +2 -0
- package/dist/ta-IN.js +2 -0
- package/dist/ta-IN.umd.js +2 -0
- package/dist/te-IN.js +2 -0
- package/dist/te-IN.umd.js +2 -0
- package/dist/th-TH.js +2 -0
- package/dist/th-TH.umd.js +2 -0
- package/dist/tr-TR.js +2 -0
- package/dist/tr-TR.umd.js +2 -0
- package/dist/uk-UA.js +2 -0
- package/dist/uk-UA.umd.js +2 -0
- package/dist/ur-PK.js +2 -0
- package/dist/ur-PK.umd.js +2 -0
- package/dist/vi-VN.js +2 -0
- package/dist/vi-VN.umd.js +2 -0
- package/dist/yo-NG.js +2 -0
- package/dist/yo-NG.umd.js +2 -0
- package/dist/zh-Hans-CN.js +2 -0
- package/dist/zh-Hans-CN.umd.js +2 -0
- package/dist/zh-Hant-TW.js +2 -0
- package/dist/zh-Hant-TW.umd.js +2 -0
- package/package.json +61 -88
- package/src/am-ET.d.ts +40 -0
- package/src/am-ET.js +269 -0
- package/src/am-Latn-ET.d.ts +35 -0
- package/src/am-Latn-ET.js +264 -0
- package/src/ar-SA.d.ts +49 -0
- package/{lib/languages/ar.js → src/ar-SA.js} +177 -15
- package/src/az-AZ.d.ts +37 -0
- package/src/az-AZ.js +312 -0
- package/src/bn-BD.d.ts +36 -0
- package/{lib/languages/bn.js → src/bn-BD.js} +110 -6
- package/src/cs-CZ.d.ts +49 -0
- package/{lib/languages/cs.js → src/cs-CZ.js} +240 -14
- package/src/da-DK.d.ts +44 -0
- package/{lib/languages/da.js → src/da-DK.js} +131 -11
- package/src/de-DE.d.ts +57 -0
- package/src/de-DE.js +603 -0
- package/src/el-GR.d.ts +40 -0
- package/src/el-GR.js +418 -0
- package/src/en-AU.d.ts +47 -0
- package/src/en-AU.js +423 -0
- package/src/en-BD.d.ts +49 -0
- package/src/en-BD.js +415 -0
- package/src/en-CA.d.ts +63 -0
- package/src/en-CA.js +518 -0
- package/src/en-GB.d.ts +56 -0
- package/src/en-GB.js +469 -0
- package/src/en-GH.d.ts +11 -0
- package/src/en-GH.js +345 -0
- package/src/en-IE.d.ts +56 -0
- package/src/en-IE.js +479 -0
- package/src/en-IN.d.ts +49 -0
- package/src/en-IN.js +415 -0
- package/src/en-KE.d.ts +11 -0
- package/src/en-KE.js +345 -0
- package/src/en-MY.d.ts +11 -0
- package/src/en-MY.js +347 -0
- package/src/en-NG.d.ts +56 -0
- package/src/en-NG.js +479 -0
- package/src/en-NZ.d.ts +11 -0
- package/{lib/languages/en.js → src/en-NZ.js} +164 -31
- package/src/en-PH.d.ts +11 -0
- package/src/en-PH.js +345 -0
- package/src/en-PK.d.ts +49 -0
- package/src/en-PK.js +415 -0
- package/src/en-SG.d.ts +11 -0
- package/src/en-SG.js +345 -0
- package/src/en-US.d.ts +63 -0
- package/src/en-US.js +516 -0
- package/src/en-ZA.d.ts +56 -0
- package/src/en-ZA.js +478 -0
- package/src/es-ES.d.ts +65 -0
- package/src/es-ES.js +541 -0
- package/src/es-MX.d.ts +58 -0
- package/{lib/languages/es.js → src/es-MX.js} +228 -18
- package/src/es-US.d.ts +58 -0
- package/src/es-US.js +446 -0
- package/src/fa-IR.d.ts +38 -0
- package/src/fa-IR.js +246 -0
- package/src/fi-FI.d.ts +46 -0
- package/{lib/languages/fi.js → src/fi-FI.js} +152 -11
- package/src/fil-PH.d.ts +37 -0
- package/{lib/languages/fil.js → src/fil-PH.js} +144 -8
- package/src/fr-BE.d.ts +49 -0
- package/{lib/languages → src}/fr-BE.js +175 -13
- package/src/fr-FR.d.ts +63 -0
- package/{lib/languages/fr.js → src/fr-FR.js} +182 -16
- package/src/gu-IN.d.ts +35 -0
- package/{lib/languages/gu.js → src/gu-IN.js} +115 -6
- package/src/ha-NG.d.ts +37 -0
- package/{lib/languages/ha.js → src/ha-NG.js} +107 -8
- package/src/hbo-IL.d.ts +39 -0
- package/{lib/languages/hbo.js → src/hbo-IL.js} +211 -19
- package/src/he-IL.d.ts +37 -0
- package/src/he-IL.js +537 -0
- package/src/hi-IN.d.ts +36 -0
- package/{lib/languages/hi.js → src/hi-IN.js} +116 -6
- package/src/hr-HR.d.ts +42 -0
- package/src/hr-HR.js +463 -0
- package/src/hu-HU.d.ts +38 -0
- package/{lib/languages/hu.js → src/hu-HU.js} +164 -6
- package/src/id-ID.d.ts +38 -0
- package/{lib/languages/id.js → src/id-ID.js} +99 -8
- package/src/it-IT.d.ts +59 -0
- package/{lib/languages/it.js → src/it-IT.js} +179 -15
- package/src/ja-JP.d.ts +49 -0
- package/{lib/languages/ja.js → src/ja-JP.js} +111 -12
- package/src/ka-GE.d.ts +44 -0
- package/{lib/languages/ka.js → src/ka-GE.js} +113 -11
- package/src/kn-IN.d.ts +35 -0
- package/{lib/languages/kn.js → src/kn-IN.js} +115 -6
- package/src/ko-KR.d.ts +45 -0
- package/{lib/languages/ko.js → src/ko-KR.js} +94 -12
- package/src/lt-LT.d.ts +49 -0
- package/src/lt-LT.js +543 -0
- package/src/lv-LV.d.ts +49 -0
- package/src/lv-LV.js +595 -0
- package/src/mr-IN.d.ts +36 -0
- package/{lib/languages/mr.js → src/mr-IN.js} +116 -6
- package/src/ms-MY.d.ts +37 -0
- package/{lib/languages/ms.js → src/ms-MY.js} +111 -8
- package/src/nb-NO.d.ts +44 -0
- package/{lib/languages/nb.js → src/nb-NO.js} +153 -11
- package/src/nl-NL.d.ts +54 -0
- package/{lib/languages/nl.js → src/nl-NL.js} +260 -18
- package/src/pa-IN.d.ts +36 -0
- package/{lib/languages/pa.js → src/pa-IN.js} +116 -6
- package/src/pl-PL.d.ts +55 -0
- package/src/pl-PL.js +585 -0
- package/src/pt-BR.d.ts +31 -0
- package/src/pt-BR.js +534 -0
- package/src/pt-PT.d.ts +45 -0
- package/{lib/languages/pt.js → src/pt-PT.js} +234 -12
- package/src/ro-RO.d.ts +44 -0
- package/{lib/languages/ro.js → src/ro-RO.js} +212 -18
- package/src/ru-RU.d.ts +50 -0
- package/src/ru-RU.js +535 -0
- package/src/sr-Cyrl-RS.d.ts +49 -0
- package/src/sr-Cyrl-RS.js +503 -0
- package/src/sr-Latn-RS.d.ts +49 -0
- package/src/sr-Latn-RS.js +503 -0
- package/src/sv-SE.d.ts +44 -0
- package/{lib/languages/sv.js → src/sv-SE.js} +136 -11
- package/src/sw-KE.d.ts +37 -0
- package/{lib/languages/sw.js → src/sw-KE.js} +117 -6
- package/src/ta-IN.d.ts +35 -0
- package/{lib/languages/ta.js → src/ta-IN.js} +109 -6
- package/src/te-IN.d.ts +35 -0
- package/{lib/languages/te.js → src/te-IN.js} +115 -6
- package/src/th-TH.d.ts +38 -0
- package/{lib/languages/th.js → src/th-TH.js} +99 -6
- package/src/tr-TR.d.ts +48 -0
- package/{lib/languages/tr.js → src/tr-TR.js} +168 -23
- package/src/uk-UA.d.ts +42 -0
- package/src/uk-UA.js +463 -0
- package/src/ur-PK.d.ts +36 -0
- package/{lib/languages/ur.js → src/ur-PK.js} +116 -6
- package/src/utils/expand-scientific.d.ts +32 -0
- package/src/utils/expand-scientific.js +65 -0
- package/src/utils/parse-cardinal.d.ts +14 -0
- package/{lib/utils/parse-numeric.js → src/utils/parse-cardinal.js} +14 -44
- package/src/utils/parse-currency.d.ts +14 -0
- package/src/utils/parse-currency.js +91 -0
- package/src/utils/parse-ordinal.d.ts +10 -0
- package/src/utils/parse-ordinal.js +103 -0
- package/src/vi-VN.d.ts +48 -0
- package/{lib/languages/vi.js → src/vi-VN.js} +102 -11
- package/src/yo-NG.d.ts +37 -0
- package/{lib/languages/yo.js → src/yo-NG.js} +109 -9
- package/src/zh-Hans-CN.d.ts +48 -0
- package/{lib/languages/zh-Hans.js → src/zh-Hans-CN.js} +140 -8
- package/src/zh-Hant-TW.d.ts +50 -0
- package/{lib/languages/zh-Hant.js → src/zh-Hant-TW.js} +139 -8
- package/dist/languages/am-Latn.js +0 -3
- package/dist/languages/am-Latn.js.map +0 -1
- package/dist/languages/am.js +0 -3
- package/dist/languages/am.js.map +0 -1
- package/dist/languages/ar.js +0 -3
- package/dist/languages/ar.js.map +0 -1
- package/dist/languages/az.js +0 -3
- package/dist/languages/az.js.map +0 -1
- package/dist/languages/bn.js +0 -3
- package/dist/languages/bn.js.map +0 -1
- package/dist/languages/cs.js +0 -3
- package/dist/languages/cs.js.map +0 -1
- package/dist/languages/da.js +0 -3
- package/dist/languages/da.js.map +0 -1
- package/dist/languages/de.js +0 -3
- package/dist/languages/de.js.map +0 -1
- package/dist/languages/el.js +0 -3
- package/dist/languages/el.js.map +0 -1
- package/dist/languages/en.js +0 -3
- package/dist/languages/en.js.map +0 -1
- package/dist/languages/es.js +0 -3
- package/dist/languages/es.js.map +0 -1
- package/dist/languages/fa.js +0 -3
- package/dist/languages/fa.js.map +0 -1
- package/dist/languages/fi.js +0 -3
- package/dist/languages/fi.js.map +0 -1
- package/dist/languages/fil.js +0 -3
- package/dist/languages/fil.js.map +0 -1
- package/dist/languages/fr-BE.js +0 -3
- package/dist/languages/fr-BE.js.map +0 -1
- package/dist/languages/fr.js +0 -3
- package/dist/languages/fr.js.map +0 -1
- package/dist/languages/gu.js +0 -3
- package/dist/languages/gu.js.map +0 -1
- package/dist/languages/ha.js +0 -3
- package/dist/languages/ha.js.map +0 -1
- package/dist/languages/hbo.js +0 -3
- package/dist/languages/hbo.js.map +0 -1
- package/dist/languages/he.js +0 -3
- package/dist/languages/he.js.map +0 -1
- package/dist/languages/hi.js +0 -3
- package/dist/languages/hi.js.map +0 -1
- package/dist/languages/hr.js +0 -3
- package/dist/languages/hr.js.map +0 -1
- package/dist/languages/hu.js +0 -3
- package/dist/languages/hu.js.map +0 -1
- package/dist/languages/id.js +0 -3
- package/dist/languages/id.js.map +0 -1
- package/dist/languages/it.js +0 -3
- package/dist/languages/it.js.map +0 -1
- package/dist/languages/ja.js +0 -3
- package/dist/languages/ja.js.map +0 -1
- package/dist/languages/ka.js +0 -3
- package/dist/languages/ka.js.map +0 -1
- package/dist/languages/kn.js +0 -3
- package/dist/languages/kn.js.map +0 -1
- package/dist/languages/ko.js +0 -3
- package/dist/languages/ko.js.map +0 -1
- package/dist/languages/lt.js +0 -3
- package/dist/languages/lt.js.map +0 -1
- package/dist/languages/lv.js +0 -3
- package/dist/languages/lv.js.map +0 -1
- package/dist/languages/mr.js +0 -3
- package/dist/languages/mr.js.map +0 -1
- package/dist/languages/ms.js +0 -3
- package/dist/languages/ms.js.map +0 -1
- package/dist/languages/nb.js +0 -3
- package/dist/languages/nb.js.map +0 -1
- package/dist/languages/nl.js +0 -3
- package/dist/languages/nl.js.map +0 -1
- package/dist/languages/pa.js +0 -3
- package/dist/languages/pa.js.map +0 -1
- package/dist/languages/pl.js +0 -3
- package/dist/languages/pl.js.map +0 -1
- package/dist/languages/pt.js +0 -3
- package/dist/languages/pt.js.map +0 -1
- package/dist/languages/ro.js +0 -3
- package/dist/languages/ro.js.map +0 -1
- package/dist/languages/ru.js +0 -3
- package/dist/languages/ru.js.map +0 -1
- package/dist/languages/sr-Cyrl.js +0 -3
- package/dist/languages/sr-Cyrl.js.map +0 -1
- package/dist/languages/sr-Latn.js +0 -3
- package/dist/languages/sr-Latn.js.map +0 -1
- package/dist/languages/sv.js +0 -3
- package/dist/languages/sv.js.map +0 -1
- package/dist/languages/sw.js +0 -3
- package/dist/languages/sw.js.map +0 -1
- package/dist/languages/ta.js +0 -3
- package/dist/languages/ta.js.map +0 -1
- package/dist/languages/te.js +0 -3
- package/dist/languages/te.js.map +0 -1
- package/dist/languages/th.js +0 -3
- package/dist/languages/th.js.map +0 -1
- package/dist/languages/tr.js +0 -3
- package/dist/languages/tr.js.map +0 -1
- package/dist/languages/uk.js +0 -3
- package/dist/languages/uk.js.map +0 -1
- package/dist/languages/ur.js +0 -3
- package/dist/languages/ur.js.map +0 -1
- package/dist/languages/vi.js +0 -3
- package/dist/languages/vi.js.map +0 -1
- package/dist/languages/yo.js +0 -3
- package/dist/languages/yo.js.map +0 -1
- package/dist/languages/zh-Hans.js +0 -3
- package/dist/languages/zh-Hans.js.map +0 -1
- package/dist/languages/zh-Hant.js +0 -3
- package/dist/languages/zh-Hant.js.map +0 -1
- package/dist/n2words.js +0 -3
- package/dist/n2words.js.map +0 -1
- package/lib/languages/am-Latn.d.ts +0 -7
- package/lib/languages/am-Latn.js +0 -159
- package/lib/languages/am.d.ts +0 -7
- package/lib/languages/am.js +0 -159
- package/lib/languages/ar.d.ts +0 -17
- package/lib/languages/az.d.ts +0 -7
- package/lib/languages/az.js +0 -171
- package/lib/languages/bn.d.ts +0 -7
- package/lib/languages/cs.d.ts +0 -18
- package/lib/languages/da.d.ts +0 -14
- package/lib/languages/de.d.ts +0 -17
- package/lib/languages/de.js +0 -320
- package/lib/languages/el.d.ts +0 -14
- package/lib/languages/el.js +0 -236
- package/lib/languages/en.d.ts +0 -17
- package/lib/languages/es.d.ts +0 -21
- package/lib/languages/fa.d.ts +0 -7
- package/lib/languages/fa.js +0 -134
- package/lib/languages/fi.d.ts +0 -14
- package/lib/languages/fil.d.ts +0 -7
- package/lib/languages/fr-BE.d.ts +0 -11
- package/lib/languages/fr.d.ts +0 -21
- package/lib/languages/gu.d.ts +0 -7
- package/lib/languages/ha.d.ts +0 -7
- package/lib/languages/hbo.d.ts +0 -13
- package/lib/languages/he.d.ts +0 -13
- package/lib/languages/he.js +0 -265
- package/lib/languages/hi.d.ts +0 -7
- package/lib/languages/hr.d.ts +0 -11
- package/lib/languages/hr.js +0 -224
- package/lib/languages/hu.d.ts +0 -7
- package/lib/languages/id.d.ts +0 -7
- package/lib/languages/it.d.ts +0 -19
- package/lib/languages/ja.d.ts +0 -17
- package/lib/languages/ka.d.ts +0 -17
- package/lib/languages/kn.d.ts +0 -7
- package/lib/languages/ko.d.ts +0 -14
- package/lib/languages/lt.d.ts +0 -18
- package/lib/languages/lt.js +0 -301
- package/lib/languages/lv.d.ts +0 -18
- package/lib/languages/lv.js +0 -312
- package/lib/languages/mr.d.ts +0 -7
- package/lib/languages/ms.d.ts +0 -7
- package/lib/languages/nb.d.ts +0 -14
- package/lib/languages/nl.d.ts +0 -26
- package/lib/languages/pa.d.ts +0 -7
- package/lib/languages/pl.d.ts +0 -22
- package/lib/languages/pl.js +0 -317
- package/lib/languages/pt.d.ts +0 -17
- package/lib/languages/ro.d.ts +0 -18
- package/lib/languages/ru.d.ts +0 -11
- package/lib/languages/ru.js +0 -245
- package/lib/languages/sr-Cyrl.d.ts +0 -11
- package/lib/languages/sr-Cyrl.js +0 -221
- package/lib/languages/sr-Latn.d.ts +0 -11
- package/lib/languages/sr-Latn.js +0 -221
- package/lib/languages/sv.d.ts +0 -14
- package/lib/languages/sw.d.ts +0 -7
- package/lib/languages/ta.d.ts +0 -7
- package/lib/languages/te.d.ts +0 -7
- package/lib/languages/th.d.ts +0 -7
- package/lib/languages/tr.d.ts +0 -18
- package/lib/languages/uk.d.ts +0 -11
- package/lib/languages/uk.js +0 -224
- package/lib/languages/ur.d.ts +0 -7
- package/lib/languages/vi.d.ts +0 -17
- package/lib/languages/yo.d.ts +0 -7
- package/lib/languages/zh-Hans.d.ts +0 -11
- package/lib/languages/zh-Hant.d.ts +0 -11
- package/lib/n2words.d.ts +0 -55
- package/lib/n2words.js +0 -126
- package/lib/utils/parse-numeric.d.ts +0 -17
- /package/{lib → src}/utils/is-plain-object.d.ts +0 -0
- /package/{lib → src}/utils/is-plain-object.js +0 -0
- /package/{lib → src}/utils/validate-options.d.ts +0 -0
- /package/{lib → src}/utils/validate-options.js +0 -0
package/src/en-KE.js
ADDED
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kenyan English language converter
|
|
3
|
+
*
|
|
4
|
+
* CLDR: en-KE | English as used in Kenya
|
|
5
|
+
*
|
|
6
|
+
* Exports:
|
|
7
|
+
* - toCardinal(value) - Cardinal numbers: 42 → "forty-two"
|
|
8
|
+
* - toOrdinal(value) - Ordinal numbers: 42 → "forty-second"
|
|
9
|
+
* - toCurrency(value, options?) - Currency: 42.50 → "forty-two shillings and fifty cents"
|
|
10
|
+
*
|
|
11
|
+
* Kenyan English conventions:
|
|
12
|
+
* - Follows British English style
|
|
13
|
+
* - "and" after hundreds: "one hundred and twenty-three"
|
|
14
|
+
* - "and" before final segment: "one million and one"
|
|
15
|
+
* - Hyphenated tens-ones: "twenty-one", "forty-two"
|
|
16
|
+
* - Western numbering system (short scale: billion = 10^9)
|
|
17
|
+
* - Currency: Kenyan Shilling (KES) - shilling/shillings, cent/cents
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { parseCardinalValue } from './utils/parse-cardinal.js'
|
|
21
|
+
import { parseCurrencyValue } from './utils/parse-currency.js'
|
|
22
|
+
import { parseOrdinalValue } from './utils/parse-ordinal.js'
|
|
23
|
+
import { validateOptions } from './utils/validate-options.js'
|
|
24
|
+
|
|
25
|
+
// ============================================================================
|
|
26
|
+
// Vocabulary (module-level constants)
|
|
27
|
+
// ============================================================================
|
|
28
|
+
|
|
29
|
+
const ONES = ['', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']
|
|
30
|
+
const TEENS = ['ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen']
|
|
31
|
+
const TENS = ['', '', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety']
|
|
32
|
+
|
|
33
|
+
const SCALES = [
|
|
34
|
+
'thousand', 'million', 'billion', 'trillion', 'quadrillion',
|
|
35
|
+
'quintillion', 'sextillion', 'septillion', 'octillion', 'nonillion',
|
|
36
|
+
'decillion', 'undecillion', 'duodecillion', 'tredecillion', 'quattuordecillion',
|
|
37
|
+
'quindecillion', 'sexdecillion', 'septendecillion', 'octodecillion', 'novemdecillion',
|
|
38
|
+
'vigintillion'
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
const HUNDRED = 'hundred'
|
|
42
|
+
const ZERO = 'zero'
|
|
43
|
+
const NEGATIVE = 'minus'
|
|
44
|
+
const DECIMAL_SEP = 'point'
|
|
45
|
+
|
|
46
|
+
// Ordinal vocabulary
|
|
47
|
+
const ORDINAL_ONES = ['', 'first', 'second', 'third', 'fourth', 'fifth', 'sixth', 'seventh', 'eighth', 'ninth']
|
|
48
|
+
const ORDINAL_TEENS = ['tenth', 'eleventh', 'twelfth', 'thirteenth', 'fourteenth', 'fifteenth', 'sixteenth', 'seventeenth', 'eighteenth', 'nineteenth']
|
|
49
|
+
const ORDINAL_TENS = ['', '', 'twentieth', 'thirtieth', 'fortieth', 'fiftieth', 'sixtieth', 'seventieth', 'eightieth', 'ninetieth']
|
|
50
|
+
|
|
51
|
+
// Currency vocabulary (Kenyan Shilling)
|
|
52
|
+
const SHILLING = 'shilling'
|
|
53
|
+
const SHILLINGS = 'shillings'
|
|
54
|
+
const CENT = 'cent'
|
|
55
|
+
const CENTS = 'cents'
|
|
56
|
+
|
|
57
|
+
// ============================================================================
|
|
58
|
+
// Segment Building
|
|
59
|
+
// ============================================================================
|
|
60
|
+
|
|
61
|
+
const segmentResult = { word: '', hasHundred: false }
|
|
62
|
+
|
|
63
|
+
function buildSegment (n) {
|
|
64
|
+
if (n === 0) {
|
|
65
|
+
segmentResult.word = ''
|
|
66
|
+
segmentResult.hasHundred = false
|
|
67
|
+
return segmentResult
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const ones = n % 10
|
|
71
|
+
const tens = Math.trunc(n / 10) % 10
|
|
72
|
+
const hundreds = Math.trunc(n / 100)
|
|
73
|
+
|
|
74
|
+
let tensOnes = ''
|
|
75
|
+
if (tens === 1) {
|
|
76
|
+
tensOnes = TEENS[ones]
|
|
77
|
+
} else if (tens >= 2) {
|
|
78
|
+
tensOnes = ones > 0 ? TENS[tens] + '-' + ONES[ones] : TENS[tens]
|
|
79
|
+
} else if (ones > 0) {
|
|
80
|
+
tensOnes = ONES[ones]
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (hundreds > 0) {
|
|
84
|
+
if (tensOnes) {
|
|
85
|
+
segmentResult.word = ONES[hundreds] + ' ' + HUNDRED + ' and ' + tensOnes
|
|
86
|
+
} else {
|
|
87
|
+
segmentResult.word = ONES[hundreds] + ' ' + HUNDRED
|
|
88
|
+
}
|
|
89
|
+
segmentResult.hasHundred = true
|
|
90
|
+
} else {
|
|
91
|
+
segmentResult.word = tensOnes
|
|
92
|
+
segmentResult.hasHundred = false
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return segmentResult
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// ============================================================================
|
|
99
|
+
// Conversion Functions
|
|
100
|
+
// ============================================================================
|
|
101
|
+
|
|
102
|
+
function integerToWords (n) {
|
|
103
|
+
if (n === 0n) return ZERO
|
|
104
|
+
|
|
105
|
+
if (n < 1000n) {
|
|
106
|
+
return buildSegment(Number(n)).word
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (n < 1_000_000n) {
|
|
110
|
+
const thousands = Number(n / 1000n)
|
|
111
|
+
const remainder = Number(n % 1000n)
|
|
112
|
+
|
|
113
|
+
const { word: thousandsWord } = buildSegment(thousands)
|
|
114
|
+
let result = thousandsWord + ' ' + SCALES[0]
|
|
115
|
+
|
|
116
|
+
if (remainder > 0) {
|
|
117
|
+
const { word: remainderWord, hasHundred } = buildSegment(remainder)
|
|
118
|
+
result += hasHundred ? ' ' + remainderWord : ' and ' + remainderWord
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return result
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return buildLargeNumberWords(n)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function buildLargeNumberWords (n) {
|
|
128
|
+
const segments = []
|
|
129
|
+
let temp = n
|
|
130
|
+
while (temp > 0n) {
|
|
131
|
+
segments.push(Number(temp % 1000n))
|
|
132
|
+
temp = temp / 1000n
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
let firstNonZeroIdx = -1
|
|
136
|
+
for (let i = 0; i < segments.length; i++) {
|
|
137
|
+
if (segments[i] !== 0) {
|
|
138
|
+
firstNonZeroIdx = i
|
|
139
|
+
break
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
let result = ''
|
|
144
|
+
let prevWasScale = false
|
|
145
|
+
|
|
146
|
+
for (let i = segments.length - 1; i >= 0; i--) {
|
|
147
|
+
const segment = segments[i]
|
|
148
|
+
if (segment === 0) continue
|
|
149
|
+
|
|
150
|
+
const { word, hasHundred } = buildSegment(segment)
|
|
151
|
+
const isLastSegment = (i === firstNonZeroIdx)
|
|
152
|
+
|
|
153
|
+
if (result && isLastSegment && prevWasScale && !hasHundred) {
|
|
154
|
+
result += ' and'
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (result) result += ' '
|
|
158
|
+
result += word
|
|
159
|
+
|
|
160
|
+
if (i > 0) {
|
|
161
|
+
result += ' ' + SCALES[i - 1]
|
|
162
|
+
prevWasScale = true
|
|
163
|
+
} else {
|
|
164
|
+
prevWasScale = false
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return result
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function decimalPartToWords (decimalPart) {
|
|
172
|
+
let result = ''
|
|
173
|
+
|
|
174
|
+
let i = 0
|
|
175
|
+
while (i < decimalPart.length && decimalPart[i] === '0') {
|
|
176
|
+
if (result) result += ' '
|
|
177
|
+
result += ZERO
|
|
178
|
+
i++
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const remainder = decimalPart.slice(i)
|
|
182
|
+
if (remainder) {
|
|
183
|
+
if (result) result += ' '
|
|
184
|
+
result += integerToWords(BigInt(remainder))
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return result
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Converts a numeric value to Kenyan English words.
|
|
192
|
+
*
|
|
193
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
194
|
+
* @returns {string} The number in English words
|
|
195
|
+
* @throws {TypeError} If value is not a valid numeric type
|
|
196
|
+
* @throws {Error} If value is not a valid number format
|
|
197
|
+
*/
|
|
198
|
+
function toCardinal (value) {
|
|
199
|
+
const { isNegative, integerPart, decimalPart } = parseCardinalValue(value)
|
|
200
|
+
|
|
201
|
+
let result = ''
|
|
202
|
+
|
|
203
|
+
if (isNegative) {
|
|
204
|
+
result = NEGATIVE + ' '
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
result += integerToWords(integerPart)
|
|
208
|
+
|
|
209
|
+
if (decimalPart) {
|
|
210
|
+
result += ' ' + DECIMAL_SEP + ' ' + decimalPartToWords(decimalPart)
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return result
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// ============================================================================
|
|
217
|
+
// ORDINAL
|
|
218
|
+
// ============================================================================
|
|
219
|
+
|
|
220
|
+
function buildOrdinalSegment (n) {
|
|
221
|
+
const ones = n % 10
|
|
222
|
+
const tens = Math.trunc(n / 10) % 10
|
|
223
|
+
const hundreds = Math.trunc(n / 100)
|
|
224
|
+
|
|
225
|
+
let tensOnesOrdinal = ''
|
|
226
|
+
if (tens === 1) {
|
|
227
|
+
tensOnesOrdinal = ORDINAL_TEENS[ones]
|
|
228
|
+
} else if (tens >= 2) {
|
|
229
|
+
if (ones > 0) {
|
|
230
|
+
tensOnesOrdinal = TENS[tens] + '-' + ORDINAL_ONES[ones]
|
|
231
|
+
} else {
|
|
232
|
+
tensOnesOrdinal = ORDINAL_TENS[tens]
|
|
233
|
+
}
|
|
234
|
+
} else if (ones > 0) {
|
|
235
|
+
tensOnesOrdinal = ORDINAL_ONES[ones]
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (hundreds > 0) {
|
|
239
|
+
if (tensOnesOrdinal) {
|
|
240
|
+
return ONES[hundreds] + ' ' + HUNDRED + ' ' + tensOnesOrdinal
|
|
241
|
+
} else {
|
|
242
|
+
return ONES[hundreds] + ' hundredth'
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return tensOnesOrdinal
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function integerToOrdinal (n) {
|
|
250
|
+
if (n < 1000n) {
|
|
251
|
+
return buildOrdinalSegment(Number(n))
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
if (n < 1_000_000n) {
|
|
255
|
+
const thousands = Number(n / 1000n)
|
|
256
|
+
const remainder = Number(n % 1000n)
|
|
257
|
+
|
|
258
|
+
if (remainder === 0) {
|
|
259
|
+
return buildSegment(thousands).word + ' ' + SCALES[0] + 'th'
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const { word: thousandsWord } = buildSegment(thousands)
|
|
263
|
+
return thousandsWord + ' ' + SCALES[0] + ' ' + buildOrdinalSegment(remainder)
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
return buildLargeOrdinal(n)
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
function buildLargeOrdinal (n) {
|
|
270
|
+
const segments = []
|
|
271
|
+
let temp = n
|
|
272
|
+
while (temp > 0n) {
|
|
273
|
+
segments.push(Number(temp % 1000n))
|
|
274
|
+
temp = temp / 1000n
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
let lowestNonZeroIdx = 0
|
|
278
|
+
for (let i = 0; i < segments.length; i++) {
|
|
279
|
+
if (segments[i] !== 0) {
|
|
280
|
+
lowestNonZeroIdx = i
|
|
281
|
+
break
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
let result = ''
|
|
286
|
+
|
|
287
|
+
for (let i = segments.length - 1; i >= 0; i--) {
|
|
288
|
+
const segment = segments[i]
|
|
289
|
+
if (segment === 0) continue
|
|
290
|
+
|
|
291
|
+
const isLowestSegment = (i === lowestNonZeroIdx)
|
|
292
|
+
|
|
293
|
+
if (result) result += ' '
|
|
294
|
+
|
|
295
|
+
if (isLowestSegment) {
|
|
296
|
+
if (i === 0) {
|
|
297
|
+
result += buildOrdinalSegment(segment)
|
|
298
|
+
} else {
|
|
299
|
+
result += buildSegment(segment).word + ' ' + SCALES[i - 1] + 'th'
|
|
300
|
+
}
|
|
301
|
+
} else {
|
|
302
|
+
result += buildSegment(segment).word
|
|
303
|
+
if (i > 0) {
|
|
304
|
+
result += ' ' + SCALES[i - 1]
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
return result
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
function toOrdinal (value) {
|
|
313
|
+
const integerPart = parseOrdinalValue(value)
|
|
314
|
+
return integerToOrdinal(integerPart)
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// ============================================================================
|
|
318
|
+
// CURRENCY
|
|
319
|
+
// ============================================================================
|
|
320
|
+
|
|
321
|
+
function toCurrency (value, options) {
|
|
322
|
+
options = validateOptions(options)
|
|
323
|
+
const { isNegative, dollars: shillings, cents } = parseCurrencyValue(value)
|
|
324
|
+
const { and: useAnd = true } = options
|
|
325
|
+
|
|
326
|
+
let result = ''
|
|
327
|
+
if (isNegative) result = NEGATIVE + ' '
|
|
328
|
+
|
|
329
|
+
if (shillings > 0n || cents === 0n) {
|
|
330
|
+
result += integerToWords(shillings)
|
|
331
|
+
result += ' ' + (shillings === 1n ? SHILLING : SHILLINGS)
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
if (cents > 0n) {
|
|
335
|
+
if (shillings > 0n) {
|
|
336
|
+
result += useAnd ? ' and ' : ' '
|
|
337
|
+
}
|
|
338
|
+
result += integerToWords(cents)
|
|
339
|
+
result += ' ' + (cents === 1n ? CENT : CENTS)
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
return result
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
export { toCardinal, toOrdinal, toCurrency }
|
package/src/en-MY.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts a numeric value to Malaysian English words.
|
|
3
|
+
*
|
|
4
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
5
|
+
* @returns {string} The number in English words
|
|
6
|
+
* @throws {TypeError} If value is not a valid numeric type
|
|
7
|
+
* @throws {Error} If value is not a valid number format
|
|
8
|
+
*/
|
|
9
|
+
export function toCardinal(value: number | string | bigint): string;
|
|
10
|
+
export function toOrdinal(value: any): string;
|
|
11
|
+
export function toCurrency(value: any, options: any): string;
|
package/src/en-MY.js
ADDED
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Malaysian English language converter
|
|
3
|
+
*
|
|
4
|
+
* CLDR: en-MY | English as used in Malaysia
|
|
5
|
+
*
|
|
6
|
+
* Exports:
|
|
7
|
+
* - toCardinal(value) - Cardinal numbers: 42 → "forty-two"
|
|
8
|
+
* - toOrdinal(value) - Ordinal numbers: 42 → "forty-second"
|
|
9
|
+
* - toCurrency(value, options?) - Currency: 42.50 → "forty-two ringgit and fifty sen"
|
|
10
|
+
*
|
|
11
|
+
* Malaysian English conventions:
|
|
12
|
+
* - Follows British English style
|
|
13
|
+
* - "and" after hundreds: "one hundred and twenty-three"
|
|
14
|
+
* - "and" before final segment: "one million and one"
|
|
15
|
+
* - Hyphenated tens-ones: "twenty-one", "forty-two"
|
|
16
|
+
* - Western numbering system (short scale: billion = 10^9)
|
|
17
|
+
* - Currency: Malaysian Ringgit (MYR) - ringgit (invariable), sen (invariable)
|
|
18
|
+
*
|
|
19
|
+
* Note: Both "ringgit" and "sen" are typically invariable (same for singular and plural)
|
|
20
|
+
* in Malaysian English.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { parseCardinalValue } from './utils/parse-cardinal.js'
|
|
24
|
+
import { parseCurrencyValue } from './utils/parse-currency.js'
|
|
25
|
+
import { parseOrdinalValue } from './utils/parse-ordinal.js'
|
|
26
|
+
import { validateOptions } from './utils/validate-options.js'
|
|
27
|
+
|
|
28
|
+
// ============================================================================
|
|
29
|
+
// Vocabulary (module-level constants)
|
|
30
|
+
// ============================================================================
|
|
31
|
+
|
|
32
|
+
const ONES = ['', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']
|
|
33
|
+
const TEENS = ['ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen']
|
|
34
|
+
const TENS = ['', '', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety']
|
|
35
|
+
|
|
36
|
+
const SCALES = [
|
|
37
|
+
'thousand', 'million', 'billion', 'trillion', 'quadrillion',
|
|
38
|
+
'quintillion', 'sextillion', 'septillion', 'octillion', 'nonillion',
|
|
39
|
+
'decillion', 'undecillion', 'duodecillion', 'tredecillion', 'quattuordecillion',
|
|
40
|
+
'quindecillion', 'sexdecillion', 'septendecillion', 'octodecillion', 'novemdecillion',
|
|
41
|
+
'vigintillion'
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
const HUNDRED = 'hundred'
|
|
45
|
+
const ZERO = 'zero'
|
|
46
|
+
const NEGATIVE = 'minus'
|
|
47
|
+
const DECIMAL_SEP = 'point'
|
|
48
|
+
|
|
49
|
+
// Ordinal vocabulary
|
|
50
|
+
const ORDINAL_ONES = ['', 'first', 'second', 'third', 'fourth', 'fifth', 'sixth', 'seventh', 'eighth', 'ninth']
|
|
51
|
+
const ORDINAL_TEENS = ['tenth', 'eleventh', 'twelfth', 'thirteenth', 'fourteenth', 'fifteenth', 'sixteenth', 'seventeenth', 'eighteenth', 'nineteenth']
|
|
52
|
+
const ORDINAL_TENS = ['', '', 'twentieth', 'thirtieth', 'fortieth', 'fiftieth', 'sixtieth', 'seventieth', 'eightieth', 'ninetieth']
|
|
53
|
+
|
|
54
|
+
// Currency vocabulary (Malaysian Ringgit - both words are invariable)
|
|
55
|
+
const RINGGIT = 'ringgit'
|
|
56
|
+
const SEN = 'sen'
|
|
57
|
+
|
|
58
|
+
// ============================================================================
|
|
59
|
+
// Segment Building
|
|
60
|
+
// ============================================================================
|
|
61
|
+
|
|
62
|
+
const segmentResult = { word: '', hasHundred: false }
|
|
63
|
+
|
|
64
|
+
function buildSegment (n) {
|
|
65
|
+
if (n === 0) {
|
|
66
|
+
segmentResult.word = ''
|
|
67
|
+
segmentResult.hasHundred = false
|
|
68
|
+
return segmentResult
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const ones = n % 10
|
|
72
|
+
const tens = Math.trunc(n / 10) % 10
|
|
73
|
+
const hundreds = Math.trunc(n / 100)
|
|
74
|
+
|
|
75
|
+
let tensOnes = ''
|
|
76
|
+
if (tens === 1) {
|
|
77
|
+
tensOnes = TEENS[ones]
|
|
78
|
+
} else if (tens >= 2) {
|
|
79
|
+
tensOnes = ones > 0 ? TENS[tens] + '-' + ONES[ones] : TENS[tens]
|
|
80
|
+
} else if (ones > 0) {
|
|
81
|
+
tensOnes = ONES[ones]
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (hundreds > 0) {
|
|
85
|
+
if (tensOnes) {
|
|
86
|
+
segmentResult.word = ONES[hundreds] + ' ' + HUNDRED + ' and ' + tensOnes
|
|
87
|
+
} else {
|
|
88
|
+
segmentResult.word = ONES[hundreds] + ' ' + HUNDRED
|
|
89
|
+
}
|
|
90
|
+
segmentResult.hasHundred = true
|
|
91
|
+
} else {
|
|
92
|
+
segmentResult.word = tensOnes
|
|
93
|
+
segmentResult.hasHundred = false
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return segmentResult
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// ============================================================================
|
|
100
|
+
// Conversion Functions
|
|
101
|
+
// ============================================================================
|
|
102
|
+
|
|
103
|
+
function integerToWords (n) {
|
|
104
|
+
if (n === 0n) return ZERO
|
|
105
|
+
|
|
106
|
+
if (n < 1000n) {
|
|
107
|
+
return buildSegment(Number(n)).word
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (n < 1_000_000n) {
|
|
111
|
+
const thousands = Number(n / 1000n)
|
|
112
|
+
const remainder = Number(n % 1000n)
|
|
113
|
+
|
|
114
|
+
const { word: thousandsWord } = buildSegment(thousands)
|
|
115
|
+
let result = thousandsWord + ' ' + SCALES[0]
|
|
116
|
+
|
|
117
|
+
if (remainder > 0) {
|
|
118
|
+
const { word: remainderWord, hasHundred } = buildSegment(remainder)
|
|
119
|
+
result += hasHundred ? ' ' + remainderWord : ' and ' + remainderWord
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return result
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return buildLargeNumberWords(n)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function buildLargeNumberWords (n) {
|
|
129
|
+
const segments = []
|
|
130
|
+
let temp = n
|
|
131
|
+
while (temp > 0n) {
|
|
132
|
+
segments.push(Number(temp % 1000n))
|
|
133
|
+
temp = temp / 1000n
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
let firstNonZeroIdx = -1
|
|
137
|
+
for (let i = 0; i < segments.length; i++) {
|
|
138
|
+
if (segments[i] !== 0) {
|
|
139
|
+
firstNonZeroIdx = i
|
|
140
|
+
break
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
let result = ''
|
|
145
|
+
let prevWasScale = false
|
|
146
|
+
|
|
147
|
+
for (let i = segments.length - 1; i >= 0; i--) {
|
|
148
|
+
const segment = segments[i]
|
|
149
|
+
if (segment === 0) continue
|
|
150
|
+
|
|
151
|
+
const { word, hasHundred } = buildSegment(segment)
|
|
152
|
+
const isLastSegment = (i === firstNonZeroIdx)
|
|
153
|
+
|
|
154
|
+
if (result && isLastSegment && prevWasScale && !hasHundred) {
|
|
155
|
+
result += ' and'
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (result) result += ' '
|
|
159
|
+
result += word
|
|
160
|
+
|
|
161
|
+
if (i > 0) {
|
|
162
|
+
result += ' ' + SCALES[i - 1]
|
|
163
|
+
prevWasScale = true
|
|
164
|
+
} else {
|
|
165
|
+
prevWasScale = false
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return result
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function decimalPartToWords (decimalPart) {
|
|
173
|
+
let result = ''
|
|
174
|
+
|
|
175
|
+
let i = 0
|
|
176
|
+
while (i < decimalPart.length && decimalPart[i] === '0') {
|
|
177
|
+
if (result) result += ' '
|
|
178
|
+
result += ZERO
|
|
179
|
+
i++
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const remainder = decimalPart.slice(i)
|
|
183
|
+
if (remainder) {
|
|
184
|
+
if (result) result += ' '
|
|
185
|
+
result += integerToWords(BigInt(remainder))
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return result
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Converts a numeric value to Malaysian English words.
|
|
193
|
+
*
|
|
194
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
195
|
+
* @returns {string} The number in English words
|
|
196
|
+
* @throws {TypeError} If value is not a valid numeric type
|
|
197
|
+
* @throws {Error} If value is not a valid number format
|
|
198
|
+
*/
|
|
199
|
+
function toCardinal (value) {
|
|
200
|
+
const { isNegative, integerPart, decimalPart } = parseCardinalValue(value)
|
|
201
|
+
|
|
202
|
+
let result = ''
|
|
203
|
+
|
|
204
|
+
if (isNegative) {
|
|
205
|
+
result = NEGATIVE + ' '
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
result += integerToWords(integerPart)
|
|
209
|
+
|
|
210
|
+
if (decimalPart) {
|
|
211
|
+
result += ' ' + DECIMAL_SEP + ' ' + decimalPartToWords(decimalPart)
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return result
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// ============================================================================
|
|
218
|
+
// ORDINAL
|
|
219
|
+
// ============================================================================
|
|
220
|
+
|
|
221
|
+
function buildOrdinalSegment (n) {
|
|
222
|
+
const ones = n % 10
|
|
223
|
+
const tens = Math.trunc(n / 10) % 10
|
|
224
|
+
const hundreds = Math.trunc(n / 100)
|
|
225
|
+
|
|
226
|
+
let tensOnesOrdinal = ''
|
|
227
|
+
if (tens === 1) {
|
|
228
|
+
tensOnesOrdinal = ORDINAL_TEENS[ones]
|
|
229
|
+
} else if (tens >= 2) {
|
|
230
|
+
if (ones > 0) {
|
|
231
|
+
tensOnesOrdinal = TENS[tens] + '-' + ORDINAL_ONES[ones]
|
|
232
|
+
} else {
|
|
233
|
+
tensOnesOrdinal = ORDINAL_TENS[tens]
|
|
234
|
+
}
|
|
235
|
+
} else if (ones > 0) {
|
|
236
|
+
tensOnesOrdinal = ORDINAL_ONES[ones]
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
if (hundreds > 0) {
|
|
240
|
+
if (tensOnesOrdinal) {
|
|
241
|
+
return ONES[hundreds] + ' ' + HUNDRED + ' ' + tensOnesOrdinal
|
|
242
|
+
} else {
|
|
243
|
+
return ONES[hundreds] + ' hundredth'
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return tensOnesOrdinal
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function integerToOrdinal (n) {
|
|
251
|
+
if (n < 1000n) {
|
|
252
|
+
return buildOrdinalSegment(Number(n))
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
if (n < 1_000_000n) {
|
|
256
|
+
const thousands = Number(n / 1000n)
|
|
257
|
+
const remainder = Number(n % 1000n)
|
|
258
|
+
|
|
259
|
+
if (remainder === 0) {
|
|
260
|
+
return buildSegment(thousands).word + ' ' + SCALES[0] + 'th'
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const { word: thousandsWord } = buildSegment(thousands)
|
|
264
|
+
return thousandsWord + ' ' + SCALES[0] + ' ' + buildOrdinalSegment(remainder)
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
return buildLargeOrdinal(n)
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function buildLargeOrdinal (n) {
|
|
271
|
+
const segments = []
|
|
272
|
+
let temp = n
|
|
273
|
+
while (temp > 0n) {
|
|
274
|
+
segments.push(Number(temp % 1000n))
|
|
275
|
+
temp = temp / 1000n
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
let lowestNonZeroIdx = 0
|
|
279
|
+
for (let i = 0; i < segments.length; i++) {
|
|
280
|
+
if (segments[i] !== 0) {
|
|
281
|
+
lowestNonZeroIdx = i
|
|
282
|
+
break
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
let result = ''
|
|
287
|
+
|
|
288
|
+
for (let i = segments.length - 1; i >= 0; i--) {
|
|
289
|
+
const segment = segments[i]
|
|
290
|
+
if (segment === 0) continue
|
|
291
|
+
|
|
292
|
+
const isLowestSegment = (i === lowestNonZeroIdx)
|
|
293
|
+
|
|
294
|
+
if (result) result += ' '
|
|
295
|
+
|
|
296
|
+
if (isLowestSegment) {
|
|
297
|
+
if (i === 0) {
|
|
298
|
+
result += buildOrdinalSegment(segment)
|
|
299
|
+
} else {
|
|
300
|
+
result += buildSegment(segment).word + ' ' + SCALES[i - 1] + 'th'
|
|
301
|
+
}
|
|
302
|
+
} else {
|
|
303
|
+
result += buildSegment(segment).word
|
|
304
|
+
if (i > 0) {
|
|
305
|
+
result += ' ' + SCALES[i - 1]
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
return result
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function toOrdinal (value) {
|
|
314
|
+
const integerPart = parseOrdinalValue(value)
|
|
315
|
+
return integerToOrdinal(integerPart)
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// ============================================================================
|
|
319
|
+
// CURRENCY
|
|
320
|
+
// ============================================================================
|
|
321
|
+
|
|
322
|
+
function toCurrency (value, options) {
|
|
323
|
+
options = validateOptions(options)
|
|
324
|
+
const { isNegative, dollars: ringgit, cents: sen } = parseCurrencyValue(value)
|
|
325
|
+
const { and: useAnd = true } = options
|
|
326
|
+
|
|
327
|
+
let result = ''
|
|
328
|
+
if (isNegative) result = NEGATIVE + ' '
|
|
329
|
+
|
|
330
|
+
// Note: Both "ringgit" and "sen" are invariable in Malaysian English
|
|
331
|
+
if (ringgit > 0n || sen === 0n) {
|
|
332
|
+
result += integerToWords(ringgit)
|
|
333
|
+
result += ' ' + RINGGIT
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
if (sen > 0n) {
|
|
337
|
+
if (ringgit > 0n) {
|
|
338
|
+
result += useAnd ? ' and ' : ' '
|
|
339
|
+
}
|
|
340
|
+
result += integerToWords(sen)
|
|
341
|
+
result += ' ' + SEN
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
return result
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
export { toCardinal, toOrdinal, toCurrency }
|