From 1ea5730aa50a329efa874dc0b306b1ddb375abba Mon Sep 17 00:00:00 2001 From: gerjanvangeest Date: Tue, 13 Jun 2023 14:57:26 +0200 Subject: [PATCH] fix(localize): align currency symbol usage for all browsers (#2011) --- .changeset/purple-spoons-think.md | 5 ++ .../forceENAUSymbols.js | 25 -------- ...ceNoSpaceBetweenCurrencySymbolAndNumber.js | 22 +++++++ .../forceSymbols.js | 64 +++++++++++++++++++ .../forceYenSymbol.js | 15 ----- .../normalizeIntl.js | 20 ++++-- .../localize/test/number/formatNumber.test.js | 34 ++-------- 7 files changed, 110 insertions(+), 75 deletions(-) create mode 100644 .changeset/purple-spoons-think.md delete mode 100644 packages/ui/components/localize/src/number/utils/normalize-format-number-to-parts/forceENAUSymbols.js create mode 100644 packages/ui/components/localize/src/number/utils/normalize-format-number-to-parts/forceNoSpaceBetweenCurrencySymbolAndNumber.js create mode 100644 packages/ui/components/localize/src/number/utils/normalize-format-number-to-parts/forceSymbols.js delete mode 100644 packages/ui/components/localize/src/number/utils/normalize-format-number-to-parts/forceYenSymbol.js diff --git a/.changeset/purple-spoons-think.md b/.changeset/purple-spoons-think.md new file mode 100644 index 000000000..8b61680e3 --- /dev/null +++ b/.changeset/purple-spoons-think.md @@ -0,0 +1,5 @@ +--- +'@lion/ui': patch +--- + +[localize] align currency symbol usage for all browsers diff --git a/packages/ui/components/localize/src/number/utils/normalize-format-number-to-parts/forceENAUSymbols.js b/packages/ui/components/localize/src/number/utils/normalize-format-number-to-parts/forceENAUSymbols.js deleted file mode 100644 index 4a75c14ba..000000000 --- a/packages/ui/components/localize/src/number/utils/normalize-format-number-to-parts/forceENAUSymbols.js +++ /dev/null @@ -1,25 +0,0 @@ -/** @type {Object.} */ -const CURRENCY_CODE_SYMBOL_MAP = { - EUR: '€', - USD: '$', - JPY: '¥', -}; - -/** - * Change the symbols for locale 'en-AU', due to bug in Chrome - * - * @typedef {import('../../../../types/LocalizeMixinTypes.js').FormatNumberPart} FormatNumberPart - * @param {FormatNumberPart[]} formattedParts - * @param {import('../../../../types/LocalizeMixinTypes.js').FormatNumberOptions} options - * @returns {FormatNumberPart[]} - */ -export function forceENAUSymbols(formattedParts, { currency, currencyDisplay } = {}) { - const result = formattedParts; - if (formattedParts.length > 1 && currencyDisplay === 'symbol' && currency) { - if (Object.keys(CURRENCY_CODE_SYMBOL_MAP).includes(currency)) { - result[0].value = CURRENCY_CODE_SYMBOL_MAP[currency]; - } - result[1].value = ''; - } - return result; -} diff --git a/packages/ui/components/localize/src/number/utils/normalize-format-number-to-parts/forceNoSpaceBetweenCurrencySymbolAndNumber.js b/packages/ui/components/localize/src/number/utils/normalize-format-number-to-parts/forceNoSpaceBetweenCurrencySymbolAndNumber.js new file mode 100644 index 000000000..3fa77fe0a --- /dev/null +++ b/packages/ui/components/localize/src/number/utils/normalize-format-number-to-parts/forceNoSpaceBetweenCurrencySymbolAndNumber.js @@ -0,0 +1,22 @@ +/** + * Force no space between currency symbol and amount + * + * @typedef {import('../../../../types/LocalizeMixinTypes.js').FormatNumberPart} FormatNumberPart + * @param {FormatNumberPart[]} formattedParts + * @param {import('../../../../types/LocalizeMixinTypes.js').FormatNumberOptions} options + * @returns {FormatNumberPart[]} + */ +export function forceNoSpaceBetweenCurrencySymbolAndNumber( + formattedParts, + { currency, currencyDisplay } = {}, +) { + const result = formattedParts; + if (formattedParts.length > 1 && currencyDisplay === 'symbol' && currency) { + formattedParts.forEach((part, i) => { + if (part.type === 'literal') { + result[i].value = ''; + } + }); + } + return result; +} diff --git a/packages/ui/components/localize/src/number/utils/normalize-format-number-to-parts/forceSymbols.js b/packages/ui/components/localize/src/number/utils/normalize-format-number-to-parts/forceSymbols.js new file mode 100644 index 000000000..b80055a88 --- /dev/null +++ b/packages/ui/components/localize/src/number/utils/normalize-format-number-to-parts/forceSymbols.js @@ -0,0 +1,64 @@ +/** + * @typedef {import('../../../../types/LocalizeMixinTypes.js').FormatNumberPart} FormatNumberPart + */ + +/** @type {Object.} */ +const CURRENCY_CODE_SYMBOL_MAP = { + EUR: '€', + USD: '$', + JPY: '¥', +}; + +/** + * Change the symbols differences in browsers + * + * @param {FormatNumberPart[]} formattedParts + * @param {import('../../../../types/LocalizeMixinTypes.js').FormatNumberOptions} options + * @param {string[]} currencyScope + * @returns {FormatNumberPart[]} + */ +export function forceSymbols(formattedParts, { currency, currencyDisplay } = {}, currencyScope) { + const result = formattedParts; + if ( + formattedParts.length > 1 && + currencyDisplay === 'symbol' && + currency && + currencyScope.includes(currency) + ) { + formattedParts.forEach((part, i) => { + if (part.type === 'currency' && Object.keys(CURRENCY_CODE_SYMBOL_MAP).includes(currency)) { + result[i].value = CURRENCY_CODE_SYMBOL_MAP[currency]; + } + }); + } + return result; +} + +/** + * Change the symbols for fr-BE differences in browsers + * + * @param {FormatNumberPart[]} formattedParts + * @param {import('../../../../types/LocalizeMixinTypes.js').FormatNumberOptions} options + * @param {string[]} currencyScope + * @returns {FormatNumberPart[]} + */ +export function forceFRBESymbols( + formattedParts, + { currency, currencyDisplay } = {}, + currencyScope, +) { + const result = formattedParts; + if ( + formattedParts.length > 1 && + currencyDisplay === 'symbol' && + currency && + currencyScope.includes(currency) + ) { + formattedParts.forEach((part, i) => { + if (part.type === 'currency' && Object.keys(CURRENCY_CODE_SYMBOL_MAP).includes(currency)) { + result[i].value = '$US'; + } + }); + } + return result; +} diff --git a/packages/ui/components/localize/src/number/utils/normalize-format-number-to-parts/forceYenSymbol.js b/packages/ui/components/localize/src/number/utils/normalize-format-number-to-parts/forceYenSymbol.js deleted file mode 100644 index 93b972a1c..000000000 --- a/packages/ui/components/localize/src/number/utils/normalize-format-number-to-parts/forceYenSymbol.js +++ /dev/null @@ -1,15 +0,0 @@ -/** - * @typedef {import('../../../../types/LocalizeMixinTypes.js').FormatNumberPart} FormatNumberPart - * @param {FormatNumberPart[]} formattedParts - * @param {import('../../../../types/LocalizeMixinTypes.js').FormatNumberOptions} options - * @returns {FormatNumberPart[]} - */ -export function forceYenSymbol(formattedParts, { currency, currencyDisplay } = {}) { - const result = formattedParts; - const numberOfParts = result.length; - // Change the symbol from JPY to ¥, due to bug in Chrome - if (numberOfParts > 1 && currency === 'JPY' && currencyDisplay === 'symbol') { - result[numberOfParts - 1].value = '¥'; - } - return result; -} diff --git a/packages/ui/components/localize/src/number/utils/normalize-format-number-to-parts/normalizeIntl.js b/packages/ui/components/localize/src/number/utils/normalize-format-number-to-parts/normalizeIntl.js index 0857d77ad..aae5845f6 100644 --- a/packages/ui/components/localize/src/number/utils/normalize-format-number-to-parts/normalizeIntl.js +++ b/packages/ui/components/localize/src/number/utils/normalize-format-number-to-parts/normalizeIntl.js @@ -1,12 +1,12 @@ import { getGroupSeparator } from '../../getGroupSeparator.js'; import { forceAddGroupSeparators } from './forceAddGroupSeparators.js'; import { forceCurrencyToEnd } from './forceCurrencyToEnd.js'; +import { forceNoSpaceBetweenCurrencySymbolAndNumber } from './forceNoSpaceBetweenCurrencySymbolAndNumber.js'; import { forceNormalSpaces } from './forceNormalSpaces.js'; import { forceSpaceBetweenCurrencyCodeAndNumber } from './forceSpaceBetweenCurrencyCodeAndNumber.js'; -import { forceYenSymbol } from './forceYenSymbol.js'; import { forceSpaceInsteadOfZeroForGroup } from './forceSpaceInsteadOfZeroForGroup.js'; import { forceTryCurrencyCode } from './forceTryCurrencyCode.js'; -import { forceENAUSymbols } from './forceENAUSymbols.js'; +import { forceFRBESymbols, forceSymbols } from './forceSymbols.js'; /** * Normalizes function "formatNumberToParts" @@ -33,9 +33,18 @@ export function normalizeIntl(formattedParts, options = {}, _locale) { if (_locale === 'en-GB' || _locale === 'en-US' || _locale === 'en-AU' || _locale === 'en-PH') { normalize = forceSpaceBetweenCurrencyCodeAndNumber(normalize, options); } - // Force missing Japanese Yen symbol + if (_locale === 'en-AU') { + normalize = forceSymbols(normalize, options, ['EUR', 'USD', 'JPY']); + normalize = forceNoSpaceBetweenCurrencySymbolAndNumber(normalize, options); + } + if (_locale === 'en-PH') { + normalize = forceSymbols(normalize, options, ['USD', 'JPY']); + } if (_locale === 'fr-FR' || _locale === 'fr-BE') { - normalize = forceYenSymbol(normalize, options); + normalize = forceSymbols(normalize, options, ['JPY']); + } + if (_locale === 'fr-BE') { + normalize = forceFRBESymbols(normalize, options, ['USD']); } if (_locale === 'tr-TR') { normalize = forceTryCurrencyCode(normalize, options); @@ -43,9 +52,6 @@ export function normalizeIntl(formattedParts, options = {}, _locale) { normalize = forceCurrencyToEnd(normalize); } } - if (_locale === 'en-AU') { - normalize = forceENAUSymbols(normalize, options); - } } return normalize; } diff --git a/packages/ui/components/localize/test/number/formatNumber.test.js b/packages/ui/components/localize/test/number/formatNumber.test.js index 21a4552a1..8c5f963c2 100644 --- a/packages/ui/components/localize/test/number/formatNumber.test.js +++ b/packages/ui/components/localize/test/number/formatNumber.test.js @@ -2,12 +2,6 @@ import { expect } from '@open-wc/testing'; import { getLocalizeManager, formatNumber } from '@lion/ui/localize-no-side-effects.js'; import { localizeTearDown } from '@lion/ui/localize-test-helpers.js'; -// TODO: This is broken only in Safari 13.1.2 Wait till ci is on 13.1.3 and remove -const isSafari = (() => { - const ua = navigator.userAgent.toLowerCase(); - return ua.indexOf('safari') !== -1 && ua.indexOf('chrome') === -1; -})(); - const currencyCode = /** @param {string} currency */ currency => ({ style: 'currency', currencyDisplay: 'code', @@ -278,19 +272,17 @@ Please specify .groupSeparator / .decimalSeparator on the formatOptions object t }); describe('en-AU', () => { - // TODO: This is broken only in Safari 13.1.2 Wait till ci is on 13.1.3 and remove - if (isSafari) { - return; - } - it('supports basics', () => { localizeManager.locale = 'en-AU'; expect(formatNumber(123456.789, currencyCode('EUR'))).to.equal('EUR 123,456.79'); expect(formatNumber(123456.789, currencyCode('USD'))).to.equal('USD 123,456.79'); expect(formatNumber(123456.789, currencyCode('JPY'))).to.equal('JPY 123,457'); - expect(formatNumber(123456.789, currencySymbol('EUR'))).to.equal('€123,456.79'); // TODO: fix - expect(formatNumber(123456.789, currencySymbol('USD'))).to.equal('$123,456.79'); // TODO: fix - expect(formatNumber(123456.789, currencySymbol('JPY'))).to.equal('¥123,457'); // TODO: fix + expect(formatNumber(123456.789, currencySymbol('EUR'))).to.equal('€123,456.79'); + expect(formatNumber(-123456.789, currencySymbol('EUR'))).to.equal('−€123,456.79'); + expect(formatNumber(123456.789, currencySymbol('USD'))).to.equal('$123,456.79'); + expect(formatNumber(-123456.789, currencySymbol('USD'))).to.equal('−$123,456.79'); + expect(formatNumber(123456.789, currencySymbol('JPY'))).to.equal('¥123,457'); + expect(formatNumber(-123456.789, currencySymbol('JPY'))).to.equal('−¥123,457'); }); }); @@ -319,11 +311,6 @@ Please specify .groupSeparator / .decimalSeparator on the formatOptions object t }); describe('nl-BE', () => { - // TODO: This is broken only in Safari 13.1.2 Wait till ci is on 13.1.3 and remove - if (isSafari) { - return; - } - it('supports basics', () => { localizeManager.locale = 'nl-BE'; expect(formatNumber(123456.789, currencyCode('EUR'))).to.equal('123.456,79 EUR'); @@ -349,10 +336,6 @@ Please specify .groupSeparator / .decimalSeparator on the formatOptions object t describe('fr-BE', () => { it('supports basics', () => { - // TODO: This test is broken on Safari, check and fix when the intl change is permanent - if (isSafari) { - return; - } localizeManager.locale = 'fr-BE'; expect(formatNumber(123456.789, currencyCode('EUR'))).to.equal('123 456,79 EUR'); expect(formatNumber(123456.789, currencyCode('USD'))).to.equal('123 456,79 USD'); @@ -397,11 +380,6 @@ Please specify .groupSeparator / .decimalSeparator on the formatOptions object t }); describe('tr-TR', () => { - // TODO: This is broken only in Safari 13.1.2 Wait till ci is on 13.1.3 and remove - if (isSafari) { - return; - } - it('supports basics', () => { localizeManager.locale = 'tr-TR'; expect(formatNumber(123456.789, currencyCode('EUR'))).to.equal('123.456,79 EUR');