Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Goals: Allowing multiple languages to be incorporated to the impac dashboard project (currently exclusively english).

Tools: angular translate (An angular library used to translate)
Challenges: In order to internationalize the library we need to go through every layer of the code to check that all the sentences displayed are being translated.

Problems encountered:

- Internationalisation can become challenging when you get code behaviours depending on the words that should be translated.
An example would be the date of a widget that gets updated when the user selects a different period (day, week, month, year).
If the code is using the words: day, week,... then there will be a problem when it get translated to another language.

E.g: The program will expect to receive "day" normally but if we switch to another language such as chinese, it will get 天 which does not correspond to any of the period defined.
A solution is to keep the English terms as values and create labels that can be translated in different languages.

Impac Angular (frontend):

You will need to translate values within the HTML code sometimes, as well as in the directives (java script files).

JSON file

All the translations are kept in data-interchange formats (json, yaml, ...) that are then compiled as an angularjs module.

Code Block
languagexml
themeRDark
titlesrc/locales/en-gb.json
linenumberstrue
{
	"my.awesome.translation.of.hello_world": "Hello World",
	"namespace.to.avoid.confusion.or.conflicts": "Each variable has a unique name to avoid conflicts"
}

Each variable is using a common namespace (in this case impac) to avoid potential clashes.

HTML code

Default

In order to translate terms within the HTML code, angular translate gives you several ways (filters or directive):

...

Code Block
languagexml
themeRDark
linenumberstrue
<!-- Favourite syntax -->
<p translate>my.awesome.translation.of.hello_world</p>
<!-- To avoid if possible, but exists  -->
<p>{{'my.awesome.translation.of.hello_world' | translate}}</p>

    -> Better approach


Advanced (translations with variables)

You can create more complex structure then a simple string translation. You can add variables.

...

Code Block
languagexml
themeRDark
titlesrc/views/**/some-views.html
linenumberstrue
<!-- Favourite syntax -->
<p translate="my.value.to.translate.hello_x" translate-values="{name: 'John'}"></p>

Directive code

Default

To translate an expression in a controller you need to use angular translate service: $translate
Since Angular translate is asynchronous, it will return a promise.
Once you've imported it in your controller you can simply use it like this:

Code Block
languagejs
themeRDark
titlesrc/views/**/some-views.directive.coffee
linenumberstrue
module.controller('...', ($translate) ->
	[...]
	$translate('my.awesome.translation.of.hello_world').then(
		(translation) ->
			scope.yourVariable = translation
	)


	// OR (if you have many values to translate)
	$translate(['my.awesome.translation.of.hello_world', 'another.value.cat']).then(
		(translation) ->
			scope.yourVariable = translation["my.awesome.translation.of.hello_world"]
			scope.anotherVariable = translation["another.value.cat"]
	)
)

Advanced

Code Block
languagejs
themeRDark
titlesrc/views/**/some-views.directive.coffee
linenumberstrue
$translate('my.value.to.translate.hello_x', {name: 'John'}).then(
	(translation) ->
		scope.yourVariable = translation
)


Pluralization

You might need to add pluralization to your translations. In order to do that we use an additional module called messageformat.

It is enabled by default so you don't need to add anything.

Code Block
languagejs
themeRDark
titlesrc/views/**/some-views.directive.coffee
linenumberstrue
<p translate="mno_enterprise.templates.impac.dock.settings.nb_of_users"
   translate-values="{ num_users: app.licences_count }"></p>

The translation would have the following schema:

{name_of_your_variable, typeOfFormat (plural or gender), =case_1{translation 1} =case_2{translation 2} other{translation by default}}

E.g:

Code Block
languagejs
themeRDark
titlesrc/views/**/some-views.directive.coffee
linenumberstrue
{
	"impac.name.path.nb_of_users": 'There {num_users, plural, =0{are no users} =1{is one user} other{are # users}}';
}

Any question or more examples, details: look at the well made documentation

https://angular-translate.github.io/docs/#/guide/

Impac (Backend): 

Sometimes the expressions to translate are set and sent from the backend.
As we need the translation to be simple and easy to manage we want to keep it in the frontend.
In order to be retro-compatible we will need to keep the current data sent by the API and add extra fields called keys.

...

The backend will then take care of the translation of these keys and falls back into the 'normal' field if no translation exist.

What you should remember

  • NEVER hardcode text in a template or in a directive: use a key that has a translation in the json file

    Code Block
    languagexml
    themeRDark
    titlesrc/views/**/some-views.html
    linenumberstrue
    <!-- Wrong -->
    <p>This is wrong</p>
    
    <!-- Correct -->
    <p translate>impac.name.path.this_is_better</p>




    Code Block
    languagexml
    themeRDark
    titlesrc/locales/en-gb.json
    linenumberstrue
    {
    	"impac.name.path.this_is_better": "This is better"
    }





  • If you need to get text from the back-end, add a key field to the response and process it in the front-end.

    Code Block
    languagejs
    themeRDark
    linenumberstrue
    title: "I am an english title"
    //Add this field
    title_key: "impac.name.path.title"


  • Always create a new key, even if there is already a translation for it.
    If there is already a translation, you may assign it like a variable.

    This allow more flexibility to change the name if needed. 

    Code Block
    languagexml
    themeRDark
    titlesrc/locales/en-gb.json
    linenumberstrue
    {
    	"impac.common.action.cancel": "Cancel,
    	"impac.widget.accounting_values.turnover.cancel": "@:impac.common.action.cancel"
    }


  • Remember that translations take into account gender and pluralization.

...