Click here to Skip to main content
Click here to Skip to main content

Detecting User Regional Settings In The Web Browser

, 31 May 2010
Rate this:
Please Sign up or sign in to vote.
Detecting User Regional Settings In The Web Browser
free hit counters

Recently, a friend of mine asked me something like: “How do I get the user’s regional settings for a request to a web server?”

As far as I know, web browser only sends an Accept-Language HTTP header and nothing more. You can take this and use the default regional settings for that language but, if your user is anything like me, you’ll be wrong.

So, what’s the problem of getting it wrong?

If you are just generating HTML and keep it consistent, nothing’s wrong. But what if your user wants to copy some numeric and/or date values to, say, Excel? Or if you want to export some data as a CSV file?

A solution

Going through the JScript Language Reference, I found that both Number and Date have locale related toString methods and I started playing with them.

Numeric format settings

To the numeric format settings, first we need a number that will behave in a predictable manner in any culture (“any culture” means “any culture I know”) and for all possible settings and convert it to a string using the toLocaleString method:

var number = 111111111.111111111;
var numberString = number.toLocaleString();

(With my regional settings, numberString becomes 111 111 111.11)

To get the decimal separator, all it takes is getting the first non 1 from the end:

var decimalSeparator;
var decimalDigits;
for (var i = numberString.length - 1; i >= 0; i--) {
    var char = numberString.charAt(i);
    if (char != "1") {
        decimalSeparator = char;
        decimalDigits = numberString.length - i - 1;
        break;
    }
}

And if you count how many 1s were skipped, we get the number of decimal digits.

In a similar way, the first non 1 will be the digit grouping separator:

var groupSeparator;
for (var i = 0; i < numberString.length; i++) {
    var char = numberString.charAt(i);
    if (char != "1") {
        groupSeparator = char;
        break;
    }
}

Now that we have the digit grouping separator, we can get the digit groups (these groups might not all have the same size):

var digitGrouping = numberString.substring(0, 
    numberString.length - decimalDigits - 1).split(groupSeparator);
for (g in digitGrouping) {
    digitGrouping[g] = digitGrouping[g].length;
}
Date and time settings

Date and time values are more difficult to parse and you might not need all information. So, I’ll just get the value and let the parsing to you:

var dateTime = new Date(9999, 11, 31, 23, 30, 45);
dateTimeString = dateTime.toLocaleString();
List settings

The last setting is the list separator (very useful for those CSV files):

var list = ["a", "b"];
listSeparator = list.toLocaleString().substring(1, 2);

Test page

Here is a test page that gets all these settings:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
    <title>Test Page</title>
    <style type="text/css">
        label  { width: 8em; text-align: right; 
    padding-right: 0.5em; white-space: nowrap; }
        span { border: 1px solid; white-space: nowrap; }
    </style>
    <script type="text/javascript">
        function init() {
            document.all.userLanguage.innerText = window.navigator.userLanguage;
            document.all.systemLanguage.innerText = window.navigator.systemLanguage;

            // Decimal separator and decimal digits
            var number = 111111111.111111111;
            var numberString = (111111111.111111111).toLocaleString();

            var decimalSeparator;
            var decimalDigits;
            for (var i = numberString.length - 1; i >= 0; i--) {
                var char = numberString.charAt(i);
                if (char != "1") {
                    decimalSeparator = char;
                    decimalDigits = numberString.length - i - 1;
                    break;
                }
            }
            document.all.decimalSeparator.innerText = decimalSeparator;
            document.all.decimalDigits.innerText = decimalDigits;

            // Digit grouping separator and digit goups
            var groupSeparator;
            for (var i = 0; i < numberString.length; i++) {
                var char = numberString.charAt(i);
                if (char != "1") {
                    groupSeparator = char;
                    break;
                }
            }
            document.all.groupSeparator.innerText = groupSeparator;

            var digitGrouping = numberString.substring(0, 
        numberString.length - decimalDigits - 1).split(groupSeparator);
            for (g in digitGrouping) {
                digitGrouping[g] = digitGrouping[g].length;
            }
            document.all.digitGrouping.innerText = digitGrouping.toString();

            // Date format
            var dateTime = new Date(9999, 11, 31, 23, 30, 45);
            var dateTimeString = dateTime.toLocaleString();
            document.all.dateTimeFormat.innerText = dateTimeString;

            // List separator
            var list = ["a", "b"];
            var listSeparator = list.toLocaleString().substring(1, 2);
            document.all.listSeparator.innerText = listSeparator;
        }
    </script>
</head>
<body onload="init()">
    <p><label for="userLanguage">User language:</label>
        <span id="userLanguage"></span></p>
    <p><label for="systemLanguage">System language:</label>
        <span id="systemLanguage"></span></p>
    <p><label for="decimalSeparator">Decimal separator:</label>
        <span id="decimalSeparator"></span></p>
    <p><label for="decimalDigits">Decimal digits:</label>
        <span id="decimalDigits"></span></p>
    <p><label for="groupSeparator">Digit separator:</label>
        <span id="groupSeparator"></span></p>
    <p><label for="digitGrouping">Digit grouping:</label>
        <span id="digitGrouping"></span></p>
    <p><label for="dateTimeFormat">Date/Time format:</label>
        <span id="dateTimeFormat"></span></p>
    <p><label for="listSeparator">List separator:</label>
        <span id="listSeparator"></span></p>
</body>
</html>

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Paulo Morgado
Software Developer (Senior) Paulo Morgado
Portugal Portugal

Comments and Discussions

 
GeneralArray.toLocalString() works only on IE PinmemberGinni Benjamin28-Mar-11 22:47 
GeneralRe: Array.toLocalString() works only on IE PinmemberPaulo Morgado29-Mar-11 5:57 
GeneralinnerText is IE-specific PinmemberDaniel15au10-May-10 18:24 
GeneralRe: innerText is IE-specific PinmemberPaulo Morgado11-May-10 12:36 
GeneralRe: innerText is IE-specific Pinmemberzpaulo_carraca9-Jun-10 0:12 
GeneralRe: innerText is IE-specific PinmemberPaulo Morgado10-Jun-10 14:54 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140709.1 | Last Updated 31 May 2010
Article Copyright 2010 by Paulo Morgado
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid