Here’s my test codes running from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat
const number = 123456.789;
const locale = new Intl.Locale('en-DE', { region: 'DE' });
console.log(new Intl.NumberFormat(locale, { style: 'currency', currency: 'EUR' }).format(number));
console.log(new Intl.NumberFormat('en-DE', { style: 'currency', currency: 'EUR' }).format(number));
console.log(new Intl.NumberFormat(locale).format(number));
console.log(new Intl.NumberFormat('en-DE').format(number));
In Safari, it outputs the following results:
> "123.456,79 €"
> "123.456,79 €"
> "123.456,789"
> "123.456,789"
In Chrome, it outputs the following:
> "€123,456.79"
> "€123,456.79"
> "123.456,789"
> "123.456,789"
Language locale is "English(Germany)", region is "Germany". The expectation is that the number should be formatted by region which is Germany. Safari appears to be correct and consistent between currency number and non-currency number. In Chrome however, the currency number is displayed in English format while the non-currency number is displayed in German format.
What is more troubling for me is that the exact behavior is mirrored in React Native. In iOS the result is the same as in Safari, while in Android the result is the same as in Chrome.
Any suggestions for a fix or workaround, especially on the React Native side?
2
Answers
I ended up with a workaround by using the
@ladjs/country-language
library. I take the country code and then query the language code of the country to format the locale code to be usedIntl.NumberFormat
API.Example: For English(Germany)
en-DE
, I get the country codeDE
. Queryingcountry-language
library I getde
as the language code. So I combine them to get the localede-DE
to be passed toIntl.NumberFormat
.Some countries have multiple languages, I try to use the one that matches the device language. If no match, just use the first in the array.
I filed: https://bugs.webkit.org/show_bug.cgi?id=252239
https://cldr.unicode.org/translation/number-currency-formats/number-symbols
"For English regional locales (e.g. en_DE) where English is not the primary language of the country/region (e.g. en_DE; English as used in Germany), the number formats and date formats should follow the English formatting usage in that country/region. Often, the formatting usage in English tend to follow the British or American formatting rather than the formatting of the primary language. Consult with the English versions of prominent magazines or newspapers for guidance on date and number format usage."
Steps to Reproduce:
Number(‘1234.5’).toLocaleString(‘en-DE’, {style: ‘currency’, currency: ‘EUR’});
Expected behavior:
Returns ‘€1,234.50’ (same as V8 and SpiderMonkey)
Actual behavior:
Returns ‘1.234,50 €’