fix(localize): align currency symbol usage for all browsers (#2011)

This commit is contained in:
gerjanvangeest 2023-06-13 14:57:26 +02:00 committed by GitHub
parent 3cfc9f9744
commit 1ea5730aa5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 110 additions and 75 deletions

View file

@ -0,0 +1,5 @@
---
'@lion/ui': patch
---
[localize] align currency symbol usage for all browsers

View file

@ -1,25 +0,0 @@
/** @type {Object.<string,string>} */
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;
}

View file

@ -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;
}

View file

@ -0,0 +1,64 @@
/**
* @typedef {import('../../../../types/LocalizeMixinTypes.js').FormatNumberPart} FormatNumberPart
*/
/** @type {Object.<string,string>} */
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;
}

View file

@ -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;
}

View file

@ -1,12 +1,12 @@
import { getGroupSeparator } from '../../getGroupSeparator.js'; import { getGroupSeparator } from '../../getGroupSeparator.js';
import { forceAddGroupSeparators } from './forceAddGroupSeparators.js'; import { forceAddGroupSeparators } from './forceAddGroupSeparators.js';
import { forceCurrencyToEnd } from './forceCurrencyToEnd.js'; import { forceCurrencyToEnd } from './forceCurrencyToEnd.js';
import { forceNoSpaceBetweenCurrencySymbolAndNumber } from './forceNoSpaceBetweenCurrencySymbolAndNumber.js';
import { forceNormalSpaces } from './forceNormalSpaces.js'; import { forceNormalSpaces } from './forceNormalSpaces.js';
import { forceSpaceBetweenCurrencyCodeAndNumber } from './forceSpaceBetweenCurrencyCodeAndNumber.js'; import { forceSpaceBetweenCurrencyCodeAndNumber } from './forceSpaceBetweenCurrencyCodeAndNumber.js';
import { forceYenSymbol } from './forceYenSymbol.js';
import { forceSpaceInsteadOfZeroForGroup } from './forceSpaceInsteadOfZeroForGroup.js'; import { forceSpaceInsteadOfZeroForGroup } from './forceSpaceInsteadOfZeroForGroup.js';
import { forceTryCurrencyCode } from './forceTryCurrencyCode.js'; import { forceTryCurrencyCode } from './forceTryCurrencyCode.js';
import { forceENAUSymbols } from './forceENAUSymbols.js'; import { forceFRBESymbols, forceSymbols } from './forceSymbols.js';
/** /**
* Normalizes function "formatNumberToParts" * 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') { if (_locale === 'en-GB' || _locale === 'en-US' || _locale === 'en-AU' || _locale === 'en-PH') {
normalize = forceSpaceBetweenCurrencyCodeAndNumber(normalize, options); 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') { 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') { if (_locale === 'tr-TR') {
normalize = forceTryCurrencyCode(normalize, options); normalize = forceTryCurrencyCode(normalize, options);
@ -43,9 +52,6 @@ export function normalizeIntl(formattedParts, options = {}, _locale) {
normalize = forceCurrencyToEnd(normalize); normalize = forceCurrencyToEnd(normalize);
} }
} }
if (_locale === 'en-AU') {
normalize = forceENAUSymbols(normalize, options);
}
} }
return normalize; return normalize;
} }

View file

@ -2,12 +2,6 @@ import { expect } from '@open-wc/testing';
import { getLocalizeManager, formatNumber } from '@lion/ui/localize-no-side-effects.js'; import { getLocalizeManager, formatNumber } from '@lion/ui/localize-no-side-effects.js';
import { localizeTearDown } from '@lion/ui/localize-test-helpers.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 => ({ const currencyCode = /** @param {string} currency */ currency => ({
style: 'currency', style: 'currency',
currencyDisplay: 'code', currencyDisplay: 'code',
@ -278,19 +272,17 @@ Please specify .groupSeparator / .decimalSeparator on the formatOptions object t
}); });
describe('en-AU', () => { 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', () => { it('supports basics', () => {
localizeManager.locale = 'en-AU'; localizeManager.locale = 'en-AU';
expect(formatNumber(123456.789, currencyCode('EUR'))).to.equal('EUR 123,456.79'); 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('USD'))).to.equal('USD 123,456.79');
expect(formatNumber(123456.789, currencyCode('JPY'))).to.equal('JPY 123,457'); 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('EUR'))).to.equal('€123,456.79');
expect(formatNumber(123456.789, currencySymbol('USD'))).to.equal('$123,456.79'); // TODO: fix expect(formatNumber(-123456.789, currencySymbol('EUR'))).to.equal('€123,456.79');
expect(formatNumber(123456.789, currencySymbol('JPY'))).to.equal('¥123,457'); // TODO: fix 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', () => { 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', () => { it('supports basics', () => {
localizeManager.locale = 'nl-BE'; localizeManager.locale = 'nl-BE';
expect(formatNumber(123456.789, currencyCode('EUR'))).to.equal('123.456,79 EUR'); 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', () => { describe('fr-BE', () => {
it('supports basics', () => { 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'; localizeManager.locale = 'fr-BE';
expect(formatNumber(123456.789, currencyCode('EUR'))).to.equal('123 456,79 EUR'); expect(formatNumber(123456.789, currencyCode('EUR'))).to.equal('123 456,79 EUR');
expect(formatNumber(123456.789, currencyCode('USD'))).to.equal('123 456,79 USD'); 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', () => { 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', () => { it('supports basics', () => {
localizeManager.locale = 'tr-TR'; localizeManager.locale = 'tr-TR';
expect(formatNumber(123456.789, currencyCode('EUR'))).to.equal('123.456,79 EUR'); expect(formatNumber(123456.789, currencyCode('EUR'))).to.equal('123.456,79 EUR');