3

I have stumbled upon an inconsistency in number formatting for the "km-KH" locale between Firefox, Chrome, and the ASP.NET MVC Core web application.

In Chrome and the ASP.NET MVC Core web application, numbers use the dot for decimal separator and comma for thousands separator. But in Firefox, it is the other way around, which obviously causes a disrepancy.

If one were to paste the following snippet in the browser console:

(1234.56).toLocaleString('km-KH')
// or
new Intl.NumberFormat('km-KH').format(1234.56)

Chrome would render:

"1,234.56"

Firefox would render:

"1.234,56"

My primary question is simple: how to fix this inconsistency?

As far as I can tell, Firefox is misbehaving, while Chrome and ASP.NET MVC Core are working as intended.


Fun fact: there is also an inconsistency in the CLDR definition for the "km" number formatting: https://github.com/unicode-cldr/cldr-numbers-full/blob/master/main/km/numbers.json

Defined symbols are: comma as the decimal separator and dot as the grouping separator

"symbols-numberSystem-latn": {
  "decimal": ",",
  "group": ".",
  // ...
}

But when they specify the decimal format, they use it the other way around:

"decimalFormats-numberSystem-latn": {
  "standard": "#,##0.###",
  // ...
}

Is this an actual bug in the localization definition?

alesc
  • 2,776
  • 3
  • 27
  • 45
  • 1
    Hmm, it seems like an actual bug in Firefox. Perhaps you need to file a bug report with them and then make some sort of patch on your end in the mean time. – VLAZ Sep 30 '19 at 12:18
  • 1
    Just to muddy things further, Internet Explorer 11 outputs `"១,២៣៤.៥៦"`. So apparently whatever DB it's working from disagrees that Latin is the default number system, it prefers to use the "native" one -- but uses `,` for grouping and `.` for decimal, like Chrome. **But**, Edge agrees with...Firefox! Latin numbers (well, Arabic-derived, but...) and `.` for grouping and `,` for decimal. What a mess. – T.J. Crowder Sep 30 '19 at 12:23
  • 1
    Looking for other references online, [opinions](https://lh.2xlibre.net/locale/km_KH/) seem to [differ](http://www.localeplanet.com/icu/km-KH/index.html) on the separators. *sigh* – T.J. Crowder Sep 30 '19 at 12:27
  • @T.J.Crowder: IE doesn't use the latin numbering system by default for `km-KH`. You can override this with: `(1234.56).toLocaleString('km-KH-u-nu-latn')`, which will also be consistent with Chrome. Another point in my case that Firefox is not consistent. – alesc Sep 30 '19 at 13:04
  • @alesc - Perhaps, but with other inconsistent sources out there, one begins to wonder whether asking more than one person in Northern Khmer would get you more than one answer. :-) – T.J. Crowder Sep 30 '19 at 13:30

1 Answers1

0

Since this topic is fairly complex, I don't insist that my answer points to the exact reason but, one of the reasons might be in something from the following.

.toLocaleString is known to work inconsistently between browsers. It happens since there are no particularly strict specifications for this function. Check out this answer.

As @T.J. Crowder correctly points out in his comment, specifications have evolved a lot in newer versions of the ECMA script specifications.

Nevertheless, because of historical or other reasons output of .toLocaleString is still pretty browser-dependent. While it works very consistently for some languages (for instance, in my case the output of locales fr, ru & en-AU was precisely the same across Firefox, Chrome & even Safari), it might differ a lot in case of other languages (in my case locales jp, km-KH & sq-AL had outputted 3 different things in 3 different browsers).

I can't find the reference now, but at some point I've found out that apart from other things, the difference is that Firefox tries to use language preference of your OS meanwhile Chrome uses language preferences set (or auto-detected) specifically in Chrome.

In case if you use (or possibly plan to) SSR, this might provide yet another challenge since depending on your toolset the format might be picked up from the server environment, like it is in Node.js.

If you would like to control the exact format of the output, well, so much loved & appreciated here on SO moment.js may help you with it.

Igor Bykov
  • 2,532
  • 3
  • 11
  • 19
  • *"It happens since there are no particularly strict specifications for this function."* That hasn't been true for years, since **at least** ES2015 (in 2015). It's specified [here](https://tc39.es/ecma262/#sec-object.prototype.tolocalestring) and [here](https://www.ecma-international.org/ecma-402/6.0/index.html#Title). The ES5 specification didn't mention ECMA-402, which is why I say at least since ES2015, which does, but in this case the ES2015 spec was just codifying an already-agreed position. ES2015 just took a long time to finish. – T.J. Crowder Sep 30 '19 at 13:29
  • Even if I use the "proper" way to localize, I get the same inconsistency. For example: `new Intl.NumberFormat('km-KH').format(1234.56)`. Also, auto-detect doesn't apply here, since I clearly specify the actual locale. – alesc Sep 30 '19 at 13:41
  • @alesc Even if you specify the actual locale, it might simply be unsupported by the browser you are checking it in. In this case, it will fail silently defaulting to a locale that is supported in your browser & seemed as a good choice for the browser. Even if locale is supported, its format will be browser-dependent & there's no guarantee it'll work precisely the same. IRL it would be fair enough just to assume some small differences. If the goal's i18n, it will do significantly > good than damage. If you just like a particular format, you'd probably need to consider a library/custom solution. – Igor Bykov Sep 30 '19 at 14:22