## 5 Internationalization

A commonLogger may have a Resource Bundle name associated with it. The corresponding Resource Bundle can be used to map between raw message strings and localized message strings.
The Common Logging Framework relies on the underlying logging implementation to take into account the Resource Bundle by requesting the appropriate API. When instantiated a commonLogger object can be associated with a ResourceBundle name by provided in the getLogger method on the LoggerFactory.

The following class named, logi18n, illustrates how the Common Logging Framework manages i18n.

import com.hp.mw.common.util.logging.CommonLevel; import com.hp.mw.common.util.logging.commonLogger; import com.hp.mw.common.util.logging.LoggerFactory; import com.hp.mw.common.util.logging.LogManager; import java.util.*; public class logi18n{ static LoggerFactory log_fac = LogManager.getLogFactory(); static String language = System.getProperty("language", "en"); static String country = System.getProperty("country", "US"); private static Locale currentLocale = new Locale(language,country); //(1) private static ResourceBundle log_mesg = ResourceBundle.getBundle("logging_msg", currentLocale); // (2) static commonLogger mylog = (CommonLogger)log_fac.getLogger(logi18n.class.getName(), "logging_msg_"+language+"_"+country); public static void main(String[] args) { mylog.log(CommonLevel.FATAL,"FATAL_Message"); mylog.log(CommonLevel.INFO,"INFO_Message"); } }

Within the logi18n class, messages defined with specific keys are displayed according to the language or Locale object specified by the application (1). As mentioned the US English is chosen by default. To determine the national text associated with a key (given with the log request), The ResourceBundle object is then created (3) and associated with the “logging_msg” which indicates to the ResourceBundle to seek a file beginning with its name as a prefix, where the rest of the file name is obtained with the Locale object. For instance, if the language chosen by the application is the US English, the file name to be considered is “logging_msg_en_US.properties”, while for the French used in France, the file name to be considered will be “logging_msg_fr_FR.properties”. Such properties file contains a national corresponding a key provided in the logging request.
The following files illustrate how national texts are provided for the English and the French. Additional files appropriate to other languages can be defined in a similar way.

- logging_msg_en_US.properties
FATAL_Message = This is a Fatal message
INFO_Message = This is an Info message
- logging_msg_fr_FR.properties
FATAL_Message = Ceci est un message Fatal
INFO_Message = Ceci est un message pour information

A log message provided with a string key, used as an entry by the ResourceBundle object to determine the corresponding text in a properties file, may be associated with a set of arguments for which their positions have previewed in the properties files. The following example illustrates how a set of arguments is associated with a key in the properties file. Assume that the logging_msg_en_US and logging_msg_fr_FR file contain respectively the following entry:

> - English
> IDENTIFICATION = The FirstName is {0} and the LastName is {1}
> - French
> IDENTIFICATION = Le prenom est {0} et le nom est {1}

The class logi18n may extended with:

public class logi18n{ . . . public static void main(String[] args) { Object[] myParams = new Object[2]; myParams[0]= “Foo”; myParams[1]= “Bar”; mylog.info("IDENTIFICATION",myParams); . . . } }

When the logi18n class is executed the variable replacement, defined with the key named IDENTIFICATION, are specified with the arguments provided in myParams.

#### Missing Resource

If a commonLogger object is used to manage i18n, any string key provided in a logging request should have an entry in the properties file. If not the commonLogger object accepts the provided key, but uses this key as a text to be logger in addition to mention that the associated entry does not exist in the provided bundle name. The following example is an illustration. In the class logi18n described above we assume that an additional logging request is invoked on the commonLogger object but using an entry which does not exist in the properties files

public class logi18n{ . . . public static void main(String[] args) { mylog.log(CommonLevel.FATAL,"Test_Message"); . . . } }

Assuming that the FATAL log level is enabled, and the language is the French, the produced log message is.

> [19 mars 2002 - 10:51:26][main ][FATAL] - String "FATAL_Message" not found in bundle "logging_msg_fr_FR".

Note that the message is “String “Test Message” is in English”

#### Per Class/Per Module Resource Bundle

When requested to log a message, a commonLogger object can determine if the provided message has to be sent as it to the output or corresponds to a key associated with a resource bundle (then used to retrieve a national text). To distinguish these two cases, the commonLogger can determine if a resource bundle is associated with a log request as follow:

- Default resource bundle associated with the commonLogger;
There are two ways to associate a default resource bundle with a commonLogger:

- At the creation via the getLogger method defined by the LoggerFactory, as follow:
commonLogger getLogger(String key, String resourceBundleName);
- Set a resource bundle name with the following method defined by the commonLogger
void setResourceBundleName(String BaseName);

- Resource bundle name specified with the log request
A set of methods with a “b” suffix (“b” for bundle) have been defined on the commonLogger interface to allow the possibility to specify the resource bundle that should be used by the commonLogger to retrieve the String associated to a message. These methods are: logb, debugb, infob, warnb, errorb and fatalb.
If requested with a method defining a resource bundle, a commonLogger object will seek the specified resource bundle. If found, the message is sought within the loaded resource bundle, If the specified resource bundle does not exist the commonLogger checks if a default resource bundle has been specified to use instead.

A commonLogger object can be used either by one particular class or by a set of classes, which may belong to a particular set we refer as a module. A class using a commonLogger object can either define its own resource bundle – resource bundle per class- or share one with other classes – resource bundle per module.
To enable a class to specify the resource bundle to use for it’s a log request, methods allowing to provide the resource bundle name are used.

#### Get the String without logging

An application can request a commonLogger object to obtain a string associated with a message defined in a resource bundle. The following methods are provided for this aim – these methods do not sent the message to the output with a particular log level.

/** Get an object from the commonLogger using a string key if a default * ResourceBundle is associated with it. */ String getString(String Key) throws MissingResourceException ; /** Get an object from the commonLogger using a key and arguments if a default * ResourceBundle is associated with it. */ String getString(String Key, Object[] arguments) throws MissingResourceException; /** Get an object from the commonLogger using a string key in the ResourceBundle * specified with BundleName. */ String getString(String BundleName, String Key) throws MissingResourceException ; /** Get an object from the commonLogger using a key and arguments in the * ResourceBundle specified with BundleName.*/ String getString(String BundleName, String Key, Object[] arguments) throws MissingResourceException;

#### Resource Bundle List

In addition to the possibility to define a default resource bundle name at the commonLogger creation via the method getLogger (getLogger(String key, String resourceBundleName), or setResourceBundle, a list of default resource bundle names can be associated with a commonLogger. Hence, a string provided with a logging request will be sought not only in one default resource bundle but in all resource bundles defined in the list. In order to define such resource bundle list the following class is provided:

package com.hp.mw.common.util.logging; public class ListBundleNames { /** Constructs a new instance of ListBundleNames */ public ListBundleNames() {. . . } /** add a resource bundle name in the list */ public void add(Object obj) { . . . } /** remove a resource bundle name from the list */ public void remove(Object obj) { . . . } /** Determines if a resource bundle name is in the list */ public boolean contains(Object obj) {. . .} /** Get the first resource bundle name from the list */ public Object getFirst() {. . . } /** Get the last resource bundle name from the list */ public Object getLast() {. . . } /** Get a resource bundle name from the list */ public Object getElement(int index) {. . . } /** Determines if the list is empty */ public boolean isEmpty() {. . . } /** get the nombre of elements in the list */ public int size() {. . . } }

The following scenario illustrates how a resource bundle list can be associated to a commonLogger at is creation and how an element can be removed from the list.

import com.hp.mw.common.util.logging.CommonLevel; import com.hp.mw.common.util.logging.commonLogger; import com.hp.mw.common.util.logging.LoggerFactory; import com.hp.mw.common.util.logging.LogManager; import com.hp.mw.common.util.logging.ListBundleNames; import java.util.*; public class BundleList{ static LoggerFactory log_fac = LogManager.getLogFactory(); static String language = System.getProperty("language", "en"); static String country = System.getProperty("country", "US"); private static Locale currentLocale = new Locale(language,country); static ListBundleNames myBundList = new ListBundleNames(); static commonLogger mylog ; public static void main(String[] args) { myBundList.add("logging_msg_"+language+"_"+country); myBundList.add("logging_msg_test"); System.out.println("My bund list size is : "+myBundList.size()); mylog = (commonLogger)log_fac.getLogger("BundleList", myBundList); Object[] myParams = new Object[2]; myParams[0]= “Foo”; myParams[1]= “Bar”; mylog.info("IDENTIFICATION",myParams); mylog.log(CommonLevel.FATAL,"FATAL_Message"); mylog.log(CommonLevel.INFO,"INFO_Message"); myBundList.remove("logging_msg_test"); mylog.log(CommonLevel.FATAL,"msg_test"); myBundList.remove("logging_msg_test"); mylog.log(CommonLevel.FATAL,"msg_test"); // NOT found message is returned for the above request } }

Main Previous Next