Friday 23 September 2016

Internationalization using ResourceBundle

Internationalization is the process of developing products (or) services, so they can support different languages like English, Japanese, Chinese, Hindi etc.,

For example, you are developing an Enterprise application, where your application is going to be used by number of people across various countries. Since this is an Enterprise level application, people expect the application labels, messages etc., in their own locale.

How to make the messages Locale specific?
Here ResourceBundle comes into picture, By using ResourceBundle, you can point to the specific properties file, based on the locale.

Example1
ResourceBundle defaultPropertyFile = ResourceBundle.getBundle("app");

Above statement points to ‘app.properties’ file.

Example 2
ResourceBundle germanBundle = ResourceBundle.getBundle("app", Locale.GERMAN);

static public final Locale GERMAN = createConstant("de", "");

As you see the source code of Local.GERMAN, it looks like above. ‘createConstant’ function takes two arguments like lang, country. Based on locale selected by you, it points to specific property file.

The syntax is like below.
baseName_languageCode_countryCode.properties

In case of Example 2, baseName is “app”, languageCode is “de”, and country code is empty, so it points to app_de.properties.

Example 3
ResourceBundle canadaFrenceBundle = ResourceBundle.getBundle("app", Locale.CANADA_FRENCH);

static public final Locale CANADA_FRENCH = createConstant("fr", "CA");

As you see the source code of Locale.CANADA_FRENCH, it looks like above. As per the syntax specified in Example 2, canadaFrenceBundle  points to app_fr_CA.properties (baseName_laguageCode_countryCode.properties).

Example
app.properties
welcomeMessage = Good Morning
signoffMessage = Have a Good Day
version = 10.1


app_de.properties
welcomeMessage = Guten Morgen
signoffMessage = Haben Sie einen guten Tag

app_fr_CA.properties
welcomeMessage = Bonjour
signoffMessage = Bonne journée


Following is the screen shot of the maven project.

Following is the complete working application.
package resource_bundle.resource_bundle;

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

public class App {
 public static void main(String[] args) {
  ResourceBundle defaultPropertyFile = ResourceBundle.getBundle("app");
  ResourceBundle germanBundle = ResourceBundle.getBundle("app", Locale.GERMAN);
  ResourceBundle canadaFrenceBundle = ResourceBundle.getBundle("app", Locale.CANADA_FRENCH);

  /* Data from Default Property file information */
  System.out.println("defaultPropertyFile Values");
  System.out.println("welcomeMessage : " + defaultPropertyFile.getString("welcomeMessage"));
  System.out.println("signoffMessage : " + defaultPropertyFile.getString("signoffMessage"));
  System.out.println("version : " + defaultPropertyFile.getString("version"));

  /* Data from German Property file */
  System.out.println("\ngermanBundle Values");
  System.out.println("welcomeMessage : " + germanBundle.getString("welcomeMessage"));
  System.out.println("signoffMessage : " + germanBundle.getString("signoffMessage"));
  System.out.println("version : " + germanBundle.getString("version"));

  /* Data from Canada French property file */
  System.out.println("\ncanadaFrenceBundle Values");
  System.out.println("welcomeMessage : " + canadaFrenceBundle.getString("welcomeMessage"));
  System.out.println("signoffMessage : " + canadaFrenceBundle.getString("signoffMessage"));
  System.out.println("version : " + canadaFrenceBundle.getString("version"));

 }
}

Output
defaultPropertyFile Values
welcomeMessage : Good Morning
signoffMessage : Have a Good Day
version : 10.1

germanBundle Values
welcomeMessage : Guten Morgen
signoffMessage : Haben Sie einen guten Tag
version : 10.1

canadaFrenceBundle Values
welcomeMessage : Bonjour
signoffMessage : Bonne journée
version : 10.1

As you see the output, defaultPropertyFile instance return the values from app.properties file, germanBundle instance return the values from app_de.properties file and canadaFrenceBundle instance return the values from app_fr_CA.properties file.

One Key thing to note
As you see the property file, app_fr_CA.properties, app_de.properties, the property "version" is not present. But as you see the output the version is printing as '10.1'.

From where this version10.1 came?
If a ResourceBundle class for the specified Locale does not exist, getBundle tries to find the closest match. For example, if ButtonLabel_fr_CA_UNIX is the desired class and the default Locale is en_US, getBundle will look for classes in the following order:

ButtonLabel_fr_CA_UNIX
ButtonLabel_fr_CA
ButtonLabel_fr
ButtonLabel_en_US
ButtonLabel_en
ButtonLabel

So in our case the property version is not present in the files ‘app_de.properties’, ‘app_fr_CA.properties’, So ResourceBundle class tries to get the property from the nearest match, which is app.properties.

What if the property files are in some folder, not in src/main/resources?

If the property files are in folder "lang", you should use the baseName as "lang/app".

Ex:
String baseName = "lang/app";
                
ResourceBundle defaultPropertyFile = ResourceBundle.getBundle(baseName);
ResourceBundle germanBundle = ResourceBundle.getBundle(baseName, Locale.GERMAN);

ResourceBundle canadaFrenceBundle = ResourceBundle.getBundle(baseName, Locale.CANADA_FRENCH);

Following is the complete working application.
package resource_bundle.resource_bundle;

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

public class App {
 public static void main(String[] args) {
  String baseName = "lang/app";

  ResourceBundle defaultPropertyFile = ResourceBundle.getBundle(baseName);
  ResourceBundle germanBundle = ResourceBundle.getBundle(baseName, Locale.GERMAN);
  ResourceBundle canadaFrenceBundle = ResourceBundle.getBundle(baseName, Locale.CANADA_FRENCH);

  /* Data from Default Property file information */
  System.out.println("defaultPropertyFile Values");
  System.out.println("welcomeMessage : " + defaultPropertyFile.getString("welcomeMessage"));
  System.out.println("signoffMessage : " + defaultPropertyFile.getString("signoffMessage"));
  System.out.println("version : " + defaultPropertyFile.getString("version"));

  /* Data from German Property file */
  System.out.println("\ngermanBundle Values");
  System.out.println("welcomeMessage : " + germanBundle.getString("welcomeMessage"));
  System.out.println("signoffMessage : " + germanBundle.getString("signoffMessage"));
  System.out.println("version : " + germanBundle.getString("version"));

  /* Data from Canada French property file */
  System.out.println("\ncanadaFrenceBundle Values");
  System.out.println("welcomeMessage : " + canadaFrenceBundle.getString("welcomeMessage"));
  System.out.println("signoffMessage : " + canadaFrenceBundle.getString("signoffMessage"));
  System.out.println("version : " + canadaFrenceBundle.getString("version"));

 }
}







No comments:

Post a Comment