Skip to content

Instantly share code, notes, and snippets.

@georgiee
Last active September 15, 2023 08:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save georgiee/3dad946733779d0b30c58f7d24270319 to your computer and use it in GitHub Desktop.
Save georgiee/3dad946733779d0b30c58f7d24270319 to your computer and use it in GitHub Desktop.
Browser Localization Issues with input[type=numeric]

Intro

Questions to answer:

  • How does a numeric input handle locales?
  • How can I determine the output?
  • How can I change it?

Innocent questions but it's a wild ride.

Description

Regarding input involved we're dealing with this standard: https://html.spec.whatwg.org/multipage/input.html#number-state-(type=number)

Where the locale representation is not really defined. Browser vendors are only "encouraged". And the language can be detected either through given lang attribute (on html or the input itself) or use the users's preferred locale. Whatever this now means.

Browsers are encouraged to use user interfaces that present dates, times, and numbers according to the conventions of either the locale implied by the input element's language or the user's preferred locale. Using the page's locale will ensure consistency with page-provided data.

Of course browsers have different interpretations of this and now we suffer from different representations depending on the combination of browser and language settings.

Environment:

  • My OS is OSX v12.3, with the language set to English and the region to German (which brings the decimal separator config on the OS level)
  • My browsers have all set English as the preferred language if possible.
  • Firefox has the optiont to use the OS settings to format number disabled (tried that without reliable results so I pinned this)

I've prepared a codepen for analysis. There you'll find three inputs showing the value 555.55. The first input uses default language, the next tries to override it with en and the third one tries to set de. In addition I output a few values in the console from the Number.toLocaleString(), a related technology but not strictly bound to inputs. Find screenshots from the results attached to this gist.

The thing you will see is irritating.

  1. Chrome render the input with the correct decimal separator. Its heuristic recognizes the German region. Chromes it ignores the lang attribute. The standard doesn't set this as a requirement, so standard-wise that's okay but takes the only option to influence the output. Surprisingly the detected language is en-GB. So English with the region GB while I would have expected en-DE.

  2. Firefox uses a dot as the decimal separator. Its heuristic somehow recognizes English as the region. On the bright side, you can use lang to override it and a lang value of de convinces firefox to use a comma. Confusingly the language detected is en-DE so Firefox must give the language (en) a higher priority then the region (DE) ?

  3. Safari Safari behaves the opposite of Chrome. Instead of commas dots all the way ignoring the lang values like Chrome but somehow identifying English the the correct locale. Similar to Chrome it finds en-GB and within those aspects it's more correct than Chrome.

  4. Edge (Windows) Not much surprising. Identical result to Chrome as it uses the same engine. The detected language are different as it's a virtual environment. The language of the OS is set to English but region is German. The detected language is de or de-DE (using the datetimeformat resolver). The involved languages are almost opposites (en-GB vs de-DE) but the browsers show the same result: a comma. That's a sign that the browser uses a heuristic which doesn't expose its detected language through the involved apis (navigator, resolveOptions of intl)

The results are disturbing because the automatic heuristic of the browsers are different (Firefox & Safari yield a dot, while Chrome & Edge yield the command) and if that wouldn't be bad you can't reliable set/enforce the locale as lang is only respected by Firefox.

If you look at the toLocaleString outputs in the console you will see that the browsers yield different results too. That's kind of expected if you check the standards. Mozilla speaks of "language-sensitive" and tc39 of host environment locale whatever this means.

The toLocaleString() method of Number values returns a string with a language-sensitive representation of this number. Reference

Funny enough tc39 defines it a little bit more different using the words "current locale" whatever this means

This method produces a String value that represents this Number value formatted according to the conventions of the host environment's current locale.

Reference

The results: Firefox: Input shows dot while toLocaleString shows the comma. Contradicting results probably due to different heursistics. Worse the detetced language is en but Firefox decides to output the command matching the region. Doesn't fit the defention of being language-sensitive.

Chrome: Outputs a dot which is different from the input. The language-senstive part of the standard is adhered as the recongized language throug the navigator is en

Safari: Same result as the input and fits the expectation language-sensitive from the standard.

Edge: Outputs a comma which is the same as the input. Detected language is de so it fits that part too.


That's it. It's a mess. I don't think that any production application that relies on proper localization can work without any form of workarounds

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment