InternationalisationOverviewToday, few of the existing applications adopt themselves to the user's preferred language and customs. The problem is of especial interest for applications distributed over the Internet, where the language of the end user is not known. The best solution would be for the software to automatically detect the user's language and tailor the user interface accordingly. Another critical case is a multi-user environment with its need for software that supports several languages and enables the end user to choose between them. The fact that an application is available in several languages does not always solve the problem. For example, in order to make it speak both English and French, the customer usually needs to purchase and install a full English and a full French versions of the application. For many applications even this solution is not possible as the two versions cannot co-exist.Java InfoTorg application automatically detects and acts according to
the user's preferred language and customs. If no support for the required
language is available, the user is prompted to choose between the available
ones. Moreover, the language of the application can be changed at the run-time
and all the visual information and sounds will change accordingly. The
application's internationalisation architecture is extensible - adding
support for a new language does not require a recompilation of the existing
code. The work of the translator is taken into account. No knowledge of
the programming language or any special environment is required, the translator
works only with text files that contain lists of text equivalencies of
the following type:
Internationalisation support in JavaJava designers thought of internationalisation from the beginning of the Java design. Java uses the Unicode character encoding that covers most of the written languages of the world. It provides solutions for code internationalisation, which means separating language dependent code from language independent code. Internationalisation implies writing programs so that user texts, images and sounds of the GUI are not hardcoded directly in the program. Facilities for this programming technique have been integrated into Java API beginning from the version 1.1. You can learn more about it reading Writing Global Programs in Java Tutorial.What is a resource?Internationalisation means separating language dependent code from language independent code. When an internationalized application is translated into a new language, only the language dependent code is changed. Internationalisation implies writing programs so that texts, images and sounds of the GUI are not hard coded directly into the program. They are put in a separate file called resource file. Its location does not have to be that of the program's. A resource is thus a container for strings, images, sounds or other objects that are accessed by application code from an external source. The Java 1.1 API provides a mechanism to access resource files in a location independent manner. Any kind of resource files can be accessed by means of two methods in the class Class: getResource() and getResourceAsStream(). Both use the same search strategy to locate resources. In an application context, this search strategy implies looking up a resource on the local file system. In an applet context, it also includes looking it up on the Web server from which the applet was loaded.Getting a resource as URLThe method getResource(String name) of the class Class returns an URL for the resource. An URL provides access to image and audio files. To create an image from the file "infostore.gif", you can use the following code :
URL resourceasURL = getClass().getResource(resourcename); Toolkit toolkit = java.awt.Toolkit.getDefaultToolkit(); Image resource = toolkit.getImage(resourceasURL); Getting a resource as InputStreamThe method getResourceAsStream(String name) of the class Class returns an InputStream object. It can be used to initialize a Properties object that provides access to text strings. Here is an example :
Properties resource = new Properties(); InputStream resourceAsStream = getClass().getResourceAsStream(resourcename); resource.load(resourceAsStream);
What is a locale?Internationalisation in Java uses the locale concept. The same concept is also used in operating systems such as Unix and Windows. A locale represents a geographical or political region that shares the same language customs. The following are all examples of locale-sensitive data: labels for GUI
elements,
The Java 1.1 API supports the concept of Locale through the Locale
class. Internationalized programs use a Locale object to identify the user's
locale settings and behave differently according to its value. A Locale
object is frequently defined by a language, which is represented by its
standard lowercase two-letter code, such as en for English or fr
for French. Its specification can optionally include a country and a variant.
Variants are vendor and browser specific.
Locale localefrance = new Locale (code,"");
String canadacountrycode = "CA"; Locale localecanada = new Locale (code,canadacountrycode);
String canadacountrycode = "CA"; Locale localecanada = new Locale (code,canadacountrycode); Locale.setDefault (localecanada); Resource bundling classes in Java 1.1 APIOnce an application is internationalized, it needs a mechanism to access a particular resource that corresponds to a given locale. Java API provides resource bundling classes to manage resources. A resource bundle is a set of related classes that inherit from the abstract class ResourceBundle. The resources are seen as resource bundle families. For example, a resource bundle family that manages sounds of an application that supports British English, American English and French will be as follows:
SoundBundle_en_US.class SoundBundle_fr.class
String relativebundlefamilyname = "LabelBundle"; String bundlefamilyname = package + "." + relativebundlefamilyname; Locale locale = Locale.getDefault(); ResourceBundle buttonlabels = ResourceBundle.getBundle(bundlename,locale); Java Infotorg's internationalisation architectureJava Infotorg gets the most out of the internationalisation support in Java. The packages semagroup.infodata.client.ui.graphical.language and semagroup.infodata.client.ui.graphical represent the part of the program's structure that deals with the internationalisation.The package semagroup.infodata.client.ui.graphical.language manages internationalized resources of the application. The classes in semagroup.infodata.client.ui.graphical contains the implementation of the GUI.Before explaining the implementation in detail, here is a code extract
that shows how a label is created:
Label label = new java.awt.Label(labeltextpassword); Note that there is no hardcoded text in the program and the label will have a different title according to the language chosen by the user. The number of languages supported by the application can grow dynamically without any need for recompiling. Implementing resources in Java Infotorg [ PENDING ]Let us take the example of the login screen in Java Infotorg.It is made of two objects:
The resource handling object has as many methods as there are resources for the login screen. These methods have self explanatory names. getLabelTextPassword() retrieves the title of the label placed besides the field in which the user enters his password. getAudioWelcome() retrieves the audio message that welcomes the user to the application. You might wonder why we do not mention languages or locales in this section. The Locale is set at the beginning of the application and is used when we create the Resource handling object. Afterwards you just need to invoke the specific methods of the Resource handling object. This is how we load the resource bundle for the login screen. Note that
the bundle name argument is dynamically built in the actual application.
String TEXTS = "Texts"; String relativebundlename = "ResourceGraphicalConnectDataInputPeer"; String bundlename = package + "." + TEXTS + "." + relativebundlename; Locale locale = getLocale(); ResourceBundle resource = ResourceBundle.getBundle(bundlename,locale); This figure shows the different packages of the application mapped onto directories as well as the resource handling classes.
Factoring resource implementation in Java Infotorg [ PENDING ]The section below describes the implementation choices made in Java Infotorg.As mentioned earlier, internationalized resources are used by classes that implement the graphical user interface of the application. Each of these classes needs a handle to its resource handling class. Java Infotorg includes a helper class named semagroup.infodata.client.ui.UserInterface that creates a GUI object and its corresponding Resource handling object. Thus the method that instantiates the resource handling object is implemented in this helper class. It is named getResourceFor(ApplicationInputPeer peer) and here is its implementation. The comments inside the piece of code use the login screen example.
String LOCALE_PACKAGE = "language"; ResourceGraphicalApplicationInputPeer resource = null; // semagroup.infodata.util.ClassNameTokenizer is a helper class that // provides methods to manipulate class and package names. // For example, it supplies methods to build a resource handling class // name knowing its corresponding GUI class name. In the chosen context, // peer is an object of type // semagroup.infodata.client.ui.graphical. GraphicalConnectDataInputPeer. // The ClassNameTokenizer object initializes its // packageName property with the string // "semagroup.infodata.client.ui.graphical" and its relativeClassName // property with "GraphicalConnectDataInputPeer". ClassNameTokenizer classnametokenizer = new ClassNameTokenizer(peer); // The strings LOCALE_PACKAGE and "." are appended to the packageName // property. classnametokenizer.extendPackageNameBy(LOCALE_PACKAGE); // The string RESOURCE_PREFIX is prepended to the relativeClassName // property. classnametokenizer.extendClassNameBy(RESOURCE_PREFIX,true); // The ClassNameTokenizer object getClassName() method returns the class // name it has just built that is to say the string // "semagroup.infodata.client.ui.graphical.language. ResourceGraphicalConnectDataInputPeer". Class resourcetype = classnametokenizer.getClassName(); // The following line instantiates an object of type // semagroup.infodata.client.ui.graphical.language. ResourceGraphicalConnectDataInputPeer. resource = (ResourceApplicationInputPeer)createObject(resourcetype); // The resource variable is returned. return resource; Note that the returned variable resource is of type ResourceApplicationInputPeer. GraphicalConnectDataInputPeer needs to downcast it to its specific resource handling type ResourceGraphicalConnectDataInputPeer. As we already mentioned, resources are not hardcoded in Java Infotorg,
not only text but also images and audios. We store them in property files.
Images and audios are stored as relative paths to image and audio files.
Thus resource handling classes need specific methods to build
an image out of a path to an image file and an audio message out of a path
to an audio file.
return getAudio(PROPERTY_KEY); If you want to have a look at the code that implements the architecture
we have just described, here is the source code of the classes and
property files involved in the internationalisation of the login screen:
ResourceGraphicalConnectDataInputPeerImpl.properties ResourceGraphicalApplicationInputPeer gives the application access to internationalized resources. It provides methods to retrieve strings, images and sounds that are language dependent. This page describes Java Infotorg internationalisation architecture and explains how to extend it. Understanding the current architecture The application is a set of screens. Two objects describe a screen of
the application:
a Peer object of type ApplicationInputPeer
that provides the user interface
The Resource handling object uses property files to access language
dependent resources. A property file stores key/value pairs. For each
Let us take the example of the application login screen which is called
the ConnectData screen. The ConnectData screen is represented
private static String CANCEL = "ConnectData.text.cancel"; ConnectData.text.cancel is they key you will find with a different value
in each property file. Property file names are built by
a suffix corresponding to ResourceGraphicalConnectDataInputPeer
implementation class suffix, "Impl"
Language two-letter codes that follow the "_" are standardized. You
can find a full list of these codes on the following Unicode site. The
ConnectData.text.cancel=Cancel Implementing resources for a screen This part is meant to show how to provide resources for an existing
screen. Let us suppose this screen is called ConnectData and its
List of classes and files to provide Classes semagroup.infodata.client.ui.graphical.language. ResourceGraphicalConnectDataInputPeerImpl Files ResourceGraphicalConnectDataInputPeerImpl_fr.properties
(one for each language)
Methods ResourceGraphicalConnectDataInputPeerImpl implements the methods retrieving
the ConnectData screen specific resources.
Go to Index Go to Table of Contents Author : f92-bro@nada.kth.se
|