Internationalization
Internationalisation (I18N) is a means of adapting your application to different languages to allow for regional differences. Follow these steps to enable internationalisation in your application.
Only use UTF-8!
Play supports only one encoding: UTF-8. Since encoding problems can be weird and difficult to deal with, we made the choice to support only one encoding. UTF-8 allows you to display all characters for all languages.
Be sure to be consistent with UTF-8 usage throughout your application:
- Edit all your source files as UTF-8
- Define proper encoding headers in HTTP
- Set your HTML meta tags to UTF-8
- If you use a database, configure it to use UTF-8, and always connect to it using UTF-8
Note
The UTF-8 encoding issue is the reason why most of the Play configuration files, even though they are Java properties files, are not named *.properties
. Java imposes the requirement that properties files must be encoded with the ISO-8859-1 encoding. Play configuration files must be UTF-8 encoded. Need we say more?
Externalize your messages
To support I18N you have to externalize all messages in your application.
Create a file named messages
in the application’s conf/
directory. This file is really just a Java properties file.
hello=Hello!
back=Back
Then you can define a specific message
file for each language used in your application. Just add the ISO language code as a file extension.
For example, the message file containing the corresponding French translations is conf/messages.fr
:
hello=Bonjour!
back=Retour
Define languages supported by the application
Define a list of supported languages in the application.langs configuration.
On the first request from a new user, Play will guess the default language to use. It does so by parsing the HTTP Accept-language
header. It will then save the chosen language in a PLAY_LANG
cookie. So the next request will use the same language.
You can use language/country pair if you want to distinguish between variant, such as en_US and en_GB, or zh_CN and zh_TW. However, be aware that some users may only expose a language and not a country in their Accept-language. For that reason, you should always provide the “naked” language (e.g. en).
For example, if most of your users are from US but you also want to support British English, it is recommended to use simply “en” of US English and “en_GB” for British English.
From your application code your can retrieve the current language for the user by accessing the play.i18n.Lang
object:
String lang = Lang.get();
If you want to permanently change the user language, use the change() method:
Lang.change("ja");
The new value will be saved back to the user’s language cookie.
Define date format according to your locale
Configure date.format to specify the default date format to use.
Retrieve localized messages
Message arguments
From the application code, you can retrieve messages defined in message files. From Java, use the play.i18n.Messages
object.
public static void hello() {
renderText(Messages.get("hello"));
}
We support message formatting through the standard java.util.Formatter
‘Format string syntax’. You can also define dynamic content in your messages:
hello=Hello %s!
where %s
represents a message argument that will be output as a String
. Message arguments are provided by additional (varargs) arguments to Messages.get
:
public static void hello(String user) {
renderText(Messages.get("hello", user));
}
Template output
From a template you can use the special &{…}
syntax to display localized messages:
<h1>&{'hello'}</h1>
or using dynamic content in message arguments:
<h1>&{'hello', params.user}</h1>
Multiple arguments
You can define multiple message arguments, such as this message which refers to two ‘decimal integer’ arguments:
guess=Please pick a number between %d and %d
which you display by specifying the message arguments in the right order:
<p>&{'guess', low, high}</p>
Argument indices
You can also specify the message argument explicitly, to use a different order. For example, suppose a message in English has two parameters:
guess.characteristic=Guess %s’s %s.
with message output like:
<p>&{'guess.characteristic', person.name, 'age'}</p>
The French localisation has the two message in the opposite order, so in the French localisation we specify the argument indices:
guess.characteristic=Devinez %2$s de %1$s.
where %2$s
outputs the second argument as a decimal integer.
Finally, we want to localise the characteristic name ‘age’ as well, so we would change the output to use the message key person.age
, and change the message definitions to:
guess.characteristic=Guess %s’s &{%s}.
person.age = age
and
guess.characteristic=Devinez &{%2$s} de %1$s.
person.age = l’age
where &{%s}
is itself a message look-up, with the argument value as the message key.
Continuing the discussion
Next: Cache.