Introduction to IBM Classes for
Unicode
2.2 Translate
Strings
The first step to take in preparing your
program is to enable translation of display strings by separating them from the rest of
your code. This is done via ResourceBundles . These provide a general mechanism
that allows you to access strings and other objects according to locale conventions. In
principle, they are fairly simple: They simply provide a mapping from <key,locale>
to <value>. However, they also supply inheritance among locale resources that allows
you to minimize duplication across countries, and gives you a graceful degradation in case
the exact locale does not have localized resources. As you will see, the use of
ResourceBundles requires a different syntax in Java then it does in C++ (and thus C).
Unfortunately, at this point in time, you will have to change your code by hand to make
your strings translatable. You can do the bulk of the work with a PERL script if you want,
but you will still have to check the results. The general problem with converting strings
automatically is the difficulty in distinguishing display strings from non-display
strings. In the case of Java, once the commercial Java development environments fully
support resource bundles, this task should become easier, since they will make it easy to
avoid mixing display strings in the code in the first place.
Resource bundles do not have the same meaning in Java as they do in C/C++. In Java,
they are both the object and the class file (compiled format) storing relevant localized
information. In C/C++ a Resource Bundle is the object that allows your programs to
interface with a text format resource file containing relevant localized information.
Resource bundles in Java are very flexible--so flexible that getting started may be
mystifying. You can use list resource bundles, property resource bundles, or you can make
your own. You can have fine-grained bundles or coarse-grained, and so on. To give you some
direction, we'll start by showing one particular way to use resource bundles, you can see
other options by looking at the JDK API.
Making a
ResourceBundle in Java
In Java, create a class called MyResources.
A French resource bundle might contain the following
Java |
| public class
MyResources extends ListResourceBundle { // boilerplate
public static ResourceBundle rb = ResourceBundle.getBundle("MyResources");
public Object[][] getContents() { return contents; }
static final Object[][] contents = {
{"Greeting", "Bonjour"},
{"Thanks", "Merci"}
{"DayAbreviations",
new String[] {
"dim.", "lun.", "mar.",
"mer.", "jeu.", "ven.", "sam."
}
}
};
}
//rb is a convenience for getting resource bundle objects
//getContents is required in all ListResourceBundles
//contents will hold localization data, as we'll see
later |
Making a
ResourceBundle in C++/C
The resource bundle file is a text
(ASCII or Unicode) file with the format:
"Key1" {Value1}
"Key2" {Value2}
The keys are used to retrieve the value later. You may not have multiple instances of the
same key.
e.g. A French Locale file might contain the following:
C/C++ |
"Greeting" {"Bonjour"}
"Thanks" {"Merci"}
"DayAbbreviations" {
"dim.", "lun.", "mar.",
"mer.", "jeu.", "ven.", "sam."
}
|
Four value types
are supported. These are solitary strings, comma-delimited lists of strings, 2-dimensional
arrays of strings, and tagged lists of strings. See Appendix C for more details.
Moving Strings to
Resource Bundles
Move the text for display strings
into resource bundles. Instead of hard coding the display string, the new code will use a
resource bundle and a key to look up the localized display strings.
Java |
| Old |
| display("Clean ink cartridge
before printing document"); |
| new |
| display(MyResources.rb.getString("CleanCartridge")); |
| Resource
Bundle |
| quot;CleanCartridge",
"Clean ink cartridge before printing document"}, |
C++ |
| Old |
| display("Clean ink cartridge
before printing document"); |
| new |
rb.getString("CleanCartridge",
uniString, err);
display(uniString); |
C |
| Old |
| display("Clean ink cartridge before printing
document"); |
| new |
T_ResourceBundle_getString(rb,"CleanCartridge",uniString,&err);
display(uniString); |
C/C++ Resource Bundle |
| "CleanCartridge"
{"Clean ink cartridge before printing document"} |
You have now set up a series of resource pairs of the form "{key, value}" in
Java and"key1 {value1)" in C/C++). The resource key (such as "CleanCartridge")
can be any unique string you want, even the original string. However, you are better off
using short, clear names: remember that your translators will be seeing these too.
Translating Resource
Bundles
In Java,
To then create a new French translation for your program in Java:
- Copy MyResources.java and rename it to MyResources_fr.java by
appending the proper Java language ID. (You can see a list of the language IDs on the Unicode
Web site. By convention, language codes are lowercased.)
- Make it extend its parent, MyResources.
- Remove the static rb (you only want this on the root class).
- Translate the resource values into French (but not the keys!).
- If any of the values are unchanged--the same as the parent--remove the whole {key,
value} pair. (You can do this because the {key, value} pairs are inherited from the
parent.)
- Do the same again for any other language you want to support.
- Once you have set up a resource Bundle, replace literal strings in your code by
accessing the resource bundle (The literal strings are moved to the resource bundle)
If you have special strings for a particular country--and not just language--then you
do much the same as above.
- Create a bundle in the same way for that country, such as MyResources_fr_BE for
Belgium, by appending the proper Java country ID (You can see a list of the country IDs on
the Unicode Web site By convention, country codes are uppercased.)
- Make it extend its parent; in this case, MyResources_fr
- If any of the values are unchanged--the same as the parent--remove the whole {key,
value} pair.
Java
Resource Bundle |
| English |
| //MyResources.java public class MyResources extends ListResourceBundle {
// boilerplate
public static ResourceBundle rb = ResourceBundle.getBundle("MyResources");
public Object[][] getContents() { return contents; }
static final Object[][] contents = {
{"CleanCartridge", "Clean ink cartridge before printing document"}
};
} |
| French |
| //MyResources_fr.java public class MyResources_fr extends
MyResources {
public Object[][] getContents() { return contents; }
static final Object[][] contents = {
{"CleanCartridge", "Nettoyez la cartouche d'encre avant d'inprimer votre
document"}
};
} |
| French
(Belgium) |
| //MyResources_fr_BE.java public class MyResources_fr_BE extends
MyResources_fr {
public Object[][] getContents() { return contents; }
static final Object[][] contents = {
{"CleanCartridge", "Citoyens Belges: Nettoyez la cartouche d'encre avant
d'inprimer votre document"}
};
} |
If your resource bundle gets too large then you can subdivide it into other resource
bundles, such as myPrintingResources following the same pattern. You can make
this as fine-grained as you want, so that you only load the resources for a part of your
program when that part gets used. You can return arbitrary objects, not only strings,
since it is often easier (and sometimes necessary, such as for graphics that need to be
localized).
In C++ and C,
To then create a new French translation for
your program in C++ or C:
- Make sure that a locale file is present in the specified directory with the appropriate
language ID.(You can see a list of the language IDs on the
Unicode
Web site. By convention, language codes are lowercased.).
Create an ResourceBundle object that will allow your program to interface with the
information in the Resource bundle file
If more specific locale is available for a language, create a file with a more specific
Locale ID name, containing the appropriate information.
C/C++
Resource Bundle |
| English |
| //in
MyResources.txt "CleanCartridge"
{"Clean ink cartridge before printing document"}, |
| French |
| //in
MyResources_fr.txt "CleanCartridge"
{"Nettoyez la cartouche d'encre avant d'inprimer votre document"}, |
| French
(Belgium) |
| //in
MyResources_fr_BE.txt "CleanCartridge" {"Citoyens Belges: Nettoyez la cartouche
d'encre avant d'inprimer votre document"}, |
Moving Objects to
Resource Bundles in Java
For convenience, and because the Java language
allows it, you can store localized objects in resource bundles in Java as the following
example shows in Java you can store objects in Resource Bundles:
Java |
| Old |
| MyCheckbox = new
Checkbox("Clean ink cartridge before printing document"); |
| New |
| MyCheckbox = (Checkbox)
MyResources.rb.getObject("CleanCartridge"); |
| Resource
Bundle |
{"CleanCartridge", new
Checkbox("Clean ink cartridge before printing document")},
... |
|
JavaTM is a trademark of Sun Microsystems, Inc.
Microsoft is a registered trademark of Microsoft Corporation.
Other companies, products, and service names may be trademarks or
service marks of others.
Copyright Trademark
|