n2words 3.1.0 → 4.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 +44 -0
- 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-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 +47 -82
- 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-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
|
@@ -0,0 +1,503 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Serbian (Serbia, Latin script) language converter
|
|
3
|
+
*
|
|
4
|
+
* CLDR: sr-Latn-RS | Serbian as used in Serbia (Latin script)
|
|
5
|
+
*
|
|
6
|
+
* Key features:
|
|
7
|
+
* - Three-form pluralization (one/few/many)
|
|
8
|
+
* - Gender: thousands are feminine, millions+ are masculine
|
|
9
|
+
* - Irregular hundreds (dvesta, trista, etc.)
|
|
10
|
+
* - Long scale naming with -ard forms
|
|
11
|
+
* - Latin script
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { parseCardinalValue } from './utils/parse-cardinal.js'
|
|
15
|
+
import { parseCurrencyValue } from './utils/parse-currency.js'
|
|
16
|
+
import { parseOrdinalValue } from './utils/parse-ordinal.js'
|
|
17
|
+
import { validateOptions } from './utils/validate-options.js'
|
|
18
|
+
|
|
19
|
+
// ============================================================================
|
|
20
|
+
// Vocabulary
|
|
21
|
+
// ============================================================================
|
|
22
|
+
|
|
23
|
+
const ONES_MASC = ['', 'jedan', 'dva', 'tri', 'četiri', 'pet', 'šest', 'sedam', 'osam', 'devet']
|
|
24
|
+
const ONES_FEM = ['', 'jedna', 'dve', 'tri', 'četiri', 'pet', 'šest', 'sedam', 'osam', 'devet']
|
|
25
|
+
const TEENS = ['deset', 'jedanaest', 'dvanaest', 'trinaest', 'četrnaest', 'petnaest', 'šesnaest', 'sedamnaest', 'osamnaest', 'devetnaest']
|
|
26
|
+
const TENS = ['', '', 'dvadeset', 'trideset', 'četrdeset', 'pedeset', 'šezdeset', 'sedamdeset', 'osamdeset', 'devedeset']
|
|
27
|
+
const HUNDREDS = ['', 'sto', 'dvesta', 'trista', 'četiristo', 'petsto', 'šesto', 'sedamsto', 'osamsto', 'devetsto']
|
|
28
|
+
|
|
29
|
+
const ZERO = 'nula'
|
|
30
|
+
const NEGATIVE = 'minus'
|
|
31
|
+
const DECIMAL_SEP = 'zapeta'
|
|
32
|
+
|
|
33
|
+
// ============================================================================
|
|
34
|
+
// Ordinal Vocabulary (masculine nominative)
|
|
35
|
+
// ============================================================================
|
|
36
|
+
|
|
37
|
+
// Ordinal ones: prvi, drugi, treći...
|
|
38
|
+
const ORDINAL_ONES = ['', 'prvi', 'drugi', 'treći', 'četvrti', 'peti', 'šesti', 'sedmi', 'osmi', 'deveti']
|
|
39
|
+
|
|
40
|
+
// Ordinal teens: deseti, jedanaesti...
|
|
41
|
+
const ORDINAL_TEENS = ['deseti', 'jedanaesti', 'dvanaesti', 'trinaesti', 'četrnaesti', 'petnaesti', 'šesnaesti', 'sedamnaesti', 'osamnaesti', 'devetnaesti']
|
|
42
|
+
|
|
43
|
+
// Ordinal tens: dvadeseti, trideseti...
|
|
44
|
+
const ORDINAL_TENS = ['', '', 'dvadeseti', 'trideseti', 'četrdeseti', 'pedeseti', 'šezdeseti', 'sedamdeseti', 'osamdeseti', 'devedeseti']
|
|
45
|
+
|
|
46
|
+
// Ordinal hundreds: stoti, dvestoti...
|
|
47
|
+
const ORDINAL_HUNDREDS = ['', 'stoti', 'dvestoti', 'tristoti', 'četiristoti', 'petstoti', 'šestoti', 'sedamstoti', 'osamstoti', 'devetstoti']
|
|
48
|
+
|
|
49
|
+
// Ordinal scale words (hiljaditi, milioniti, etc.)
|
|
50
|
+
const ORDINAL_SCALES = [
|
|
51
|
+
'hiljaditi',
|
|
52
|
+
'milioniti',
|
|
53
|
+
'milijarditi',
|
|
54
|
+
'bilioniti',
|
|
55
|
+
'bilijarditi',
|
|
56
|
+
'trilioniti',
|
|
57
|
+
'trilijarditi',
|
|
58
|
+
'kvadrilioniti',
|
|
59
|
+
'kvadrilijarditi'
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
// ============================================================================
|
|
63
|
+
// Currency Vocabulary (Serbian Dinar)
|
|
64
|
+
// ============================================================================
|
|
65
|
+
|
|
66
|
+
// Dinar: masculine, [singular, few, many]
|
|
67
|
+
const DINAR_FORMS = ['dinar', 'dinara', 'dinara']
|
|
68
|
+
|
|
69
|
+
// Para: feminine, [singular, few, many]
|
|
70
|
+
const PARA_FORMS = ['para', 'pare', 'para']
|
|
71
|
+
|
|
72
|
+
// Scale words: [singular, few, many]
|
|
73
|
+
const SCALE_FORMS = [
|
|
74
|
+
['hiljada', 'hiljade', 'hiljada'],
|
|
75
|
+
['milion', 'miliona', 'miliona'],
|
|
76
|
+
['milijarda', 'milijarde', 'milijarda'],
|
|
77
|
+
['bilion', 'biliona', 'biliona'],
|
|
78
|
+
['bilijarda', 'bilijarde', 'bilijarda'],
|
|
79
|
+
['trilion', 'triliona', 'triliona'],
|
|
80
|
+
['trilijarda', 'trilijarde', 'trilijarda'],
|
|
81
|
+
['kvadrilion', 'kvadriliona', 'kvadriliona'],
|
|
82
|
+
['kvadrilijarda', 'kvadrilijarde', 'kvadrilijarda']
|
|
83
|
+
]
|
|
84
|
+
|
|
85
|
+
// ============================================================================
|
|
86
|
+
// Segment Building
|
|
87
|
+
// ============================================================================
|
|
88
|
+
|
|
89
|
+
function pluralize (n, forms) {
|
|
90
|
+
const num = typeof n === 'bigint' ? Number(n) : n
|
|
91
|
+
const lastDigit = num % 10
|
|
92
|
+
const lastTwoDigits = num % 100
|
|
93
|
+
|
|
94
|
+
if (lastTwoDigits >= 11 && lastTwoDigits <= 19) {
|
|
95
|
+
return forms[2]
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (lastDigit === 1) return forms[0]
|
|
99
|
+
if (lastDigit >= 2 && lastDigit <= 4) return forms[1]
|
|
100
|
+
return forms[2]
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function buildSegmentMasc (n) {
|
|
104
|
+
if (n === 0) return ''
|
|
105
|
+
|
|
106
|
+
const onesDigit = n % 10
|
|
107
|
+
const tensDigit = Math.trunc(n / 10) % 10
|
|
108
|
+
const hundredsDigit = Math.trunc(n / 100)
|
|
109
|
+
|
|
110
|
+
const parts = []
|
|
111
|
+
|
|
112
|
+
if (hundredsDigit > 0) {
|
|
113
|
+
parts.push(HUNDREDS[hundredsDigit])
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (tensDigit > 1) {
|
|
117
|
+
parts.push(TENS[tensDigit])
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (tensDigit === 1) {
|
|
121
|
+
parts.push(TEENS[onesDigit])
|
|
122
|
+
} else if (onesDigit > 0) {
|
|
123
|
+
parts.push(ONES_MASC[onesDigit])
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return parts.join(' ')
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function buildSegmentFem (n) {
|
|
130
|
+
if (n === 0) return ''
|
|
131
|
+
|
|
132
|
+
const onesDigit = n % 10
|
|
133
|
+
const tensDigit = Math.trunc(n / 10) % 10
|
|
134
|
+
const hundredsDigit = Math.trunc(n / 100)
|
|
135
|
+
|
|
136
|
+
const parts = []
|
|
137
|
+
|
|
138
|
+
if (hundredsDigit > 0) {
|
|
139
|
+
parts.push(HUNDREDS[hundredsDigit])
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (tensDigit > 1) {
|
|
143
|
+
parts.push(TENS[tensDigit])
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (tensDigit === 1) {
|
|
147
|
+
parts.push(TEENS[onesDigit])
|
|
148
|
+
} else if (onesDigit > 0) {
|
|
149
|
+
parts.push(ONES_FEM[onesDigit])
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return parts.join(' ')
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// ============================================================================
|
|
156
|
+
// Conversion Functions
|
|
157
|
+
// ============================================================================
|
|
158
|
+
|
|
159
|
+
function integerToWords (n, gender) {
|
|
160
|
+
if (n === 0n) return ZERO
|
|
161
|
+
|
|
162
|
+
if (n < 1000n) {
|
|
163
|
+
return gender === 'feminine' ? buildSegmentFem(Number(n)) : buildSegmentMasc(Number(n))
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return buildLargeNumberWords(n, gender)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function buildLargeNumberWords (n, gender) {
|
|
170
|
+
const numStr = n.toString()
|
|
171
|
+
const len = numStr.length
|
|
172
|
+
|
|
173
|
+
const segments = []
|
|
174
|
+
const segmentSize = 3
|
|
175
|
+
|
|
176
|
+
const remainderLen = len % segmentSize
|
|
177
|
+
let pos = 0
|
|
178
|
+
if (remainderLen > 0) {
|
|
179
|
+
segments.push(Number(numStr.slice(0, remainderLen)))
|
|
180
|
+
pos = remainderLen
|
|
181
|
+
}
|
|
182
|
+
while (pos < len) {
|
|
183
|
+
segments.push(Number(numStr.slice(pos, pos + segmentSize)))
|
|
184
|
+
pos += segmentSize
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const parts = []
|
|
188
|
+
let scaleIndex = segments.length - 1
|
|
189
|
+
|
|
190
|
+
for (let i = 0; i < segments.length; i++) {
|
|
191
|
+
const segment = segments[i]
|
|
192
|
+
|
|
193
|
+
if (segment !== 0) {
|
|
194
|
+
if (scaleIndex === 0) {
|
|
195
|
+
parts.push(gender === 'feminine' ? buildSegmentFem(segment) : buildSegmentMasc(segment))
|
|
196
|
+
} else {
|
|
197
|
+
const scaleForms = SCALE_FORMS[scaleIndex - 1]
|
|
198
|
+
const scaleWord = pluralize(segment, scaleForms)
|
|
199
|
+
// Thousands (scaleIndex=1) are feminine, others masculine
|
|
200
|
+
const isFeminine = scaleIndex === 1
|
|
201
|
+
const segmentWord = isFeminine ? buildSegmentFem(segment) : buildSegmentMasc(segment)
|
|
202
|
+
parts.push(segmentWord + ' ' + scaleWord)
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
scaleIndex--
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return parts.join(' ')
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function decimalPartToWords (decimalPart, gender) {
|
|
213
|
+
let result = ''
|
|
214
|
+
let i = 0
|
|
215
|
+
|
|
216
|
+
while (i < decimalPart.length && decimalPart[i] === '0') {
|
|
217
|
+
if (result) result += ' '
|
|
218
|
+
result += ZERO
|
|
219
|
+
i++
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const remainder = decimalPart.slice(i)
|
|
223
|
+
if (remainder) {
|
|
224
|
+
if (result) result += ' '
|
|
225
|
+
result += integerToWords(BigInt(remainder), gender)
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return result
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Converts a numeric value to Serbian (Latin) words.
|
|
233
|
+
*
|
|
234
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
235
|
+
* @param {Object} [options] - Optional configuration
|
|
236
|
+
* @param {('masculine'|'feminine')} [options.gender='masculine'] - Grammatical gender
|
|
237
|
+
* @returns {string} The number in Serbian Latin words
|
|
238
|
+
*/
|
|
239
|
+
function toCardinal (value, options) {
|
|
240
|
+
options = validateOptions(options)
|
|
241
|
+
const { isNegative, integerPart, decimalPart } = parseCardinalValue(value)
|
|
242
|
+
|
|
243
|
+
// Apply option defaults
|
|
244
|
+
const { gender = 'masculine' } = options
|
|
245
|
+
|
|
246
|
+
let result = ''
|
|
247
|
+
|
|
248
|
+
if (isNegative) {
|
|
249
|
+
result = NEGATIVE + ' '
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
result += integerToWords(integerPart, gender)
|
|
253
|
+
|
|
254
|
+
if (decimalPart) {
|
|
255
|
+
result += ' ' + DECIMAL_SEP + ' ' + decimalPartToWords(decimalPart, gender)
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return result
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// ============================================================================
|
|
262
|
+
// ORDINAL: toOrdinal(value)
|
|
263
|
+
// ============================================================================
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Builds ordinal for a 0-99 segment when it's the final (ordinal) part.
|
|
267
|
+
* Returns ordinal form: "prvi", "dvadeset prvi", etc.
|
|
268
|
+
*
|
|
269
|
+
* @param {number} n - Number 0-99
|
|
270
|
+
* @returns {string} Ordinal words
|
|
271
|
+
*/
|
|
272
|
+
function buildOrdinalTensOnes (n) {
|
|
273
|
+
if (n === 0) return ''
|
|
274
|
+
|
|
275
|
+
const onesDigit = n % 10
|
|
276
|
+
const tensDigit = Math.trunc(n / 10)
|
|
277
|
+
|
|
278
|
+
if (tensDigit === 0) {
|
|
279
|
+
// Single digit: prvi, drugi, etc.
|
|
280
|
+
return ORDINAL_ONES[onesDigit]
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
if (tensDigit === 1) {
|
|
284
|
+
// Teens: deseti, jedanaesti, etc.
|
|
285
|
+
return ORDINAL_TEENS[onesDigit]
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// Tens >= 20
|
|
289
|
+
if (onesDigit === 0) {
|
|
290
|
+
// Round tens: dvadeseti, trideseti, etc.
|
|
291
|
+
return ORDINAL_TENS[tensDigit]
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Compound: dvadeset prvi, trideset drugi, etc.
|
|
295
|
+
return TENS[tensDigit] + ' ' + ORDINAL_ONES[onesDigit]
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Converts a positive integer to Serbian ordinal words (masculine nominative).
|
|
300
|
+
*
|
|
301
|
+
* In Serbian ordinals, only the LAST component becomes ordinal.
|
|
302
|
+
* E.g., 121 = "sto dvadeset prvi" (one hundred twenty first)
|
|
303
|
+
*
|
|
304
|
+
* @param {bigint} n - Positive integer to convert
|
|
305
|
+
* @returns {string} Ordinal Serbian words
|
|
306
|
+
*/
|
|
307
|
+
function integerToOrdinal (n) {
|
|
308
|
+
// Fast path: numbers < 100
|
|
309
|
+
if (n < 100n) {
|
|
310
|
+
return buildOrdinalTensOnes(Number(n))
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// Fast path: numbers < 1000
|
|
314
|
+
if (n < 1000n) {
|
|
315
|
+
const num = Number(n)
|
|
316
|
+
const hundredsDigit = Math.trunc(num / 100)
|
|
317
|
+
const remainder = num % 100
|
|
318
|
+
|
|
319
|
+
if (remainder === 0) {
|
|
320
|
+
// Exact hundreds: stoti, dvestoti, etc.
|
|
321
|
+
return ORDINAL_HUNDREDS[hundredsDigit]
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// Has remainder: cardinal hundreds + ordinal remainder
|
|
325
|
+
return HUNDREDS[hundredsDigit] + ' ' + buildOrdinalTensOnes(remainder)
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// Fast path: numbers < 1,000,000
|
|
329
|
+
if (n < 1_000_000n) {
|
|
330
|
+
const thousands = Number(n / 1000n)
|
|
331
|
+
const remainder = Number(n % 1000n)
|
|
332
|
+
|
|
333
|
+
if (remainder === 0) {
|
|
334
|
+
// Exact thousands: hiljaditi, etc.
|
|
335
|
+
if (thousands === 1) {
|
|
336
|
+
return ORDINAL_SCALES[0]
|
|
337
|
+
}
|
|
338
|
+
// Use cardinal segment + ordinal scale
|
|
339
|
+
return buildSegmentFem(thousands) + ' ' + ORDINAL_SCALES[0]
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// Has remainder: cardinal thousands + ordinal remainder
|
|
343
|
+
const thousandsWord = buildSegmentFem(thousands)
|
|
344
|
+
const scaleWord = pluralize(thousands, SCALE_FORMS[0])
|
|
345
|
+
return thousandsWord + ' ' + scaleWord + ' ' + integerToOrdinal(BigInt(remainder))
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// For numbers >= 1,000,000, use scale decomposition
|
|
349
|
+
return buildLargeOrdinal(n)
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Builds ordinal words for numbers >= 1,000,000.
|
|
354
|
+
* All segments except the final one are cardinal; final segment is ordinal.
|
|
355
|
+
*
|
|
356
|
+
* @param {bigint} n - Number >= 1,000,000
|
|
357
|
+
* @returns {string} Ordinal Serbian words
|
|
358
|
+
*/
|
|
359
|
+
function buildLargeOrdinal (n) {
|
|
360
|
+
const numStr = n.toString()
|
|
361
|
+
const len = numStr.length
|
|
362
|
+
|
|
363
|
+
// Extract segments (most-significant first)
|
|
364
|
+
const segments = []
|
|
365
|
+
const segmentSize = 3
|
|
366
|
+
|
|
367
|
+
const remainderLen = len % segmentSize
|
|
368
|
+
let pos = 0
|
|
369
|
+
if (remainderLen > 0) {
|
|
370
|
+
segments.push(Number(numStr.slice(0, remainderLen)))
|
|
371
|
+
pos = remainderLen
|
|
372
|
+
}
|
|
373
|
+
while (pos < len) {
|
|
374
|
+
segments.push(Number(numStr.slice(pos, pos + segmentSize)))
|
|
375
|
+
pos += segmentSize
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// Find the last non-zero segment
|
|
379
|
+
let lastNonZeroIdx = segments.length - 1
|
|
380
|
+
while (lastNonZeroIdx >= 0 && segments[lastNonZeroIdx] === 0) {
|
|
381
|
+
lastNonZeroIdx--
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
const parts = []
|
|
385
|
+
let scaleIndex = segments.length - 1
|
|
386
|
+
|
|
387
|
+
for (let i = 0; i < segments.length; i++) {
|
|
388
|
+
const segment = segments[i]
|
|
389
|
+
|
|
390
|
+
if (segment !== 0) {
|
|
391
|
+
const isLastNonZero = (i === lastNonZeroIdx)
|
|
392
|
+
|
|
393
|
+
if (scaleIndex === 0) {
|
|
394
|
+
// Units position (no scale)
|
|
395
|
+
if (isLastNonZero) {
|
|
396
|
+
parts.push(integerToOrdinal(BigInt(segment)))
|
|
397
|
+
} else {
|
|
398
|
+
parts.push(buildSegmentMasc(segment))
|
|
399
|
+
}
|
|
400
|
+
} else {
|
|
401
|
+
// Has scale word
|
|
402
|
+
if (isLastNonZero) {
|
|
403
|
+
// This scale position is the final ordinal
|
|
404
|
+
if (segment === 1) {
|
|
405
|
+
parts.push(ORDINAL_SCALES[scaleIndex - 1])
|
|
406
|
+
} else {
|
|
407
|
+
// Use cardinal segment + ordinal scale
|
|
408
|
+
const isFeminine = scaleIndex === 1 // thousands are feminine
|
|
409
|
+
const segmentWord = isFeminine ? buildSegmentFem(segment) : buildSegmentMasc(segment)
|
|
410
|
+
parts.push(segmentWord + ' ' + ORDINAL_SCALES[scaleIndex - 1])
|
|
411
|
+
}
|
|
412
|
+
} else {
|
|
413
|
+
// Not the final segment: use cardinal
|
|
414
|
+
const scaleForms = SCALE_FORMS[scaleIndex - 1]
|
|
415
|
+
const scaleWord = pluralize(segment, scaleForms)
|
|
416
|
+
const isFeminine = scaleIndex === 1
|
|
417
|
+
const segmentWord = isFeminine ? buildSegmentFem(segment) : buildSegmentMasc(segment)
|
|
418
|
+
parts.push(segmentWord + ' ' + scaleWord)
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
scaleIndex--
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
return parts.join(' ')
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* Converts a numeric value to Serbian ordinal words (masculine nominative).
|
|
431
|
+
*
|
|
432
|
+
* @param {number | string | bigint} value - The numeric value to convert (must be a positive integer)
|
|
433
|
+
* @returns {string} The number as ordinal words (e.g., "prvi", "četrdeset drugi")
|
|
434
|
+
* @throws {TypeError} If value is not a valid numeric type
|
|
435
|
+
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
436
|
+
*
|
|
437
|
+
* @example
|
|
438
|
+
* toOrdinal(1) // 'prvi'
|
|
439
|
+
* toOrdinal(2) // 'drugi'
|
|
440
|
+
* toOrdinal(3) // 'treći'
|
|
441
|
+
* toOrdinal(21) // 'dvadeset prvi'
|
|
442
|
+
* toOrdinal(42) // 'četrdeset drugi'
|
|
443
|
+
* toOrdinal(100) // 'stoti'
|
|
444
|
+
* toOrdinal(1000) // 'hiljaditi'
|
|
445
|
+
*/
|
|
446
|
+
function toOrdinal (value) {
|
|
447
|
+
const integerPart = parseOrdinalValue(value)
|
|
448
|
+
return integerToOrdinal(integerPart)
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// ============================================================================
|
|
452
|
+
// CURRENCY: toCurrency(value, options?)
|
|
453
|
+
// ============================================================================
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Converts a numeric value to Serbian currency words (Serbian Dinar).
|
|
457
|
+
*
|
|
458
|
+
* @param {number | string | bigint} value - The currency amount to convert
|
|
459
|
+
* @param {Object} [options] - Optional configuration
|
|
460
|
+
* @param {boolean} [options.and=true] - Use "i" between dinars and para
|
|
461
|
+
* @returns {string} The amount in Serbian currency words
|
|
462
|
+
* @throws {TypeError} If value is not a valid numeric type
|
|
463
|
+
* @throws {Error} If value is not a valid number format
|
|
464
|
+
*
|
|
465
|
+
* @example
|
|
466
|
+
* toCurrency(42.50) // 'četrdeset dva dinara i pedeset para'
|
|
467
|
+
* toCurrency(1) // 'jedan dinar'
|
|
468
|
+
* toCurrency(0.99) // 'devedeset devet para'
|
|
469
|
+
* toCurrency(0.01) // 'jedna para'
|
|
470
|
+
* toCurrency(42.50, { and: false }) // 'četrdeset dva dinara pedeset para'
|
|
471
|
+
*/
|
|
472
|
+
function toCurrency (value, options) {
|
|
473
|
+
options = validateOptions(options)
|
|
474
|
+
const { isNegative, dollars: dinars, cents: para } = parseCurrencyValue(value)
|
|
475
|
+
const { and: useAnd = true } = options
|
|
476
|
+
|
|
477
|
+
// Build result
|
|
478
|
+
let result = ''
|
|
479
|
+
if (isNegative) result = NEGATIVE + ' '
|
|
480
|
+
|
|
481
|
+
// Dinars part (masculine) - show if non-zero, or if no para
|
|
482
|
+
if (dinars > 0n || para === 0n) {
|
|
483
|
+
result += integerToWords(dinars, 'masculine')
|
|
484
|
+
result += ' ' + pluralize(dinars, DINAR_FORMS)
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
// Para part (feminine)
|
|
488
|
+
if (para > 0n) {
|
|
489
|
+
if (dinars > 0n) {
|
|
490
|
+
result += useAnd ? ' i ' : ' '
|
|
491
|
+
}
|
|
492
|
+
result += integerToWords(para, 'feminine')
|
|
493
|
+
result += ' ' + pluralize(para, PARA_FORMS)
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
return result
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
// ============================================================================
|
|
500
|
+
// Exports
|
|
501
|
+
// ============================================================================
|
|
502
|
+
|
|
503
|
+
export { toCardinal, toOrdinal, toCurrency }
|
package/src/sv-SE.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts a numeric value to Swedish words.
|
|
3
|
+
*
|
|
4
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
5
|
+
* @returns {string} The number in Swedish 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
|
+
* @example
|
|
10
|
+
* toCardinal(42) // 'fyrtio-två'
|
|
11
|
+
* toCardinal(101) // 'hundra och ett'
|
|
12
|
+
* toCardinal(1000000) // 'en miljon'
|
|
13
|
+
*/
|
|
14
|
+
export function toCardinal(value: number | string | bigint): string;
|
|
15
|
+
/**
|
|
16
|
+
* Converts a numeric value to Swedish ordinal words.
|
|
17
|
+
*
|
|
18
|
+
* @param {number | string | bigint} value - The numeric value to convert (positive integer)
|
|
19
|
+
* @returns {string} The number as ordinal words
|
|
20
|
+
* @throws {TypeError} If value is not a valid numeric type
|
|
21
|
+
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* toOrdinal(1) // 'första'
|
|
25
|
+
* toOrdinal(2) // 'andra'
|
|
26
|
+
* toOrdinal(21) // 'tjugo-ettde'
|
|
27
|
+
*/
|
|
28
|
+
export function toOrdinal(value: number | string | bigint): string;
|
|
29
|
+
/**
|
|
30
|
+
* Converts a numeric value to Swedish currency words (Swedish Krona).
|
|
31
|
+
*
|
|
32
|
+
* Uses krona/kronor and öre (100 öre = 1 krona).
|
|
33
|
+
*
|
|
34
|
+
* @param {number | string | bigint} value - The currency amount to convert
|
|
35
|
+
* @returns {string} The amount in Swedish currency words
|
|
36
|
+
* @throws {TypeError} If value is not a valid numeric type
|
|
37
|
+
* @throws {Error} If value is not a valid number format
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* toCurrency(1) // 'en krona'
|
|
41
|
+
* toCurrency(42) // 'fyrtio-två kronor'
|
|
42
|
+
* toCurrency(1.50) // 'en krona och femtio öre'
|
|
43
|
+
*/
|
|
44
|
+
export function toCurrency(value: number | string | bigint): string;
|