diff --git a/packages/localize/src/number/formatNumberToParts.js b/packages/localize/src/number/formatNumberToParts.js index d89cc0df8..7f01c5816 100644 --- a/packages/localize/src/number/formatNumberToParts.js +++ b/packages/localize/src/number/formatNumberToParts.js @@ -26,16 +26,12 @@ export function formatNumberToParts(number, options) { } let formattedParts = []; const formattedNumber = Intl.NumberFormat(computedLocale, options).format(parsedNumber); - const regexSymbol = /[A-Z.,\s0-9]/; - const regexCode = /[A-Z]/; - - // U+002D, Hyphen-Minus, - - const regexMinusSign = /[-]/; - + const regexCurrency = /[.,\s0-9]/; + const regexMinusSign = /[-]/; // U+002D, Hyphen-Minus, - const regexNum = /[0-9]/; const regexSeparator = /[.,]/; const regexSpace = /[\s]/; - let currencyCode = ''; + let currency = ''; let numberPart = ''; let fraction = false; for (let i = 0; i < formattedNumber.length; i += 1) { @@ -47,34 +43,17 @@ export function formatNumberToParts(number, options) { if (regexNum.test(formattedNumber[i])) { numberPart += formattedNumber[i]; } - // detect currency symbol - if (!regexSymbol.test(formattedNumber[i]) && !regexMinusSign.test(formattedNumber[i])) { - // Write number grouping - if (numberPart && !fraction) { - formattedParts.push({ type: 'integer', value: numberPart }); - numberPart = ''; - } else if (numberPart) { - formattedParts.push({ type: 'fraction', value: numberPart }); - numberPart = ''; - } - formattedParts.push({ type: 'currency', value: formattedNumber[i] }); + + // detect currency (symbol or code) + if (!regexCurrency.test(formattedNumber[i]) && !regexMinusSign.test(formattedNumber[i])) { + currency += formattedNumber[i]; } - // detect currency code - if (regexCode.test(formattedNumber[i])) { - currencyCode += formattedNumber[i]; - // Write number grouping - if (numberPart && !fraction) { - formattedParts.push({ type: 'integer', value: numberPart }); - numberPart = ''; - } else if (numberPart) { - formattedParts.push({ type: 'fraction', value: numberPart }); - numberPart = ''; - } - if (currencyCode.length === 3) { - formattedParts.push({ type: 'currency', value: currencyCode }); - currencyCode = ''; - } + // push when another character then currency or end of loop + if ((regexCurrency.test(formattedNumber[i]) || formattedNumber.length === i + 1) && currency) { + formattedParts.push({ type: 'currency', value: currency }); + currency = ''; } + // detect dot and comma separators if (regexSeparator.test(formattedNumber[i])) { // Write number grouping diff --git a/packages/localize/src/number/normalizeIntl.js b/packages/localize/src/number/normalizeIntl.js index 92e8b4643..7a84bf863 100644 --- a/packages/localize/src/number/normalizeIntl.js +++ b/packages/localize/src/number/normalizeIntl.js @@ -27,7 +27,7 @@ export function normalizeIntl(formattedParts, options, _locale) { normalize = forceSpaceInsteadOfZeroForGroup(normalize); } // Force space between currency code and number - if (_locale === 'en-GB' || _locale === 'en-US' || _locale === 'en-AU') { + if (_locale === 'en-GB' || _locale === 'en-US' || _locale === 'en-AU' || _locale === 'en-PH') { normalize = forceSpaceBetweenCurrencyCodeAndNumber(normalize, options); } // Force missing Japanese Yen symbol diff --git a/packages/localize/stories/date.stories.js b/packages/localize/stories/date.stories.js new file mode 100644 index 000000000..d88ed9580 --- /dev/null +++ b/packages/localize/stories/date.stories.js @@ -0,0 +1,72 @@ +import { storiesOf, html } from '@open-wc/demoing-storybook'; +import { css } from '@lion/core'; +import { formatDate } from '../index.js'; + +const formatDateDemoStyle = css` + .demo-table { + border-collapse: collapse; + text-align: right; + } + + .demo-table thead > tr { + border-bottom: 1px solid grey; + } + + .demo-table thead > tr > :first-child, + .demo-table tbody > tr > :first-child, + .demo-table tfoot > tr > :first-child { + text-align: left; + } + + .demo-table th, + .demo-table td { + padding: 8px; + } +`; + +storiesOf('Localize System|Date', module).add( + 'formatDate', + () => html` + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionsCodeOutput
DefaultformatDate(new Date())${formatDate(new Date())}
Date display + formatDate(new + Date(){weekday:'long',year:'numeric',month:'long',day:'2-digit'}) + + ${formatDate(new Date(), { + weekday: 'long', + year: 'numeric', + month: 'long', + day: '2-digit', + })} +
LocaleformatDate(new Date(){locale:'nl-NL'})${formatDate(new Date(), { locale: 'nl-NL' })}
+ `, +); diff --git a/packages/localize/stories/index.stories.js b/packages/localize/stories/index.stories.js index de703834c..2035ee423 100644 --- a/packages/localize/stories/index.stories.js +++ b/packages/localize/stories/index.stories.js @@ -1,201 +1,3 @@ -import { storiesOf, html } from '@open-wc/demoing-storybook'; - -import { html as litHtml } from '@lion/core'; -import { LionLitElement } from '@lion/core/src/LionLitElement.js'; -import { - localize, - LocalizeMixin, - formatNumber, - formatNumberToParts, - getGroupSeparator, - getDecimalSeparator, - formatDate, - parseDate, - getDateFormatBasedOnLocale, -} from '../index.js'; - -storiesOf('Localize System|Localize', module).add('lit component', () => { - class LitHtmlExample extends LocalizeMixin(LionLitElement) { - static get localizeNamespaces() { - return [ - { 'lit-html-example': locale => import(`./translations/${locale}.js`) }, - ...super.localizeNamespaces, - ]; - } - - static get properties() { - return { - now: { - type: 'Date', - }, - }; - } - - render() { - // this is as simple as localization can be in JavaScript - // the Promise is used to delay inserting of the content until data is loaded - // for the first time as soon as `now` is provided or changed, it will rerender - // with a new value if locale is changed, there is a preconfigured listener - // to rerender when new data is loaded all thanks to lit-html capabilities - const headerDate = this.msgLit('lit-html-example:headerDate'); - const headerNumber = this.msgLit('lit-html-example:headerNumber'); - const date = this.now ? this.msgLit('lit-html-example:date', { now: this.now }) : ''; - const time = this.now ? this.msgLit('lit-html-example:time', { now: this.now }) : ''; - - // dateFormat - const options1 = { - weekday: 'long', - year: 'numeric', - month: 'long', - day: 'numeric', - }; - options1.timeZone = 'UTC'; - options1.timeZoneName = 'short'; - const dateParse1 = parseDate('01-05-2012'); - const dateParse2 = parseDate('12/05/2012'); - const dateParse3 = parseDate('1-5-2017'); - const dateFormat1 = formatDate(dateParse1, options1); - const dateFormat2 = formatDate(dateParse2, options1); - const dateFormat3 = formatDate(dateParse3, options1); - const dateFormat = getDateFormatBasedOnLocale(); - const datum = new Date(); - const options2 = { - weekday: 'long', - year: 'numeric', - month: 'long', - day: 'numeric', - }; - options2.timeZone = 'UTC'; - options2.timeZoneName = 'short'; - options2.locale = 'ja-JP-u-ca-japanese'; - const dateFormatted = formatDate(datum, options2); - - // numberFormat - const number1 = formatNumber(123456.789, { - style: 'currency', - currency: 'EUR', - currencyDisplay: 'code', - }); - const formatNumberToParts1 = formatNumberToParts(123456.789, { - style: 'currency', - currency: 'EUR', - currencyDisplay: 'code', - }); - let printParts1 = ''; - for (let i = 0; i < formatNumberToParts1.length; i += 1) { - printParts1 += `{ ${formatNumberToParts1[i].type}: ${formatNumberToParts1[i].value} }`; - } - - const number2 = formatNumber(1234.5, { style: 'decimal' }); - const formatNumberToParts2 = formatNumberToParts(1234.5, { style: 'decimal' }); - let printParts2 = ''; - for (let i = 0; i < formatNumberToParts2.length; i += 1) { - printParts2 += `{ ${formatNumberToParts2[i].type}: ${formatNumberToParts2[i].value} }`; - } - - const number3 = formatNumber(-1234.5, { - style: 'currency', - currency: 'EUR', - currencyDisplay: 'code', - }); - const formatNumberToParts3 = formatNumberToParts(-1234.5, { - style: 'currency', - currency: 'EUR', - currencyDisplay: 'code', - }); - let printParts3 = ''; - for (let i = 0; i < formatNumberToParts3.length; i += 1) { - printParts3 += `{ ${formatNumberToParts3[i].type}: ${formatNumberToParts3[i].value} }`; - } - const printGroupSeparator = getGroupSeparator(); - const printDecimalSeparator = getDecimalSeparator(); - return litHtml` -

