Internationalization in Java

Fortunately Java has a very usable mechanism to provide multiple translations for an application built in. Java makes use of ResourceBundle which are basically key-value stores - in most cases just an instance of the Properties class.

Resource bundle hierarchy

Resource bundles are resolved using a locale, and a locale is defined by three settings:

  • language
  • region
  • variant

It is common to define a locale using only the first two points, such as en_US or de_DE for US English or German with the Germany region. The variant can be used as you like, for example to create a more specialized translation on a per customer base or for different sub-regions.

When Java loads a resource bundle it will make use of that hierarchy and load resource bundles in that order and merge the language, region and variant into the higher resource bundle. When loading the strings bundle with a locale of "de_DE_XY" it will load the files:

  1. strings.properties
  2. strings_de.properties
  3. strings_de_DE.properties
  4. strings_de_DE_XY.properties

These files are not expected to exist: when they don't they are ignored and the loading process continues with the next one.

The upper example lists in the first step a strings.properties file that has no locale info attached to it. This file is used for the default translation and usually contains all translation keys and some value for them. This default translation can be the language you develop in or some debug-text to help you find untranslated strings:

# In strings.properties:
some.key.a = xx-some.key.a-xx
some.key.b = xx-some.key.b-xx

# In strings_en.properties:
some.key.a = Hello World!

If you now used the English translation file and your application displays the translated text for the key some.key.b you will see the debug text to notify you that the translation is missing from the English file.

Loading resource bundles

To load a resource bundle you provide the name of the bundle and the locale from which the language, region and variant are taken. You can use the locale from the user's system info or just construct one yourself - usually taken from your application's settings:

public class ResourceTest {

    public static void main(String args[]) {
        Locale locale = new Locale("en", "US");
        ResourceBundle resources = ResourceBundle.getBundle("strings", locale);
    }
}

The resources object can now be used to retrieve translations for translation keys.

TODO

  • Loading resource bundles
  • Using a resource bundle in plain java (simple and parameterized)
  • Link to further info