A good framework attracts great developers and great developers fill the gaps left by the framework. There are some good community projects to make Angular localization easy. We are going to discuss two of those here: one that targets the dynamic locale change, and the other that helps with content localization.
Locale changes using angular-dynamic-locale
To tackle the first limitation related to changing the locale on the fly, there is a community project angular-dynamic-locale (http://lgalfaso.github.io/angular-dynamic-locale/). This module allows us to dynamically change the locale once the application has been bootstrapped. Installing and using angular-dynamic-locale is easy.
Using angular-translate for text translations
Content translation may seem simple but there are some technical challenges here too. To understand these challenges, you need to understand how the process of content translation works. The task of content/text translation begins with identifying what content should be translated. Such content can broadly be classified in two categories,
- Fixed string literals: In any HTML page, there are parts that are dynamic and parts that are fixed. If we hardcoded strings anywhere in the view, those are fixed-string literals and are potential candidates for localization.
- Dynamic string literals: Any string/text fragments retrieved from the server and rendered in the view are dynamic string literals. The exercise name shown during workout execution is a good example of this.
Localizing fixed string literals is comparatively easy. Depending upon the number of locales to support, the content is generated for each locale and is made available to a tool/library. The library then based on the locale requested embeds the locale-specific content in the HTML. Once the translations are registered, we are ready to use these translations in our app. There are three ways to use them:
Using the $translate service:
We can retrieve a specific translation in the controller using the $translate service. Although not used much, it allows us to get the localized version of a translation key. For example:
- $translate('START.HEADER').then(function (header) {
- $scope.header = header;
- });
The retrieval syntax is promise-based, and there is a reason for this. The library also allows asynchronous loading of localization content from remote locations.
Using the translate filter: Replace the literal string with a translation key and apply the translate filter; we are done:
- <h1>Ready for a Workout?</h1> // Replace this
- <h1>{{'START.HEADER'|translate}}</h1> // With this
Using the START.HEADER key, the translate filter replaces the interpolation with the localized version of the content from the registered translations. Remember, every translation filter adds to the number of watches on the page. The static content now becomes dynamic and for a large page there may be a performance impact due to this. A better but restricted approach is to use a directive for translations.
Using the translate directive: The translate directive does something similar to the translate filter. The directive replaces the inner content of HTML on which it is declared with the translated text. This is how we use directives for translations:
- <h2 translate>START.WORKOUTS</h2> <-- OR --> <h2 translate="START.WORKOUTS"></h2>
The nice thing about the translate directive is that it supports interpolations too, allowing a dynamic translation key. For example, look at this:
- <h2 translate>{{scopeVariable}}</h2> OR <h2 translate="{{scopeVariable}}"></h2>
Prefer the directive version over filter version as the directive does not create a watch-like filter. But remember, the translate directive may not work everywhere and in such scenarios, the filter is the only choice. A good example of this is an attribute that needs localization: