20

In my application there are several places where the user is expected to enter a monetary value. The application supports storing these monetary values in multiple currencies as well as localization.

I'm using the Intl.NumberFormat object in Javascript to format a number into any currency and locale I need, but there's no way to unformat the number using that.

All of the libraries I've found so far require you to provide the decimal and thousands separators in order for the formatting/unformatting functions to work. However, I need a way to find what the decimal and thousands separators are in the first place so I can't use those.

How can I reliably get the decimal separator for the current locale?

Sergei
  • 241
  • 1
  • 2
  • 8
  • 1
    Here's a [nice library](http://openexchangerates.github.io/accounting.js) which can do that. – Derek 朕會功夫 Oct 15 '15 at 22:14
  • I've reworded the question to be less opinion based, and hopefully provide a clearer picture of what I'm trying to achieve. The accounting.js library is indeed pretty good, but it still requires me to know what the separators are for the locale, and I don't know how to do that. – Sergei Oct 16 '15 at 14:52

1 Answers1

45

Option 1: using Intl.NumberFormat#formatToParts

Most reliable method, only works for browsers supporting the Intl API. Otherwise it requires an Intl polyfill

function getDecimalSeparator(locale) {
    const numberWithDecimalSeparator = 1.1;
    return Intl.NumberFormat(locale)
        .formatToParts(numberWithDecimalSeparator)
        .find(part => part.type === 'decimal')
        .value;
}

Option 2: using toLocaleString

Less elegant, it relies on the fact that a separator is always one character long, which seems to be the case for all languages: Decimal separator - Wikipedia

function getDecimalSeparator(locale) {
    const numberWithDecimalSeparator = 1.1;

    return numberWithDecimalSeparator
        .toLocaleString(locale)
        .substring(1, 2);
}

This has been suggested here: With a browser, how do I know which decimal separator that the client is using?

Examples:

> getDecimalSeparator()
"."
> getDecimalSeparator('fr-FR')
","

Bonus of option 1:

We could extend it to retrieve either the decimal or group separator of a given locale:

function getSeparator(locale, separatorType) {
        const numberWithGroupAndDecimalSeparator = 1000.1;
        return Intl.NumberFormat(locale)
            .formatToParts(numberWithGroupAndDecimalSeparator)
            .find(part => part.type === separatorType)
            .value;
    }

Examples:

> getSeparator('en-US', 'decimal')
"."
> getSeparator('en-US', 'group')
","
> getSeparator('fr-FR', 'decimal')
","
> getSeparator('fr-FR', 'group')
" "
JBE
  • 11,917
  • 7
  • 49
  • 51
  • This code almost worked for me, but it would not find the group separator if I used the number 1000.1 from the example. When I used 10000.1 it worked. – Nathan May 30 '21 at 20:50