fix(localize): align currency symbol usage for all browsers (#2011)
This commit is contained in:
parent
3cfc9f9744
commit
1ea5730aa5
7 changed files with 110 additions and 75 deletions
5
.changeset/purple-spoons-think.md
Normal file
5
.changeset/purple-spoons-think.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@lion/ui': patch
|
||||
---
|
||||
|
||||
[localize] align currency symbol usage for all browsers
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
|
|
|
|||
Loading…
Reference in a new issue