Skip to content
This repository has been archived by the owner on Jul 18, 2023. It is now read-only.

HOWTO : Internationalization

tsimbalar edited this page May 22, 2012 · 5 revisions

Objective

We want to support several languages in the application. To accomplish that we must externalize all the translatable text out of the code.It works differently for texts generated on server-side (Scala code and templates), and text used on client-side (javascript).

Important side note

ALWAYS use UTF-8 encoding. For all files, code, resources, client side, server side. For everything.

Server-side

The recommended way seems to be using Message files.

Adding a language

Here is the procedure :

  1. Add the language/locale in conf/application.conf, for instance :
    application.langs="en,fr,xx-ZZ"
  2. Create a new file messages.xx-ZZ in the conf folder.
  3. Add the necessary key/values in the file. Take inspiration from the original (default) messages file.

In your code, just use Messages("theKey") wherever you would usually use a String.

Important considerations

By default, the language is taken from the implicit request's header Accepted Languages. It will only work with that request in the current scope, and add it in the declaration of the templates, as in :

@(roomId : String,  room: Room, user: User)(implicit flash: Flash, request: RequestHeader, lang: Lang)

See also

More details here in the official documentation : Messages and internationalization

Client-side

jquery-i18n-properties

We are using a js library called jquery-i18n-properties . This library allows to retrieve from the server some message files using the .properties format and access their content from javascript scripts in the page.

In order for this to work, the jquery-i18n-properties js file must be referenced prior to any script that needs translation. In addition, the translations need to be loaded, thanks to a code snippet like this one :

    // initialize translations - must be done before robotagram.js so translations can be retrieved
    jQuery.i18n.properties({
        name:'Messages.client', //base name of translation files
        path:'@routes.Assets.at("i18n/")',
        mode:'map', // make translation available through jQuery.i18n.prop('xxx') - other options : 'vars' or 'both'
        cache:true, // let the browser cache the translations it's ok as we have one file with all translations (false means a random querystring is added to the referenced file)
        language:'@lang.code' //take the same language the server figured out
    });

Note that we are specifying explicitly the same language code as the one the server has detected.

According to the configuration above, the page will first load the file /public/i18n/Messages.client.properties - the default translation file - , and then, depending on the language/culture code , it will load the file /public/i18n/Messages.client_fr.properties (or Messages.client_pt_PT.properties etc) - the language-specific file. When loading a translation by key, it will first look for a match in the language-specific file, and fall back to the default file.

Access to messages

Once jquery-i18n-properties has been loaded and initialized, you can use jQuery.i18n.prop to load a translation.

For example, if we defined this translation in the messages file:

    msg_hello=Hello world

Then it will extract the correspound string with that key:

    jQuery.i18n.prop('msg_hello'); // "Hello world"

It can also handle messages with placeholders. If we have this translation in our messages file :

    msg_complex = Good morning {0}!

Then it will replace the placeholder with the value of the parameter :

    jQuery.i18n.prop('msg_complex', 'John'); // "Good morning John!"

Alias for jquery-i18n-properties

Because the default jQuery.i18n.prop is a bit verbose, we can define an shorter alias such as $_like this :

    var $_ = jQuery.i18n.prop;

Thanks to this trick, translations can be accessed as :

    $_('msg_hello'); // "Hello world"
    $_('msg_complex', 'John'); // "Good morning John!"

Loading translations as js variables - don't do it!

jquery-i18n-properties also optionally allows to load all the messages from the message files directly into the global scope (this is done with mode:'vars' or mode:'both' when initializing the library). This would mean that if we defined in our messages file the following translation:

theMessage=This is so cool

then a variable called theMessage with the value "This is so cool" would exist in the global scope, and could be used directly :

alert(theMessage)

This would cause problems when translation keys are javascript-reserved keywords or invalid javascript variable names, so we do not use this feature, and only use mode:'map'.

See also

Interesting resources about javascript internationalization :