Win a copy of The Business Blockchain this week in the Cloud forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

3 Features of Java for Internationalization

 
scott irwin
Ranch Hand
Posts: 87
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I did a thread search and found confusion. The objective doesn't ask where to do internationalization (blue prints 4.5.1), but rather what specifically in the Java language supports internationalization. There are way more than 3 classes to support internationalization. So I guess we get to pick from some list which classes do and don't.
java.util.ListResourceBundle
java.util.ResourceBundle
java.util.PropertyResourceBundle
java.util.Locale
java.text.DateFormat
java.text.NumberFormat
java.text.MessageFormat
More classes
Since this is not a programming test, I'm only studying what they do, not their API.
What are you guys studying for internationalization?
Scott
 
John Wetherbie
Rancher
Posts: 1449
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Here are my notes. References are listed at the bottom. Hope they help.
Sun Certified Enterprise Architect for Java 2
Study Notes for Internationalization
General
An internationalized program has the following characteristics:
With the addition of localization data, the same executable can run worldwide.
Textual elements, such as status messages and the GUI component labels, are not hard-coded in
the program. Instead they are stored outside the source code and retrieved dynamically.
Support for new languages does not require recompilation.
Culturally-dependent data, such as dates and currencies, appear in formats that conform to the end
user's region and language.
It can be localized quickly.
Localization is the process of adapting a program for use in a specific locale. A locale is a geographic or political region that shares the same language and customs. Localization includes the translation of text such as GUI labels, error messages, and online help. It also includes the culture-specific formatting of data items such as monetary values, times, dates, and numbers.
Objectives
1) State three aspects of any application that might need to be varied or customized in different deployment locales.
There are many types of data that vary with region or language. Examples of this data are:
Messages
Labels on GUI components
Online help
Sounds
Colors
Graphics
Icons
Dates
Times
Numbers
Currencies
Measurements
Phone numbers
Honorifics and personal titles
Postal addresses
Page layouts
2) Match the following features of the Java 2 platform with descriptions of their functionality, purpose or typical uses: Properties, Locale, ResourceBundle, Unicode, java.text package, InputStreamReader and OutputStreamWriter.
Properties:
The java.util.Properties class represents a persistent set of properties. The Properties can be saved to a stream or loaded from a stream. Each key and its corresponding value in the property list is a string.. A properties file stores information about the characteristics of a program or environment including internationalization/localization information.
By creating a Properties object and using the load method a program can read a properties file. The program can then access the values by using the key as follows:
Properties props = new Properties();
props.load(new BufferedInputStream(new FileInputStream("filename");
String value = System.getProperty("key");
If the key is not found getProperty returns null.

Locale:
A java.util.Locale object represents a specific geographical, political, or cultural region. An operation that requires a Locale to perform its task is called locale-sensitive and uses the Locale to tailor information for the user. For example, displaying a number is a locale-sensitive operation--the number should be formatted according to the customs/conventions of the user's native country, region, or culture.
Because a Locale object is just an identifier for a region, no validity check is performed when you construct a Locale. If you want to see whether particular resources are available for the Locale you construct, you must query those resources. For example, ask the NumberFormat for the locales it supports using its getAvailableLocales method.
Note: When you ask for a resource for a particular locale, you get back the best available match, not necessarily precisely what you asked for. For more information, refer to the ResourceBundle section.
The Locale class provides a number of convenient constants that you can use to create Locale objects for commonly used locales. For example, the following creates a Locale object for the United States:
Locale.US
Once you've created a Locale you can query it for information about itself. Use getCountry to get the ISO Country Code and getLanguage to get the ISO Language Code. You can use getDisplayCountry to get the name of the country suitable for displaying to the user. Similarly, you can use getDisplayLanguage to get the name of the language suitable for displaying to the user. Interestingly, the getDisplayXXX methods are themselves locale-sensitive and have two versions: one that uses the default locale and one that uses the locale specified in the argument.
ResourceBundle:
Resource bundles contain locale-specific objects. When your program needs a locale-specific resource, a String for example, your program can load it from the resource bundle that is appropriate for the current user's locale. In this way, you can write program code that is largely independent of the user's locale isolating most, if not all, of the locale-specific information in resource bundles.
This allows you to write programs that can:
�be easily localized, or translated, into different languages
�handle multiple locales at once
�be easily modified later to support even more locales
One resource bundle is, conceptually, a set of related classes that inherit from ResourceBundle. Each related subclass of ResourceBundle has the same base name plus an additional component that identifies its locale. For example, suppose your resource bundle is named MyResources. The first class you are likely to write is the default resource bundle which simply has the same name as its family--MyResources. You can also provide as many related locale-specific classes as you need: for example, perhaps you would provide a German one named MyResources_de.
Each related subclass of ResourceBundle contains the same items, but the items have been translated for the locale represented by that ResourceBundle subclass. For example, both MyResources and MyResources_de may have a String that's used on a button for canceling operations. In MyResources the String may contain Cancel and in MyResources_de it may contain Abbrechen.
If there are different resources for different countries, you can make specializations: for example, MyResources_de_CH is the German language (de) in Switzerland (CH). If you want to only modify some of the resources in the specialization, you can do so.
When your program needs a locale-specific object, it loads the ResourceBundle class using the getBundle method:
ResourceBundle myResources =
ResourceBundle.getBundle("MyResources", currentLocale);

The first argument specifies the family name of the resource bundle that contains the object in question. The second argument indicates the desired locale. getBundle uses these two arguments to construct the name of the ResourceBundle subclass it should load as follows.
The resource bundle lookup searches for classes with various suffixes on the basis of (1) the desired locale and (2) the current default locale as returned by Locale.getDefault(), and (3) the root resource bundle (baseclass), in the following order from lower-level (more specific) to parent-level (less specific):
baseclass + "_" + language1 + "_" + country1 + "_" + variant1
baseclass + "_" + language1 + "_" + country1 + "_" + variant1 + ".properties"
baseclass + "_" + language1 + "_" + country1
baseclass + "_" + language1 + "_" + country1 + ".properties"
baseclass + "_" + language1
baseclass + "_" + language1 + ".properties"
baseclass + "_" + language2 + "_" + country2 + "_" + variant2
baseclass + "_" + language2 + "_" + country2 + "_" + variant2 + ".properties"
baseclass + "_" + language2 + "_" + country2
baseclass + "_" + language2 + "_" + country2 + ".properties"
baseclass + "_" + language2
baseclass + "_" + language2 + ".properties"
baseclass
baseclass + ".properties"
For example, if the current default locale is en_US, the locale the caller is interested in is fr_CH, and the resource bundle name is MyResources, resource bundle lookup will search for the following classes, in order:
MyResources_fr_CH
MyResources_fr
MyResources_en_US
MyResources_en
MyResources
The result of the lookup is a class, but that class may be backed by a properties file on disk. That is, if getBundle does not find a class of a given name, it appends ".properties" to the class name and searches for a properties file of that name. If it finds such a file, it creates a new PropertyResourceBundle object to hold it. Following on the previous example, it will return classes and and files giving preference as follows: (class) MyResources_fr_CH (file) MyResources_fr_CH.properties (class) MyResources_fr (file) MyResources_fr.properties (class) MyResources_en_US (file) MyResources_en_US.properties (class) MyResources_en (file) MyResources_en.properties (class) MyResources (file) MyResources.properties If a lookup fails, getBundle() throws a MissingResourceException.
The baseclass must be fully qualified (for example, myPackage.MyResources, not just MyResources). It must also be accessable by your code; it cannot be a class that is private to the package where ResourceBundle.getBundle is called.
Note: ResourceBundles are used internally in accessing NumberFormats, Collations, and so on. The lookup strategy is the same.
Resource bundles contain key/value pairs. The keys uniquely identify a locale-specific object in the bundle. Here's an example of a ListResourceBundle that contains two key/value pairs:
class MyResource extends ListResourceBundle {
public Object[][] getContents() {
return contents;
}
static final Object[][] contents = {
// LOCALIZE THIS
{"OkKey", "OK"},
{"CancelKey", "Cancel"},
// END OF MATERIAL TO LOCALIZE
};
}

Keys are always Strings. In this example, the keys are OkKey and CancelKey. In the above example, the values are also Strings--OK and Cancel--but they don't have to be. The values can be any type of object.
You retrieve an object from resource bundle using the appropriate getter method. Because OkKey and CancelKey are both strings, you would use getString to retrieve them:
button1 = new Button(myResourceBundle.getString("OkKey"));
button2 = new Button(myResourceBundle.getString("CancelKey"));

The getter methods all require the key as an argument and return the object if found. If the object is not found, the getter method throws a MissingResourceException.
Besides getString; ResourceBundle supports a number of other methods for getting different types of objects such as getStringArray. If you don't have an object that matches one of these methods, you can use getObject and cast the result to the appropriate type. For example:
int[] myIntegers = (int[]) myResources.getObject("intList");

NOTE: You should always supply a baseclass with no suffixes. This will be the class of "last resort", if a locale is requested that does not exist. In fact, you must provide all of the classes in any given inheritance chain that you provide a resource for. For example, if you provide MyResources_fr_BE, you must provide both MyResources and MyResources_fr or the resource bundle lookup won't work right.
The Java 2 platform provides two subclasses of ResourceBundle, ListResourceBundle and PropertyResourceBundle, that provide a fairly simple way to create resources. (Once serialization is fully integrated, we will provide another way.) As you saw briefly in a previous example, ListResourceBundle manages its resource as a List of key/value pairs. PropertyResourceBundle uses a properties file to manage its resources.
If ListResourceBundle or PropertyResourceBundle do not suit your needs, you can write your own ResourceBundle subclass. Your subclasses must override two methods: handleGetObject and getKeys().
The following is a very simple example of a ResourceBundle subclass, MyResources, that manages two resources (for a larger number of resources you would probably use a Hashtable). Notice that if the key is not found, handleGetObject must return null. If the key is null, a NullPointerException should be thrown. Notice also that you don't need to supply a value if a "parent-level" ResourceBundle handles the same key with the same value (as in United Kingdom below). Also notice that because you specify an en_GB resource bundle, you also have to provide a default en resource bundle even though it inherits all its data from the root resource bundle.
Example:
// default (English language, United States)
abstract class MyResources extends ResourceBundle {
public Object handleGetObject(String key) {
if (key.equals("okKey")) return "Ok";
if (key.equals("cancelKey")) return "Cancel";
return null;
}
}
// German language
public class MyResources_de extends MyResources {
public Object handleGetObject(String key) {
// don't need okKey, since parent level handles it.
if (key.equals("cancelKey")) return "Abbrechen";
return null;
}
}

You do not have to restrict yourself to using a single family of ResourceBundles. For example, you could have a set of bundles for exception messages, ExceptionResources (ExceptionResources_fr, ExceptionResources_de, ...), and one for widgets, WidgetResource (WidgetResources_fr, WidgetResources_de, ...); breaking up the resources however you like.
Unicode:
Unicode is an international effort to provide a single character set that everyone can use.
Java uses the Unicode 2.0 (or 2.1) character encoding standard. In Unicode, every character occupies two bytes. Ranges of character encodings represent different writing systems or other special symbols. For example, Unicode characters in the range 0x0000 through 0x007F represent the basic Latin alphabet, and characters in the range 0xAC00 through 0x9FFF represent the Han characters used in China, Japan, Korea, Taiwan, and Vietnam.
UTF is a multibyte encoding format, which stores some characters as one byte and others as two or three bytes. If most of your data is ASCII characters, it is more compact than Unicode, but in the worst case, a UTF string can be 50 percent larger than thecorresponding Unicode string. Overall, it is fairly efficient.
Despite the advantages of Unicode, there are some drawbacks: Unicode support is limited on many platforms because of the lack of fonts capable of displaying all the Unicode characters.
java.text:
This package provides classes and interfaces for handling text, dates, numbers, and messages in ways that are independent of natural languages. This allows programs to be written in a language-independent manner and relies on separate, dynamically linked localized resources.
These classes are capable of formatting dates, numbers, and messages, parsing; searching and sorting strings; and iterating over characters, words, sentences, and line breaks. This package contains three main groups of classes and interfaces:
Classes for iteration over text
Classes for formatting and parsing
Classes for string collation
Some of the classes in the java.text package are:
Annotation
An Annotation object is used as a wrapper for a text attribute value if the attribute has annotation characteristics. These characteristics are:
The text range that the attribute is applied to is critical to the semantics of the range. That means, the attribute cannot be applied to subranges of the text range that it applies to, and, if two adjacent text ranges have the same value for this attribute, the attribute still cannot be applied to the combined range as a whole with this value.
The attribute or its value usually no longer applies if the underlying text is changed.
An example is grammatical information attached to a sentence: For the previous sentence, you can say that "an example" is the subject, but you cannot say the same about "an", "example", or "exam". When the text is changed, the grammatical information typically becomes invalid. Another example is Japanese reading information (yomi).
Wrapping the attribute value into an Annotation object guarantees that adjacent text runs don't get merged even if the attribute values are equal, and indicates to text containers that the attribute should be discarded if the underlying text is modified.
CollationKey
A CollationKey represents a String under the rules of a specific Collator object. Comparing two
CollationKeys returns the relative order of the Strings they represent. Using CollationKeys to compare
Strings is generally faster than using Collator.compare. Thus, when the Strings must be compared multiple
times, for example when sorting a list of Strings. It's more efficient to use CollationKeys.
You can not create CollationKeys directly. Rather, generate them by calling Collator.getCollationKey. You
can only compare CollationKeys generated from the same Collator object.
Generating a CollationKey for a String involves examining the entire String and converting it to series of bits that can be compared bitwise. This allows fast comparisons once the keys are generated. The cost of generating keys is recouped in faster comparisons when Strings need to be compared many times. On the other hand, the result of a comparison is often determined by the first couple of characters of each String. Collator.compare examines only as many characters as it needs which allows it to be faster when doing single comparisons.
Collator
The Collator class performs locale-sensitive String comparison. You use this class to build searching and sorting routines for natural language text.
Collator is an abstract base class. Subclasses implement specific collation strategies. You can use the static factory method, getInstance, to obtain the appropriate Collator object for a given locale.
Format
Format is an abstract base class for formatting locale-sensitive information such as dates, messages, and numbers.
Format defines the programming interface for formatting locale-sensitive objects into Strings (the format method) and for parsing Strings back into objects (the parseObject method). Any String formatted by format is guaranteed to be parseable by parseObject.
Format has three subclasses: DateFormat, MessageFormat, NumberFormat
InputStreamReader:
An InputStreamReader is a bridge from byte streams to character streams: It reads bytes and translates them into characters according to a specified character encoding. The encoding that it uses may be specified by name, or the platform's default encoding may be accepted.
The class has two constructors: one that uses the platform's default encoding and one that takes an encoding (as a String). Encodings can be represented by their ISO numbers, i.e., ISO 8859-9 is represented by "8859_9".
There is no easy way to determine which encodings are supported. You can use the getEncoding() method to get the name of the encoding being used by the Reader.
Characters that do not exist in a specific character set produce a substitution character, usually a question mark.
OutputStreamReader:
An OutputStreamWriter is a bridge from character streams to byte streams: Characters written to it are translated into bytes according to a specified character encoding. The encoding that it uses may be specified by name, or the platform's default encoding may be accepted.
Each invocation of a write() method causes the encoding converter to be invoked on the given character(s). The resulting bytes are accumulated in a buffer before being written to the underlying output stream. The size of this buffer may be specified, but by default it is large enough for most purposes. Note that the characters passed to the write() methods are not buffered.
The class has two constructors: one that uses the platform's default encoding and one that takes an encoding (as a String). Encodings can be represented by their ISO numbers, i.e., ISO 8859-9 is represented by "8859_9".
There is no easy way to determine which encodings are supported. You can use the getEncoding() method to get the name of the encoding being used by the Writer.
Characters that do not exist in a specific character set produce a substitution character, usually a question mark.

References:
Java 2 API http://java.sun.com/j2se/1.3/docs/api/index.html
Java I/OE. R. Harold, O'Reilly, 1999
 
scott irwin
Ranch Hand
Posts: 87
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for the notes!
Scott
 
Raj Mohan
Ranch Hand
Posts: 73
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for the notes John.
 
Madhu Juneja
Ranch Hand
Posts: 176
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Two chapters on I18n are available online from the Oreilly Book Java Internationalization.
Refer : http://developer.java.sun.com/developer/Books/Internationalization/index.html?frontpage-jdc
 
Angela Poynton
Ranch Hand
Posts: 3143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
That is an excellent book BTW .. I'm reading it right now!
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic