-
Notifications
You must be signed in to change notification settings - Fork 0
HOWTO : Internationalization
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).
ALWAYS use UTF-8 encoding. For all files, code, resources, client side, server side. For everything.
The recommended way seems to be using Message
files.
Here is the procedure :
- Add the language/locale in
conf/application.conf
, for instance :
application.langs="en,fr,xx-ZZ"
- Create a new file
messages.xx-ZZ
in theconf
folder. - 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
.
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)
More details here in the official documentation : Messages and internationalization
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.
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!"
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!"
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'
.
Interesting resources about javascript internationalization :
- jquery-i18n-properties (http://code.google.com/p/jquery-i18n-properties/)
- i18next (http://jamuhl.github.com/i18next/) ...
- or a home-made solution (http://24ways.org/2007/javascript-internationalisation).