Friday, October 4, 2013

Internationalization in Java

If you are developing an application which is supposed to be used across many countries with different languages, currency, number formats, etc., then you must have a way to change locale specific things in your application. This procedure is known as internationalization which simply known as i18n because there are 18 characters between i and n of the word 'internationalization'. Texts that are visible to the end user is one major aspect that has to be considered when an application is internationalized. In Java this is very simple as you will see in the following example. In an internationalized application, texts that needs to be displayed in UIs etc are taken from external file corresponding to the required language. Consider the following code in which String type parameter for the System.out.println() method is passed according to the language instead of hard coding it.

Application.java
package blog.samila.i18n;

import java.util.Locale;
import java.util.ResourceBundle;

public class Application {
    ResourceBundle messages;
    public Application(Locale locale) {
        this.messages = ResourceBundle.getBundle("messages",locale);
    }

    public void start() {
        System.out.println(messages.getString("application.started"));
        System.out.println(messages.getString("application.running"));
        System.out.println(messages.getString("application.stopped"));
        System.out.println();
    }

    public static void main(String[] args) {
        new Application(new Locale("sv", "SE")).start();
        new Application(new Locale("de", "DE")).start();
    }
}

This application prints three messages as defined according to Swedish and German languages. Now create follwoing files. These messages must be defined in external property files created in src folder of your project in IDE or in class path if you are running from a jar.

messages_sv_SE.properties
application.started=igång

application.running=rinnande

application.stopped=stoppad

messages_de_DE.properties
application.started=gestartet

application.running=läuft

application.stopped=gestoppt

messages.properties
application.started=started

application.running=running

application.stopped=stopped

Your text must be defined in properties files as shown above. File name must begin with the name you use in getBundle() method which is 'messages' in this example. Remaining part of the name is constituted by appending the language code and country code separated by '_'. File with no language code nor country code is the default file. In case of a defined locale cannot be found or if the required message could not be found, this file is referred by the application. Now run the application and you will get the following output.

igång
rinnande
stoppad

gestartet
läuft
gestoppt

These texts are taken from messages_sv_SE.properties, messages_de_DE.properties which includes Swedish and German texts respectively. The selected file is determined by the locale you specified as you can see in the code above. Locale object can be created by specifying language code and country code respectively. Use of dot separated keys in language files increases the readability and creates a good namespace. You can internationalize your Labels, JButtons, etc simply using this concept. In this manner you can start internationalization of your Java application and further you can add number formatting etc.