andyearnshaw / Intl.js

Compatibility implementation of the ECMAScript Internationalization API (ECMA-402) for JavaScript -- UNMAINTAINED
Other
1.7k stars 215 forks source link

Improper spacing with Intl.NumberFormat(..., {style: currency, ...})? #221

Open belden opened 8 years ago

belden commented 8 years ago

Why does the following code not put a space after PYG?

new Intl.NumberFormat('es-MX', {style: 'currency', currency: 'PYG'}).format(12345);
// "PYG12,345"

This missing space occurs with:

The CLDR definition for ¤ says:

This will be replaced by a currency symbol, such as $ or USD. Note: by default a space is automatically added between letters in a currency symbol and adjacent numbers. So you don't need to add a space between them if your language writes "$12" but "USD 12".

(emphasis mine)

The relevant section from the CLDR data files for es-MX seems to come from es_419.xml:

<currencyFormats numberSystem="latn">
        <currencyFormatLength>
                <currencyFormat type="standard">
                        <pattern>¤#,##0.00</pattern>
                </currencyFormat>
                <currencyFormat type="accounting">
                        <pattern>¤#,##0.00</pattern>
                </currencyFormat>
        </currencyFormatLength>
</currencyFormats>

It appears from the quoted document above that the intent of the line <pattern>¤#,##0.00</pattern> is that the above JavaScript should show PYG 12,345.

Why does the output of this library, and the native Intl libraries, not include the space after PYG?

caridy commented 7 years ago

@belden this is very interesting. we can definitely follow up with vendors to make sure that they do the right thing, and we can fix the polyfill for sure. I will keep you posted.

/cc @reiniergs this is the answer to your question from few days ago. As @belden as pointed out, the space can be added when using the currency code.

caridy commented 7 years ago

This is more complicated that expected. We have PR #254 trying to address this issue but another case popped as part of the testing of that PR. Specifically, there are locales in CLDR that already contain the space between adjacent currency code and value, and others that doesn't, but there is not a clear rule on when to add the space. It seems to me that it is related to the position in the skeleton, and we might need some clarification of the rule.

The following example doesn't have an space in CLDR, and it is not added by the browsers neither.

new Intl.NumberFormat('bn', {
    style: 'currency',
    currency: 'BDT',
    currencyDisplay: 'code',
}).format(12345)
"১২,৩৪৫.০০BDT"

While others have the space defined in CLDR directly, e.g.:

new Intl.NumberFormat('cs', {
    style: 'currency',
    currency: 'CSK',
    currencyDisplay: 'code',
}).format(12345)
"12\xa0345,00\xa0CSK"

Empirically, I'm adding spaces when currency symbol exist (before the value). We need more validation around this, and probably loop-in some CLDR folks in case we are missing something obvious here. /cc @srl295 @JCEmmons

I have added few tests to the suite to validate this approach:

https://github.com/andyearnshaw/Intl.js/pull/254/files#diff-0a263d09c0a1a696efaf1aa4c7dcf064

caridy commented 7 years ago

ping @srl295 @JCEmmons @zbraniecki

bojanz commented 6 years ago

Any updates on this? I have the same bug in my reimplementation of number formatting in PHP, would love to know the correct approach. The currencySpacing rules are a bit hard to read.