News Geek on the Block

I18n: Let’s talk about AngularJS and Internationalization

Developping an Enterprise Social Network demands a lot of translated things so we can touch more people. Using AngularJS as our main frontend framework, I’ve had to seek for a good solution to internationalize our ESN.

First we should define some problematics and set up a little glossary. There are 5 main problematics here :

  • Internationalization: It is the translation of words or sentences in different languages
  • Localization: It is mostly about formats and how we format number or date for instance.
  • Genderalization:
  • Pluralization: Countries have different plural forms. Some have 2 while others have 3 or more plural forms.
  • Globalization: It’s all of the above.

I’ve chosen to restrict the analysis in 2 parts:

  • Formatting: It is all about formatting Date, Number and Currency.
  • Translation: It is all about text replacement, plural and genderalization.

Now comes the study of existing solutions we could use for the ESN with pros and cons for each solutions.



The native ‘date’ AngularJS filter

{{1288323623006 | date:'medium'}} // Oct 29, 2010 5:40:23 AM
{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}} // 2010-10-29 05:40:23 +0200
{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}} // 10/29/2010 @ 5:40AM

Filters are very nice in AngularJS as they are very easy to use or to implement. AngularJS has a ‘date’ filter which formats date the way we want. AngularJS also comes with its own i18n system. First we have to add those js files in our web sites then AngularJS automatically internationalize our application.


  • No additional library needed
  • Support Timezones


  • It does not implement complexe date calculation


var fr = moment().lang('fr');
fr.lang().months(moment([2012, 0])) // janvier
fr.lang().months(moment([2012, 0])) // January

Momentjs is a very well known nodejs library. It comes with several js files used to internationalize an application.


  • Very mature and well known (17000+ stars on github)
  • Implements complexe date calculation methods

    moment().startOf(‘hour’).fromNow(); // 29 minutes ago
    moment().subtract(‘days’, 10).calendar(); // 05/10/2014

  • Supports Timezones

  • Usage: client-side as well as server-side


  • Well…

The Date module of globalize.js

Globalize.formatDate( new Date( 2010, 10, 1, 17, 55 ), { datetime: "short" } )
// en: "11/1/10, 5:55 PM" - de: "01.11.10 17:55"

Globalize is a nice solution which comes with several modules. This solution tries to be the all-in-one solution. The ‘Date’ module provides everything needed to format a date, provided that we have provisioned Globalize with internationalization datas.


  • One solution to rule them all
  • Fully uses Unicode CLDR for datas in which we can find the most complete internationalization datas


  • Still in an alpha version. It cannot be used in production


The native ‘number’ AngularJS filter

{{1234.56789 | number}}    // 1,234.568
{{1234.56789 | number:0}}  // 1,235
{{-1234.56789 | number:4}} // -1,234.5679

The ‘number’ filter of Angular offers a quick and easy way to localize numbers.


  • No additional library needed


accounting.formatNumber(5318008); // 5,318,008
accounting.formatNumber(9876543.21, 3, " "); // 9 876 543.210

[Accounting.js}( is a little javascript library for number, money and currency formatting.


  • No external dependencies are needed


  • It does not provide any localization files (but it is localizable)
  • We need to wrap it into Angular filters

The Number module of globalize.js

Globalize.locale( "en" );
Globalize.formatNumber( 3.141592 );           // "3.142"
Globalize.formatNumber( 3.141592, {}, "es" ); // "3,142"
Globalize.formatNumber( 3.141592, {}, "ar" ); // "3٫142"

The ‘Number’ module of Globalize provides nearly the same features than the native ‘number’ Angularjs filter.


  • It also does what we want


  • Still in Alpha


The native ‘currency’ AngularJS filter

{{1234.56 | currency}} // $1,234.56
{{1234.56 | currency:"USD$"}} // USD$1,234.56

The ‘currency’ filter of Angular localizes currency by replacing the currency symbol to the proper one.
All datas are already provided by those js files.


  • No additional library needed


  • Does not automatically convert currency amount. It only replaces the symbol.


accounting.formatMoney(4999.99, "€", 2, ".", ","); // €4.999,99


  • Easy to use
  • No external dependencies are needed


  • Need to be implemented in Angular with filters and services
  • Does not automatically do the convertion of the amount


fx.convert(12.99, {from: "GBP", to: "HKD"});

money.js is a little library which convert currency using the open exchange rates api. We can use it along with accounting.js or the AngularJS filter to manipulate and localize currencies.



Text replacement

There is no native mechanism in AngularJS which does the text replacement for us and we must provide one.


Angular implements a ngPluralize directive. The drawback is that there is no genderalization implementation right now.

ng-pluralize count="personCount" offset=2
  when="{'0': 'Nobody is viewing.',
         '1': '{{person1}} is viewing.',
         '2': '{{person1}} and {{person2}} are viewing.',
         'one': '{{person1}}, {{person2}} and one other person are viewing.',
         'other': '{{person1}}, {{person2}} and {} other people are viewing.'}">


Text replacement

<h1>{{'TITLE' | translate}}</h1>

Angular-translate is an AngularJS module which provides a lot of features and full pluralization support through MessageFormat.

Some of those cool features are:

  • Seamless integration with AngularJS with directives and filters
  • Fallback mechanism
  • Lazy and Asynchronous loading
  • determinePreferredLanguage method which tries to find the correct language


Angular-translate is the only solution I have found that natively implements a genderalization mechanism.

We provides datas like:

"LIKE_TEXT": "{GENDER, select, male{He} female{She} other{They}} liked this."

which is then used in our templating like that:

{{ 'LIKE_TEXT' | translate:"{ GENDER: 'male' }" }}

It can become complexe :

{GENDER, select,
        male {He}
      female {She}
       other {They}
} found {NUM_RESULTS, plural,
        one {1 result}
      other {# results}
} in {NUM_CATEGORIES, plural,
        one {1 category}
      other {# categories}


Text replacement

Angular-gettext also provides a seamless Angular integrated module. It uses Gettext and the PO files to translate an application.

<a href="/">Hello {{name}}</a>

The best cons in using angular-gettext and the PO format is that it can easily be used with localization plateform like Pootle or Transiflex due to the PO format.


    There is {{count}} message

Pluralization here offers the same features than AngularJS pluralization mechanism.


Text replacement

Globalize.loadMessages( "pt_BR", {
    greetings: {
    hello: "Olá",
    bye: "Tchau"
Globalize.locale( "pt_BR" );
Globalize.translate( "greetings/bye" ); // "Tchau"


Unfortunately, I did not find anything about pluralization in globalize.js.


First thing to note is that every solutions propose the same API. And most solutions seem viable.

For our needs, in the formatting part we have chosen to stick with AngularJS filters (with a filter for money.js to convert money) and momentjs for everything about dates. In the translation part we will use angular-translate which offers very nice features plus the fact that one of our internal development team was already using it with success.

, , , ,

One thought on “I18n: Let’s talk about AngularJS and Internationalization
  • Andrew says:

    on the note of globalize.js… While its technically in Alpha it is in a very production ready state. I’ve had apps that utilize globalize.js that have been built, run-on-production and then retired. It’s most importantly one of the few libraries that I’ve used that actually catches all of the nastier corner formatting corner cases..

Leave a Reply to Andrew Cancel reply

Your email address will not be published. Required fields are marked *


You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>