Merge pull request #292 from ing-bank/fix/currency-symbols
Fix/currency symbols
This commit is contained in:
commit
93f631c785
15 changed files with 374 additions and 266 deletions
|
|
@ -26,16 +26,12 @@ export function formatNumberToParts(number, options) {
|
||||||
}
|
}
|
||||||
let formattedParts = [];
|
let formattedParts = [];
|
||||||
const formattedNumber = Intl.NumberFormat(computedLocale, options).format(parsedNumber);
|
const formattedNumber = Intl.NumberFormat(computedLocale, options).format(parsedNumber);
|
||||||
const regexSymbol = /[A-Z.,\s0-9]/;
|
const regexCurrency = /[.,\s0-9]/;
|
||||||
const regexCode = /[A-Z]/;
|
const regexMinusSign = /[-]/; // U+002D, Hyphen-Minus, -
|
||||||
|
|
||||||
// U+002D, Hyphen-Minus, -
|
|
||||||
const regexMinusSign = /[-]/;
|
|
||||||
|
|
||||||
const regexNum = /[0-9]/;
|
const regexNum = /[0-9]/;
|
||||||
const regexSeparator = /[.,]/;
|
const regexSeparator = /[.,]/;
|
||||||
const regexSpace = /[\s]/;
|
const regexSpace = /[\s]/;
|
||||||
let currencyCode = '';
|
let currency = '';
|
||||||
let numberPart = '';
|
let numberPart = '';
|
||||||
let fraction = false;
|
let fraction = false;
|
||||||
for (let i = 0; i < formattedNumber.length; i += 1) {
|
for (let i = 0; i < formattedNumber.length; i += 1) {
|
||||||
|
|
@ -47,34 +43,17 @@ export function formatNumberToParts(number, options) {
|
||||||
if (regexNum.test(formattedNumber[i])) {
|
if (regexNum.test(formattedNumber[i])) {
|
||||||
numberPart += formattedNumber[i];
|
numberPart += formattedNumber[i];
|
||||||
}
|
}
|
||||||
// detect currency symbol
|
|
||||||
if (!regexSymbol.test(formattedNumber[i]) && !regexMinusSign.test(formattedNumber[i])) {
|
// detect currency (symbol or code)
|
||||||
// Write number grouping
|
if (!regexCurrency.test(formattedNumber[i]) && !regexMinusSign.test(formattedNumber[i])) {
|
||||||
if (numberPart && !fraction) {
|
currency += formattedNumber[i];
|
||||||
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 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
|
// detect dot and comma separators
|
||||||
if (regexSeparator.test(formattedNumber[i])) {
|
if (regexSeparator.test(formattedNumber[i])) {
|
||||||
// Write number grouping
|
// Write number grouping
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ export function normalizeIntl(formattedParts, options, _locale) {
|
||||||
normalize = forceSpaceInsteadOfZeroForGroup(normalize);
|
normalize = forceSpaceInsteadOfZeroForGroup(normalize);
|
||||||
}
|
}
|
||||||
// Force space between currency code and number
|
// 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);
|
normalize = forceSpaceBetweenCurrencyCodeAndNumber(normalize, options);
|
||||||
}
|
}
|
||||||
// Force missing Japanese Yen symbol
|
// Force missing Japanese Yen symbol
|
||||||
|
|
|
||||||
72
packages/localize/stories/date.stories.js
Normal file
72
packages/localize/stories/date.stories.js
Normal file
|
|
@ -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`
|
||||||
|
<style>
|
||||||
|
${formatDateDemoStyle}
|
||||||
|
</style>
|
||||||
|
<table class="demo-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Options</th>
|
||||||
|
<th>Code</th>
|
||||||
|
<th>Output</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Default</td>
|
||||||
|
<td><code>formatDate(new Date())</code></td>
|
||||||
|
<td>${formatDate(new Date())}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Date display</td>
|
||||||
|
<td>
|
||||||
|
<code
|
||||||
|
>formatDate(new
|
||||||
|
Date(){weekday:'long',year:'numeric',month:'long',day:'2-digit'})</code
|
||||||
|
>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
${formatDate(new Date(), {
|
||||||
|
weekday: 'long',
|
||||||
|
year: 'numeric',
|
||||||
|
month: 'long',
|
||||||
|
day: '2-digit',
|
||||||
|
})}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Locale</td>
|
||||||
|
<td><code>formatDate(new Date(){locale:'nl-NL'})</code></td>
|
||||||
|
<td>${formatDate(new Date(), { locale: 'nl-NL' })}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
`,
|
||||||
|
);
|
||||||
|
|
@ -1,201 +1,3 @@
|
||||||
import { storiesOf, html } from '@open-wc/demoing-storybook';
|
import './message.stories.js';
|
||||||
|
import './number.stories.js';
|
||||||
import { html as litHtml } from '@lion/core';
|
import './date.stories.js';
|
||||||
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`
|
|
||||||
<h2>${headerDate}</h2>
|
|
||||||
<div>${date}</div>
|
|
||||||
<div>Order of date parts: ${dateFormat}</div>
|
|
||||||
<div>Parsed date (01-05-2012): ${dateFormat1}</div>
|
|
||||||
<div>Parsed date (12/05/2012): ${dateFormat2}</div>
|
|
||||||
<div>Parsed date (1/5/2017) : ${dateFormat3}</div>
|
|
||||||
<div>Japanese date: ${dateFormatted}</div>
|
|
||||||
<div>${time}</div>
|
|
||||||
<h2>${headerNumber}</h2>
|
|
||||||
<div>${number1} ${printParts1}</div>
|
|
||||||
<div>${number2} ${printParts2}</div>
|
|
||||||
<div>${number3} ${printParts3}</div>
|
|
||||||
<div>getGroupSeparator(): "${printGroupSeparator}"</div>
|
|
||||||
<div>getDecimalSeparator(): "${printDecimalSeparator}"</div>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!customElements.get('lit-html-example')) {
|
|
||||||
customElements.define('lit-html-example', LitHtmlExample);
|
|
||||||
}
|
|
||||||
|
|
||||||
return html`
|
|
||||||
<lit-html-example .now=${new Date()}></lit-html-example>
|
|
||||||
<button
|
|
||||||
@click=${() => {
|
|
||||||
localize.locale = 'en-GB';
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
en-GB
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
@click=${() => {
|
|
||||||
localize.locale = 'en-US';
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
en-US
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
@click=${() => {
|
|
||||||
localize.locale = 'en-AU';
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
en-AU
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
@click=${() => {
|
|
||||||
localize.locale = 'nl-NL';
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
nl-NL
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
@click=${() => {
|
|
||||||
localize.locale = 'nl-BE';
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
nl-BE
|
|
||||||
</button>
|
|
||||||
`;
|
|
||||||
});
|
|
||||||
// .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`
|
|
||||||
// <p>try 'demo:bar' as well</p>
|
|
||||||
// <input type="text" value="demo:foo" id="keyInput">
|
|
||||||
//
|
|
||||||
// <button @click=${() => console.log(localize.msg(keyInput.value))}>
|
|
||||||
// Translate to Action Logger
|
|
||||||
// </button>
|
|
||||||
// <br />
|
|
||||||
// <button @click=${() => { localize.locale = 'en'; }}>en</button>
|
|
||||||
// <button @click=${() => { localize.locale = 'en-GB'; }}>en-GB</button>
|
|
||||||
// <br /><br />
|
|
||||||
// <button @click=${() => console.log(localize.__storage)}>
|
|
||||||
// Log available Data to Action Logger
|
|
||||||
// </button>
|
|
||||||
// `;
|
|
||||||
|
|
|
||||||
65
packages/localize/stories/message.stories.js
Normal file
65
packages/localize/stories/message.stories.js
Normal file
|
|
@ -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`
|
||||||
|
<div aria-live="polite">
|
||||||
|
<h1>${this.msgLit('lit-html-example:header', { locale: localize.locale })}</h1>
|
||||||
|
<p>${this.msgLit('lit-html-example:body')}</p>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!customElements.get('message-example')) {
|
||||||
|
customElements.define('message-example', messageExample);
|
||||||
|
}
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<button
|
||||||
|
@click=${() => {
|
||||||
|
localize.locale = 'en-GB';
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
en-GB
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
@click=${() => {
|
||||||
|
localize.locale = 'en-US';
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
en-US
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
@click=${() => {
|
||||||
|
localize.locale = 'en-AU';
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
en-AU
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
@click=${() => {
|
||||||
|
localize.locale = 'nl-NL';
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
nl-NL
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
@click=${() => {
|
||||||
|
localize.locale = 'nl-BE';
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
nl-BE
|
||||||
|
</button>
|
||||||
|
<message-example></message-example>
|
||||||
|
`;
|
||||||
|
});
|
||||||
158
packages/localize/stories/number.stories.js
Normal file
158
packages/localize/stories/number.stories.js
Normal file
|
|
@ -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`
|
||||||
|
<style>
|
||||||
|
${formatNumberDemoStyle}
|
||||||
|
</style>
|
||||||
|
<p>Formatted value is ${value}</p>
|
||||||
|
<table class="demo-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Options</th>
|
||||||
|
<th>Code</th>
|
||||||
|
<th>Output</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Default</td>
|
||||||
|
<td></td>
|
||||||
|
<td>${formatNumber(value)}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Currency symbol</td>
|
||||||
|
<td>
|
||||||
|
<code
|
||||||
|
>formatNumber({ style: 'currency', currencyDisplay: 'symbol', currency: 'EUR'
|
||||||
|
})</code
|
||||||
|
>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
${formatNumber(value, {
|
||||||
|
style: 'currency',
|
||||||
|
currencyDisplay: 'symbol',
|
||||||
|
currency: 'EUR',
|
||||||
|
})}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Currency code</td>
|
||||||
|
<td>
|
||||||
|
<code
|
||||||
|
>formatNumber({ style: 'currency', currencyDisplay: 'code', currency: 'EUR' })</code
|
||||||
|
>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
${formatNumber(value, {
|
||||||
|
style: 'currency',
|
||||||
|
currencyDisplay: 'code',
|
||||||
|
currency: 'EUR',
|
||||||
|
})}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Locale</td>
|
||||||
|
<td><code>formatNumber({ locale: 'nl-NL' })</code></td>
|
||||||
|
<td>${formatNumber(value, { locale: 'nl-NL' })}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>No decimals</td>
|
||||||
|
<td>
|
||||||
|
<code>formatNumber({ minimumFractionDigits: 0, maximumFractionDigits: 0, })</code>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
${formatNumber(value, {
|
||||||
|
minimumFractionDigits: 0,
|
||||||
|
maximumFractionDigits: 0,
|
||||||
|
})}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
`,
|
||||||
|
)
|
||||||
|
.add(
|
||||||
|
'formatNumberToParts',
|
||||||
|
() => html`
|
||||||
|
<style>
|
||||||
|
${formatNumberDemoStyle}
|
||||||
|
</style>
|
||||||
|
<p>Formatted value is ${value}</p>
|
||||||
|
<table class="demo-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Part</th>
|
||||||
|
<th>Output</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
${formatNumberToParts(value, { style: 'currency', currency: 'EUR' }).map(
|
||||||
|
part => html`
|
||||||
|
<tr>
|
||||||
|
<td>${part.type}</td>
|
||||||
|
<td>${part.value}</td>
|
||||||
|
</tr>
|
||||||
|
`,
|
||||||
|
)}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
`,
|
||||||
|
)
|
||||||
|
.add(
|
||||||
|
'Common locales',
|
||||||
|
() => html`
|
||||||
|
<style>
|
||||||
|
${formatNumberDemoStyle}
|
||||||
|
</style>
|
||||||
|
<p>Formatted value is ${value}</p>
|
||||||
|
<table class="demo-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Locale</th>
|
||||||
|
<th>Output Euro</th>
|
||||||
|
<th>Output US Dollar</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
${['en-GB', 'en-US', 'nl-NL', 'nl-BE', 'fr-FR', 'de-DE'].map(
|
||||||
|
locale => html`
|
||||||
|
<tr>
|
||||||
|
<td>${locale}</td>
|
||||||
|
<td>${formatNumber(value, { locale, style: 'currency', currency: 'EUR' })}</td>
|
||||||
|
<td>${formatNumber(value, { locale, style: 'currency', currency: 'USD' })}</td>
|
||||||
|
</tr>
|
||||||
|
`,
|
||||||
|
)}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
`,
|
||||||
|
);
|
||||||
|
|
@ -2,6 +2,5 @@ import en from './en.js';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
...en,
|
...en,
|
||||||
headerDate: 'en-AU: Date & Time',
|
body: 'I am from Australia',
|
||||||
headerNumber: 'en-AU: Number formatting',
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,5 @@ import en from './en.js';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
...en,
|
...en,
|
||||||
headerDate: 'en-GB: Date & Time',
|
body: 'I am from England',
|
||||||
headerNumber: 'en-GB: Number formatting',
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,5 @@ import en from './en.js';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
...en,
|
...en,
|
||||||
headerDate: 'en-US: Date & Time',
|
body: 'I am from the USA',
|
||||||
headerNumber: 'en-US: Number formatting',
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,4 @@
|
||||||
export default {
|
export default {
|
||||||
headerDate: 'en: Date & Time',
|
header: '{ locale }: Localize message example',
|
||||||
headerNumber: 'en: Number formatting',
|
body: 'I am English',
|
||||||
date: 'Today is {now, date, full}.',
|
|
||||||
time: 'Time is {now, time, full}.',
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,5 @@ import nl from './nl.js';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
...nl,
|
...nl,
|
||||||
headerDate: 'nl-BE: Datum en tijd',
|
body: 'Ik kom uit Belgie',
|
||||||
headerNumber: 'nl-BE: Nummer formatting',
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,5 @@ import nl from './nl.js';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
...nl,
|
...nl,
|
||||||
headerDate: 'nl-NL: Datum en tijd',
|
body: 'Ik kom uit Nederland',
|
||||||
headerNumber: 'nl-NL: Nummer formatting',
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,4 @@
|
||||||
export default {
|
export default {
|
||||||
headerDate: 'nl: Datum en tijd',
|
header: '{ locale }: Localize message voorbeeld',
|
||||||
headerNumber: 'nl: Nummer formatting',
|
body: 'Ik kom uit Nederland',
|
||||||
date: 'Vandaag is {now, date, full}.',
|
|
||||||
time: 'Tijd is {now, time, full}.',
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ describe('formatNumber', () => {
|
||||||
|
|
||||||
it('can display currency as symbol', () => {
|
it('can display currency as symbol', () => {
|
||||||
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('US$123,456.79');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('uses minus U+2212 (and not dash) to indicate negative numbers ', () => {
|
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('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');
|
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');
|
||||||
expect(formatNumber(123456.789, currencySymbol('JPY'))).to.equal('¥123,457');
|
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('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');
|
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');
|
||||||
expect(formatNumber(123456.789, currencySymbol('JPY'))).to.equal('¥123,457');
|
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('USD'))).to.equal('123.456,79 USD');
|
||||||
expect(formatNumber(123456.789, currencyCode('JPY'))).to.equal('123.457 JPY');
|
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('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');
|
||||||
expect(formatNumber(123456.789, currencySymbol('JPY'))).to.equal('¥ 123.457');
|
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('USD'))).to.equal('123.456,79 USD');
|
||||||
expect(formatNumber(123456.789, currencyCode('JPY'))).to.equal('123.457 JPY');
|
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('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');
|
||||||
expect(formatNumber(123456.789, currencySymbol('JPY'))).to.equal('¥ 123.457');
|
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('USD'))).to.equal('123 456,79 USD');
|
||||||
expect(formatNumber(123456.789, currencyCode('JPY'))).to.equal('123 457 JPY');
|
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('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 ¥');
|
expect(formatNumber(123456.789, currencySymbol('JPY'))).to.equal('123 457 ¥');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('fr-BE', () => {
|
describe('fr-BE', () => {
|
||||||
it('supports basics', () => {
|
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('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');
|
||||||
expect(formatNumber(123456.789, currencyCode('JPY'))).to.equal('123 457 JPY');
|
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('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 ¥');
|
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');
|
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č');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,34 @@ const stringifyParts = parts => parts.map(part => part.value).join('');
|
||||||
describe('formatNumberToParts', () => {
|
describe('formatNumberToParts', () => {
|
||||||
afterEach(localizeTearDown);
|
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 = [
|
const specs = [
|
||||||
['en-GB', 'EUR', 1234.5, [c('EUR'), l(' '), i('1'), g(','), i('234'), d('.'), f('50')]],
|
['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')]],
|
['en-GB', 'EUR', -1234.5, [m, c('EUR'), l(' '), i('1'), g(','), i('234'), d('.'), f('50')]],
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue