diff --git a/.changeset/funny-dingos-worry.md b/.changeset/funny-dingos-worry.md new file mode 100644 index 00000000..a30edc27 --- /dev/null +++ b/.changeset/funny-dingos-worry.md @@ -0,0 +1,5 @@ +--- +'@razorpay/i18nify-js': patch +--- + +[feat]: add major/minor conversion apis in currency module diff --git a/packages/i18nify-js/README.md b/packages/i18nify-js/README.md index 58097f9d..8ad5a4f3 100644 --- a/packages/i18nify-js/README.md +++ b/packages/i18nify-js/README.md @@ -29,7 +29,7 @@ Welcome to the command center for your i18n experience! This module serves as th #### Functions -**setState(newState: Partial``):** Customize and update your i18n state with ease! Whether you're changing locales or tweaking directions, this function is your ticket to tailor your i18n experience precisely how you want it! 🎨 +**setState(newState: Partial ``):** Customize and update your i18n state with ease! Whether you're changing locales or tweaking directions, this function is your ticket to tailor your i18n experience precisely how you want it! 🎨 ``` import { setState } from "@razorpay/i18nify-js/core"; @@ -68,6 +68,28 @@ resetState(); This module's your go-to guru for everything currency/number-related. 🤑 It's all about formatting, validations, and handy tricks to make dealing with money/numbers a breeze. Here are the cool APIs and utilities this Currency Module gives you to play with! 🚀💸 +#### convertToMajorUnit(amount, options) + +💵🔄 This function is your go-to tool for scaling currency values from lower to major units. Just input the amount in a minor unit (like cents or pence) along with the currency code, and voilà! You get the amount in a major unit (like dollars or pounds). And if you stumble upon an unsupported currency code, it'll promptly let you know by throwing an error. + +##### Examples + +```javascript +console.log(convertToMajorUnit(10000, 'USD')); // Outputs the amount in dollars for 10000 cents (e.g., 100.00) +console.log(convertToMajorUnit(5000, 'GBP')); // Converts 5000 pence to pounds (e.g., 50.00) +``` + +#### convertToMinorUnit(amount, options) + +💵🔄 This function is your go-to tool for scaling currency values from higher to minor units. Just input the amount in a major unit (like dollars or pounds) along with the currency code, and voilà! You get the amount in a minor unit (like cents or pence). And if you stumble upon an unsupported currency code, it'll promptly let you know by throwing an error. + +##### Examples + +```javascript +console.log(convertToMinorUnit(100, 'USD')); // Outputs the amount in cents for 10000 dollars (e.g., 10000) +console.log(convertToMinorUnit(50, 'GBP')); // Converts 50 pounds to pence (e.g., 5000) +``` + #### formatNumber(amount, options) 🎩✨ This little wizard helps you jazz up numerical values in all sorts of fancy ways. And guess what? It uses the Internationalization API (Intl) to sprinkle that magic dust and give you snazzy, locale-specific number formats—especially for currencies! 🌟💸 @@ -105,101 +127,32 @@ console.log( ``` console.log(getCurrencyList()); /* { - AED: { symbol: 'د.إ', name: 'United Arab Emirates Dirham' }, - ALL: { symbol: 'Lek', name: 'Albanian Lek' }, - AMD: { symbol: '֏', name: 'Armenian Dram' }, - ARS: { symbol: 'ARS', name: 'Argentine Peso' }, - AUD: { symbol: 'A$', name: 'Australian Dollar' }, - AWG: { symbol: 'Afl.', name: 'Aruban Florin' }, - BBD: { symbol: '$', name: 'Barbadian Dollar' }, - BDT: { symbol: '৳', name: 'Bangladeshi Taka' }, - BMD: { symbol: '$', name: 'Bermudian Dollar' }, - BND: { symbol: 'BND', name: 'Brunei Dollar' }, - BOB: { symbol: 'Bs', name: 'Bolivian Boliviano' }, - BSD: { symbol: 'B$', name: 'Bahamian Dollar' }, - BWP: { symbol: 'P', name: 'Botswanan Pula' }, - BZD: { symbol: 'BZ$', name: 'Belize Dollar' }, - CAD: { symbol: 'C$', name: 'Canadian Dollar' }, - CHF: { symbol: 'CHf', name: 'Swiss Franc' }, - CNY: { symbol: '¥', name: 'Chinese Yuan' }, - COP: { symbol: 'COL$', name: 'Colombian Peso' }, - CRC: { symbol: '₡', name: 'Costa Rican Colón' }, - CUP: { symbol: '$MN', name: 'Cuban Peso' }, - CZK: { symbol: 'Kč', name: 'Czech Koruna' }, - DKK: { symbol: 'DKK', name: 'Danish Krone' }, - DOP: { symbol: 'RD$', name: 'Dominican Peso' }, - DZD: { symbol: 'د.ج', name: 'Algerian Dinar' }, - EGP: { symbol: 'E£', name: 'Egyptian Pound' }, - ETB: { symbol: 'ብር', name: 'Ethiopian Birr' }, - EUR: { symbol: '€', name: 'Euro' }, - FJD: { symbol: 'FJ$', name: 'Fijian Dollar' }, - GBP: { symbol: '£', name: 'British Pound' }, - GHS: { symbol: 'GH₵', name: 'Ghanaian Cedi' }, - GIP: { symbol: 'GIP', name: 'Gibraltar Pound' }, - GMD: { symbol: 'D', name: 'Gambian Dalasi' }, - GTQ: { symbol: 'Q', name: 'Guatemalan Quetzal' }, - GYD: { symbol: 'G$', name: 'Guyanese Dollar' }, - HKD: { symbol: 'HK$', name: 'Hong Kong Dollar' }, - HNL: { symbol: 'HNL', name: 'Honduran Lempira' }, - HRK: { symbol: 'kn', name: 'Croatian Kuna' }, - HTG: { symbol: 'G', name: 'Haitian Gourde' }, - HUF: { symbol: 'Ft', name: 'Hungarian Forint' }, - IDR: { symbol: 'Rp', name: 'Indonesian Rupiah' }, - ILS: { symbol: '₪', name: 'Israeli New Shekel' }, - INR: { symbol: '₹', name: 'Indian Rupee' }, - JMD: { symbol: 'J$', name: 'Jamaican Dollar' }, - KES: { symbol: 'Ksh', name: 'Kenyan Shilling' }, - KGS: { symbol: 'Лв', name: 'Kyrgystani Som' }, - KHR: { symbol: '៛', name: 'Cambodian Riel' }, - KYD: { symbol: 'CI$', name: 'Cayman Islands Dollar' }, - KZT: { symbol: '₸', name: 'Kazakhstani Tenge' }, - LAK: { symbol: '₭', name: 'Laotian Kip' }, - LKR: { symbol: 'රු', name: 'Sri Lankan Rupee' }, - LRD: { symbol: 'L$', name: 'Liberian Dollar' }, - LSL: { symbol: 'LSL', name: 'Lesotho Loti' }, - MAD: { symbol: 'د.م.', name: 'Moroccan Dirham' }, - MDL: { symbol: 'MDL', name: 'Moldovan Leu' }, - MKD: { symbol: 'ден', name: 'Macedonian Denar' }, - MMK: { symbol: 'MMK', name: 'Myanmar Kyat' }, - MNT: { symbol: '₮', name: 'Mongolian Tugrik' }, - MOP: { symbol: 'MOP$', name: 'Macanese Pataca' }, - MUR: { symbol: '₨', name: 'Mauritian Rupee' }, - MVR: { symbol: 'Rf', name: 'Maldivian Rufiyaa' }, - MWK: { symbol: 'MK', name: 'Malawian Kwacha' }, - MXN: { symbol: 'Mex$', name: 'Mexican Peso' }, - MYR: { symbol: 'RM', name: 'Malaysian Ringgit' }, - NAD: { symbol: 'N$', name: 'Namibian Dollar' }, - NGN: { symbol: '₦', name: 'Nigerian Naira' }, - NIO: { symbol: 'NIO', name: 'Nicaraguan Córdoba' }, - NOK: { symbol: 'NOK', name: 'Norwegian Krone' }, - NPR: { symbol: 'रू', name: 'Nepalese Rupee' }, - NZD: { symbol: 'NZ$', name: 'New Zealand Dollar' }, - PEN: { symbol: 'S/', name: 'Peruvian Nuevo Sol' }, - PGK: { symbol: 'PGK', name: 'Papua New Guinean Kina' }, - PHP: { symbol: '₱', name: 'Philippine Peso' }, - PKR: { symbol: '₨', name: 'Pakistani Rupee' }, - QAR: { symbol: 'QR', name: 'Qatari Riyal' }, - RUB: { symbol: '₽', name: 'Russian Ruble' }, - SAR: { symbol: 'SR', name: 'Saudi Riyal' }, - SCR: { symbol: 'SRe', name: 'Seychellois Rupee' }, - SEK: { symbol: 'SEK', name: 'Swedish Krona' }, - SGD: { symbol: 'S$', name: 'Singapore Dollar' }, - SLL: { symbol: 'Le', name: 'Sierra Leonean Leone' }, - SOS: { symbol: 'Sh.so.', name: 'Somali Shilling' }, - SSP: { symbol: 'SS£', name: 'South Sudanese Pound' }, - SVC: { symbol: '₡', name: 'Salvadoran Colón' }, - SZL: { symbol: 'E', name: 'Swazi Lilangeni' }, - THB: { symbol: '฿', name: 'Thai Baht' }, - TTD: { symbol: 'TT$', name: 'Trinidad and Tobago Dollar' }, - TZS: { symbol: 'Sh', name: 'Tanzanian Shilling' }, - USD: { symbol: '$', name: 'United States Dollar' }, - UYU: { symbol: '$U', name: 'Uruguayan Peso' }, - UZS: { symbol: "so'm", name: 'Uzbekistani Som' }, - YER: { symbol: '﷼', name: 'Yemeni Rial' }, - ZAR: { symbol: 'R', name: 'South African Rand' }, - KWD: { symbol: 'د.ك', name: 'Kuwaiti Dinar' }, - BHD: { symbol: 'د.ب.', name: 'Bahraini Dinar' }, - OMR: { symbol: 'ر.ع.', name: 'Omani Rial' }, + AED: { + symbol: 'د.إ', + name: 'United Arab Emirates Dirham', + lowerUnitName: 'Fils', + }, + ALL: { + symbol: 'Lek', + name: 'Albanian Lek', + lowerUnitName: 'Qindarka', + }, + AMD: { + symbol: '֏', + name: 'Armenian Dram', + lowerUnitName: 'Luma', + }, + ARS: { + symbol: 'ARS', + name: 'Argentine Peso', + lowerUnitName: 'Centavo', + }, + AUD: { + symbol: 'A$', + name: 'Australian Dollar', + lowerUnitName: 'Cent', + }, + ... rest of the country } */ ``` diff --git a/packages/i18nify-js/src/modules/.internal/utils/getIntlInstanceWithOptions.ts b/packages/i18nify-js/src/modules/.internal/utils/getIntlInstanceWithOptions.ts index 3c267c7d..bb5e18e0 100644 --- a/packages/i18nify-js/src/modules/.internal/utils/getIntlInstanceWithOptions.ts +++ b/packages/i18nify-js/src/modules/.internal/utils/getIntlInstanceWithOptions.ts @@ -1,12 +1,12 @@ -import { CURRENCIES } from '../../currency/data/currencies'; +import type { CurrencyCodeType, I18nifyNumberFormatOptions } from '../../currency/types'; import state from '../state'; import { getLocale } from './getLocale'; export const getIntlInstanceWithOptions = ( options: { - currency?: keyof typeof CURRENCIES; + currency?: CurrencyCodeType; locale?: string; - intlOptions?: Intl.NumberFormatOptions; + intlOptions?: I18nifyNumberFormatOptions; } = {}, ) => { /** retrieve locale from below areas in order of preference @@ -30,5 +30,8 @@ export const getIntlInstanceWithOptions = ( if (!locale) throw new Error('Pass valid locale !'); - return new Intl.NumberFormat(locale || undefined, intlOptions); + return new Intl.NumberFormat( + locale || undefined, + intlOptions as Intl.NumberFormatOptions, + ); }; diff --git a/packages/i18nify-js/src/modules/currency/__tests__/convertToMajorUnit.test.ts b/packages/i18nify-js/src/modules/currency/__tests__/convertToMajorUnit.test.ts new file mode 100644 index 00000000..e71f2991 --- /dev/null +++ b/packages/i18nify-js/src/modules/currency/__tests__/convertToMajorUnit.test.ts @@ -0,0 +1,28 @@ +import convertToMajorUnit from '../convertToMajorUnit'; +import { CurrencyCodeType } from '../types'; + +describe('currency - convertToMajorUnit', () => { + const testCases: { + amount: number; + currency: CurrencyCodeType; + expectedResult: number; + }[] = [ + { amount: 100, currency: 'USD', expectedResult: 1 }, + { amount: 100, currency: 'GBP', expectedResult: 1 }, + ]; + + testCases.forEach(({ amount, currency, expectedResult }) => { + it(`should correctly convert ${amount} of minor unit ${currency} to ${expectedResult}`, () => { + const result = convertToMajorUnit(amount, { currency: currency }); + expect(result).toBe(expectedResult); + }); + }); + + it('should throw an error for unsupported currency codes', () => { + const unsupportedCurrencyCode = 'XXX'; + expect(() => { + // @ts-expect-error intented invalid currencyCode for testing + convertToMajorUnit(100, { currency: unsupportedCurrencyCode }); + }).toThrow('Unsupported currency XXX'); + }); +}); diff --git a/packages/i18nify-js/src/modules/currency/__tests__/convertToMinorUnit.test.ts b/packages/i18nify-js/src/modules/currency/__tests__/convertToMinorUnit.test.ts new file mode 100644 index 00000000..b4c33b89 --- /dev/null +++ b/packages/i18nify-js/src/modules/currency/__tests__/convertToMinorUnit.test.ts @@ -0,0 +1,28 @@ +import convertToMinorUnit from '../convertToMinorUnit'; +import { CurrencyCodeType } from '../types'; + +describe('currency - convertToMinorUnit', () => { + const testCases: { + amount: number; + currency: CurrencyCodeType; + expectedResult: number; + }[] = [ + { amount: 1, currency: 'USD', expectedResult: 100 }, + { amount: 1, currency: 'GBP', expectedResult: 100 }, + ]; + + testCases.forEach(({ amount, currency, expectedResult }) => { + it(`should correctly convert ${amount} of minor unit ${currency} to ${expectedResult}`, () => { + const result = convertToMinorUnit(amount, { currency: currency }); + expect(result).toBe(expectedResult); + }); + }); + + it('should throw an error for unsupported currency codes', () => { + const unsupportedCurrencyCode = 'XXX'; + expect(() => { + // @ts-expect-error intented invalid currencyCode for testing + convertToMinorUnit(100, { currency: unsupportedCurrencyCode }); + }).toThrow('Unsupported currency XXX'); + }); +}); diff --git a/packages/i18nify-js/src/modules/currency/convertToMajorUnit.ts b/packages/i18nify-js/src/modules/currency/convertToMajorUnit.ts new file mode 100644 index 00000000..71d37316 --- /dev/null +++ b/packages/i18nify-js/src/modules/currency/convertToMajorUnit.ts @@ -0,0 +1,34 @@ +import { withErrorBoundary } from '../../common/errorBoundary'; +import { CURRENCIES } from './data/currencies'; +import { CurrencyCodeType, CurrencyType } from './types'; + +/** + * Converts an amount from a minor currency unit to a major currency unit. + * + * The function takes an amount in the minor unit (e.g., cents, pence) and a currency code, + * then converts the amount to the major unit (e.g., dollars, pounds) using the conversion rate + * defined in the CURRENCIES object. If the currency code is not supported, it throws an error. + * + * @param {number} amount - The amount in the minor currency unit. + * @param {object} options - The options object + * @returns {number} - The amount converted to the major currency unit. + * @throws Will throw an error if the currency code is not supported. + */ +const convertToMajorUnit = ( + amount: number, + options: { + currency: CurrencyCodeType; + }, +): number => { + const currencyInfo = CURRENCIES[options.currency] as CurrencyType; + + if (!currencyInfo) + throw new Error(`Unsupported currency ${options.currency}`); + + const minorUnitMultiplier = currencyInfo.minorUnitMultiplier || 100; + + const higherCurrencyValue = amount / minorUnitMultiplier; + return higherCurrencyValue; +}; + +export default withErrorBoundary(convertToMajorUnit); diff --git a/packages/i18nify-js/src/modules/currency/convertToMinorUnit.ts b/packages/i18nify-js/src/modules/currency/convertToMinorUnit.ts new file mode 100644 index 00000000..e26f7271 --- /dev/null +++ b/packages/i18nify-js/src/modules/currency/convertToMinorUnit.ts @@ -0,0 +1,34 @@ +import { withErrorBoundary } from '../../common/errorBoundary'; +import { CURRENCIES } from './data/currencies'; +import { CurrencyCodeType, CurrencyType } from './types'; + +/** + * Converts an amount from a major currency unit to a minor currency unit. + * + * The function takes an amount in the major unit (e.g., dollars, pounds) and a currency code, + * then converts the amount to the minor unit (e.g., cents, pence) using the conversion rate + * defined in the CURRENCIES object. If the currency code is not supported, it throws an error. + * + * @param {number} amount - The amount in the major currency unit. + * @param {object} options - The options object + * @returns {number} - The amount converted to the minor currency unit. + * @throws Will throw an error if the currency code is not supported. + */ +const convertToMinorUnit = ( + amount: number, + options: { + currency: CurrencyCodeType; + }, +): number => { + const currencyInfo = CURRENCIES[options.currency] as CurrencyType; + + if (!currencyInfo) + throw new Error(`Unsupported currency ${options.currency}`); + + const minorUnitMultiplier = currencyInfo.minorUnitMultiplier || 100; + + const lowerCurrencyValue = amount * minorUnitMultiplier; + return lowerCurrencyValue; +}; + +export default withErrorBoundary(convertToMinorUnit); diff --git a/packages/i18nify-js/src/modules/currency/data/currencies.ts b/packages/i18nify-js/src/modules/currency/data/currencies.ts index a50af6c9..42ac19b1 100644 --- a/packages/i18nify-js/src/modules/currency/data/currencies.ts +++ b/packages/i18nify-js/src/modules/currency/data/currencies.ts @@ -1,98 +1,486 @@ export const CURRENCIES = { - AED: { symbol: 'د.إ', name: 'United Arab Emirates Dirham' }, - ALL: { symbol: 'Lek', name: 'Albanian Lek' }, - AMD: { symbol: '֏', name: 'Armenian Dram' }, - ARS: { symbol: 'ARS', name: 'Argentine Peso' }, - AUD: { symbol: 'A$', name: 'Australian Dollar' }, - AWG: { symbol: 'Afl.', name: 'Aruban Florin' }, - BBD: { symbol: '$', name: 'Barbadian Dollar' }, - BDT: { symbol: '৳', name: 'Bangladeshi Taka' }, - BMD: { symbol: '$', name: 'Bermudian Dollar' }, - BND: { symbol: 'BND', name: 'Brunei Dollar' }, - BOB: { symbol: 'Bs', name: 'Bolivian Boliviano' }, - BSD: { symbol: 'B$', name: 'Bahamian Dollar' }, - BWP: { symbol: 'P', name: 'Botswanan Pula' }, - BZD: { symbol: 'BZ$', name: 'Belize Dollar' }, - CAD: { symbol: 'C$', name: 'Canadian Dollar' }, - CHF: { symbol: 'CHf', name: 'Swiss Franc' }, - CNY: { symbol: '¥', name: 'Chinese Yuan' }, - COP: { symbol: 'COL$', name: 'Colombian Peso' }, - CRC: { symbol: '₡', name: 'Costa Rican Colón' }, - CUP: { symbol: '$MN', name: 'Cuban Peso' }, - CZK: { symbol: 'Kč', name: 'Czech Koruna' }, - DKK: { symbol: 'DKK', name: 'Danish Krone' }, - DOP: { symbol: 'RD$', name: 'Dominican Peso' }, - DZD: { symbol: 'د.ج', name: 'Algerian Dinar' }, - EGP: { symbol: 'E£', name: 'Egyptian Pound' }, - ETB: { symbol: 'ብር', name: 'Ethiopian Birr' }, - EUR: { symbol: '€', name: 'Euro' }, - FJD: { symbol: 'FJ$', name: 'Fijian Dollar' }, - GBP: { symbol: '£', name: 'British Pound' }, - GHS: { symbol: 'GH₵', name: 'Ghanaian Cedi' }, - GIP: { symbol: 'GIP', name: 'Gibraltar Pound' }, - GMD: { symbol: 'D', name: 'Gambian Dalasi' }, - GTQ: { symbol: 'Q', name: 'Guatemalan Quetzal' }, - GYD: { symbol: 'G$', name: 'Guyanese Dollar' }, - HKD: { symbol: 'HK$', name: 'Hong Kong Dollar' }, - HNL: { symbol: 'HNL', name: 'Honduran Lempira' }, - HRK: { symbol: 'kn', name: 'Croatian Kuna' }, - HTG: { symbol: 'G', name: 'Haitian Gourde' }, - HUF: { symbol: 'Ft', name: 'Hungarian Forint' }, - IDR: { symbol: 'Rp', name: 'Indonesian Rupiah' }, - ILS: { symbol: '₪', name: 'Israeli New Shekel' }, - INR: { symbol: '₹', name: 'Indian Rupee' }, - JMD: { symbol: 'J$', name: 'Jamaican Dollar' }, - KES: { symbol: 'Ksh', name: 'Kenyan Shilling' }, - KGS: { symbol: 'Лв', name: 'Kyrgystani Som' }, - KHR: { symbol: '៛', name: 'Cambodian Riel' }, - KYD: { symbol: 'CI$', name: 'Cayman Islands Dollar' }, - KZT: { symbol: '₸', name: 'Kazakhstani Tenge' }, - LAK: { symbol: '₭', name: 'Laotian Kip' }, - LKR: { symbol: 'රු', name: 'Sri Lankan Rupee' }, - LRD: { symbol: 'L$', name: 'Liberian Dollar' }, - LSL: { symbol: 'LSL', name: 'Lesotho Loti' }, - MAD: { symbol: 'د.م.', name: 'Moroccan Dirham' }, - MDL: { symbol: 'MDL', name: 'Moldovan Leu' }, - MKD: { symbol: 'ден', name: 'Macedonian Denar' }, - MMK: { symbol: 'MMK', name: 'Myanmar Kyat' }, - MNT: { symbol: '₮', name: 'Mongolian Tugrik' }, - MOP: { symbol: 'MOP$', name: 'Macanese Pataca' }, - MUR: { symbol: '₨', name: 'Mauritian Rupee' }, - MVR: { symbol: 'Rf', name: 'Maldivian Rufiyaa' }, - MWK: { symbol: 'MK', name: 'Malawian Kwacha' }, - MXN: { symbol: 'Mex$', name: 'Mexican Peso' }, - MYR: { symbol: 'RM', name: 'Malaysian Ringgit' }, - NAD: { symbol: 'N$', name: 'Namibian Dollar' }, - NGN: { symbol: '₦', name: 'Nigerian Naira' }, - NIO: { symbol: 'NIO', name: 'Nicaraguan Córdoba' }, - NOK: { symbol: 'NOK', name: 'Norwegian Krone' }, - NPR: { symbol: 'रू', name: 'Nepalese Rupee' }, - NZD: { symbol: 'NZ$', name: 'New Zealand Dollar' }, - PEN: { symbol: 'S/', name: 'Peruvian Nuevo Sol' }, - PGK: { symbol: 'PGK', name: 'Papua New Guinean Kina' }, - PHP: { symbol: '₱', name: 'Philippine Peso' }, - PKR: { symbol: '₨', name: 'Pakistani Rupee' }, - QAR: { symbol: 'QR', name: 'Qatari Riyal' }, - RUB: { symbol: '₽', name: 'Russian Ruble' }, - SAR: { symbol: 'SR', name: 'Saudi Riyal' }, - SCR: { symbol: 'SRe', name: 'Seychellois Rupee' }, - SEK: { symbol: 'SEK', name: 'Swedish Krona' }, - SGD: { symbol: 'S$', name: 'Singapore Dollar' }, - SLL: { symbol: 'Le', name: 'Sierra Leonean Leone' }, - SOS: { symbol: 'Sh.so.', name: 'Somali Shilling' }, - SSP: { symbol: 'SS£', name: 'South Sudanese Pound' }, - SVC: { symbol: '₡', name: 'Salvadoran Colón' }, - SZL: { symbol: 'E', name: 'Swazi Lilangeni' }, - THB: { symbol: '฿', name: 'Thai Baht' }, - TTD: { symbol: 'TT$', name: 'Trinidad and Tobago Dollar' }, - TZS: { symbol: 'Sh', name: 'Tanzanian Shilling' }, - USD: { symbol: '$', name: 'United States Dollar' }, - UYU: { symbol: '$U', name: 'Uruguayan Peso' }, - UZS: { symbol: "so'm", name: 'Uzbekistani Som' }, - YER: { symbol: '﷼', name: 'Yemeni Rial' }, - ZAR: { symbol: 'R', name: 'South African Rand' }, - KWD: { symbol: 'د.ك', name: 'Kuwaiti Dinar' }, - BHD: { symbol: 'د.ب.', name: 'Bahraini Dinar' }, - OMR: { symbol: 'ر.ع.', name: 'Omani Rial' }, - JPY: { symbol: '¥', name: 'Japanese Yen' }, + AED: { + symbol: 'د.إ', + name: 'United Arab Emirates Dirham', + lowerUnitName: 'Fils', + }, + ALL: { + symbol: 'Lek', + name: 'Albanian Lek', + lowerUnitName: 'Qindarka', + }, + AMD: { + symbol: '֏', + name: 'Armenian Dram', + lowerUnitName: 'Luma', + }, + ARS: { + symbol: 'ARS', + name: 'Argentine Peso', + lowerUnitName: 'Centavo', + }, + AUD: { + symbol: 'A$', + name: 'Australian Dollar', + lowerUnitName: 'Cent', + }, + AWG: { + symbol: 'Afl.', + name: 'Aruban Florin', + lowerUnitName: 'Cent', + }, + BBD: { + symbol: '$', + name: 'Barbadian Dollar', + lowerUnitName: 'Cent', + }, + BDT: { + symbol: '৳', + name: 'Bangladeshi Taka', + lowerUnitName: 'Poisha', + }, + BMD: { + symbol: '$', + name: 'Bermudian Dollar', + lowerUnitName: 'Cent', + }, + BND: { + symbol: 'BND', + name: 'Brunei Dollar', + lowerUnitName: 'Sen', + }, + BOB: { + symbol: 'Bs', + name: 'Bolivian Boliviano', + lowerUnitName: 'Centavo', + }, + BSD: { + symbol: 'B$', + name: 'Bahamian Dollar', + lowerUnitName: 'Cent', + }, + BWP: { + symbol: 'P', + name: 'Botswanan Pula', + lowerUnitName: 'Thebe', + }, + BZD: { + symbol: 'BZ$', + name: 'Belize Dollar', + lowerUnitName: 'Cent', + }, + CAD: { + symbol: 'C$', + name: 'Canadian Dollar', + lowerUnitName: 'Cent', + }, + CHF: { + symbol: 'CHf', + name: 'Swiss Franc', + lowerUnitName: 'Rappen', + }, + CNY: { + symbol: '¥', + name: 'Chinese Yuan', + lowerUnitName: 'Fen', + }, + COP: { + symbol: 'COL$', + name: 'Colombian Peso', + lowerUnitName: 'Centavo', + }, + CRC: { + symbol: '₡', + name: 'Costa Rican Colón', + lowerUnitName: 'Céntimo', + }, + CUP: { + symbol: '$MN', + name: 'Cuban Peso', + lowerUnitName: 'Centavo', + }, + CZK: { + symbol: 'Kč', + name: 'Czech Koruna', + lowerUnitName: 'Haléř', + }, + DKK: { + symbol: 'DKK', + name: 'Danish Krone', + lowerUnitName: 'Øre', + }, + DOP: { + symbol: 'RD$', + name: 'Dominican Peso', + lowerUnitName: 'Centavo', + }, + DZD: { + symbol: 'د.ج', + name: 'Algerian Dinar', + lowerUnitName: 'Santeem', + }, + EGP: { + symbol: 'E£', + name: 'Egyptian Pound', + lowerUnitName: 'Piastre', + }, + ETB: { + symbol: 'ብር', + name: 'Ethiopian Birr', + lowerUnitName: 'Santim', + }, + EUR: { + symbol: '€', + name: 'Euro', + lowerUnitName: 'Cent', + }, + FJD: { + symbol: 'FJ$', + name: 'Fijian Dollar', + lowerUnitName: 'Cent', + }, + GBP: { + symbol: '£', + name: 'British Pound', + lowerUnitName: 'Penny', + }, + GHS: { + symbol: 'GH₵', + name: 'Ghanaian Cedi', + lowerUnitName: 'Pesewa', + }, + GIP: { + symbol: 'GIP', + name: 'Gibraltar Pound', + lowerUnitName: 'Penny', + }, + GMD: { + symbol: 'D', + name: 'Gambian Dalasi', + lowerUnitName: 'Butut', + }, + GTQ: { + symbol: 'Q', + name: 'Guatemalan Quetzal', + lowerUnitName: 'Centavo', + }, + GYD: { + symbol: 'G$', + name: 'Guyanese Dollar', + lowerUnitName: 'Cent', + }, + HKD: { + symbol: 'HK$', + name: 'Hong Kong Dollar', + lowerUnitName: 'Cent', + }, + HNL: { + symbol: 'HNL', + name: 'Honduran Lempira', + lowerUnitName: 'Centavo', + }, + HRK: { + symbol: 'kn', + name: 'Croatian Kuna', + lowerUnitName: 'Lipa', + }, + HTG: { + symbol: 'G', + name: 'Haitian Gourde', + lowerUnitName: 'Centime', + }, + HUF: { + symbol: 'Ft', + name: 'Hungarian Forint', + lowerUnitName: 'Fillér', + }, + IDR: { + symbol: 'Rp', + name: 'Indonesian Rupiah', + lowerUnitName: 'Sen', + }, + ILS: { + symbol: '₪', + name: 'Israeli New Shekel', + lowerUnitName: 'Agora', + }, + INR: { + symbol: '₹', + name: 'Indian Rupee', + lowerUnitName: 'Paisa', + }, + JMD: { + symbol: 'J$', + name: 'Jamaican Dollar', + lowerUnitName: 'Cent', + }, + KES: { + symbol: 'Ksh', + name: 'Kenyan Shilling', + lowerUnitName: 'Cent', + }, + KGS: { + symbol: 'Лв', + name: 'Kyrgystani Som', + lowerUnitName: 'Tyiyn', + }, + KHR: { + symbol: '៛', + name: 'Cambodian Riel', + lowerUnitName: 'Sen', + }, + KYD: { + symbol: 'CI$', + name: 'Cayman Islands Dollar', + lowerUnitName: 'Cent', + }, + KZT: { + symbol: '₸', + name: 'Kazakhstani Tenge', + lowerUnitName: 'Tiyn', + }, + LAK: { + symbol: '₭', + name: 'Laotian Kip', + lowerUnitName: 'Att', + }, + LKR: { + symbol: 'රු', + name: 'Sri Lankan Rupee', + lowerUnitName: 'Cent', + }, + LRD: { + symbol: 'L$', + name: 'Liberian Dollar', + lowerUnitName: 'Cent', + }, + LSL: { + symbol: 'LSL', + name: 'Lesotho Loti', + lowerUnitName: 'Sente', + }, + MAD: { + symbol: 'د.م.', + name: 'Moroccan Dirham', + lowerUnitName: 'Centime', + }, + MDL: { + symbol: 'MDL', + name: 'Moldovan Leu', + lowerUnitName: 'Ban', + }, + MKD: { + symbol: 'ден', + name: 'Macedonian Denar', + lowerUnitName: 'Deni', + }, + MMK: { + symbol: 'MMK', + name: 'Myanmar Kyat', + lowerUnitName: 'Pya', + }, + MNT: { + symbol: '₮', + name: 'Mongolian Tugrik', + lowerUnitName: 'Möngö', + }, + MOP: { + symbol: 'MOP$', + name: 'Macanese Pataca', + lowerUnitName: 'Avo', + }, + MUR: { + symbol: '₨', + name: 'Mauritian Rupee', + lowerUnitName: 'Cent', + }, + MVR: { + symbol: 'Rf', + name: 'Maldivian Rufiyaa', + lowerUnitName: 'Laari', + }, + MWK: { + symbol: 'MK', + name: 'Malawian Kwacha', + lowerUnitName: 'Tambala', + }, + MXN: { + symbol: 'Mex$', + name: 'Mexican Peso', + lowerUnitName: 'Centavo', + }, + MYR: { + symbol: 'RM', + name: 'Malaysian Ringgit', + lowerUnitName: 'Sen', + }, + NAD: { + symbol: 'N$', + name: 'Namibian Dollar', + lowerUnitName: 'Cent', + }, + NGN: { + symbol: '₦', + name: 'Nigerian Naira', + lowerUnitName: 'Kobo', + }, + NIO: { + symbol: 'NIO', + name: 'Nicaraguan Córdoba', + lowerUnitName: 'Centavo', + }, + NOK: { + symbol: 'NOK', + name: 'Norwegian Krone', + lowerUnitName: 'Øre', + }, + NPR: { + symbol: 'रू', + name: 'Nepalese Rupee', + lowerUnitName: 'Paisa', + }, + NZD: { + symbol: 'NZ$', + name: 'New Zealand Dollar', + lowerUnitName: 'Cent', + }, + PEN: { + symbol: 'S/', + name: 'Peruvian Nuevo Sol', + lowerUnitName: 'Céntimo', + }, + PGK: { + symbol: 'PGK', + name: 'Papua New Guinean Kina', + lowerUnitName: 'Toea', + }, + PHP: { + symbol: '₱', + name: 'Philippine Peso', + lowerUnitName: 'Centavo', + }, + PKR: { + symbol: '₨', + name: 'Pakistani Rupee', + lowerUnitName: 'Paisa', + }, + QAR: { + symbol: 'QR', + name: 'Qatari Riyal', + lowerUnitName: 'Dirham', + }, + RUB: { + symbol: '₽', + name: 'Russian Ruble', + lowerUnitName: 'Kopeck', + }, + SAR: { + symbol: 'SR', + name: 'Saudi Riyal', + lowerUnitName: 'Halala', + }, + SCR: { + symbol: 'SRe', + name: 'Seychellois Rupee', + lowerUnitName: 'Cent', + }, + SEK: { + symbol: 'SEK', + name: 'Swedish Krona', + lowerUnitName: 'Öre', + }, + SGD: { + symbol: 'S$', + name: 'Singapore Dollar', + lowerUnitName: 'Cent', + }, + SLL: { + symbol: 'Le', + name: 'Sierra Leonean Leone', + lowerUnitName: 'Cent', + }, + SOS: { + symbol: 'Sh.so.', + name: 'Somali Shilling', + lowerUnitName: 'Senti', + }, + SSP: { + symbol: 'SS£', + name: 'South Sudanese Pound', + lowerUnitName: 'Piaster', + }, + SVC: { + symbol: '₡', + name: 'Salvadoran Colón', + lowerUnitName: 'Centavo', + }, + SZL: { + symbol: 'E', + name: 'Swazi Lilangeni', + lowerUnitName: 'Cent', + }, + THB: { + symbol: '฿', + name: 'Thai Baht', + lowerUnitName: 'Satang', + }, + TTD: { + symbol: 'TT$', + name: 'Trinidad and Tobago Dollar', + lowerUnitName: 'Cent', + }, + TZS: { + symbol: 'Sh', + name: 'Tanzanian Shilling', + lowerUnitName: 'Cent', + }, + USD: { + symbol: '$', + name: 'United States Dollar', + lowerUnitName: 'Cent', + }, + UYU: { + symbol: '$U', + name: 'Uruguayan Peso', + lowerUnitName: 'Centésimo', + }, + UZS: { + symbol: "so'm", + name: 'Uzbekistani Som', + lowerUnitName: 'Tiyin', + }, + YER: { + symbol: '﷼', + name: 'Yemeni Rial', + lowerUnitName: 'Fils', + }, + ZAR: { + symbol: 'R', + name: 'South African Rand', + lowerUnitName: 'Cent', + }, + KWD: { + symbol: 'د.ك', + name: 'Kuwaiti Dinar', + lowerUnitName: 'Fils', + minorUnitMultiplier: 1000, + }, + BHD: { + symbol: 'د.ب.', + name: 'Bahraini Dinar', + lowerUnitName: 'Fils', + minorUnitMultiplier: 1000, + }, + OMR: { + symbol: 'ر.ع.', + name: 'Omani Rial', + lowerUnitName: 'Baisa', + minorUnitMultiplier: 1000, + }, + JPY: { + symbol: '¥', + name: 'Japanese Yen', + lowerUnitName: '', + minorUnitMultiplier: 1, + }, } as const; diff --git a/packages/i18nify-js/src/modules/currency/formatNumber.ts b/packages/i18nify-js/src/modules/currency/formatNumber.ts index 4445f83e..de727d17 100644 --- a/packages/i18nify-js/src/modules/currency/formatNumber.ts +++ b/packages/i18nify-js/src/modules/currency/formatNumber.ts @@ -1,14 +1,14 @@ -import { CURRENCIES } from './data/currencies'; import { withErrorBoundary } from '../../common/errorBoundary'; import { getIntlInstanceWithOptions } from '../.internal/utils'; +import { CurrencyCodeType, I18nifyNumberFormatOptions } from './types'; // this function formats number based on different arguments passed const formatNumber = ( amount: string | number, options: { - currency?: keyof typeof CURRENCIES; + currency?: CurrencyCodeType; locale?: string; - intlOptions?: Intl.NumberFormatOptions; + intlOptions?: I18nifyNumberFormatOptions; } = {}, ): string => { if (!Number(amount) && Number(amount) !== 0) diff --git a/packages/i18nify-js/src/modules/currency/formatNumberByParts.ts b/packages/i18nify-js/src/modules/currency/formatNumberByParts.ts index 8acb4d67..6165d137 100644 --- a/packages/i18nify-js/src/modules/currency/formatNumberByParts.ts +++ b/packages/i18nify-js/src/modules/currency/formatNumberByParts.ts @@ -1,5 +1,9 @@ -import { CURRENCIES } from './data/currencies'; -import { ByParts, FormattedPartsObject } from './types'; +import { + ByParts, + CurrencyCodeType, + FormattedPartsObject, + I18nifyNumberFormatOptions, +} from './types'; import { withErrorBoundary } from '../../common/errorBoundary'; import { getIntlInstanceWithOptions } from '../.internal/utils'; import { ALLOWED_FORMAT_PARTS_KEYS } from './constants'; @@ -7,9 +11,9 @@ import { ALLOWED_FORMAT_PARTS_KEYS } from './constants'; const formatNumberByParts = ( amount: string | number, options: { - currency?: keyof typeof CURRENCIES; + currency?: CurrencyCodeType; locale?: string; - intlOptions?: Intl.NumberFormatOptions; + intlOptions?: I18nifyNumberFormatOptions; } = {}, ): ByParts => { if (!Number(amount) && Number(amount) !== 0) diff --git a/packages/i18nify-js/src/modules/currency/getCurrencySymbol.ts b/packages/i18nify-js/src/modules/currency/getCurrencySymbol.ts index 556a36e4..d9381f83 100644 --- a/packages/i18nify-js/src/modules/currency/getCurrencySymbol.ts +++ b/packages/i18nify-js/src/modules/currency/getCurrencySymbol.ts @@ -1,7 +1,8 @@ import { CURRENCIES } from './data/currencies'; import { withErrorBoundary } from '../../common/errorBoundary'; +import { CurrencyCodeType } from './types'; -const getCurrencySymbol = (currencyCode: keyof typeof CURRENCIES): string => { +const getCurrencySymbol = (currencyCode: CurrencyCodeType): string => { if (currencyCode in CURRENCIES) return CURRENCIES[currencyCode]?.symbol; else throw new Error('Invalid currencyCode!'); }; diff --git a/packages/i18nify-js/src/modules/currency/index.ts b/packages/i18nify-js/src/modules/currency/index.ts index 95743d4f..a196d12b 100644 --- a/packages/i18nify-js/src/modules/currency/index.ts +++ b/packages/i18nify-js/src/modules/currency/index.ts @@ -2,3 +2,6 @@ export { default as formatNumber } from './formatNumber'; export { default as getCurrencyList } from './getCurrencyList'; export { default as getCurrencySymbol } from './getCurrencySymbol'; export { default as formatNumberByParts } from './formatNumberByParts'; +export { default as convertToMajorUnit } from './convertToMajorUnit'; +export { default as convertToMinorUnit } from './convertToMinorUnit'; +export type { CurrencyCodeType } from './types'; diff --git a/packages/i18nify-js/src/modules/currency/types.ts b/packages/i18nify-js/src/modules/currency/types.ts index 17bfc672..7204d41f 100644 --- a/packages/i18nify-js/src/modules/currency/types.ts +++ b/packages/i18nify-js/src/modules/currency/types.ts @@ -1,4 +1,5 @@ import { ALLOWED_FORMAT_PARTS_KEYS } from './constants'; +import { CURRENCIES } from './data/currencies'; export type FormattedPartsObject = { [key in (typeof ALLOWED_FORMAT_PARTS_KEYS)[number]]?: string | undefined; @@ -7,3 +8,52 @@ export interface ByParts extends FormattedPartsObject { isPrefixSymbol: boolean; rawParts: Array<{ type: string; value: unknown }>; } + +export interface CurrencyType { + symbol: string; + name: string; + lowerUnitName: string; + minorUnitMultiplier?: number; +} + +export interface I18nifyNumberFormatOptions { + numberingSystem?: string; + currencyDisplay?: 'code' | 'symbol' | 'narrowSymbol' | 'name' | undefined; + currencySign?: 'standard' | 'accounting' | undefined; + roundingPriority?: 'auto' | 'morePrecision' | 'lessPrecision'; + roundingIncrement?: number; + roundingMode?: + | 'ceil' + | 'floor' + | 'expand' + | 'trunc' + | 'halfCeil' + | 'halfFloor' + | 'halfExpand' + | 'halfTrunc' + | 'halfEven'; + trailingZeroDisplay?: 'auto' | 'stripIfInteger'; + useGrouping?: 'always' | 'auto' | 'min2' | true | false | undefined; + signDisplay?: + | 'auto' + | 'always' + | 'exceptZero' + | 'negative' + | 'never' + | undefined; + + compactDisplay?: 'short' | 'long' | undefined; + notation?: 'standard' | 'scientific' | 'engineering' | 'compact' | undefined; + unit?: string | undefined; + unitDisplay?: 'short' | 'long' | 'narrow' | undefined; + localeMatcher?: string | undefined; + style?: string | undefined; + currency?: string | undefined; + minimumIntegerDigits?: number | undefined; + minimumFractionDigits?: number | undefined; + maximumFractionDigits?: number | undefined; + minimumSignificantDigits?: number | undefined; + maximumSignificantDigits?: number | undefined; +} + +export type CurrencyCodeType = keyof typeof CURRENCIES;