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
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Portuguese language converter
|
|
2
|
+
* Portuguese (Portugal) language converter
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* CLDR: pt-PT | European Portuguese as used in Portugal
|
|
5
5
|
*
|
|
6
6
|
* Portuguese-specific rules:
|
|
7
7
|
* - "e" conjunction everywhere: vinte e um, cento e um, mil e um
|
|
8
8
|
* - "cem" for exact 100, "cento" for 100+ remainder
|
|
9
9
|
* - Irregular hundreds: duzentos, trezentos, quatrocentos, etc.
|
|
10
|
-
* -
|
|
10
|
+
* - Long scale: milhão (10^6), mil milhões (10^9), bilião (10^12)
|
|
11
11
|
* - Omit "um" before "mil"
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import {
|
|
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'
|
|
15
18
|
|
|
16
19
|
// ============================================================================
|
|
17
20
|
// Vocabulary (module-level constants)
|
|
@@ -29,6 +32,18 @@ const ZERO = 'zero'
|
|
|
29
32
|
const NEGATIVE = 'menos'
|
|
30
33
|
const DECIMAL_SEP = 'vírgula'
|
|
31
34
|
|
|
35
|
+
// Ordinal vocabulary
|
|
36
|
+
const ORDINAL_ONES = ['', 'primeiro', 'segundo', 'terceiro', 'quarto', 'quinto', 'sexto', 'sétimo', 'oitavo', 'nono']
|
|
37
|
+
const ORDINAL_TEENS = ['décimo', 'décimo primeiro', 'décimo segundo', 'décimo terceiro', 'décimo quarto', 'décimo quinto', 'décimo sexto', 'décimo sétimo', 'décimo oitavo', 'décimo nono']
|
|
38
|
+
const ORDINAL_TENS = ['', '', 'vigésimo', 'trigésimo', 'quadragésimo', 'quinquagésimo', 'sexagésimo', 'septuagésimo', 'octogésimo', 'nonagésimo']
|
|
39
|
+
const ORDINAL_HUNDREDS = ['', 'centésimo', 'ducentésimo', 'tricentésimo', 'quadringentésimo', 'quingentésimo', 'sexcentésimo', 'septingentésimo', 'octingentésimo', 'nongentésimo']
|
|
40
|
+
|
|
41
|
+
// Currency vocabulary (Euro)
|
|
42
|
+
const EURO = 'euro'
|
|
43
|
+
const EUROS = 'euros'
|
|
44
|
+
const CENTIMO = 'cêntimo'
|
|
45
|
+
const CENTIMOS = 'cêntimos'
|
|
46
|
+
|
|
32
47
|
// ============================================================================
|
|
33
48
|
// Segment Building
|
|
34
49
|
// ============================================================================
|
|
@@ -44,8 +59,8 @@ function buildSegment (n) {
|
|
|
44
59
|
if (n === 100) return { word: 'cem', isExactHundred: true }
|
|
45
60
|
|
|
46
61
|
const ones = n % 10
|
|
47
|
-
const tens = Math.
|
|
48
|
-
const hundreds = Math.
|
|
62
|
+
const tens = Math.trunc(n / 10) % 10
|
|
63
|
+
const hundreds = Math.trunc(n / 100)
|
|
49
64
|
|
|
50
65
|
const parts = []
|
|
51
66
|
|
|
@@ -263,12 +278,12 @@ function decimalPartToWords (decimalPart) {
|
|
|
263
278
|
* @throws {Error} If value is not a valid number format
|
|
264
279
|
*
|
|
265
280
|
* @example
|
|
266
|
-
*
|
|
267
|
-
*
|
|
268
|
-
*
|
|
281
|
+
* toCardinal(21) // 'vinte e um'
|
|
282
|
+
* toCardinal(100) // 'cem'
|
|
283
|
+
* toCardinal(1000000) // 'um milhão'
|
|
269
284
|
*/
|
|
270
|
-
function
|
|
271
|
-
const { isNegative, integerPart, decimalPart } =
|
|
285
|
+
function toCardinal (value) {
|
|
286
|
+
const { isNegative, integerPart, decimalPart } = parseCardinalValue(value)
|
|
272
287
|
|
|
273
288
|
let result = ''
|
|
274
289
|
|
|
@@ -285,8 +300,215 @@ function toWords (value) {
|
|
|
285
300
|
return result
|
|
286
301
|
}
|
|
287
302
|
|
|
303
|
+
// ============================================================================
|
|
304
|
+
// Ordinal Functions
|
|
305
|
+
// ============================================================================
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Builds ordinal words for 0-999.
|
|
309
|
+
*
|
|
310
|
+
* @param {number} n - Number 0-999
|
|
311
|
+
* @returns {string} Portuguese ordinal words
|
|
312
|
+
*/
|
|
313
|
+
function buildOrdinalSegment (n) {
|
|
314
|
+
if (n === 0) return ''
|
|
315
|
+
|
|
316
|
+
const ones = n % 10
|
|
317
|
+
const tens = Math.trunc(n / 10) % 10
|
|
318
|
+
const hundreds = Math.trunc(n / 100)
|
|
319
|
+
|
|
320
|
+
const parts = []
|
|
321
|
+
|
|
322
|
+
// Hundreds ordinal
|
|
323
|
+
if (hundreds > 0) {
|
|
324
|
+
parts.push(ORDINAL_HUNDREDS[hundreds])
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// Tens and ones
|
|
328
|
+
if (tens === 1) {
|
|
329
|
+
// 10-19: use teens array (décimo, décimo primeiro, etc.)
|
|
330
|
+
parts.push(ORDINAL_TEENS[ones])
|
|
331
|
+
} else if (tens >= 2) {
|
|
332
|
+
parts.push(ORDINAL_TENS[tens])
|
|
333
|
+
if (ones > 0) {
|
|
334
|
+
parts.push(ORDINAL_ONES[ones])
|
|
335
|
+
}
|
|
336
|
+
} else if (ones > 0) {
|
|
337
|
+
parts.push(ORDINAL_ONES[ones])
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
return parts.join(' ')
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Builds ordinal words for large numbers.
|
|
345
|
+
*
|
|
346
|
+
* @param {bigint} n - Non-negative integer
|
|
347
|
+
* @returns {string} Portuguese ordinal words
|
|
348
|
+
*/
|
|
349
|
+
function buildLargeOrdinal (n) {
|
|
350
|
+
// Extract segments
|
|
351
|
+
const segments = []
|
|
352
|
+
let temp = n
|
|
353
|
+
while (temp > 0n) {
|
|
354
|
+
segments.push(Number(temp % 1000n))
|
|
355
|
+
temp = temp / 1000n
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Find the lowest non-zero segment (index 0 = units, lowest scale)
|
|
359
|
+
let lowestNonZeroIdx = 0
|
|
360
|
+
for (let i = 0; i < segments.length; i++) {
|
|
361
|
+
if (segments[i] !== 0) {
|
|
362
|
+
lowestNonZeroIdx = i
|
|
363
|
+
break
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// Scale ordinal words (singular forms)
|
|
368
|
+
const SCALE_ORDINAL = ['', 'milésimo', 'milionésimo', 'mil milionésimo', 'bilionésimo', 'mil bilionésimo', 'trilionésimo']
|
|
369
|
+
|
|
370
|
+
let result = ''
|
|
371
|
+
|
|
372
|
+
for (let i = segments.length - 1; i >= 0; i--) {
|
|
373
|
+
const segment = segments[i]
|
|
374
|
+
if (segment === 0) continue
|
|
375
|
+
|
|
376
|
+
if (result) result += ' '
|
|
377
|
+
|
|
378
|
+
if (i === lowestNonZeroIdx) {
|
|
379
|
+
// Last non-zero segment gets ordinal form
|
|
380
|
+
if (i === 0) {
|
|
381
|
+
// Units: just ordinal
|
|
382
|
+
result += buildOrdinalSegment(segment)
|
|
383
|
+
} else if (segment === 1 && i > 0) {
|
|
384
|
+
// Exact scale: "milésimo", "milionésimo", etc.
|
|
385
|
+
result += SCALE_ORDINAL[i]
|
|
386
|
+
} else {
|
|
387
|
+
// Segment + scale ordinal
|
|
388
|
+
result += buildOrdinalSegment(segment) + ' ' + SCALE_ORDINAL[i]
|
|
389
|
+
}
|
|
390
|
+
} else {
|
|
391
|
+
// Higher segments use cardinal form
|
|
392
|
+
if (i === 0) {
|
|
393
|
+
result += buildSegment(segment).word
|
|
394
|
+
} else if (i === 1) {
|
|
395
|
+
if (segment === 1) {
|
|
396
|
+
result += THOUSAND
|
|
397
|
+
} else {
|
|
398
|
+
result += buildSegment(segment).word + ' ' + THOUSAND
|
|
399
|
+
}
|
|
400
|
+
} else {
|
|
401
|
+
const scaleWord = segment === 1 ? SCALE_WORDS_SINGULAR[i] : SCALE_WORDS_PLURAL[i]
|
|
402
|
+
if (segment === 1) {
|
|
403
|
+
result += 'um ' + scaleWord
|
|
404
|
+
} else {
|
|
405
|
+
result += buildSegment(segment).word + ' ' + scaleWord
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
return result
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Converts a number to Portuguese ordinal words.
|
|
416
|
+
*
|
|
417
|
+
* @param {number | string | bigint} value - The number to convert
|
|
418
|
+
* @returns {string} Portuguese ordinal words
|
|
419
|
+
*
|
|
420
|
+
* @example
|
|
421
|
+
* toOrdinal(1) // 'primeiro'
|
|
422
|
+
* toOrdinal(21) // 'vigésimo primeiro'
|
|
423
|
+
* toOrdinal(100) // 'centésimo'
|
|
424
|
+
*/
|
|
425
|
+
function toOrdinal (value) {
|
|
426
|
+
const n = parseOrdinalValue(value)
|
|
427
|
+
|
|
428
|
+
// Fast path: 1-9
|
|
429
|
+
if (n < 10n) {
|
|
430
|
+
return ORDINAL_ONES[Number(n)]
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// Fast path: 10-19
|
|
434
|
+
if (n < 20n) {
|
|
435
|
+
return ORDINAL_TEENS[Number(n) - 10]
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// Fast path: 20-99
|
|
439
|
+
if (n < 100n) {
|
|
440
|
+
const ones = Number(n % 10n)
|
|
441
|
+
const tens = Number(n / 10n)
|
|
442
|
+
if (ones === 0) {
|
|
443
|
+
return ORDINAL_TENS[tens]
|
|
444
|
+
}
|
|
445
|
+
return ORDINAL_TENS[tens] + ' ' + ORDINAL_ONES[ones]
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// Fast path: 100-999
|
|
449
|
+
if (n < 1000n) {
|
|
450
|
+
return buildOrdinalSegment(Number(n))
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// Large numbers
|
|
454
|
+
return buildLargeOrdinal(n)
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// ============================================================================
|
|
458
|
+
// Currency Functions
|
|
459
|
+
// ============================================================================
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Converts a number to Portuguese currency words (Euro).
|
|
463
|
+
*
|
|
464
|
+
* @param {number | string | bigint} value - The amount to convert
|
|
465
|
+
* @param {Object} [options]
|
|
466
|
+
* @param {boolean} [options.and=true] - Include "e" between euros and cents
|
|
467
|
+
* @returns {string} Portuguese currency words
|
|
468
|
+
*
|
|
469
|
+
* @example
|
|
470
|
+
* toCurrency(42.50) // 'quarenta e dois euros e cinquenta cêntimos'
|
|
471
|
+
* toCurrency(1) // 'um euro'
|
|
472
|
+
* toCurrency(0.01) // 'um cêntimo'
|
|
473
|
+
*/
|
|
474
|
+
function toCurrency (value, options) {
|
|
475
|
+
options = validateOptions(options)
|
|
476
|
+
const { isNegative, dollars: euros, cents } = parseCurrencyValue(value)
|
|
477
|
+
const { and = true } = options
|
|
478
|
+
|
|
479
|
+
let result = ''
|
|
480
|
+
|
|
481
|
+
if (isNegative) {
|
|
482
|
+
result = NEGATIVE + ' '
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
const hasEuros = euros > 0n
|
|
486
|
+
const hasCents = cents > 0n
|
|
487
|
+
|
|
488
|
+
if (!hasEuros && !hasCents) {
|
|
489
|
+
return ZERO + ' ' + EUROS
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
if (hasEuros) {
|
|
493
|
+
const euroWords = integerToWords(euros)
|
|
494
|
+
const euroUnit = euros === 1n ? EURO : EUROS
|
|
495
|
+
result += euroWords + ' ' + euroUnit
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
if (hasCents) {
|
|
499
|
+
if (hasEuros) {
|
|
500
|
+
result += and ? ' e ' : ' '
|
|
501
|
+
}
|
|
502
|
+
const centWords = integerToWords(cents)
|
|
503
|
+
const centUnit = cents === 1n ? CENTIMO : CENTIMOS
|
|
504
|
+
result += centWords + ' ' + centUnit
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
return result
|
|
508
|
+
}
|
|
509
|
+
|
|
288
510
|
// ============================================================================
|
|
289
511
|
// Public API
|
|
290
512
|
// ============================================================================
|
|
291
513
|
|
|
292
|
-
export {
|
|
514
|
+
export { toCardinal, toOrdinal, toCurrency }
|
package/src/ro-RO.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts a numeric value to Romanian words.
|
|
3
|
+
*
|
|
4
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
5
|
+
* @param {Object} [options] - Conversion options
|
|
6
|
+
* @param {string} [options.gender='masculine'] - Gender for numbers
|
|
7
|
+
* @returns {string} The number in Romanian words
|
|
8
|
+
* @throws {TypeError} If value is not a valid numeric type
|
|
9
|
+
* @throws {Error} If value is not a valid number format
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* toCardinal(21) // 'douăzeci și unu'
|
|
13
|
+
* toCardinal(1, { gender: 'feminine' }) // 'una'
|
|
14
|
+
* toCardinal(1000) // 'o mie'
|
|
15
|
+
*/
|
|
16
|
+
export function toCardinal(value: number | string | bigint, options?: {
|
|
17
|
+
gender?: string | undefined;
|
|
18
|
+
}): string;
|
|
19
|
+
/**
|
|
20
|
+
* Converts a numeric value to Romanian ordinal words.
|
|
21
|
+
*
|
|
22
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
23
|
+
* @returns {string} The ordinal in Romanian words
|
|
24
|
+
* @throws {TypeError} If value is not a valid numeric type
|
|
25
|
+
* @throws {Error} If value is not a positive integer
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* toOrdinal(1) // 'primul'
|
|
29
|
+
* toOrdinal(21) // 'douăzeci și primul'
|
|
30
|
+
*/
|
|
31
|
+
export function toOrdinal(value: number | string | bigint): string;
|
|
32
|
+
/**
|
|
33
|
+
* Converts a numeric value to Romanian Leu currency words.
|
|
34
|
+
*
|
|
35
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
36
|
+
* @returns {string} The currency in Romanian words
|
|
37
|
+
* @throws {TypeError} If value is not a valid numeric type
|
|
38
|
+
* @throws {Error} If value is not a valid number format
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* toCurrency(1) // 'un leu'
|
|
42
|
+
* toCurrency(2.50) // 'doi lei cincizeci de bani'
|
|
43
|
+
*/
|
|
44
|
+
export function toCurrency(value: number | string | bigint): string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Romanian language converter
|
|
2
|
+
* Romanian (Romania) language converter
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* CLDR: ro-RO | Romanian as used in Romania
|
|
5
5
|
*
|
|
6
6
|
* Key features:
|
|
7
7
|
* - Gender agreement (unu/una, doi/două)
|
|
@@ -10,8 +10,10 @@
|
|
|
10
10
|
* - Feminine units for thousands
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
13
|
+
import { parseCardinalValue } from './utils/parse-cardinal.js'
|
|
14
|
+
import { parseCurrencyValue } from './utils/parse-currency.js'
|
|
15
|
+
import { parseOrdinalValue } from './utils/parse-ordinal.js'
|
|
16
|
+
import { validateOptions } from './utils/validate-options.js'
|
|
15
17
|
|
|
16
18
|
// ============================================================================
|
|
17
19
|
// Vocabulary (module-level constants)
|
|
@@ -31,6 +33,20 @@ const ZERO = 'zero'
|
|
|
31
33
|
const NEGATIVE = 'minus'
|
|
32
34
|
const DECIMAL_SEP = 'virgulă'
|
|
33
35
|
|
|
36
|
+
// Ordinal vocabulary (masculine forms)
|
|
37
|
+
const ORDINAL_ONES = ['', 'primul', 'al doilea', 'al treilea', 'al patrulea', 'al cincilea', 'al șaselea', 'al șaptelea', 'al optulea', 'al nouălea']
|
|
38
|
+
const ORDINAL_TEENS = ['al zecelea', 'al unsprezecelea', 'al doisprezecelea', 'al treisprezecelea', 'al paisprezecelea', 'al cincisprezecelea', 'al șaisprezecelea', 'al șaptesprezecelea', 'al optsprezecelea', 'al nouăsprezecelea']
|
|
39
|
+
const ORDINAL_TENS = ['', '', 'al douăzecilea', 'al treizecilea', 'al patruzecilea', 'al cincizecilea', 'al șaizecilea', 'al șaptezecilea', 'al optzecilea', 'al nouăzecilea']
|
|
40
|
+
const ORDINAL_HUNDRED = 'al sutălea'
|
|
41
|
+
const ORDINAL_THOUSAND = 'al miilea'
|
|
42
|
+
const ORDINAL_MILLION = 'al milionulea'
|
|
43
|
+
|
|
44
|
+
// Currency (Romanian Leu)
|
|
45
|
+
const LEU_SINGULAR = 'leu'
|
|
46
|
+
const LEU_PLURAL = 'lei'
|
|
47
|
+
const BAN_SINGULAR = 'ban'
|
|
48
|
+
const BAN_PLURAL = 'bani'
|
|
49
|
+
|
|
34
50
|
// Scale metadata: [singular, plural, article, feminine, needsDe]
|
|
35
51
|
// - singular: form for 1
|
|
36
52
|
// - plural: form for 2+
|
|
@@ -64,7 +80,7 @@ function spellUnder100 (n, feminine = false, masculineTeens = false) {
|
|
|
64
80
|
if (n < 20) {
|
|
65
81
|
return masculineTeens ? TEENS_MASC[n - 10] : TEENS[n - 10]
|
|
66
82
|
}
|
|
67
|
-
const t = Math.
|
|
83
|
+
const t = Math.trunc(n / 10)
|
|
68
84
|
const u = n % 10
|
|
69
85
|
if (u === 0) {
|
|
70
86
|
return TWENTIES[t]
|
|
@@ -80,7 +96,7 @@ function spellUnder1000 (n, feminine = false, masculineTeens = false) {
|
|
|
80
96
|
if (n === 0) return ''
|
|
81
97
|
if (n < 100) return spellUnder100(n, feminine, masculineTeens)
|
|
82
98
|
|
|
83
|
-
const h = Math.
|
|
99
|
+
const h = Math.trunc(n / 100)
|
|
84
100
|
const r = n % 100
|
|
85
101
|
const hundredWord = HUNDREDS[h]
|
|
86
102
|
|
|
@@ -126,16 +142,16 @@ function buildScalePhrase (segment, scaleIndex) {
|
|
|
126
142
|
* @param {Object} options - Conversion options
|
|
127
143
|
* @returns {string} Romanian words
|
|
128
144
|
*/
|
|
129
|
-
function integerToWords (n,
|
|
145
|
+
function integerToWords (n, gender) {
|
|
130
146
|
if (n === 0n) return ZERO
|
|
131
147
|
|
|
132
148
|
// Fast path: numbers < 1000
|
|
133
149
|
if (n < 1000n) {
|
|
134
|
-
const feminine =
|
|
150
|
+
const feminine = gender === 'feminine'
|
|
135
151
|
return spellUnder1000(Number(n), feminine)
|
|
136
152
|
}
|
|
137
153
|
|
|
138
|
-
return buildLargeNumberWords(n,
|
|
154
|
+
return buildLargeNumberWords(n, gender)
|
|
139
155
|
}
|
|
140
156
|
|
|
141
157
|
/**
|
|
@@ -146,7 +162,7 @@ function integerToWords (n, options = {}) {
|
|
|
146
162
|
* @param {Object} options - Conversion options
|
|
147
163
|
* @returns {string} Romanian words
|
|
148
164
|
*/
|
|
149
|
-
function buildLargeNumberWords (n,
|
|
165
|
+
function buildLargeNumberWords (n, gender) {
|
|
150
166
|
// Extract segments using BigInt division (faster than string slicing)
|
|
151
167
|
// Segments stored least-significant first (index 0 = ones, 1 = thousands, etc.)
|
|
152
168
|
const segmentValues = []
|
|
@@ -166,7 +182,7 @@ function buildLargeNumberWords (n, options) {
|
|
|
166
182
|
let segmentWords
|
|
167
183
|
if (i === 0) {
|
|
168
184
|
// Units segment - use gender from options
|
|
169
|
-
const feminine =
|
|
185
|
+
const feminine = gender === 'feminine'
|
|
170
186
|
segmentWords = spellUnder1000(segment, feminine)
|
|
171
187
|
} else {
|
|
172
188
|
// Scale segment
|
|
@@ -227,13 +243,16 @@ function decimalPartToWords (decimalPart) {
|
|
|
227
243
|
* @throws {Error} If value is not a valid number format
|
|
228
244
|
*
|
|
229
245
|
* @example
|
|
230
|
-
*
|
|
231
|
-
*
|
|
232
|
-
*
|
|
246
|
+
* toCardinal(21) // 'douăzeci și unu'
|
|
247
|
+
* toCardinal(1, { gender: 'feminine' }) // 'una'
|
|
248
|
+
* toCardinal(1000) // 'o mie'
|
|
233
249
|
*/
|
|
234
|
-
function
|
|
250
|
+
function toCardinal (value, options) {
|
|
235
251
|
options = validateOptions(options)
|
|
236
|
-
const { isNegative, integerPart, decimalPart } =
|
|
252
|
+
const { isNegative, integerPart, decimalPart } = parseCardinalValue(value)
|
|
253
|
+
|
|
254
|
+
// Apply option defaults
|
|
255
|
+
const { gender = 'masculine' } = options
|
|
237
256
|
|
|
238
257
|
let result = ''
|
|
239
258
|
|
|
@@ -241,7 +260,7 @@ function toWords (value, options) {
|
|
|
241
260
|
result = NEGATIVE + ' '
|
|
242
261
|
}
|
|
243
262
|
|
|
244
|
-
result += integerToWords(integerPart,
|
|
263
|
+
result += integerToWords(integerPart, gender)
|
|
245
264
|
|
|
246
265
|
if (decimalPart) {
|
|
247
266
|
result += ' ' + DECIMAL_SEP + ' ' + decimalPartToWords(decimalPart)
|
|
@@ -250,8 +269,183 @@ function toWords (value, options) {
|
|
|
250
269
|
return result
|
|
251
270
|
}
|
|
252
271
|
|
|
272
|
+
// ============================================================================
|
|
273
|
+
// Ordinal Functions
|
|
274
|
+
// ============================================================================
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Builds ordinal for tens and ones (0-99).
|
|
278
|
+
*
|
|
279
|
+
* @param {number} n - Number 0-99
|
|
280
|
+
* @returns {string} Ordinal word
|
|
281
|
+
*/
|
|
282
|
+
function buildOrdinalTensOnes (n) {
|
|
283
|
+
if (n === 0) return ''
|
|
284
|
+
if (n < 10) return ORDINAL_ONES[n]
|
|
285
|
+
if (n < 20) return ORDINAL_TEENS[n - 10]
|
|
286
|
+
|
|
287
|
+
const ones = n % 10
|
|
288
|
+
const tens = Math.trunc(n / 10)
|
|
289
|
+
|
|
290
|
+
if (ones === 0) {
|
|
291
|
+
return ORDINAL_TENS[tens]
|
|
292
|
+
}
|
|
293
|
+
// Compound: cardinal tens + ordinal ones (only last is ordinal)
|
|
294
|
+
return TWENTIES[tens] + ' și ' + ORDINAL_ONES[ones]
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Converts a non-negative integer to Romanian ordinal words.
|
|
299
|
+
*
|
|
300
|
+
* @param {bigint} n - Non-negative integer to convert
|
|
301
|
+
* @returns {string} Romanian ordinal words
|
|
302
|
+
*/
|
|
303
|
+
function integerToOrdinal (n) {
|
|
304
|
+
if (n === 0n) return ''
|
|
305
|
+
if (n === 1n) return ORDINAL_ONES[1]
|
|
306
|
+
|
|
307
|
+
// Numbers < 100
|
|
308
|
+
if (n < 100n) {
|
|
309
|
+
return buildOrdinalTensOnes(Number(n))
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Numbers < 1000
|
|
313
|
+
if (n < 1000n) {
|
|
314
|
+
const hundreds = Number(n / 100n)
|
|
315
|
+
const remainder = Number(n % 100n)
|
|
316
|
+
|
|
317
|
+
if (remainder === 0) {
|
|
318
|
+
return ORDINAL_HUNDRED
|
|
319
|
+
}
|
|
320
|
+
return HUNDREDS[hundreds] + ' ' + buildOrdinalTensOnes(remainder)
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Numbers < 1,000,000
|
|
324
|
+
if (n < 1_000_000n) {
|
|
325
|
+
const thousands = Number(n / 1000n)
|
|
326
|
+
const remainder = Number(n % 1000n)
|
|
327
|
+
|
|
328
|
+
if (remainder === 0) {
|
|
329
|
+
if (thousands === 1) {
|
|
330
|
+
return ORDINAL_THOUSAND
|
|
331
|
+
}
|
|
332
|
+
return buildScalePhrase(thousands, 1) + ' ' + ORDINAL_THOUSAND
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// Cardinal thousands + ordinal remainder
|
|
336
|
+
let result
|
|
337
|
+
if (thousands === 1) {
|
|
338
|
+
result = 'o mie'
|
|
339
|
+
} else {
|
|
340
|
+
result = buildScalePhrase(thousands, 1)
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
if (remainder < 100) {
|
|
344
|
+
return result + ' ' + buildOrdinalTensOnes(remainder)
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
const remHundreds = Math.trunc(remainder / 100)
|
|
348
|
+
const remTensOnes = remainder % 100
|
|
349
|
+
|
|
350
|
+
if (remTensOnes === 0) {
|
|
351
|
+
return result + ' ' + ORDINAL_HUNDRED
|
|
352
|
+
}
|
|
353
|
+
return result + ' ' + HUNDREDS[remHundreds] + ' ' + buildOrdinalTensOnes(remTensOnes)
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// Numbers >= 1,000,000
|
|
357
|
+
const millions = Number(n / 1_000_000n)
|
|
358
|
+
const remainder = n % 1_000_000n
|
|
359
|
+
|
|
360
|
+
if (remainder === 0n) {
|
|
361
|
+
if (millions === 1) {
|
|
362
|
+
return ORDINAL_MILLION
|
|
363
|
+
}
|
|
364
|
+
return buildScalePhrase(millions, 2) + ' ' + ORDINAL_MILLION
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// Cardinal millions + ordinal remainder
|
|
368
|
+
let result
|
|
369
|
+
if (millions === 1) {
|
|
370
|
+
result = 'un milion'
|
|
371
|
+
} else {
|
|
372
|
+
result = buildScalePhrase(millions, 2)
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
return result + ' ' + integerToOrdinal(remainder)
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Converts a numeric value to Romanian ordinal words.
|
|
380
|
+
*
|
|
381
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
382
|
+
* @returns {string} The ordinal in Romanian words
|
|
383
|
+
* @throws {TypeError} If value is not a valid numeric type
|
|
384
|
+
* @throws {Error} If value is not a positive integer
|
|
385
|
+
*
|
|
386
|
+
* @example
|
|
387
|
+
* toOrdinal(1) // 'primul'
|
|
388
|
+
* toOrdinal(21) // 'douăzeci și primul'
|
|
389
|
+
*/
|
|
390
|
+
function toOrdinal (value) {
|
|
391
|
+
const n = parseOrdinalValue(value)
|
|
392
|
+
return integerToOrdinal(n)
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// ============================================================================
|
|
396
|
+
// Currency Functions
|
|
397
|
+
// ============================================================================
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Converts a numeric value to Romanian Leu currency words.
|
|
401
|
+
*
|
|
402
|
+
* @param {number | string | bigint} value - The numeric value to convert
|
|
403
|
+
* @returns {string} The currency in Romanian words
|
|
404
|
+
* @throws {TypeError} If value is not a valid numeric type
|
|
405
|
+
* @throws {Error} If value is not a valid number format
|
|
406
|
+
*
|
|
407
|
+
* @example
|
|
408
|
+
* toCurrency(1) // 'un leu'
|
|
409
|
+
* toCurrency(2.50) // 'doi lei cincizeci de bani'
|
|
410
|
+
*/
|
|
411
|
+
function toCurrency (value) {
|
|
412
|
+
const { isNegative, dollars, cents } = parseCurrencyValue(value)
|
|
413
|
+
|
|
414
|
+
const parts = []
|
|
415
|
+
|
|
416
|
+
if (isNegative) {
|
|
417
|
+
parts.push(NEGATIVE)
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// Lei (masculine)
|
|
421
|
+
if (dollars > 0n || cents === 0n) {
|
|
422
|
+
if (dollars === 1n) {
|
|
423
|
+
parts.push('un ' + LEU_SINGULAR)
|
|
424
|
+
} else {
|
|
425
|
+
const leuWord = integerToWords(dollars, 'masculine')
|
|
426
|
+
parts.push(leuWord + ' ' + LEU_PLURAL)
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// Bani (masculine)
|
|
431
|
+
if (cents > 0n) {
|
|
432
|
+
const centNum = Number(cents)
|
|
433
|
+
if (centNum === 1) {
|
|
434
|
+
parts.push('un ' + BAN_SINGULAR)
|
|
435
|
+
} else if (centNum >= 20) {
|
|
436
|
+
const banWord = spellUnder100(centNum, false)
|
|
437
|
+
parts.push(banWord + ' de ' + BAN_PLURAL)
|
|
438
|
+
} else {
|
|
439
|
+
const banWord = spellUnder100(centNum, false)
|
|
440
|
+
parts.push(banWord + ' ' + BAN_PLURAL)
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
return parts.join(' ')
|
|
445
|
+
}
|
|
446
|
+
|
|
253
447
|
// ============================================================================
|
|
254
448
|
// Public API
|
|
255
449
|
// ============================================================================
|
|
256
450
|
|
|
257
|
-
export {
|
|
451
|
+
export { toCardinal, toOrdinal, toCurrency }
|
package/src/ru-RU.d.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts a numeric value to Russian 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
|
+
* @returns {string} The number in Russian words
|
|
8
|
+
*/
|
|
9
|
+
export function toCardinal(value: number | string | bigint, options?: {
|
|
10
|
+
gender?: "masculine" | "feminine" | undefined;
|
|
11
|
+
}): string;
|
|
12
|
+
/**
|
|
13
|
+
* Converts a numeric value to Russian ordinal words (masculine nominative).
|
|
14
|
+
*
|
|
15
|
+
* @param {number | string | bigint} value - The numeric value to convert (must be a positive integer)
|
|
16
|
+
* @returns {string} The number as ordinal words (e.g., "первый", "сорок второй")
|
|
17
|
+
* @throws {TypeError} If value is not a valid numeric type
|
|
18
|
+
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* toOrdinal(1) // 'первый'
|
|
22
|
+
* toOrdinal(2) // 'второй'
|
|
23
|
+
* toOrdinal(3) // 'третий'
|
|
24
|
+
* toOrdinal(21) // 'двадцать первый'
|
|
25
|
+
* toOrdinal(42) // 'сорок второй'
|
|
26
|
+
* toOrdinal(100) // 'сотый'
|
|
27
|
+
* toOrdinal(101) // 'сто первый'
|
|
28
|
+
* toOrdinal(1000) // 'тысячный'
|
|
29
|
+
*/
|
|
30
|
+
export function toOrdinal(value: number | string | bigint): string;
|
|
31
|
+
/**
|
|
32
|
+
* Converts a numeric value to Russian currency words (Russian Ruble).
|
|
33
|
+
*
|
|
34
|
+
* @param {number | string | bigint} value - The currency amount to convert
|
|
35
|
+
* @param {Object} [options] - Optional configuration
|
|
36
|
+
* @param {boolean} [options.and=true] - Use "и" between rubles and kopecks
|
|
37
|
+
* @returns {string} The amount in Russian currency words
|
|
38
|
+
* @throws {TypeError} If value is not a valid numeric type
|
|
39
|
+
* @throws {Error} If value is not a valid number format
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* toCurrency(42.50) // 'сорок два рубля и пятьдесят копеек'
|
|
43
|
+
* toCurrency(1) // 'один рубль'
|
|
44
|
+
* toCurrency(0.99) // 'девяносто девять копеек'
|
|
45
|
+
* toCurrency(0.01) // 'одна копейка'
|
|
46
|
+
* toCurrency(42.50, { and: false }) // 'сорок два рубля пятьдесят копеек'
|
|
47
|
+
*/
|
|
48
|
+
export function toCurrency(value: number | string | bigint, options?: {
|
|
49
|
+
and?: boolean | undefined;
|
|
50
|
+
}): string;
|