<commit_before>{{setTitle "Internationalization in the Browser"}}

<h1>Internationalization in the Browser</h1>

<p>
In the early days of browser development, internationalization would happen most often on the server,
since browsers did not have a standard way of formatting things like dates and numbers based on
the locale of the browser. With more modern browsers we have the benefit of the ECMAScript internationalization
API (<a href="http://www.ecma-international.org/ecma-402/1.0/#sec-8">ECMA-402</a>) which provides
language sensitive string comparison, number formatting, and date and time formatting.
</p>
<p>
This is of great benefit for developers of websites and single page applications where data is often
downloaded dynamically without location specific formatting. The
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl">{{code "Intl"}}</a> object
provides constructors for {{code "Collator"}}, {{code "NumberFormat"}}, and {{code "DateTimeFormat"}}
which give browser developers the basic tools they need for formatting.
</p>
<p>
Here are some examples:
</p>

<h2>Date Formatting</h2>

<p>
You can format dates easily once you create a {{code "Date"}} object and call
the {{code "format"}} method on {{code "Intl.DateTimeFormat"}}.
</p>

{{#code "js"}}
var date = new Date(Date.UTC(2012, 11, 20, 3, 0, 0));
alert(new Intl.DateTimeFormat().format(date));
{{/code}}

Returns "{{code "12/19/2012"}}" if run in the {{code "en-US"}} locale with time zone {{code "America/Los-Angeles"}}.
Using {{code "Intl.DateTimeFormat()"}} with no arguments will use the system's locale and time zone.

{{#code "js"}}
alert(new Intl.DateTimeFormat("en-GB").format(date));
{{/code}}

Returns "{{code "19/11/2012"}}" as British English uses day-month-year order.

{{#code "js"}}
alert(new Intl.DateTimeFormat("ko-KR").format(date));
{{/code}}

Returns "{{code "2012년 12월 19일"}}" as Korean uses year-month-day order.

<p>
You can also format dates and times via the {{code "options"}} argument:
</p>

{{#code "js"}}
var options = {weekday: "long", year: "numeric", month: "long", day: "numeric"};
alert(new Intl.DateTimeFormat("de-DE", options).format(date));
{{/code}}

Returns "{{code "Mittwoch, 19. Dezember 2012"}}" as you requested a weekday along with a long date.

<p>
Note how you have the same date information in {{code "date"}} but specifying a different locale or formatting options
changes the output. You can find out more about date formatting via the Intl specification
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat">here</a>.
<p>

<h2>Number Formatting</h2>

<p>
You can also format numbers in a similar fashion using {{code "Intl.NumberFormat"}}.
</p>

{{#code "js"}}
var number = 123456.789;
alert(new Intl.NumberFormat().format(number));
{{/code}}

Returns "{{code "123,456.789"}}" when in the US English locale.

<p>
As in {{code "Intl.DateTimeFormat"}} you can pass in a specific locale to specify a different language.
</p>


{{#code "js"}}
alert(new Intl.NumberFormat("ar-EG").format(number));
{{/code}}

Returns "{{code "١٢٣٬٤٥٦٫٧٨٩"}}" using real Arabic digits that are used in that language.

<p>
And just like  {{code "Intl.DateTimeFormat"}} ,  you can use the {{code "options"}} argument to
customize the formatting.
</p>


{{#code "js"}}
alert(new Intl.NumberFormat("de-DE", {style: "currency", currency: "EUR"}).format(number));
{{/code}}

Returns "{{code "23.456,789 €"}}" using the Euro symbol.

<h2>Browser Compatibility</h2>

For browsers that support {{code "window.Intl"}}, this makes it easy to do basic formatting of numbers
and dates. However, the {{code "window.Intl"}} object is relatively new so not all modern browsers
and devices support it. Here's a breakdown of desktop and mobile browsers support.

<h3>Desktop</h3>
<table class="pure-table">
    <tbody>
        <tr>
            <th>Feature</th>
            <th>Chrome</th>
            <th>Firefox (Gecko)</th>
            <th>Internet Explorer</th>
            <th>Opera</th>
            <th>Safari (WebKit)</th>
        </tr>
        <tr>
            <td>Basic&nbsp;support</td>
            <td>24</td>
            <td>29</td>
            <td>11</td>
            <td>15</td>
            <td><span class="warning">Not&nbsp;supported</span></td>
        </tr>
    </tbody>
</table>

<h3>Mobile</h3>
<table class="pure-table">
    <tbody>
        <tr>
            <th>Feature</th>
            <th>Android</th>
            <th>Chrome for Android</th>
            <th>Firefox Mobile (Gecko)</th>
            <th>IE Phone</th>
            <th>Opera Mobile</th>
            <th>Safari Mobile</th>
        </tr>
        <tr>
            <td>Basic support</td>
            <td><span class="warning">Not&nbsp;supported</span></td>
            <td>26</td>
            <td><span class="warning">Not&nbsp;supported</span><br>
            <a class="external external-icon" href="https://bugzilla.mozilla.org/show_bug.cgi?id=864843" title="Enable ECMAScript Internationalization API for Firefox on Android">bug&nbsp;864843</a></td>
            <td><span class="warning">Not&nbsp;supported</span></td>
            <td><span class="warning">Not&nbsp;supported</span></td>
            <td><span class="warning">Not&nbsp;supported</span></td>
        </tr>
  </tbody>
 </table>


<commit_msg>adding intl-messageformat content<commit_after>{{setTitle "Internationalization in the Browser"}}

<h1>Internationalization in the Browser</h1>

<p>
    In the early days of browser development, internationalization would happen most often on the server,
    since browsers did not have a standard way of formatting things like dates and numbers based on
    the locale of the browser. With more modern browsers we have the benefit of the ECMAScript internationalization
    API (<a href="http://www.ecma-international.org/ecma-402/1.0/#sec-8">ECMA-402</a>) which provides
    language sensitive string comparison, number formatting, and date and time formatting.
</p>
<p>
    This is of great benefit for developers of websites and single page applications where data is often
    downloaded dynamically without location specific formatting. The
    <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl">{{code "Intl"}}</a> object
    provides constructors for {{code "Collator"}}, {{code "NumberFormat"}}, and {{code "DateTimeFormat"}}
    which give browser developers the basic tools they need for formatting.
</p>
<p>
Here are some examples:
</p>

<h2>Date Formatting</h2>

<p>
    You can format dates easily once you create a {{code "Date"}} object and call
    the {{code "format"}} method on {{code "Intl.DateTimeFormat"}}.
</p>

{{#code "js"}}
var date = new Date(Date.UTC(2012, 11, 20, 3, 0, 0));
alert(new Intl.DateTimeFormat().format(date));
{{/code}}

Returns "{{code "12/19/2012"}}" if run in the {{code "en-US"}} locale with time zone {{code "America/Los-Angeles"}}.
Using {{code "Intl.DateTimeFormat()"}} with no arguments will use the system's locale and time zone.

{{#code "js"}}
alert(new Intl.DateTimeFormat("en-GB").format(date));
{{/code}}

Returns "{{code "19/11/2012"}}" as British English uses day-month-year order.

{{#code "js"}}
alert(new Intl.DateTimeFormat("ko-KR").format(date));
{{/code}}

Returns "{{code "2012년 12월 19일"}}" as Korean uses year-month-day order.

<p>
You can also format dates and times via the {{code "options"}} argument:
</p>

{{#code "js"}}
var options = {weekday: "long", year: "numeric", month: "long", day: "numeric"};
alert(new Intl.DateTimeFormat("de-DE", options).format(date));
{{/code}}

Returns "{{code "Mittwoch, 19. Dezember 2012"}}" as you requested a weekday along with a long date.

<p>
    Note how you have the same date information in {{code "date"}} but specifying a different locale or formatting options
    changes the output. You can find out more about date formatting via the Intl specification
    <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat">here</a>.
<p>

<h2>Number Formatting</h2>

<p>
    You can also format numbers in a similar fashion using {{code "Intl.NumberFormat"}}.
</p>

{{#code "js"}}
var number = 123456.789;
alert(new Intl.NumberFormat().format(number));
{{/code}}

Returns "{{code "123,456.789"}}" when in the US English locale.

<p>
    As in {{code "Intl.DateTimeFormat"}} you can pass in a specific locale to specify a different language.
</p>


{{#code "js"}}
alert(new Intl.NumberFormat("ar-EG").format(number));
{{/code}}

Returns "{{code "١٢٣٬٤٥٦٫٧٨٩"}}" using real Arabic digits that are used in that language.

<p>
    And just like  {{code "Intl.DateTimeFormat"}} ,  you can use the {{code "options"}} argument to
    customize the formatting.
</p>


{{#code "js"}}
alert(new Intl.NumberFormat("de-DE", {style: "currency", currency: "EUR"}).format(number));
{{/code}}

Returns "{{code "23.456,789 €"}}" using the Euro symbol for currency.

<h2>Browser Compatibility</h2>

For browsers that support {{code "window.Intl"}}, this makes it easy to do basic formatting of numbers
and dates. However, the {{code "window.Intl"}} object is relatively new so not all modern browsers
and devices support it. Here's a breakdown of desktop and mobile browsers support.

<h3>Desktop</h3>
<table class="pure-table-horizontal">
    <thead>
        <tr>
            <th>Feature</th>
            <th>Chrome</th>
            <th>Firefox (Gecko)</th>
            <th>Internet Explorer</th>
            <th>Opera</th>
            <th>Safari (WebKit)</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Basic support</td>
            <td>24</td>
            <td>29</td>
            <td>11</td>
            <td>15</td>
            <td><span class="warning">Not supported</span></td>
        </tr>
    </tbody>
</table>

<h3>Mobile</h3>
<table class="pure-table">
    <thead>
        <tr>
            <th>Feature</th>
            <th>Android</th>
            <th>Chrome for Android</th>
            <th>Firefox Mobile (Gecko)</th>
            <th>IE Phone</th>
            <th>Opera Mobile</th>
            <th>Safari Mobile</th>
        </tr>
    </thead>
    <tbody>

        <tr>
            <td>Basic support</td>
            <td><span class="warning">Not supported</span></td>
            <td>26</td>
            <td><span class="warning">Not supported</span><br>
            <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=864843" title="Enable ECMAScript Internationalization API for Firefox on Android">bug&nbsp;864843</a></td>
            <td><span class="warning">Not supported</span></td>
            <td><span class="warning">Not supported</span></td>
            <td><span class="warning">Not supported</span></td>
        </tr>
  </tbody>
 </table>

 (Source: <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#Browser_Compatibility">MDN</a>)

<p>
    Lacking {{code "window.Intl"}} support across browsers presents a problem for you as a developer
    since you want to use these features across all browsers and devices. Fortunately, there is a polyfill
    for Intl called <a href="https://github.com/andyearnshaw/Intl.js/">{{code "Intl.js"}}</a> written
    by <NAME>. This polyfill allows you to use the native API's
    for {{code "window.Intl"}} in legacy or unsupported environments.
</p>

<p>
    Since you only want to load this polyfill in browsers that do not support the native {{code "Intl"}} object,
    you may use a conditional loader like <a href="http://yepnopejs.com/">{{code "yepnope.js"}}</a>. Here is an example below loading {{code "Intl.js"}}
    from the Yahoo CDN along with the en-US locale information.
</p>


{{#code "js"}}

(function () {
    var locale    = "en-US", //you should obtain this information potentially from the server.
        baseUrl   = 'http://yui.yahooapis.com/combo?platform/intl/0.1.2/Intl.min.js&platform/intl/0.1.2/locale-data/jsonp/',
        comboUrl  = baseUrl + locale + '.js'
    yepnope([{
        test : !!window.Intl,
        nope : comboUrl
    }]);

})();

{{/code}}

Note the test {{code "!!window.Intl"}} which {{code "yepnope"}} uses to to decide whether to load {{code "Intl.js"}}.

<h2>intl-messageformat</h2>

<p>
    Suppose however you want to construct more complex translations? There is a Yahoo library called
    <a href="https://github.com/yahoo/intl-messageformat">{{code "intl-messageformat"}}</a> that allows you to use JavaScript to create strings with localization support, and it can be used on both the client and the server.
    The constructor looks something like this:
</p>
{{#code "js"}}
var msg = new IntlMessageFormat(pattern, locale, [optFieldFormatters]);
{{/code}}

    Where the {{code "pattern"}} and {{code "locale"}} are strings and {{code "[optFieldFormatters]"}} is an object. Let's look at some examples.


<h3>Simple String</h3>

{{#code "js"}}
// create the object
var msg = new IntlMessageFormat("My name is {NAME}.", "en-US");

// now call format on the resulting object and pass in JSON
var myNameIs = msg.format({ NAME: "<NAME>"});

// myNameIs == "My name is <NAME>."

{{/code}}

<h3>More complex</h3>



<p>
    Next, we need to know how to load the library. In a previous example, we conditionally loaded {{code "Intl.js"}} based off of the existance of {{code "window.Intl"}}. We can add to this code to also load the {{code "intl-messageformat"}} library. However there are a few options.
    <ul>
        <li>
            You might choose to load only the base library which is located in {{code "intl-messageformat/index.js"}} and then a specific locale's data via {{code "intl-messageformat/locale-data/{locale}.js"}} (where {{code "{locale}"}} is a top level locale like {{code "en"}} ).
        </li>
        <li>
            You might instead choose to load the base with a single locale built in such as {{code "intl-messageformat/build/intl-messageformat.{locale}.js"}}.
        </li>
        <li>
            A more common case may be when you choose to load the base and all of the locales ( {{code "intl-messageformat/build/intl-messageformat.complete.js"}} ), which may be a bit larger in size but removes the need to download additional locales.
        </li>
    </ul>
    For the example code below we've loaded the complete version
    which has been minified.
</p>

{{#code "js"}}
//Client-side JS goes here.
(function () {
    var locale    = APP.intl.locale,
        // TODO: expose these URLs through Express State instead
        baseUrl   = 'http://yui.yahooapis.com/combo?platform/intl/0.1.2/Intl.min.js&platform/intl/0.1.2/locale-data/jsonp/',
        comboUrl  = baseUrl + locale + '.js',
        intlMessageFormatUrl = '/bower_components/intl-messageformat/build/intl-messageformat.complete.min.js';

    yepnope([{
        test : !!window.Intl,
        nope : comboUrl
    }, {
        load     : intlMessageFormatUrl,
        complete : init
    }]);

    function init () {
        // Initialize application here
    }
})();
{{/code}}

<p>
The path used in this example assumes you have installed {{code "intl-messageformat"}} via bower using:
</p>

{{#code "js"}}
$ bower install intl-messageformat
{{/code}}

In fact, this site itself loads {{code "intl-messageformat"}} in this fashion. View source to check it out!
{'fraction_non_alphanumeric': 0.15111976630963972, 'fraction_numerical': 0.0166179811749432, 'mean_word_length': 3.416857798165138, 'pattern_counts': {'":': 0, '<': 280, '<?xml version=': 0, '>': 280, 'https://': 9, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 3, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4104639', 'n_tokens_mistral': 5097, 'n_tokens_neox': 4822, 'n_words': 1605}