${headerDate}

-
${date}
-
Order of date parts: ${dateFormat}
-
Parsed date (01-05-2012): ${dateFormat1}
-
Parsed date (12/05/2012): ${dateFormat2}
-
Parsed date (1/5/2017) : ${dateFormat3}
-
Japanese date: ${dateFormatted}
-
${time}
-

${headerNumber}

-
${number1} ${printParts1}
-
${number2} ${printParts2}
-
${number3} ${printParts3}
-
getGroupSeparator(): "${printGroupSeparator}"
-
getDecimalSeparator(): "${printDecimalSeparator}"
- `; - } - } - if (!customElements.get('lit-html-example')) { - customElements.define('lit-html-example', LitHtmlExample); - } - - return html` - - - - - - - `; -}); -// .add('message', () => { -// const en = { -// bar: '[en] hello from bar', -// foo: '[en] hey there from foo', -// }; -// const enGB = { -// ...en, -// foo: '[en-GB] hey there from foo', -// }; -// try { -// localize.addData('en', 'demo', en); -// localize.addData('en-GB', 'demo', enGB); -// } catch (error) { /* demo will get executed multiple times */ } -// -// return html` -//

try 'demo:bar' as well

-// -// -// -//
-// -// -//

-// -// `; +import './message.stories.js'; +import './number.stories.js'; +import './date.stories.js'; diff --git a/packages/localize/stories/message.stories.js b/packages/localize/stories/message.stories.js new file mode 100644 index 000000000..44f821762 --- /dev/null +++ b/packages/localize/stories/message.stories.js @@ -0,0 +1,65 @@ +import { storiesOf, html } from '@open-wc/demoing-storybook'; +import { LionLitElement } from '@lion/core/src/LionLitElement.js'; +import { localize, LocalizeMixin } from '../index.js'; + +storiesOf('Localize System|Message', module).add('locale', () => { + class messageExample extends LocalizeMixin(LionLitElement) { + static get localizeNamespaces() { + return [ + { 'lit-html-example': locale => import(`./translations/${locale}.js`) }, + ...super.localizeNamespaces, + ]; + } + + render() { + return html` +
+

${this.msgLit('lit-html-example:header', { locale: localize.locale })}

+

${this.msgLit('lit-html-example:body')}

+
+ `; + } + } + if (!customElements.get('message-example')) { + customElements.define('message-example', messageExample); + } + + return html` + + + + + + + `; +}); diff --git a/packages/localize/stories/number.stories.js b/packages/localize/stories/number.stories.js new file mode 100644 index 000000000..5858bea87 --- /dev/null +++ b/packages/localize/stories/number.stories.js @@ -0,0 +1,158 @@ +import { storiesOf, html } from '@open-wc/demoing-storybook'; +import { css } from '@lion/core'; +import { formatNumber, formatNumberToParts } from '../index.js'; + +const formatNumberDemoStyle = css` + .demo-table { + border-collapse: collapse; + text-align: right; + } + + .demo-table thead > tr { + border-bottom: 1px solid grey; + } + + .demo-table thead > tr > :first-child, + .demo-table tbody > tr > :first-child, + .demo-table tfoot > tr > :first-child { + text-align: left; + } + + .demo-table th, + .demo-table td { + padding: 8px; + } +`; + +const value = 1234.56; + +storiesOf('Localize System|Number', module) + .add( + 'formatNumber', + () => html` + +

Formatted value is ${value}

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
OptionsCodeOutput
Default${formatNumber(value)}
Currency symbol + formatNumber({ style: 'currency', currencyDisplay: 'symbol', currency: 'EUR' + }) + + ${formatNumber(value, { + style: 'currency', + currencyDisplay: 'symbol', + currency: 'EUR', + })} +
Currency code + formatNumber({ style: 'currency', currencyDisplay: 'code', currency: 'EUR' }) + + ${formatNumber(value, { + style: 'currency', + currencyDisplay: 'code', + currency: 'EUR', + })} +
LocaleformatNumber({ locale: 'nl-NL' })${formatNumber(value, { locale: 'nl-NL' })}
No decimals + formatNumber({ minimumFractionDigits: 0, maximumFractionDigits: 0, }) + + ${formatNumber(value, { + minimumFractionDigits: 0, + maximumFractionDigits: 0, + })} +
+ `, + ) + .add( + 'formatNumberToParts', + () => html` + +

Formatted value is ${value}

+ + + + + + + + + ${formatNumberToParts(value, { style: 'currency', currency: 'EUR' }).map( + part => html` + + + + + `, + )} + +
PartOutput
${part.type}${part.value}
+ `, + ) + .add( + 'Common locales', + () => html` + +

Formatted value is ${value}

+ + + + + + + + + + ${['en-GB', 'en-US', 'nl-NL', 'nl-BE', 'fr-FR', 'de-DE'].map( + locale => html` + + + + + + `, + )} + +
LocaleOutput EuroOutput US Dollar
${locale}${formatNumber(value, { locale, style: 'currency', currency: 'EUR' })}${formatNumber(value, { locale, style: 'currency', currency: 'USD' })}
+ `, + ); diff --git a/packages/localize/stories/translations/en-AU.js b/packages/localize/stories/translations/en-AU.js index 0e19c3d57..9300e50da 100644 --- a/packages/localize/stories/translations/en-AU.js +++ b/packages/localize/stories/translations/en-AU.js @@ -2,6 +2,5 @@ import en from './en.js'; export default { ...en, - headerDate: 'en-AU: Date & Time', - headerNumber: 'en-AU: Number formatting', + body: 'I am from Australia', }; diff --git a/packages/localize/stories/translations/en-GB.js b/packages/localize/stories/translations/en-GB.js index 052832e93..261ddad38 100644 --- a/packages/localize/stories/translations/en-GB.js +++ b/packages/localize/stories/translations/en-GB.js @@ -2,6 +2,5 @@ import en from './en.js'; export default { ...en, - headerDate: 'en-GB: Date & Time', - headerNumber: 'en-GB: Number formatting', + body: 'I am from England', }; diff --git a/packages/localize/stories/translations/en-US.js b/packages/localize/stories/translations/en-US.js index 39ba5f94b..0caa1a031 100644 --- a/packages/localize/stories/translations/en-US.js +++ b/packages/localize/stories/translations/en-US.js @@ -2,6 +2,5 @@ import en from './en.js'; export default { ...en, - headerDate: 'en-US: Date & Time', - headerNumber: 'en-US: Number formatting', + body: 'I am from the USA', }; diff --git a/packages/localize/stories/translations/en.js b/packages/localize/stories/translations/en.js index 6246e1657..c1ec9eb55 100644 --- a/packages/localize/stories/translations/en.js +++ b/packages/localize/stories/translations/en.js @@ -1,6 +1,4 @@ export default { - headerDate: 'en: Date & Time', - headerNumber: 'en: Number formatting', - date: 'Today is {now, date, full}.', - time: 'Time is {now, time, full}.', + header: '{ locale }: Localize message example', + body: 'I am English', }; diff --git a/packages/localize/stories/translations/nl-BE.js b/packages/localize/stories/translations/nl-BE.js index ac8931873..2eb8bc771 100644 --- a/packages/localize/stories/translations/nl-BE.js +++ b/packages/localize/stories/translations/nl-BE.js @@ -2,6 +2,5 @@ import nl from './nl.js'; export default { ...nl, - headerDate: 'nl-BE: Datum en tijd', - headerNumber: 'nl-BE: Nummer formatting', + body: 'Ik kom uit Belgie', }; diff --git a/packages/localize/stories/translations/nl-NL.js b/packages/localize/stories/translations/nl-NL.js index 941bf999d..0969817f8 100644 --- a/packages/localize/stories/translations/nl-NL.js +++ b/packages/localize/stories/translations/nl-NL.js @@ -2,6 +2,5 @@ import nl from './nl.js'; export default { ...nl, - headerDate: 'nl-NL: Datum en tijd', - headerNumber: 'nl-NL: Nummer formatting', + body: 'Ik kom uit Nederland', }; diff --git a/packages/localize/stories/translations/nl.js b/packages/localize/stories/translations/nl.js index 595219dda..e2da5015d 100644 --- a/packages/localize/stories/translations/nl.js +++ b/packages/localize/stories/translations/nl.js @@ -1,6 +1,4 @@ export default { - headerDate: 'nl: Datum en tijd', - headerNumber: 'nl: Nummer formatting', - date: 'Vandaag is {now, date, full}.', - time: 'Tijd is {now, time, full}.', + header: '{ locale }: Localize message voorbeeld', + body: 'Ik kom uit Nederland', }; diff --git a/packages/localize/test/number/formatNumber.test.js b/packages/localize/test/number/formatNumber.test.js index ae77c709e..03c817a64 100644 --- a/packages/localize/test/number/formatNumber.test.js +++ b/packages/localize/test/number/formatNumber.test.js @@ -24,7 +24,7 @@ describe('formatNumber', () => { it('can display currency as symbol', () => { 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('US$123,456.79'); }); it('uses minus U+2212 (and not dash) to indicate negative numbers ', () => { @@ -187,8 +187,8 @@ describe('formatNumber', () => { 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'); - 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('USD'))).to.equal('US$123,456.79'); + expect(formatNumber(123456.789, currencySymbol('JPY'))).to.equal('JP¥123,457'); }); }); @@ -223,8 +223,8 @@ describe('formatNumber', () => { 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'); - 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('USD'))).to.equal('US$123,456.79'); + expect(formatNumber(123456.789, currencySymbol('JPY'))).to.equal('JP¥123,457'); }); }); @@ -235,8 +235,8 @@ describe('formatNumber', () => { expect(formatNumber(123456.789, currencyCode('USD'))).to.equal('123.456,79 USD'); expect(formatNumber(123456.789, currencyCode('JPY'))).to.equal('123.457 JPY'); 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('JPY'))).to.equal('¥ 123.457'); + expect(formatNumber(123456.789, currencySymbol('USD'))).to.equal('US$ 123.456,79'); + expect(formatNumber(123456.789, currencySymbol('JPY'))).to.equal('JP¥ 123.457'); }); }); @@ -247,8 +247,8 @@ describe('formatNumber', () => { expect(formatNumber(123456.789, currencyCode('USD'))).to.equal('123.456,79 USD'); expect(formatNumber(123456.789, currencyCode('JPY'))).to.equal('123.457 JPY'); 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('JPY'))).to.equal('¥ 123.457'); + expect(formatNumber(123456.789, currencySymbol('USD'))).to.equal('US$ 123.456,79'); + expect(formatNumber(123456.789, currencySymbol('JPY'))).to.equal('JP¥ 123.457'); }); }); @@ -259,19 +259,19 @@ describe('formatNumber', () => { expect(formatNumber(123456.789, currencyCode('USD'))).to.equal('123 456,79 USD'); expect(formatNumber(123456.789, currencyCode('JPY'))).to.equal('123 457 JPY'); 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 $US'); expect(formatNumber(123456.789, currencySymbol('JPY'))).to.equal('123 457 ¥'); }); }); describe('fr-BE', () => { it('supports basics', () => { - localize.locale = 'fr-FR'; + localize.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'); expect(formatNumber(123456.789, currencyCode('JPY'))).to.equal('123 457 JPY'); 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 $US'); expect(formatNumber(123456.789, currencySymbol('JPY'))).to.equal('123 457 ¥'); }); }); @@ -293,5 +293,19 @@ describe('formatNumber', () => { expect(formatNumber(1234.567, currencyCode('EUR'))).to.equal('1 234,57 EUR'); }); }); + + describe('cs-CZ', () => { + it('supports basics', () => { + localize.locale = 'cs-CZ'; + 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('JPY'))).to.equal('123 457 JPY'); + expect(formatNumber(123456.789, currencyCode('CZK'))).to.equal('123 456,79 CZK'); + expect(formatNumber(123456.789, currencySymbol('EUR'))).to.equal('123 456,79 €'); + expect(formatNumber(123456.789, currencySymbol('USD'))).to.equal('123 456,79 US$'); + expect(formatNumber(123456.789, currencySymbol('JPY'))).to.equal('123 457 JP¥'); + expect(formatNumber(123456.789, currencySymbol('CZK'))).to.equal('123 456,79 Kč'); + }); + }); }); }); diff --git a/packages/localize/test/number/formatNumberToParts.test.js b/packages/localize/test/number/formatNumberToParts.test.js index 96aec103e..d3aa21a42 100644 --- a/packages/localize/test/number/formatNumberToParts.test.js +++ b/packages/localize/test/number/formatNumberToParts.test.js @@ -17,7 +17,34 @@ const stringifyParts = parts => parts.map(part => part.value).join(''); describe('formatNumberToParts', () => { afterEach(localizeTearDown); - describe("style: 'currency'", () => { + describe("style: 'currency symbol'", () => { + const specs = [ + ['en-GB', 'EUR', 1234.5, [c('€'), i('1'), g(','), i('234'), d('.'), f('50')]], + ['en-GB', 'USD', 1234.5, [c('US$'), i('1'), g(','), i('234'), d('.'), f('50')]], + ['nl-NL', 'EUR', 1234.5, [c('€'), l(' '), i('1'), g('.'), i('234'), d(','), f('50')]], + ['nl-NL', 'USD', 1234.5, [c('US$'), l(' '), i('1'), g('.'), i('234'), d(','), f('50')]], + ['nl-BE', 'EUR', 1234.5, [c('€'), l(' '), i('1'), g('.'), i('234'), d(','), f('50')]], + ['nl-BE', 'USD', 1234.5, [c('US$'), l(' '), i('1'), g('.'), i('234'), d(','), f('50')]], + ['fr-FR', 'EUR', 1234.5, [i('1'), g(' '), i('234'), d(','), f('50'), l(' '), c('€')]], + ['fr-FR', 'USD', 1234.5, [i('1'), g(' '), i('234'), d(','), f('50'), l(' '), c('$US')]], + ['fr-BE', 'EUR', 1234.5, [i('1'), g(' '), i('234'), d(','), f('50'), l(' '), c('€')]], + ['fr-BE', 'USD', 1234.5, [i('1'), g(' '), i('234'), d(','), f('50'), l(' '), c('$US')]], + ]; + + specs.forEach(([locale, currency, amount, expectedResult]) => { + it(`formats ${locale} ${currency} ${amount} as "${stringifyParts(expectedResult)}"`, () => { + localize.locale = locale; + expect( + formatNumberToParts(amount, { + style: 'currency', + currency, + }), + ).to.deep.equal(expectedResult); + }); + }); + }); + + describe("style: 'currency code'", () => { const specs = [ ['en-GB', 'EUR', 1234.5, [c('EUR'), l(' '), i('1'), g(','), i('234'), d('.'), f('50')]], ['en-GB', 'EUR', -1234.5, [m, c('EUR'), l(' '), i('1'), g(','), i('234'), d('.'), f('50')]],