As the world grows closer through the internet, more companies need websites that are translated into other languages. Businesses that target other cultures, nationalities, and languages need a way to provide this feature in a way that is responsive and maintainable. There are many guides and blogs online that refer to this as i18n (internationalization) and l10n (localization). This article is the first of two posts and will look at common javascript libraries and tools that can be used for translation services. It will also cover some of the features provided by angular-translate, the library that we chose for one of our apps.

When deciding how to tackle translation and localization there are many questions that need to be addressed:

Are you starting from scratch and will this be integrated from the start?

Are you translating an existing app?

Will there be language strings stored and used server-side i.e. recurring emails, password reset emails, static dropdown lists stored in a database?

Are there pieces of data or formatting that need to be entered in the middle of text?

If there is concatenated data, does the position of the data change when translated into different languages i.e. "You have 7 unread messages"?

Do users need to be able to quickly switch between languages?

How is language preference stored?

Being able to answer these questions is important when selecting a library or package. There are many tools for translating and many ways to go about it. You can do it server-side, client-side, or have a mix of both. These questions can help you to think about what you need and how you want to implement i18n and l10n. When deciding which framework to use I researched a few js based libraries. Since I wanted something that worked well with AngularJS we chose angular-translate, but the following is a little bit about other possibilities. Remember that as you look at these and other possibilities you want to find something that includes the proper tools for your situation.

What's out there?

AngularJS provides some functionality for i18n by allowing different pluralization rules through filters and by allowing users to quickly build custom solutions for string replacement. Custom solutions can be a good way to ensure that everything behaves in the way that you want it to. Obviously, if you build it, you understand what is going on behind the scenes. However, there are also drawbacks to this approach. If you build a custom solution you have to invest time building it. You have to test it to make sure it works. And you have to maintain it. If for example, AngularJS were to change, you would have to make changes accordingly. Also, every feature that you want to add means more time in development and testing. For us it made more sense to use a third party library so that we could focus on our app instead of a translation library. One promising 3rd party library is the AngularJS localization module angular-l10n. It provides translations in directives or through filters. It uses interpolations, which allow you to insert values in strings. And it even has a locale switching feature. These are fairly standard features for any translation library and this seems to be a strong contender for an AngularJS compatible library.

Another popular 3rd party library is angular-translate. We chose this library for a recent conversion of an existing English application into Spanish for a few reasons. This library has a great organization mechanism and easily integrates into an existing AngularJS application. It too has the ability to interpolate values in strings. It has locale switching, asynchronous loading for string files, and allows you to translate through directives, filters, and their $translate service. It also currently has a larger user base and therefore has more guides and questions answered. We chose this over other libraries because there was a lack of functionality with other libraries and building a custom solution would have required a lot of time to test and develop.

There are also many other libraries that are not AngularJS specific including:

i18next a generic javascript library. It provides many of the basic features through data tags and jQuery selectors in place of the AngularJS methods mentioned above.

polyglot.js a lightweight library targeted toward backbone and node (has no other dependencies). This was designed by the airBnB team and has some promising features for pluralization and interpolation.

fnando a library that has date and number localization, which are awesome features. But, works with rails applications specifically.

L20N another generic library with support for pluralization and variable replacement. It seems promising but the syntax is slightly more complicated and it uses element renaming, in the same way that AngularJS does, which might cause confusion with AngularJS directives.

This is not an exhaustive list and there are certainly other options out there that are targeted to other situations or frameworks. However, most of these can be used with AngularJS on the client side of the application, meaning that for the most part, the back end of your service remains unchanged. There are exceptions to this if you want to save language preferences with user data, which I will discuss in part 2.

How to use angular-translate?

The introduction provided is fantastic. It is very straightforward despite the English translation being a little funny. If you just want to test it out, follow the directions on the getting started section and you can quickly set up a simple translated site. Once you get a feel for the basics there are a few things that helped me to organize our application and take advantage of the library to the fullest. I will introduce a few of these features in this article and will continue part 2 with more features later.

String Concatenation/Interpolation

Generally it is not a good practice to divide strings up into sections to be concatenated dynamically. Consider a dynamic number in this string:

"You have 3 messages"

If you were to concatenate it in javascript it would be in this format:

"You have " + number_of_messages + " messages"

The problem with this format is that first, the plurality of the sentence would be wrong. Second, when you send this to a translator they may not understand that this is all one phrase. Translation is tricky and words that can mean different things in different contexts can be misunderstood if the phrase is translated piece by piece. Angular-translate allows you to use variable replacement within strings in the following format:

"You have {{number_of_messages}} messages"

Now the string can be sent to the translator with the entire context. Also, this format can easily be organized into a file of strings. As for the pluralization we need another step. In order to provide pluralization you need to add the interpolation-messageformat library (watch out when including this because the default interpolation syntax may change slightly from double curly braces to single curly braces). This changes the interpolation engine that angular-translate uses and the format becomes:

{ 'MESSAGES_TEXT' : 'You have {{number_of_messages, plural, one{one message} other{# messages}}.' } //With the results of setting the number of messages: var number_of_messages = 1 ; //"You have one message." number_of_messages = 3 ; //"You have 3 messages."

And for reference if you wanted to use this in context it would be used like so:

As a filter

{{ 'MESSAGES_TEXT' | translate : "{ number_of_messages: '3' }" }}

With the $translate service

$translate ( 'MESSAGES_TEXT' , { number_of_messages : '3' });

Using the translate directive. Keep in mind that any element could be used in place of span.

<span translate= "MESSAGES_TEXT" translate-values= "{ number_of_messages: '3' }" ></span>

Embedded HTML and AngularJS within strings

Another issue that was solved using this library was using html within strings. For example, if you have a link to some site and you would rather display some text, you would typically use an a tag with text inside.

<div> Looks like you need to <a href= "/register" class= "register-link" > Sign Up! </a> . </div>

With angular-translate, using the translate directive we can simply define a string:

{ 'SIGNUP_TEXT' : 'Looks like you need to <a href="/register" class="register-link">Sign Up!</a>.' }

<div translate= "SIGNUP_TEXT" ></div>

The html will be loaded correctly on translation and will display with the sign up text as the link. This is great because it allows us to send it to the translator and explain that the sentence needs to be translated as a whole, but the link is the only part contained within the <a> tags. Or, we could just send the sentence without the tags and decide where to place the tags later based on the spacing or layout of the app.

Another issue I faced a few times was dealing with strings that had AngularJS elements or behavior placed around or within them. Luckily this is also solved with the translate-compile directive. Simply include the AngularJS as it was previously on the page and tag the element accordingly:

<div translate= "SIGNUP_TEXT" translate-compile ></div>

Any AngularJS directives embedded as html in the string will now compile on load of the translation.

Wrap Up

This has been a quick look at what libraries exist for javascript, with a focus on AngularJS, and an overview of a few features of angular-translate. Look for my next article to learn more about angular-translate in particular and remember that translation can be addressed in almost any language or framework. I encourage you to research and find the best option for your application. If you choose to use the angular-translate library look for part 2 to learn more about string organization, alerts, drop-downs, language selection, and css changes.

Do you need an expert in web development? With a team of web development specialists covering a wide range of skill sets and backgrounds, The BHW Group is prepared to help your company make the transformations needed to remain competitive in today’s high-tech marketplace.