n2words 5.0.0 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +128 -42
- package/README.md +6 -4
- package/dist/am-ET.js +2 -2
- package/dist/am-ET.umd.js +2 -2
- package/dist/am-Latn-ET.js +2 -2
- package/dist/am-Latn-ET.umd.js +2 -2
- package/dist/ar-SA.js +2 -2
- package/dist/ar-SA.umd.js +2 -2
- package/dist/az-AZ.js +2 -2
- package/dist/az-AZ.umd.js +2 -2
- package/dist/bn-BD.js +2 -2
- package/dist/bn-BD.umd.js +2 -2
- package/dist/cs-CZ.js +2 -2
- package/dist/cs-CZ.umd.js +2 -2
- package/dist/da-DK.js +2 -2
- package/dist/da-DK.umd.js +2 -2
- package/dist/de-DE.js +2 -2
- package/dist/de-DE.umd.js +2 -2
- package/dist/el-GR.js +2 -2
- package/dist/el-GR.umd.js +2 -2
- package/dist/en-AU.js +2 -2
- package/dist/en-AU.umd.js +2 -2
- package/dist/en-BD.js +2 -2
- package/dist/en-BD.umd.js +2 -2
- package/dist/en-CA.js +2 -2
- package/dist/en-CA.umd.js +2 -2
- package/dist/en-GB.js +2 -2
- package/dist/en-GB.umd.js +2 -2
- package/dist/en-GH.js +2 -2
- package/dist/en-GH.umd.js +2 -2
- package/dist/en-IE.js +2 -2
- package/dist/en-IE.umd.js +2 -2
- package/dist/en-IN.js +2 -2
- package/dist/en-IN.umd.js +2 -2
- package/dist/en-KE.js +2 -2
- package/dist/en-KE.umd.js +2 -2
- package/dist/en-MY.js +2 -2
- package/dist/en-MY.umd.js +2 -2
- package/dist/en-NG.js +2 -2
- package/dist/en-NG.umd.js +2 -2
- package/dist/en-NZ.js +2 -2
- package/dist/en-NZ.umd.js +2 -2
- package/dist/en-PH.js +2 -2
- package/dist/en-PH.umd.js +2 -2
- package/dist/en-PK.js +2 -2
- package/dist/en-PK.umd.js +2 -2
- package/dist/en-SG.js +2 -2
- package/dist/en-SG.umd.js +2 -2
- package/dist/en-US.js +2 -2
- package/dist/en-US.umd.js +2 -2
- package/dist/en-ZA.js +2 -2
- package/dist/en-ZA.umd.js +2 -2
- package/dist/es-ES.js +2 -2
- package/dist/es-ES.umd.js +2 -2
- package/dist/es-MX.js +2 -2
- package/dist/es-MX.umd.js +2 -2
- package/dist/es-US.js +2 -2
- package/dist/es-US.umd.js +2 -2
- package/dist/fa-IR.js +2 -2
- package/dist/fa-IR.umd.js +2 -2
- package/dist/fi-FI.js +2 -2
- package/dist/fi-FI.umd.js +2 -2
- package/dist/fil-PH.js +2 -2
- package/dist/fil-PH.umd.js +2 -2
- package/dist/fr-BE.js +2 -2
- package/dist/fr-BE.umd.js +2 -2
- package/dist/fr-FR.js +2 -2
- package/dist/fr-FR.umd.js +2 -2
- package/dist/gu-IN.js +2 -2
- package/dist/gu-IN.umd.js +2 -2
- package/dist/ha-NG.js +2 -2
- package/dist/ha-NG.umd.js +2 -2
- package/dist/hbo-IL.js +2 -2
- package/dist/hbo-IL.umd.js +2 -2
- package/dist/he-IL.js +2 -2
- package/dist/he-IL.umd.js +2 -2
- package/dist/hi-IN.js +2 -2
- package/dist/hi-IN.umd.js +2 -2
- package/dist/hr-HR.js +2 -2
- package/dist/hr-HR.umd.js +2 -2
- package/dist/hu-HU.js +2 -2
- package/dist/hu-HU.umd.js +2 -2
- package/dist/id-ID.js +2 -2
- package/dist/id-ID.umd.js +2 -2
- package/dist/it-IT.js +2 -2
- package/dist/it-IT.umd.js +2 -2
- package/dist/ja-JP.js +2 -2
- package/dist/ja-JP.umd.js +2 -2
- package/dist/ka-GE.js +2 -2
- package/dist/ka-GE.umd.js +2 -2
- package/dist/kn-IN.js +2 -2
- package/dist/kn-IN.umd.js +2 -2
- package/dist/ko-KR.js +2 -2
- package/dist/ko-KR.umd.js +2 -2
- package/dist/lt-LT.js +2 -2
- package/dist/lt-LT.umd.js +2 -2
- package/dist/lv-LV.js +2 -2
- package/dist/lv-LV.umd.js +2 -2
- package/dist/mr-IN.js +2 -2
- package/dist/mr-IN.umd.js +2 -2
- package/dist/ms-MY.js +2 -2
- package/dist/ms-MY.umd.js +2 -2
- package/dist/nb-NO.js +2 -2
- package/dist/nb-NO.umd.js +2 -2
- package/dist/nl-NL.js +2 -2
- package/dist/nl-NL.umd.js +2 -2
- package/dist/pa-IN.js +2 -2
- package/dist/pa-IN.umd.js +2 -2
- package/dist/pl-PL.js +2 -2
- package/dist/pl-PL.umd.js +2 -2
- package/dist/pt-BR.js +2 -2
- package/dist/pt-BR.umd.js +2 -2
- package/dist/pt-PT.js +2 -2
- package/dist/pt-PT.umd.js +2 -2
- package/dist/ro-RO.js +2 -2
- package/dist/ro-RO.umd.js +2 -2
- package/dist/ru-RU.js +2 -2
- package/dist/ru-RU.umd.js +2 -2
- package/dist/sr-Cyrl-RS.js +2 -2
- package/dist/sr-Cyrl-RS.umd.js +2 -2
- package/dist/sr-Latn-RS.js +2 -2
- package/dist/sr-Latn-RS.umd.js +2 -2
- package/dist/sv-SE.js +2 -2
- package/dist/sv-SE.umd.js +2 -2
- package/dist/sw-KE.js +2 -2
- package/dist/sw-KE.umd.js +2 -2
- package/dist/ta-IN.js +2 -2
- package/dist/ta-IN.umd.js +2 -2
- package/dist/te-IN.js +2 -2
- package/dist/te-IN.umd.js +2 -2
- package/dist/th-TH.js +2 -2
- package/dist/th-TH.umd.js +2 -2
- package/dist/tr-TR.js +2 -2
- package/dist/tr-TR.umd.js +2 -2
- package/dist/uk-UA.js +2 -2
- package/dist/uk-UA.umd.js +2 -2
- package/dist/ur-PK.js +2 -2
- package/dist/ur-PK.umd.js +2 -2
- package/dist/vi-VN.js +2 -2
- package/dist/vi-VN.umd.js +2 -2
- package/dist/yo-NG.js +2 -2
- package/dist/yo-NG.umd.js +2 -2
- package/dist/zh-Hans-CN.js +2 -2
- package/dist/zh-Hans-CN.umd.js +2 -2
- package/dist/zh-Hant-TW.js +2 -2
- package/dist/zh-Hant-TW.umd.js +2 -2
- package/package.json +31 -22
- package/src/am-ET.d.ts +3 -5
- package/src/am-ET.js +41 -16
- package/src/am-Latn-ET.d.ts +3 -5
- package/src/am-Latn-ET.js +45 -16
- package/src/ar-SA.d.ts +44 -18
- package/src/ar-SA.js +93 -40
- package/src/az-AZ.d.ts +3 -5
- package/src/az-AZ.js +58 -20
- package/src/bn-BD.d.ts +3 -5
- package/src/bn-BD.js +32 -16
- package/src/cs-CZ.d.ts +3 -6
- package/src/cs-CZ.js +66 -42
- package/src/da-DK.d.ts +3 -6
- package/src/da-DK.js +53 -48
- package/src/de-DE.d.ts +17 -11
- package/src/de-DE.js +88 -57
- package/src/el-GR.d.ts +3 -6
- package/src/el-GR.js +45 -32
- package/src/en-AU.d.ts +17 -11
- package/src/en-AU.js +56 -41
- package/src/en-BD.d.ts +17 -11
- package/src/en-BD.js +60 -41
- package/src/en-CA.d.ts +36 -18
- package/src/en-CA.js +67 -46
- package/src/en-GB.d.ts +17 -11
- package/src/en-GB.js +56 -41
- package/src/en-GH.d.ts +32 -3
- package/src/en-GH.js +104 -26
- package/src/en-IE.d.ts +17 -11
- package/src/en-IE.js +56 -41
- package/src/en-IN.d.ts +17 -11
- package/src/en-IN.js +60 -41
- package/src/en-KE.d.ts +28 -3
- package/src/en-KE.js +93 -26
- package/src/en-MY.d.ts +26 -3
- package/src/en-MY.js +91 -26
- package/src/en-NG.d.ts +17 -11
- package/src/en-NG.js +56 -41
- package/src/en-NZ.d.ts +32 -3
- package/src/en-NZ.js +85 -31
- package/src/en-PH.d.ts +32 -3
- package/src/en-PH.js +97 -26
- package/src/en-PK.d.ts +17 -11
- package/src/en-PK.js +60 -41
- package/src/en-SG.d.ts +28 -3
- package/src/en-SG.js +93 -26
- package/src/en-US.d.ts +36 -18
- package/src/en-US.js +70 -47
- package/src/en-ZA.d.ts +17 -11
- package/src/en-ZA.js +56 -41
- package/src/es-ES.d.ts +53 -21
- package/src/es-ES.js +104 -56
- package/src/es-MX.d.ts +53 -21
- package/src/es-MX.js +104 -56
- package/src/es-US.d.ts +53 -21
- package/src/es-US.js +92 -51
- package/src/fa-IR.d.ts +3 -5
- package/src/fa-IR.js +28 -13
- package/src/fi-FI.d.ts +3 -6
- package/src/fi-FI.js +47 -29
- package/src/fil-PH.d.ts +3 -5
- package/src/fil-PH.js +61 -28
- package/src/fr-BE.d.ts +31 -15
- package/src/fr-BE.js +128 -57
- package/src/fr-FR.d.ts +31 -16
- package/src/fr-FR.js +97 -60
- package/src/gu-IN.d.ts +3 -5
- package/src/gu-IN.js +31 -16
- package/src/ha-NG.d.ts +3 -5
- package/src/ha-NG.js +55 -27
- package/src/hbo-IL.d.ts +26 -12
- package/src/hbo-IL.js +92 -51
- package/src/he-IL.d.ts +17 -10
- package/src/he-IL.js +92 -50
- package/src/hi-IN.d.ts +3 -5
- package/src/hi-IN.js +30 -17
- package/src/hr-HR.d.ts +21 -10
- package/src/hr-HR.js +89 -33
- package/src/hu-HU.d.ts +3 -5
- package/src/hu-HU.js +57 -23
- package/src/id-ID.d.ts +3 -5
- package/src/id-ID.js +56 -23
- package/src/it-IT.d.ts +17 -11
- package/src/it-IT.js +74 -43
- package/src/ja-JP.d.ts +3 -6
- package/src/ja-JP.js +39 -26
- package/src/ka-GE.d.ts +3 -6
- package/src/ka-GE.js +38 -26
- package/src/kn-IN.d.ts +3 -5
- package/src/kn-IN.js +31 -16
- package/src/ko-KR.d.ts +3 -6
- package/src/ko-KR.js +34 -26
- package/src/lt-LT.d.ts +21 -11
- package/src/lt-LT.js +64 -42
- package/src/lv-LV.d.ts +21 -11
- package/src/lv-LV.js +79 -51
- package/src/mr-IN.d.ts +3 -5
- package/src/mr-IN.js +31 -16
- package/src/ms-MY.d.ts +3 -5
- package/src/ms-MY.js +58 -24
- package/src/nb-NO.d.ts +3 -6
- package/src/nb-NO.js +54 -34
- package/src/nl-NL.d.ts +41 -20
- package/src/nl-NL.js +111 -69
- package/src/pa-IN.d.ts +3 -5
- package/src/pa-IN.js +32 -16
- package/src/pl-PL.d.ts +21 -11
- package/src/pl-PL.js +69 -45
- package/src/pt-BR.d.ts +22 -11
- package/src/pt-BR.js +93 -53
- package/src/pt-PT.d.ts +17 -11
- package/src/pt-PT.js +80 -48
- package/src/ro-RO.d.ts +21 -11
- package/src/ro-RO.js +77 -39
- package/src/ru-RU.d.ts +35 -15
- package/src/ru-RU.js +100 -38
- package/src/sr-Cyrl-RS.d.ts +35 -15
- package/src/sr-Cyrl-RS.js +100 -38
- package/src/sr-Latn-RS.d.ts +35 -15
- package/src/sr-Latn-RS.js +100 -38
- package/src/sv-SE.d.ts +3 -6
- package/src/sv-SE.js +53 -34
- package/src/sw-KE.d.ts +3 -5
- package/src/sw-KE.js +50 -20
- package/src/ta-IN.d.ts +3 -5
- package/src/ta-IN.js +29 -17
- package/src/te-IN.d.ts +3 -5
- package/src/te-IN.js +31 -16
- package/src/th-TH.d.ts +3 -5
- package/src/th-TH.js +42 -19
- package/src/tr-TR.d.ts +17 -11
- package/src/tr-TR.js +63 -37
- package/src/uk-UA.d.ts +21 -10
- package/src/uk-UA.js +89 -33
- package/src/ur-PK.d.ts +3 -5
- package/src/ur-PK.js +32 -16
- package/src/utils/check-max.d.ts +26 -0
- package/src/utils/check-max.js +33 -0
- package/src/utils/expand-scientific.d.ts +0 -4
- package/src/utils/expand-scientific.js +7 -9
- package/src/utils/is-plain-object.d.ts +3 -4
- package/src/utils/is-plain-object.js +3 -4
- package/src/utils/parse-cardinal.d.ts +1 -2
- package/src/utils/parse-cardinal.js +12 -9
- package/src/utils/parse-currency.d.ts +1 -2
- package/src/utils/parse-currency.js +9 -11
- package/src/utils/parse-ordinal.d.ts +0 -1
- package/src/utils/parse-ordinal.js +9 -10
- package/src/utils/resolve-options.d.ts +17 -0
- package/src/utils/resolve-options.js +56 -0
- package/src/utils/scale.d.ts +49 -0
- package/src/utils/scale.js +65 -0
- package/src/vi-VN.d.ts +3 -6
- package/src/vi-VN.js +41 -28
- package/src/yo-NG.d.ts +3 -5
- package/src/yo-NG.js +49 -33
- package/src/zh-Hans-CN.d.ts +45 -20
- package/src/zh-Hans-CN.js +84 -31
- package/src/zh-Hant-TW.d.ts +45 -20
- package/src/zh-Hant-TW.js +85 -34
- package/src/utils/validate-options.d.ts +0 -8
- package/src/utils/validate-options.js +0 -16
package/dist/zh-Hans-CN.umd.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! n2words/zh-Hans-CN v5.
|
|
2
|
-
var n,e;n=this,e=function(n){"use strict";function e(n){let[e,
|
|
1
|
+
/*! n2words/zh-Hans-CN v5.1.0 | MIT License | github.com/forzagreen/n2words */
|
|
2
|
+
var n,e;n=this,e=function(n){"use strict";function e(n){let[e,t]=n.toLowerCase().split("e");const r=parseInt(t,10);let i="";"-"===e[0]&&(i="-",e=e.slice(1));const o=e.indexOf("."),s=-1===o?e:e.slice(0,o)+e.slice(o+1),u=(-1===o?e.length:o)+r;return u>=s.length?i+s+"0".repeat(u-s.length):u<=0?i+"0."+"0".repeat(-u)+s:i+s.slice(0,u)+"."+s.slice(u)}function t(n){const t=n.toString();return r(t)?e(t):t}function r(n){return n.includes("e")||n.includes("E")}function i(n){const e="-"===n[0];e&&(n=n.slice(1));const t=n.indexOf(".");if(-1===t)return{isNegative:e,integerPart:BigInt(n)};const r=n.slice(0,t)||"0",i=n.slice(t+1);return{isNegative:e,integerPart:BigInt(r),decimalPart:i}}function o(n){let t=n.trim();if(0===t.length||Number.isNaN(Number(t)))throw new RangeError(`Invalid currency format: "${n}"`);r(t)&&(t=e(t));const i="-"===t[0];i&&(t=t.slice(1));const o=t.indexOf(".");if(-1===o)return{isNegative:i,dollars:BigInt(t),cents:0n};const s=t.slice(0,o)||"0",u=(t.slice(o+1)+"00").slice(0,2);return{isNegative:i,dollars:BigInt(s),cents:BigInt(u)}}function s(n,e,t){if(null===e)return;if(n<e)return;const r=e.toString().length-1,i=e===10n**BigInt(r)?`10^${r} - 1`:""+(e-1n);throw new RangeError(`Number too large to convert: the largest supported value is ${i}`)}function u(n){return 10n**BigInt(n)}function f(n,e,t){const r={...e};if(void 0===n)return r;if(!function(n){if(null===n||"object"!=typeof n)return!1;const e=Object.getPrototypeOf(n);return null===e||e===Object.prototype}(n))throw new TypeError("Invalid options: expected plain object or undefined, got "+typeof n);const i=Object.keys(e);for(const[t,o]of Object.entries(n)){if(!Object.hasOwn(e,t))throw new TypeError(`Unknown option "${t}" — expected one of: ${i.join(", ")}`);if(void 0!==o){if(typeof o!=typeof r[t])throw new TypeError(`Option "${t}" must be a ${typeof r[t]}, got ${typeof o}`);r[t]=o}}return r}const c=["零","一","二","三","四","五","六","七","八","九"],a=["零","壹","贰","叁","肆","伍","陆","柒","捌","玖"],l=u(16),g=u(16),d=u(16),b="零";function m(n,e,t,r,i){if(0n===n)return"";let o="",s=!1;const u=n/1000n,f=n%1000n;u>0n&&(o=e[Number(u)]+i,s=f>0n&&f<100n);const c=f/100n,a=f%100n;c>0n?(s&&(o+=b),o+=e[Number(c)]+r,s=a>0n&&a<10n):u>0n&&a>0n&&(s=!0);const l=a/10n,g=a%10n;return l>0n?(s&&(o+=b),o+=e[Number(l)]+t,s=!1):(c>0n||u>0n)&&g>0n&&(s=!0),g>0n&&(s&&(o+=b),o+=e[Number(g)]),o}function p(n,e,t,r,i){if(0n===n)return"";if(n>=10000n){const o=n/10000n,s=n%10000n;let u=m(o,e,t,r,i)+"万";return s>0n&&((o%10n==0n||s<1000n)&&(u+=b),u+=m(s,e,t,r,i)),u}return m(n,e,t,r,i)}function w(n,e=!0){if(0n===n)return b;const t=e?a:c,r=e?"拾":"十",i=e?"佰":"百",o=e?"仟":"千";if(n>=100000000n){const e=n%100000000n;let s=p(n/100000000n,t,r,i,o)+"亿";return e>0n&&(e<10000000n&&(s+=b),s+=p(e,t,r,i,o)),s}return p(n,t,r,i,o)}const h={formal:!0},N={formal:!0},y={formal:!0},v={zhHansCN:function(n,t){const i=function(n){const t=typeof n;if("bigint"==typeof n){if(n<=0n)throw new RangeError("Ordinals must be positive integers");return n}if("number"==typeof n){if(!Number.isFinite(n))throw new RangeError("Ordinals must be finite numbers");if(!Number.isInteger(n))throw new RangeError("Ordinals must be whole numbers");if(n<=0)throw new RangeError("Ordinals must be positive integers");return BigInt(n)}if("string"==typeof n)return function(n){const t=n.trim();if(0===t.length)throw new RangeError("Ordinals cannot be empty strings");if("-"===t[0])throw new RangeError("Ordinals cannot be negative");if(t.includes("."))throw new RangeError("Ordinals must be whole numbers");if(r(t)){const n=e(t);if(n.includes("."))throw new RangeError("Ordinals must be whole numbers");const r=BigInt(n);if(r<=0n)throw new RangeError("Ordinals must be positive integers");return r}try{const n=BigInt(t);if(n<=0n)throw new RangeError("Ordinals must be positive integers");return n}catch(e){if(e instanceof RangeError)throw e;throw new RangeError(`Invalid ordinal format: "${n}"`,{cause:e})}}(n);throw new TypeError(`Invalid value type: expected number, string, or bigint, received ${t}`)}(n);s(i,g);const{formal:o}=f(t,N);return function(n,e){return"第"+w(n,e)}(i,o)}};n.currency={zhHansCN:function(n,e){const{isNegative:r,dollars:i,cents:u}=function(n){const e=typeof n;if("bigint"==typeof n)return n<0n?{isNegative:!0,dollars:-n,cents:0n}:{isNegative:!1,dollars:n,cents:0n};if("number"==typeof n){if(!Number.isFinite(n))throw new RangeError("Currency must be a finite number");return Number.isSafeInteger(n)?n<0?{isNegative:!0,dollars:BigInt(-n),cents:0n}:{isNegative:!1,dollars:BigInt(n),cents:0n}:o(t(n))}if("string"==typeof n)return o(n);throw new TypeError(`Invalid value type: expected number, string, or bigint, received ${e}`)}(n);s(i,d);const{formal:l}=f(e,y),g=l?a:c,m=l?"圆":"元",p=u/10n,h=u%10n;let N="";return r&&(N="负"),i>0n&&(N+=w(i,l)+m),p>0n?N+=g[Number(p)]+"角":i>0n&&h>0n&&(N+=b),h>0n?N+=g[Number(h)]+"分":(i>0n||p>0n)&&(N+="整"),0n===i&&0n===p&&0n===h&&(N+=b+m+"整"),N}},n.ordinal=v,n.zhHansCN=function(n,o){const{isNegative:u,integerPart:g,decimalPart:d}=function(n){const o=typeof n;if("bigint"==typeof n)return n<0n?{isNegative:!0,integerPart:-n}:{isNegative:!1,integerPart:n};if("number"==typeof n){if(!Number.isFinite(n))throw new RangeError("Number must be finite (NaN and Infinity are not supported)");return Number.isSafeInteger(n)?n<0?{isNegative:!0,integerPart:BigInt(-n)}:{isNegative:!1,integerPart:BigInt(n)}:i(t(n))}if("string"==typeof n)return i(function(n){const t=n.trim();if(0===t.length||Number.isNaN(Number(t)))throw new RangeError(`Invalid number format: "${n}"`);return r(t)?e(t):t}(n));throw new TypeError(`Invalid value type: expected number, string, or bigint, received ${o}`)}(n);s(g,l);const{formal:b}=f(o,h);let m=u?"负":"";return m+=w(g,b),d&&(m+="点"+function(n,e){let t="";for(let r=0;r<n.length;r++)t+=e[Number(n[r])];return t}(d,b?a:c)),m}},"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((n="undefined"!=typeof globalThis?globalThis:n||self).n2words=n.n2words||{});
|
package/dist/zh-Hant-TW.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! n2words/zh-Hant-TW v5.
|
|
2
|
-
function n(n){let[e,
|
|
1
|
+
/*! n2words/zh-Hant-TW v5.1.0 | MIT License | github.com/forzagreen/n2words */
|
|
2
|
+
function n(n){let[e,t]=n.toLowerCase().split("e");const r=parseInt(t,10);let i="";"-"===e[0]&&(i="-",e=e.slice(1));const o=e.indexOf("."),s=-1===o?e:e.slice(0,o)+e.slice(o+1),u=(-1===o?e.length:o)+r;return u>=s.length?i+s+"0".repeat(u-s.length):u<=0?i+"0."+"0".repeat(-u)+s:i+s.slice(0,u)+"."+s.slice(u)}function e(e){const r=e.toString();return t(r)?n(r):r}function t(n){return n.includes("e")||n.includes("E")}function r(n){const e="-"===n[0];e&&(n=n.slice(1));const t=n.indexOf(".");if(-1===t)return{isNegative:e,integerPart:BigInt(n)};const r=n.slice(0,t)||"0",i=n.slice(t+1);return{isNegative:e,integerPart:BigInt(r),decimalPart:i}}function i(e){let r=e.trim();if(0===r.length||Number.isNaN(Number(r)))throw new RangeError(`Invalid currency format: "${e}"`);t(r)&&(r=n(r));const i="-"===r[0];i&&(r=r.slice(1));const o=r.indexOf(".");if(-1===o)return{isNegative:i,dollars:BigInt(r),cents:0n};const s=r.slice(0,o)||"0",u=(r.slice(o+1)+"00").slice(0,2);return{isNegative:i,dollars:BigInt(s),cents:BigInt(u)}}function o(n,e,t){if(null===e)return;if(n<e)return;const r=e.toString().length-1,i=e===10n**BigInt(r)?`10^${r} - 1`:""+(e-1n);throw new RangeError(`Number too large to convert: the largest supported value is ${i}`)}function s(n){return 10n**BigInt(n)}function u(n,e,t){const r={...e};if(void 0===n)return r;if(!function(n){if(null===n||"object"!=typeof n)return!1;const e=Object.getPrototypeOf(n);return null===e||e===Object.prototype}(n))throw new TypeError("Invalid options: expected plain object or undefined, got "+typeof n);const i=Object.keys(e);for(const[t,o]of Object.entries(n)){if(!Object.hasOwn(e,t))throw new TypeError(`Unknown option "${t}" — expected one of: ${i.join(", ")}`);if(void 0!==o){if(typeof o!=typeof r[t])throw new TypeError(`Option "${t}" must be a ${typeof r[t]}, got ${typeof o}`);r[t]=o}}return r}const c=["零","一","二","三","四","五","六","七","八","九"],f=["零","壹","貳","參","肆","伍","陸","柒","捌","玖"],a=s(16),l=s(16),g=s(16),p="零";function b(n,e=!0){if(0n===n)return p;const t=e?f:c,r=e?"拾":"十",i=e?"佰":"百",o=e?"仟":"千";function s(n){if(0n===n)return"";const e=[];let s=!1;const u=n/1000n,c=n%1000n;u>0n&&(e.push(t[Number(u)]+o),s=c>0n&&c<100n);const f=c/100n,a=c%100n;f>0n?(s&&e.push(p),e.push(t[Number(f)]+i),s=a>0n&&a<10n):u>0n&&a>0n&&(s=!0);const l=a/10n,g=a%10n;return l>0n?(s&&(e.push(p),s=!1),e.push(t[Number(l)]+r)):(f>0n||u>0n)&&g>0n&&(s=!0),g>0n&&(s&&e.push(p),e.push(t[Number(g)])),e.join("")}function u(n){if(0n===n)return"";const e=[];if(n>=10000n){const t=n/10000n,r=n%10000n;e.push(s(t)+"萬"),r>0n&&((t%10n==0n||r<1000n)&&e.push(p),e.push(s(r)))}else e.push(s(n));return e.join("")}const a=[];if(n>=100000000n){const e=n%100000000n,t=u(n/100000000n);a.push(t+"億"),e>0n&&(e<10000000n&&a.push(p),a.push(u(e)))}else a.push(u(n));return a.join("")}const m={formal:!0};function h(i,s){const{isNegative:l,integerPart:g,decimalPart:p}=function(i){const o=typeof i;if("bigint"==typeof i)return i<0n?{isNegative:!0,integerPart:-i}:{isNegative:!1,integerPart:i};if("number"==typeof i){if(!Number.isFinite(i))throw new RangeError("Number must be finite (NaN and Infinity are not supported)");return Number.isSafeInteger(i)?i<0?{isNegative:!0,integerPart:BigInt(-i)}:{isNegative:!1,integerPart:BigInt(i)}:r(e(i))}if("string"==typeof i)return r(function(e){const r=e.trim();if(0===r.length||Number.isNaN(Number(r)))throw new RangeError(`Invalid number format: "${e}"`);return t(r)?n(r):r}(i));throw new TypeError(`Invalid value type: expected number, string, or bigint, received ${o}`)}(i);o(g,a);const{formal:h}=u(s,m);let w="";return l&&(w="負"),w+=b(g,h),p&&(w+="點"+function(n,e=!0){const t=e?f:c,r=[];for(const e of n)r.push(t[Number(e)]);return r}(p,h).join("")),w}const w={formal:!0};function d(e,r){const i=function(e){const r=typeof e;if("bigint"==typeof e){if(e<=0n)throw new RangeError("Ordinals must be positive integers");return e}if("number"==typeof e){if(!Number.isFinite(e))throw new RangeError("Ordinals must be finite numbers");if(!Number.isInteger(e))throw new RangeError("Ordinals must be whole numbers");if(e<=0)throw new RangeError("Ordinals must be positive integers");return BigInt(e)}if("string"==typeof e)return function(e){const r=e.trim();if(0===r.length)throw new RangeError("Ordinals cannot be empty strings");if("-"===r[0])throw new RangeError("Ordinals cannot be negative");if(r.includes("."))throw new RangeError("Ordinals must be whole numbers");if(t(r)){const e=n(r);if(e.includes("."))throw new RangeError("Ordinals must be whole numbers");const t=BigInt(e);if(t<=0n)throw new RangeError("Ordinals must be positive integers");return t}try{const n=BigInt(r);if(n<=0n)throw new RangeError("Ordinals must be positive integers");return n}catch(n){if(n instanceof RangeError)throw n;throw new RangeError(`Invalid ordinal format: "${e}"`,{cause:n})}}(e);throw new TypeError(`Invalid value type: expected number, string, or bigint, received ${r}`)}(e);o(i,l);const{formal:s}=u(r,w);return function(n,e=!0){return"第"+b(n,e)}(i,s)}const N={formal:!0};function v(n,t){const{isNegative:r,dollars:s,cents:a}=function(n){const t=typeof n;if("bigint"==typeof n)return n<0n?{isNegative:!0,dollars:-n,cents:0n}:{isNegative:!1,dollars:n,cents:0n};if("number"==typeof n){if(!Number.isFinite(n))throw new RangeError("Currency must be a finite number");return Number.isSafeInteger(n)?n<0?{isNegative:!0,dollars:BigInt(-n),cents:0n}:{isNegative:!1,dollars:BigInt(n),cents:0n}:i(e(n))}if("string"==typeof n)return i(n);throw new TypeError(`Invalid value type: expected number, string, or bigint, received ${t}`)}(n);o(s,g);const{formal:l}=u(t,N),m=l?"圓":"元",h=a/10n,w=a%10n;let d="";return r&&(d="負"),(s>0n||0n===a)&&(d+=b(s,l),d+=m),h>0n&&(d+=(l?f:c)[Number(h)]+"角"),w>0n?(s>0n&&0n===h&&(d+=p),d+=(l?f:c)[Number(w)]+"分"):d+="整",d}export{m as cardinalDefaults,a as cardinalMax,N as currencyDefaults,g as currencyMax,w as ordinalDefaults,l as ordinalMax,h as toCardinal,v as toCurrency,d as toOrdinal};
|
package/dist/zh-Hant-TW.umd.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! n2words/zh-Hant-TW v5.
|
|
2
|
-
var n,e;n=this,e=function(n){"use strict";function e(n){let[e,t]=n.toLowerCase().split("e");const r=parseInt(t,10);let i="";"-"===e[0]&&(i="-",e=e.slice(1));const o=e.indexOf("."),s=-1===o?e:e.slice(0,o)+e.slice(o+1),u=(-1===o?e.length:o)+r;return u>=s.length?i+s+"0".repeat(u-s.length):u<=0?i+"0."+"0".repeat(-u)+s:i+s.slice(0,u)+"."+s.slice(u)}function t(n){const t=n.toString();return r(t)?e(t):t}function r(n){return n.includes("e")||n.includes("E")}function i(n){const e="-"===n[0];e&&(n=n.slice(1));const t=n.indexOf(".");if(-1===t)return{isNegative:e,integerPart:BigInt(n)};const r=n.slice(0,t)||"0",i=n.slice(t+1);return{isNegative:e,integerPart:BigInt(r),decimalPart:i}}function o(n){let t=n.trim();if(0===t.length||Number.isNaN(Number(t)))throw new RangeError(`Invalid currency format: "${n}"`);r(t)&&(t=e(t));const i="-"===t[0];i&&(t=t.slice(1));const o=t.indexOf(".");if(-1===o)return{isNegative:i,dollars:BigInt(t),cents:0n};const s=t.slice(0,o)||"0",u=(t.slice(o+1)+"00").slice(0,2);return{isNegative:i,dollars:BigInt(s),cents:BigInt(u)}}function s(n){if(
|
|
1
|
+
/*! n2words/zh-Hant-TW v5.1.0 | MIT License | github.com/forzagreen/n2words */
|
|
2
|
+
var n,e;n=this,e=function(n){"use strict";function e(n){let[e,t]=n.toLowerCase().split("e");const r=parseInt(t,10);let i="";"-"===e[0]&&(i="-",e=e.slice(1));const o=e.indexOf("."),s=-1===o?e:e.slice(0,o)+e.slice(o+1),u=(-1===o?e.length:o)+r;return u>=s.length?i+s+"0".repeat(u-s.length):u<=0?i+"0."+"0".repeat(-u)+s:i+s.slice(0,u)+"."+s.slice(u)}function t(n){const t=n.toString();return r(t)?e(t):t}function r(n){return n.includes("e")||n.includes("E")}function i(n){const e="-"===n[0];e&&(n=n.slice(1));const t=n.indexOf(".");if(-1===t)return{isNegative:e,integerPart:BigInt(n)};const r=n.slice(0,t)||"0",i=n.slice(t+1);return{isNegative:e,integerPart:BigInt(r),decimalPart:i}}function o(n){let t=n.trim();if(0===t.length||Number.isNaN(Number(t)))throw new RangeError(`Invalid currency format: "${n}"`);r(t)&&(t=e(t));const i="-"===t[0];i&&(t=t.slice(1));const o=t.indexOf(".");if(-1===o)return{isNegative:i,dollars:BigInt(t),cents:0n};const s=t.slice(0,o)||"0",u=(t.slice(o+1)+"00").slice(0,2);return{isNegative:i,dollars:BigInt(s),cents:BigInt(u)}}function s(n,e,t){if(null===e)return;if(n<e)return;const r=e.toString().length-1,i=e===10n**BigInt(r)?`10^${r} - 1`:""+(e-1n);throw new RangeError(`Number too large to convert: the largest supported value is ${i}`)}function u(n){return 10n**BigInt(n)}function c(n,e,t){const r={...e};if(void 0===n)return r;if(!function(n){if(null===n||"object"!=typeof n)return!1;const e=Object.getPrototypeOf(n);return null===e||e===Object.prototype}(n))throw new TypeError("Invalid options: expected plain object or undefined, got "+typeof n);const i=Object.keys(e);for(const[t,o]of Object.entries(n)){if(!Object.hasOwn(e,t))throw new TypeError(`Unknown option "${t}" — expected one of: ${i.join(", ")}`);if(void 0!==o){if(typeof o!=typeof r[t])throw new TypeError(`Option "${t}" must be a ${typeof r[t]}, got ${typeof o}`);r[t]=o}}return r}const f=["零","一","二","三","四","五","六","七","八","九"],a=["零","壹","貳","參","肆","伍","陸","柒","捌","玖"],l=u(16),g=u(16),p=u(16),d="零";function b(n,e=!0){if(0n===n)return d;const t=e?a:f,r=e?"拾":"十",i=e?"佰":"百",o=e?"仟":"千";function s(n){if(0n===n)return"";const e=[];let s=!1;const u=n/1000n,c=n%1000n;u>0n&&(e.push(t[Number(u)]+o),s=c>0n&&c<100n);const f=c/100n,a=c%100n;f>0n?(s&&e.push(d),e.push(t[Number(f)]+i),s=a>0n&&a<10n):u>0n&&a>0n&&(s=!0);const l=a/10n,g=a%10n;return l>0n?(s&&(e.push(d),s=!1),e.push(t[Number(l)]+r)):(f>0n||u>0n)&&g>0n&&(s=!0),g>0n&&(s&&e.push(d),e.push(t[Number(g)])),e.join("")}function u(n){if(0n===n)return"";const e=[];if(n>=10000n){const t=n/10000n,r=n%10000n;e.push(s(t)+"萬"),r>0n&&((t%10n==0n||r<1000n)&&e.push(d),e.push(s(r)))}else e.push(s(n));return e.join("")}const c=[];if(n>=100000000n){const e=n%100000000n,t=u(n/100000000n);c.push(t+"億"),e>0n&&(e<10000000n&&c.push(d),c.push(u(e)))}else c.push(u(n));return c.join("")}const m={formal:!0},h={formal:!0},w={formal:!0},y={zhHantTW:function(n,t){const i=function(n){const t=typeof n;if("bigint"==typeof n){if(n<=0n)throw new RangeError("Ordinals must be positive integers");return n}if("number"==typeof n){if(!Number.isFinite(n))throw new RangeError("Ordinals must be finite numbers");if(!Number.isInteger(n))throw new RangeError("Ordinals must be whole numbers");if(n<=0)throw new RangeError("Ordinals must be positive integers");return BigInt(n)}if("string"==typeof n)return function(n){const t=n.trim();if(0===t.length)throw new RangeError("Ordinals cannot be empty strings");if("-"===t[0])throw new RangeError("Ordinals cannot be negative");if(t.includes("."))throw new RangeError("Ordinals must be whole numbers");if(r(t)){const n=e(t);if(n.includes("."))throw new RangeError("Ordinals must be whole numbers");const r=BigInt(n);if(r<=0n)throw new RangeError("Ordinals must be positive integers");return r}try{const n=BigInt(t);if(n<=0n)throw new RangeError("Ordinals must be positive integers");return n}catch(e){if(e instanceof RangeError)throw e;throw new RangeError(`Invalid ordinal format: "${n}"`,{cause:e})}}(n);throw new TypeError(`Invalid value type: expected number, string, or bigint, received ${t}`)}(n);s(i,g);const{formal:o}=c(t,h);return function(n,e=!0){return"第"+b(n,e)}(i,o)}};n.currency={zhHantTW:function(n,e){const{isNegative:r,dollars:i,cents:u}=function(n){const e=typeof n;if("bigint"==typeof n)return n<0n?{isNegative:!0,dollars:-n,cents:0n}:{isNegative:!1,dollars:n,cents:0n};if("number"==typeof n){if(!Number.isFinite(n))throw new RangeError("Currency must be a finite number");return Number.isSafeInteger(n)?n<0?{isNegative:!0,dollars:BigInt(-n),cents:0n}:{isNegative:!1,dollars:BigInt(n),cents:0n}:o(t(n))}if("string"==typeof n)return o(n);throw new TypeError(`Invalid value type: expected number, string, or bigint, received ${e}`)}(n);s(i,p);const{formal:l}=c(e,w),g=l?"圓":"元",m=u/10n,h=u%10n;let y="";return r&&(y="負"),(i>0n||0n===u)&&(y+=b(i,l),y+=g),m>0n&&(y+=(l?a:f)[Number(m)]+"角"),h>0n?(i>0n&&0n===m&&(y+=d),y+=(l?a:f)[Number(h)]+"分"):y+="整",y}},n.ordinal=y,n.zhHantTW=function(n,o){const{isNegative:u,integerPart:g,decimalPart:p}=function(n){const o=typeof n;if("bigint"==typeof n)return n<0n?{isNegative:!0,integerPart:-n}:{isNegative:!1,integerPart:n};if("number"==typeof n){if(!Number.isFinite(n))throw new RangeError("Number must be finite (NaN and Infinity are not supported)");return Number.isSafeInteger(n)?n<0?{isNegative:!0,integerPart:BigInt(-n)}:{isNegative:!1,integerPart:BigInt(n)}:i(t(n))}if("string"==typeof n)return i(function(n){const t=n.trim();if(0===t.length||Number.isNaN(Number(t)))throw new RangeError(`Invalid number format: "${n}"`);return r(t)?e(t):t}(n));throw new TypeError(`Invalid value type: expected number, string, or bigint, received ${o}`)}(n);s(g,l);const{formal:d}=c(o,m);let h="";return u&&(h="負"),h+=b(g,d),p&&(h+="點"+function(n,e=!0){const t=e?a:f,r=[];for(const e of n)r.push(t[Number(e)]);return r}(p,d).join("")),h}},"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((n="undefined"!=typeof globalThis?globalThis:n||self).n2words=n.n2words||{});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n2words",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.1.0",
|
|
4
4
|
"description": "Convert numbers to words in 70+ languages with zero dependencies. Supports BigInt, decimals, and browser/Node.js environments.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"number-to-words",
|
|
@@ -75,15 +75,18 @@
|
|
|
75
75
|
"clean:dist": "rimraf dist",
|
|
76
76
|
"clean:types": "rimraf \"src/**/*.d.ts\" --glob",
|
|
77
77
|
"coverage": "c8 node --run test:unit",
|
|
78
|
+
"coverage:check": "c8 check-coverage",
|
|
78
79
|
"docs:languages": "node scripts/generate-languages-md.js",
|
|
79
80
|
"lang:add": "node scripts/add-language.js",
|
|
80
81
|
"lint": "node --run lint:js && node --run lint:md",
|
|
81
|
-
"lint:fix": "
|
|
82
|
-
"lint:js": "
|
|
82
|
+
"lint:fix": "eslint --fix && markdownlint-cli2 --fix",
|
|
83
|
+
"lint:js": "eslint",
|
|
83
84
|
"lint:md": "markdownlint-cli2",
|
|
85
|
+
"prepack": "node --run build",
|
|
84
86
|
"prepare:husky": "husky",
|
|
85
87
|
"test": "node --run test:unit && node --run build:types",
|
|
86
|
-
"test:unit": "ava \"test/*.test.js\" \"test/utils/*.test.js\""
|
|
88
|
+
"test:unit": "ava \"test/*.test.js\" \"test/utils/*.test.js\"",
|
|
89
|
+
"typecheck": "tsc --project tsconfig.build.json --noEmit"
|
|
87
90
|
},
|
|
88
91
|
"ava": {
|
|
89
92
|
"extensions": [
|
|
@@ -97,11 +100,6 @@
|
|
|
97
100
|
"concurrency": 8,
|
|
98
101
|
"workerThreads": false
|
|
99
102
|
},
|
|
100
|
-
"standard": {
|
|
101
|
-
"ignore": [
|
|
102
|
-
"!.vscode/"
|
|
103
|
-
]
|
|
104
|
-
},
|
|
105
103
|
"c8": {
|
|
106
104
|
"all": true,
|
|
107
105
|
"include": [
|
|
@@ -114,37 +112,48 @@
|
|
|
114
112
|
"lcov",
|
|
115
113
|
"text",
|
|
116
114
|
"json-summary"
|
|
117
|
-
]
|
|
115
|
+
],
|
|
116
|
+
"lines": 90,
|
|
117
|
+
"statements": 90,
|
|
118
|
+
"functions": 90,
|
|
119
|
+
"branches": 85
|
|
118
120
|
},
|
|
119
121
|
"lint-staged": {
|
|
120
122
|
"*.{js,cjs,mjs}": [
|
|
121
|
-
"
|
|
123
|
+
"eslint --fix"
|
|
122
124
|
],
|
|
123
125
|
"*.md": [
|
|
124
126
|
"markdownlint-cli2 --fix"
|
|
125
127
|
]
|
|
126
128
|
},
|
|
127
129
|
"devDependencies": {
|
|
128
|
-
"@
|
|
129
|
-
"@
|
|
130
|
-
"@
|
|
131
|
-
"@
|
|
132
|
-
"@commitlint/format": "^21.0.1",
|
|
133
|
-
"@rollup/plugin-babel": "^7.0.0",
|
|
134
|
-
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
130
|
+
"@commitlint/cli": "^21.0.2",
|
|
131
|
+
"@commitlint/config-conventional": "^21.0.2",
|
|
132
|
+
"@eslint-community/eslint-plugin-eslint-comments": "^4.7.2",
|
|
133
|
+
"@eslint/js": "^10.0.1",
|
|
135
134
|
"@rollup/plugin-terser": "^1.0.0",
|
|
136
135
|
"@rollup/plugin-virtual": "^3.0.2",
|
|
136
|
+
"@stylistic/eslint-plugin": "^5.10.0",
|
|
137
|
+
"@types/node": "^24.13.2",
|
|
137
138
|
"ava": "^8.0.1",
|
|
138
|
-
"benchmark": "^2.1.4",
|
|
139
139
|
"browserslist": "^4.28.2",
|
|
140
140
|
"c8": "^11.0.0",
|
|
141
141
|
"chalk": "^5.6.2",
|
|
142
|
+
"eslint": "^10.5.0",
|
|
143
|
+
"eslint-plugin-ava": "^17.0.1",
|
|
144
|
+
"eslint-plugin-compat": "^7.0.2",
|
|
145
|
+
"eslint-plugin-es-x": "^9.6.0",
|
|
146
|
+
"eslint-plugin-import-x": "^4.16.2",
|
|
147
|
+
"eslint-plugin-jsdoc": "^63.0.4",
|
|
148
|
+
"eslint-plugin-n": "^18.1.0",
|
|
149
|
+
"fast-check": "^4.8.0",
|
|
150
|
+
"globals": "^17.6.0",
|
|
142
151
|
"husky": "^9.1.7",
|
|
143
|
-
"lint-staged": "^17.0.
|
|
152
|
+
"lint-staged": "^17.0.7",
|
|
144
153
|
"markdownlint-cli2": "^0.22.1",
|
|
145
154
|
"rimraf": "^6.1.3",
|
|
146
|
-
"rollup": "^4.
|
|
147
|
-
"
|
|
155
|
+
"rollup": "^4.62.0",
|
|
156
|
+
"tinybench": "^6.0.2",
|
|
148
157
|
"typescript": "^6.0.3"
|
|
149
158
|
},
|
|
150
159
|
"engines": {
|
package/src/am-ET.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
export const cardinalMax: bigint;
|
|
2
|
+
export const ordinalMax: bigint;
|
|
3
|
+
export const currencyMax: bigint;
|
|
1
4
|
/**
|
|
2
5
|
* Converts a numeric value to Amharic words.
|
|
3
|
-
*
|
|
4
6
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
5
7
|
* @returns {string} The number in Amharic words
|
|
6
8
|
*/
|
|
@@ -10,12 +12,10 @@ export function toCardinal(value: number | string | bigint): string;
|
|
|
10
12
|
*
|
|
11
13
|
* Amharic ordinals: add -ኛ suffix to cardinal.
|
|
12
14
|
* Special case: 1 → አንደኛ
|
|
13
|
-
*
|
|
14
15
|
* @param {number | string | bigint} value - The numeric value to convert (positive integer)
|
|
15
16
|
* @returns {string} The number as ordinal words
|
|
16
17
|
* @throws {TypeError} If value is not a valid numeric type
|
|
17
18
|
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
18
|
-
*
|
|
19
19
|
* @example
|
|
20
20
|
* toOrdinal(1) // 'አንደኛ'
|
|
21
21
|
* toOrdinal(2) // 'ሁለትኛ'
|
|
@@ -25,12 +25,10 @@ export function toCardinal(value: number | string | bigint): string;
|
|
|
25
25
|
export function toOrdinal(value: number | string | bigint): string;
|
|
26
26
|
/**
|
|
27
27
|
* Converts a numeric value to Amharic currency words (Ethiopian Birr).
|
|
28
|
-
*
|
|
29
28
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
30
29
|
* @returns {string} The amount in Amharic currency words
|
|
31
30
|
* @throws {TypeError} If value is not a valid numeric type
|
|
32
31
|
* @throws {Error} If value is not a valid number format
|
|
33
|
-
*
|
|
34
32
|
* @example
|
|
35
33
|
* toCurrency(42.50) // 'አርባ ሁለት ብር ሃምሳ ሳንቲም'
|
|
36
34
|
* toCurrency(1) // 'አንድ ብር'
|
package/src/am-ET.js
CHANGED
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
import { parseCardinalValue } from './utils/parse-cardinal.js'
|
|
15
15
|
import { parseCurrencyValue } from './utils/parse-currency.js'
|
|
16
16
|
import { parseOrdinalValue } from './utils/parse-ordinal.js'
|
|
17
|
+
import { checkMax } from './utils/check-max.js'
|
|
18
|
+
import { western } from './utils/scale.js'
|
|
17
19
|
|
|
18
20
|
// ============================================================================
|
|
19
21
|
// Vocabulary
|
|
@@ -53,11 +55,23 @@ const SANTIM = 'ሳንቲም'
|
|
|
53
55
|
// Short scale
|
|
54
56
|
const SCALE_WORDS = ['', THOUSAND, 'ሚሊዮን', 'ቢሊዮን']
|
|
55
57
|
|
|
58
|
+
// Supported magnitude ceiling (checked at the public entry points). SCALE_WORDS
|
|
59
|
+
// reaches index SCALE_WORDS.length-1 (ቢሊዮን, 10^9), so values must stay below
|
|
60
|
+
// 10^(SCALE_WORDS.length * 3) = 10^12. Ordinal and currency build on the
|
|
61
|
+
// cardinal, so they share it. Decimals are read digit-by-digit (no ceiling).
|
|
62
|
+
export const cardinalMax = western(SCALE_WORDS.length - 1)
|
|
63
|
+
export const ordinalMax = western(SCALE_WORDS.length - 1)
|
|
64
|
+
export const currencyMax = western(SCALE_WORDS.length - 1)
|
|
65
|
+
|
|
56
66
|
// ============================================================================
|
|
57
67
|
// Precomputed Lookup Table
|
|
58
68
|
// ============================================================================
|
|
59
69
|
|
|
60
|
-
|
|
70
|
+
/**
|
|
71
|
+
* @param {number} n The three-digit segment value (0-999) to convert.
|
|
72
|
+
* @returns {string} The segment in Amharic words.
|
|
73
|
+
*/
|
|
74
|
+
function buildSegment(n) {
|
|
61
75
|
if (n === 0) return ''
|
|
62
76
|
|
|
63
77
|
const ones = n % 10
|
|
@@ -73,7 +87,8 @@ function buildSegment (n) {
|
|
|
73
87
|
|
|
74
88
|
if (tensDigit === 1) {
|
|
75
89
|
parts.push(TEENS[ones])
|
|
76
|
-
}
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
77
92
|
if (tensDigit > 1) {
|
|
78
93
|
parts.push(TENS[tensDigit])
|
|
79
94
|
}
|
|
@@ -89,7 +104,11 @@ function buildSegment (n) {
|
|
|
89
104
|
// Conversion Functions
|
|
90
105
|
// ============================================================================
|
|
91
106
|
|
|
92
|
-
|
|
107
|
+
/**
|
|
108
|
+
* @param {bigint} n The non-negative integer to convert.
|
|
109
|
+
* @returns {string} The integer in Amharic words.
|
|
110
|
+
*/
|
|
111
|
+
function integerToWords(n) {
|
|
93
112
|
if (n === 0n) return ZERO
|
|
94
113
|
|
|
95
114
|
if (n < 1000n) {
|
|
@@ -99,7 +118,11 @@ function integerToWords (n) {
|
|
|
99
118
|
return buildLargeNumberWords(n)
|
|
100
119
|
}
|
|
101
120
|
|
|
102
|
-
|
|
121
|
+
/**
|
|
122
|
+
* @param {bigint} n The integer (>= 1000) to convert using scale words.
|
|
123
|
+
* @returns {string} The integer in Amharic words.
|
|
124
|
+
*/
|
|
125
|
+
function buildLargeNumberWords(n) {
|
|
103
126
|
const numStr = n.toString()
|
|
104
127
|
const len = numStr.length
|
|
105
128
|
|
|
@@ -128,7 +151,8 @@ function buildLargeNumberWords (n) {
|
|
|
128
151
|
|
|
129
152
|
if (scaleIndex === 0) {
|
|
130
153
|
parts.push(buildSegment(segment))
|
|
131
|
-
}
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
132
156
|
parts.push(buildSegment(segment) + ' ' + scaleWord)
|
|
133
157
|
}
|
|
134
158
|
}
|
|
@@ -139,7 +163,11 @@ function buildLargeNumberWords (n) {
|
|
|
139
163
|
return parts.join(' ')
|
|
140
164
|
}
|
|
141
165
|
|
|
142
|
-
|
|
166
|
+
/**
|
|
167
|
+
* @param {string} decimalPart The digit string after the decimal point.
|
|
168
|
+
* @returns {string} The decimal digits read individually in Amharic words.
|
|
169
|
+
*/
|
|
170
|
+
function decimalPartToWords(decimalPart) {
|
|
143
171
|
// Per-digit decimal reading
|
|
144
172
|
const digits = []
|
|
145
173
|
for (const char of decimalPart) {
|
|
@@ -151,12 +179,12 @@ function decimalPartToWords (decimalPart) {
|
|
|
151
179
|
|
|
152
180
|
/**
|
|
153
181
|
* Converts a numeric value to Amharic words.
|
|
154
|
-
*
|
|
155
182
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
156
183
|
* @returns {string} The number in Amharic words
|
|
157
184
|
*/
|
|
158
|
-
function toCardinal
|
|
185
|
+
function toCardinal(value) {
|
|
159
186
|
const { isNegative, integerPart, decimalPart } = parseCardinalValue(value)
|
|
187
|
+
checkMax(integerPart, cardinalMax)
|
|
160
188
|
|
|
161
189
|
let result = ''
|
|
162
190
|
|
|
@@ -182,11 +210,10 @@ function toCardinal (value) {
|
|
|
182
210
|
*
|
|
183
211
|
* In Amharic, ordinals are formed by adding -ኛ suffix to the cardinal.
|
|
184
212
|
* Special case: 1 = አንደኛ (not አንድኛ)
|
|
185
|
-
*
|
|
186
213
|
* @param {bigint} n - Positive integer to convert
|
|
187
214
|
* @returns {string} Amharic ordinal words
|
|
188
215
|
*/
|
|
189
|
-
function integerToOrdinal
|
|
216
|
+
function integerToOrdinal(n) {
|
|
190
217
|
// Special case: 1 → አንደኛ
|
|
191
218
|
if (n === 1n) {
|
|
192
219
|
return FIRST
|
|
@@ -202,20 +229,19 @@ function integerToOrdinal (n) {
|
|
|
202
229
|
*
|
|
203
230
|
* Amharic ordinals: add -ኛ suffix to cardinal.
|
|
204
231
|
* Special case: 1 → አንደኛ
|
|
205
|
-
*
|
|
206
232
|
* @param {number | string | bigint} value - The numeric value to convert (positive integer)
|
|
207
233
|
* @returns {string} The number as ordinal words
|
|
208
234
|
* @throws {TypeError} If value is not a valid numeric type
|
|
209
235
|
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
210
|
-
*
|
|
211
236
|
* @example
|
|
212
237
|
* toOrdinal(1) // 'አንደኛ'
|
|
213
238
|
* toOrdinal(2) // 'ሁለትኛ'
|
|
214
239
|
* toOrdinal(10) // 'አስርኛ'
|
|
215
240
|
* toOrdinal(100) // 'አንድ መቶኛ'
|
|
216
241
|
*/
|
|
217
|
-
function toOrdinal
|
|
242
|
+
function toOrdinal(value) {
|
|
218
243
|
const integerPart = parseOrdinalValue(value)
|
|
244
|
+
checkMax(integerPart, ordinalMax)
|
|
219
245
|
return integerToOrdinal(integerPart)
|
|
220
246
|
}
|
|
221
247
|
|
|
@@ -225,20 +251,19 @@ function toOrdinal (value) {
|
|
|
225
251
|
|
|
226
252
|
/**
|
|
227
253
|
* Converts a numeric value to Amharic currency words (Ethiopian Birr).
|
|
228
|
-
*
|
|
229
254
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
230
255
|
* @returns {string} The amount in Amharic currency words
|
|
231
256
|
* @throws {TypeError} If value is not a valid numeric type
|
|
232
257
|
* @throws {Error} If value is not a valid number format
|
|
233
|
-
*
|
|
234
258
|
* @example
|
|
235
259
|
* toCurrency(42.50) // 'አርባ ሁለት ብር ሃምሳ ሳንቲም'
|
|
236
260
|
* toCurrency(1) // 'አንድ ብር'
|
|
237
261
|
* toCurrency(0.99) // 'ዘጠና ዘጠኝ ሳንቲም'
|
|
238
262
|
* toCurrency(0.01) // 'አንድ ሳንቲም'
|
|
239
263
|
*/
|
|
240
|
-
function toCurrency
|
|
264
|
+
function toCurrency(value) {
|
|
241
265
|
const { isNegative, dollars: birr, cents: santim } = parseCurrencyValue(value)
|
|
266
|
+
checkMax(birr, currencyMax)
|
|
242
267
|
|
|
243
268
|
// Build result
|
|
244
269
|
let result = ''
|
package/src/am-Latn-ET.d.ts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
+
export const cardinalMax: bigint;
|
|
2
|
+
export const ordinalMax: bigint;
|
|
3
|
+
export const currencyMax: bigint;
|
|
1
4
|
/**
|
|
2
5
|
* Converts a numeric value to Amharic (Latin script) words.
|
|
3
|
-
*
|
|
4
6
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
5
7
|
* @returns {string} The number in Amharic Latin words
|
|
6
8
|
*/
|
|
7
9
|
export function toCardinal(value: number | string | bigint): string;
|
|
8
10
|
/**
|
|
9
11
|
* Converts a numeric value to Amharic (Latin script) ordinal words.
|
|
10
|
-
*
|
|
11
12
|
* @param {number | string | bigint} value - The numeric value to convert (positive integer)
|
|
12
13
|
* @returns {string} The number as ordinal words
|
|
13
14
|
* @throws {TypeError} If value is not a valid numeric type
|
|
14
15
|
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
15
|
-
*
|
|
16
16
|
* @example
|
|
17
17
|
* toOrdinal(1) // 'andenya'
|
|
18
18
|
* toOrdinal(2) // 'huletnya'
|
|
@@ -21,12 +21,10 @@ export function toCardinal(value: number | string | bigint): string;
|
|
|
21
21
|
export function toOrdinal(value: number | string | bigint): string;
|
|
22
22
|
/**
|
|
23
23
|
* Converts a numeric value to Amharic (Latin script) currency words (Ethiopian Birr).
|
|
24
|
-
*
|
|
25
24
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
26
25
|
* @returns {string} The amount in Amharic (Latin) currency words
|
|
27
26
|
* @throws {TypeError} If value is not a valid numeric type
|
|
28
27
|
* @throws {Error} If value is not a valid number format
|
|
29
|
-
*
|
|
30
28
|
* @example
|
|
31
29
|
* toCurrency(42.50) // 'arba hulet birr hamsa santim'
|
|
32
30
|
* toCurrency(1) // 'and birr'
|
package/src/am-Latn-ET.js
CHANGED
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
import { parseCardinalValue } from './utils/parse-cardinal.js'
|
|
15
15
|
import { parseCurrencyValue } from './utils/parse-currency.js'
|
|
16
16
|
import { parseOrdinalValue } from './utils/parse-ordinal.js'
|
|
17
|
+
import { checkMax } from './utils/check-max.js'
|
|
18
|
+
import { western } from './utils/scale.js'
|
|
17
19
|
|
|
18
20
|
// ============================================================================
|
|
19
21
|
// Vocabulary
|
|
@@ -53,11 +55,24 @@ const SANTIM = 'santim'
|
|
|
53
55
|
// Short scale
|
|
54
56
|
const SCALE_WORDS = ['', THOUSAND, 'miliyon', 'billiyon']
|
|
55
57
|
|
|
58
|
+
// Supported magnitude ceiling (checked at the public entry points). SCALE_WORDS
|
|
59
|
+
// reaches index SCALE_WORDS.length-1 (billiyon, 10^9), so values must stay below
|
|
60
|
+
// 10^(SCALE_WORDS.length * 3) = 10^12. Ordinal and currency build on the
|
|
61
|
+
// cardinal, so they share it. Decimals are read digit-by-digit (no ceiling).
|
|
62
|
+
export const cardinalMax = western(SCALE_WORDS.length - 1)
|
|
63
|
+
export const ordinalMax = western(SCALE_WORDS.length - 1)
|
|
64
|
+
export const currencyMax = western(SCALE_WORDS.length - 1)
|
|
65
|
+
|
|
56
66
|
// ============================================================================
|
|
57
67
|
// Precomputed Lookup Table
|
|
58
68
|
// ============================================================================
|
|
59
69
|
|
|
60
|
-
|
|
70
|
+
/**
|
|
71
|
+
* Builds the words for a 3-digit segment (0-999).
|
|
72
|
+
* @param {number} n - Segment value (0-999)
|
|
73
|
+
* @returns {string} The segment in Amharic (Latin) words
|
|
74
|
+
*/
|
|
75
|
+
function buildSegment(n) {
|
|
61
76
|
if (n === 0) return ''
|
|
62
77
|
|
|
63
78
|
const ones = n % 10
|
|
@@ -73,7 +88,8 @@ function buildSegment (n) {
|
|
|
73
88
|
|
|
74
89
|
if (tensDigit === 1) {
|
|
75
90
|
parts.push(TEENS[ones])
|
|
76
|
-
}
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
77
93
|
if (tensDigit > 1) {
|
|
78
94
|
parts.push(TENS[tensDigit])
|
|
79
95
|
}
|
|
@@ -89,7 +105,12 @@ function buildSegment (n) {
|
|
|
89
105
|
// Conversion Functions
|
|
90
106
|
// ============================================================================
|
|
91
107
|
|
|
92
|
-
|
|
108
|
+
/**
|
|
109
|
+
* Converts a non-negative integer to Amharic (Latin script) words.
|
|
110
|
+
* @param {bigint} n - Non-negative integer to convert
|
|
111
|
+
* @returns {string} The integer in Amharic (Latin) words
|
|
112
|
+
*/
|
|
113
|
+
function integerToWords(n) {
|
|
93
114
|
if (n === 0n) return ZERO
|
|
94
115
|
|
|
95
116
|
if (n < 1000n) {
|
|
@@ -99,7 +120,12 @@ function integerToWords (n) {
|
|
|
99
120
|
return buildLargeNumberWords(n)
|
|
100
121
|
}
|
|
101
122
|
|
|
102
|
-
|
|
123
|
+
/**
|
|
124
|
+
* Builds the words for a number of 1000 or greater using short-scale grouping.
|
|
125
|
+
* @param {bigint} n - Integer of 1000 or greater
|
|
126
|
+
* @returns {string} The number in Amharic (Latin) words
|
|
127
|
+
*/
|
|
128
|
+
function buildLargeNumberWords(n) {
|
|
103
129
|
const numStr = n.toString()
|
|
104
130
|
const len = numStr.length
|
|
105
131
|
|
|
@@ -128,7 +154,8 @@ function buildLargeNumberWords (n) {
|
|
|
128
154
|
|
|
129
155
|
if (scaleIndex === 0) {
|
|
130
156
|
parts.push(buildSegment(segment))
|
|
131
|
-
}
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
132
159
|
parts.push(buildSegment(segment) + ' ' + scaleWord)
|
|
133
160
|
}
|
|
134
161
|
}
|
|
@@ -139,7 +166,12 @@ function buildLargeNumberWords (n) {
|
|
|
139
166
|
return parts.join(' ')
|
|
140
167
|
}
|
|
141
168
|
|
|
142
|
-
|
|
169
|
+
/**
|
|
170
|
+
* Reads the decimal part digit by digit.
|
|
171
|
+
* @param {string} decimalPart - The fractional digits as a string
|
|
172
|
+
* @returns {string} The decimal digits in Amharic (Latin) words
|
|
173
|
+
*/
|
|
174
|
+
function decimalPartToWords(decimalPart) {
|
|
143
175
|
// Per-digit decimal reading
|
|
144
176
|
const digits = []
|
|
145
177
|
for (const char of decimalPart) {
|
|
@@ -151,12 +183,12 @@ function decimalPartToWords (decimalPart) {
|
|
|
151
183
|
|
|
152
184
|
/**
|
|
153
185
|
* Converts a numeric value to Amharic (Latin script) words.
|
|
154
|
-
*
|
|
155
186
|
* @param {number | string | bigint} value - The numeric value to convert
|
|
156
187
|
* @returns {string} The number in Amharic Latin words
|
|
157
188
|
*/
|
|
158
|
-
function toCardinal
|
|
189
|
+
function toCardinal(value) {
|
|
159
190
|
const { isNegative, integerPart, decimalPart } = parseCardinalValue(value)
|
|
191
|
+
checkMax(integerPart, cardinalMax)
|
|
160
192
|
|
|
161
193
|
let result = ''
|
|
162
194
|
|
|
@@ -182,11 +214,10 @@ function toCardinal (value) {
|
|
|
182
214
|
*
|
|
183
215
|
* In Amharic, ordinals are formed by adding -nya suffix to the cardinal.
|
|
184
216
|
* Special case: 1 = andenya
|
|
185
|
-
*
|
|
186
217
|
* @param {bigint} n - Positive integer to convert
|
|
187
218
|
* @returns {string} Amharic (Latin) ordinal words
|
|
188
219
|
*/
|
|
189
|
-
function integerToOrdinal
|
|
220
|
+
function integerToOrdinal(n) {
|
|
190
221
|
// Special case: 1 → andenya
|
|
191
222
|
if (n === 1n) {
|
|
192
223
|
return FIRST
|
|
@@ -199,19 +230,18 @@ function integerToOrdinal (n) {
|
|
|
199
230
|
|
|
200
231
|
/**
|
|
201
232
|
* Converts a numeric value to Amharic (Latin script) ordinal words.
|
|
202
|
-
*
|
|
203
233
|
* @param {number | string | bigint} value - The numeric value to convert (positive integer)
|
|
204
234
|
* @returns {string} The number as ordinal words
|
|
205
235
|
* @throws {TypeError} If value is not a valid numeric type
|
|
206
236
|
* @throws {RangeError} If value is negative, zero, or has a decimal part
|
|
207
|
-
*
|
|
208
237
|
* @example
|
|
209
238
|
* toOrdinal(1) // 'andenya'
|
|
210
239
|
* toOrdinal(2) // 'huletnya'
|
|
211
240
|
* toOrdinal(10) // 'asirnya'
|
|
212
241
|
*/
|
|
213
|
-
function toOrdinal
|
|
242
|
+
function toOrdinal(value) {
|
|
214
243
|
const integerPart = parseOrdinalValue(value)
|
|
244
|
+
checkMax(integerPart, ordinalMax)
|
|
215
245
|
return integerToOrdinal(integerPart)
|
|
216
246
|
}
|
|
217
247
|
|
|
@@ -221,19 +251,18 @@ function toOrdinal (value) {
|
|
|
221
251
|
|
|
222
252
|
/**
|
|
223
253
|
* Converts a numeric value to Amharic (Latin script) currency words (Ethiopian Birr).
|
|
224
|
-
*
|
|
225
254
|
* @param {number | string | bigint} value - The currency amount to convert
|
|
226
255
|
* @returns {string} The amount in Amharic (Latin) currency words
|
|
227
256
|
* @throws {TypeError} If value is not a valid numeric type
|
|
228
257
|
* @throws {Error} If value is not a valid number format
|
|
229
|
-
*
|
|
230
258
|
* @example
|
|
231
259
|
* toCurrency(42.50) // 'arba hulet birr hamsa santim'
|
|
232
260
|
* toCurrency(1) // 'and birr'
|
|
233
261
|
* toCurrency(0.01) // 'and santim'
|
|
234
262
|
*/
|
|
235
|
-
function toCurrency
|
|
263
|
+
function toCurrency(value) {
|
|
236
264
|
const { isNegative, dollars: birr, cents: santim } = parseCurrencyValue(value)
|
|
265
|
+
checkMax(birr, currencyMax)
|
|
237
266
|
|
|
238
267
|
// Build result
|
|
239
268
|
let result = ''
|