Cheatsheet for Angular-translate

Tiety Kooistra
24-04-2017

I recently needed to make an angular web-app multilingual using angular-translate and the i18n standards. Till that point all texts were hardcoded in the codebase wherever they were needed. The first step was to replace all the text snippets with variables. Most of the texts that needed translations lived in the view of the application. The view or HTML of the application is the preferable place for them as well. It is just content in a sense that changes with a translation. But there where also some defaults defined in the JavaScript files that needed to be multilingual.

In this post a cheatsheet of the different ways you can implement translations with angular-translate. It is a personal list of the directives and filters I liked to use in specific situations in my HTML and JavaScript files. It is not about how you setup the translations themselves inside of your JavaScript and/or JSON files. For more setup information visit the side of angular-translate.

HTML

When possible it is a best practice to use the translate directive.

<h2 class="heading" translate="CHAPTER_DETAILS.HEADING"></h2>

In your translation file you would get for each language a value for the CHAPTER_DETAILS.HEADING key, as in the JSON file below.

{
    "CHAPTER_DETAILS": {
        "HEADING": "Your translation"
    }
}

An other option is the translate filter. Be aware that each filter on a page has a watcher. This can potentially make your site slow. That is why the directive is a better choice.

<h2 class="heading">{{ 'CHAPTER_DETAILS.HEADING' | translate }}</h2>

With angular you can use bindings with expressions in your HTML that angular will evaluate when you run the application. With angular translate these variables can be added to the translation as well.

<h2 class="back--heading" 
    translate="ASSIGNMENTS.PAGE_HEADER" 
    translate-values="{title: vm.current.activeChapter.shortTitle}">
</h2>

This is how it is done with the translate directive, but you can also use the filter if you have to.

<h2 class="back--heading">
    {{ 'ASSIGNMENTS.PAGE_HEADER' | translate:'{title: chapter.shortTitle}' }}
</h2>/

To compare, in the JSON file I showed before you can use the key name you specifies as a placeholder for the value it will become, just like you would normally do in HTML.

{
    "ASSIGNMENTS": {
        "PAGE_HEADER": "Translation with variable {{title}}"
    }
}

What to do with HTML tags in the text that needs to be translated? Because the translations will probably be done by none technical people we decided at the project to not support HTML tags inside of the translation. In that case you can use the translate filter and/or directive. By making as many segments as you need to support the needed translation around the HTML tags. For example in a header that is partially made <strong>.

<h1 class="page--heading">
    {{ 'CHAPTER_DETAILS.PAGE_HEADER_1' | translate}}
    <strong translate="CHAPTER_DETAILS.PAGE_HEADER_2"></strong>
</h1>

One last frequent use case, a HTML attribute, like title or alt.

<a ng-click="vm.toState()" translate-attr="{ title: 'PARAGRAPH_DETAILS.BACK_TITLE'}">
    <span class="terug" translate="PARAGRAPH_DETAILS.BACK"></span>
</a>

And how to use the filter in this case. I found that if you have custom attributes used by angular directives or components only this filter option will work.

<a ng-click="vm.toState()" title="{{ 'PARAGRAPH_DETAILS.BACK_TITLE' | translate }}">
    <span class="terug" translate="PARAGRAPH_DETAILS.BACK"></span>
</a>

JavaScript

In some cases there is also some text in JavaScript files that will need translation. Mainly this will be defaults or fallbacks that are added to compose the desirable user flow. Like in the situation below, where a fallback is created when there is no learningPath object available in the content or data.

(function () {
    'use strict';

    angular.module('AssignmentsModule').service('assignmentsService', assignmentsService);
    
    function assignmentsService($translate) {
        $translate.onReady( function() {
            noLearningPath = {
                pathName: $translate.instant('ASSIGNMENTS.PATHNAME'),
                additionalText: $translate.instant('ASSIGNMENTS.ADDITIONAL_TEXT'),
                pathCode: $translate.instant('ASSIGNMENTS.PATHCODE')
            }
        });
    }
    
})();

Translations are in almost all cases asynchronous in nature. In JavaScript we need to account for that as well. With the use of the $translate service the .onReady() method is available. As soon as there are translations available this function will be called and inside you can put all the elements that need translation. There are several ways to do this with other functions or methods as well. In my opinion this one is the most readable and easiest to setup.

I hope this is helpful for you when you need to make your own translations.

 

LEAVE A REPLY

you might also like