Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Tools

How do I Write an International Application?


Dr. Dobb's Journal July 1997: Java Q&A

Cliff, vice president of technology of Digital Focus, can be contacted at [email protected]. To submit questions, check out the Java Developer FAQ web site at http://www.digitalfocus.com/faq/.


The Internet has opened up the world to computing. Simply by using e-mail, or transferring/hosting software on the Web, it becomes as easy to work with people on the other side of the globe, as it is to work with people on the other side of town. Java helps makes this possible because it is a network-capable language. International companies want to take advantage of this boundless computing model, and write applications that customers and a global workforce can access anywhere -- in any language.

Java is touted as a multilanguage-capable computer language because it provides built-in support for Unicode. This is not enough, however, for true multilanguage support. There also needs to be support for displaying monetary currencies, and foreign number, date, and time formats. It would also be nice if multilanguage support was easy to implement, without hardcoding of language-specific strings. JDK 1.1 provides a suite of packages for multilanguage and multinational development. While I won't get into all of the features of those packages here, I will show how to use some of the more important ones.

Locales, Resources,and Resource Bundles

JDK 1.1 introduces the term "locale" -- a specification of any of spoken language, geographic location, and additional qualifiers that may be built-in. Generally, a locale can be, for example, the combination "English" and "England," or "English" and "Australia." A locale need not specify everything: The resource that most closely matches the specification is used, and if none matches, resources for a default locale are used.

The new JDK 1.1 resource mechanism (in the package called "util") is the foundation for the internationalization facilities. Resources are location-independent collections of information that may be retrieved by name. They relocate automatically with the program no matter how it is deployed. A resource can be an image file, text string, or any Java object. It may be stored in a property file or as a stream of bytes.

The key feature of a resource is that it is designed to follow the application. It may be encapsulated into a JAR file, for example. Regardless, it is always accessed the same way -- with the class loader's getResource() method. (A Class object also has a getResource() method, but it merely calls the getResource() method of the class loader that loaded the class.)

A ResourceBundle is a collection of resources specifically designed to aggregate those resources needed for a specific geographic locale or spoken language. A naming convention serves to identify specific-resource bundles according to their locale, so that the resource-bundle methods know which resource bundle to select, based on the current locale. A locale can be set on a per-object basis, as opposed to a system-wide basis, making it possible to deal with more than one locale at a time. This is important, for example, for multilanguage programs, such as language translators.

The Calculator Class

Figures 1 and 2 show multilanguage desk calculators that let you select from one of two languages (German and English), and one of two modes (Standard and Currency). Whenever one of these selections is changed, the calculator reconfigures itself accordingly. For example, when German is selected as the language (as in Figure 1), control labels are displayed in the German language. If mode is set to Currency, numeric values are displayed as currency values, either in dollars or Deutschmarks, depending on the language selected. Figure 2 shows an English version of the calculator.

The calculator class (available electronically; see "Availability," page 3) is implemented as an applet, since one use of an international program is as a browser-based application. Since JDK 1.1 is required, browsers that have not yet implemented JDK 1.1 will not be able to run it. At this writing, HotJava and Appletviewer support JDK 1.1.

The first thing the applet does is instantiate all of its GUI components in its init() method. Since this is a 1.1 application, each component specifies an event handler (an ActionListener or ItemListener, in this case). For simplicity, I have chosen to put all of the event-handling behavior in the applet, so the applet implements both ActionListener and ItemListener. The init() method then calls updateGui(), which obtains the resources needed to support the new settings, then redisplays the applet with those settings and resources. This method is also called whenever users reconfigure the applet by changing the language selection, or the calculator mode.

The first thing updateGui() does is call getLocaleSetting(). This method gets the user's language selection by comparing the text of the language-choice selection with the built-in language name string for each of our two supported languages. These are the same strings used when building the language-choice control, so one should match the user's selection. When a match is found, the private variable "locale" is set to the corresponding built-in locale. (There are presently 28 built-in locales.) getLocaleSetting() then gets the resource bundle for the locale by calling the static method java.util.ResourceBundle.getBundle("ButtonLabelResources", locale). This method attempts to locate the ButtonLabelResources resource bundle for the specified locale. A resource bundle can be a property file or Java class. I have chosen to use a property file in this case. (In fact, there are two property files -- ButtonLabelResources.properties, and ButtonLabelResources_de.properties.) The getBundle() method uses the convention "<bundle_name>_<language>_<country>.properties" to identify a resource file, and since "de" identifies German, the German language resource bundle will automatically be loaded. I could have specified a country (there are currently three German-speaking countries defined), but chose not to, so only the language will be used as a resource selection criteria. (At this writing, the supported locales are listed at http://www.javasoft.com/products/jdk/1.1/intl/html/intlspec.doc2.html.) Finally, getLocaleSetting() sets the current locale to be the one that the user has selected.

The updateGui() method makes the calls in Listing One To understand these lines, look at what is contained in the aforementioned properties files. The standard properties file (the one without _de in its name) contains Listing Two. Thus, three properties are specified. If the system chooses this properties file when it searches for the ButtonLabelBundle resource bundle, it will get these values. If on the other hand it chooses the German resource bundle, contained in ButtonLabelBundle_de.properties, it will get the values in Listing Three.

The first line contains a Unicode-escaped character sequence, which represents the German word for currency (Währung). If I had a German-language Unicode-based editor, I could have typed this word in directly, without resorting to the escape sequence.

The first line in each property file is, therefore, the label that is to be used on the radio button that the user clicks when selecting currency mode. When German is selected as the locale, this is displayed in German; when working in English mode, the word "Currency" is displayed.

The second line is the label to use for the other radio button, which selects noncurrency, or Standard mode. Since the German adjective for "standard" is the same as the English word "standard," the second line in each file is identical. The last line in each file specifies a GIF filename, which is loaded by Listing Four.

I get the name of the file resource from the resource bundle, then use that name to find the actual resource -- the file. I then request a repaint. Since my paint() method draws the imageURL object on the applet, I effectively have a different image drawn for each language selection. Note that I display the selected country's flag.

Finally, updateGui() makes the calls in Listing Five in which the first line sets a format-object reference depending on the state of the mode checkboxes. A format object (in the package called "java.text") can be one of several kinds of object that act as input and output formatting services (conceptually similar to the way C-formatted I/O functions work -- although better thought out). I use a numeric formatter when the mode is Standard, and a currency formatter when the mode is Currency. Note that specifying the locale is sufficient for the formatter to know how to format numbers and currency amounts uniquely for each locale. (In many European countries, thousands are separated with periods, and the decimal point is displayed with a comma -- exactly the reverse of the standard practice in the U.S.) The formatting is even smart enough to know that the German currency is Deutschmarks, but alas, not smart enough to call an online currency-exchange service to get the going conversion rate.Listing Six is the code the runs the applet.

The complete source code for the applet is available at the Digital Focus web site (http://www.digitalfocus.com/ddj/code/).

Conclusion

The internationalization resource mechanisms provided by JDK 1.1 are not only flexible and powerful, but extremely easy to use. There are a large number of methods, only a few of which I've touched on here. Do not be intimidated, however, because the API is well thought out and simple to understand. Furthermore, once you get used to the resource mechanism, you will find that it makes keeping track of images and other items used by a program much easier. You'll be able to package resources into a JAR file with your applet and not have to worry about whether the applet can find them.


Listing One

currencyCheckbox.setLabel(buttonLabelBundle.getString("CurrencyLabel"));standardCheckbox.setLabel(buttonLabelBundle.getString("StandardLabel"));

Back to Article

Listing Two

CurrencyLabel=CurrencyStandardLabel=Standard
FlagImage=us_flag.gif

Back to Article

Listing Three

CurrencyLabel=W\u00e4hrungStandardLabel=Standard
FlagImage=de_flag.gif

BACK TO ARTICLE

Listing Four

String imageName = buttonLabelBundle.getString("FlagImage");java.net.URL imageURL = getClass().getResource(imageName);
image = getImage(imageURL);

BACK TO ARTICLE

Listing Five

if (standardCheckbox.getState())   format = java.text.NumberFormat.getInstance(locale);
else
   format = java.text.NumberFormat.getCurrencyInstance(locale);
setDisplayValue();

BACK TO ARTICLE

Listing Six

<html><applet code="Calculator.class" width=325 height=250>
</applet>
</html>

BACK TO ARTICLE

DDJ


Copyright © 1997, Dr. Dobb's Journal


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.