Java ResourceBundle
Jakob Jenkov |
The Java ResourceBundle class, java.util.ResourceBundle
, is used to store texts and components that
are locale sensitive. For instance, the text labels used inside your application might need to change depending on the language
of the user currently using your application. The text labels are thus said to be user locale sensitive. A user's locale
is represented by the Java Locale class, by the way.
This text takes a closer look at the ResourceBundle
class and its subclasses.
The ResourceBundle Class Hierarchy
The ResourceBundle
class has two subclasses called PropertyResourceBundle
and ListResourceBundle
. Here is a diagram illustrating the class hierarchy:
ResourceBundle has the subclasses PropertiesResourceBundle and ListResourceBundle. |
The PropertyResourceBundle
class stores localized texts in standard Java property files. The
format of these files is explained in my Java Properties tutorial.
You do not directly interact with these two subclasses. All interaction goes through the
ResourceBundle
class.
Creating a ResourceBundle
You create a ResourceBundle
instance like this:
Locale locale = new Locale("en", "US"); ResourceBundle labels = ResourceBundle.getBundle("i18n.MyBundle", locale); System.out.println(labels.getString("label1"));
First you need a Locale
instance. Then you pass that Locale
instance
to the ResourceBundle.getBundle()
method along with the name of the resource bundle
to load. Finally you can access the localized values in the ResourceBundle
via
its different getString()
and getObject()
etc. methods.
You are never actually creating a ResourceBundle
instance, but an instance of one of its two subclasses.
Both are created using the above factory method. First the ResourceBundle
class will look
for a ListResourceBundle
, and then for a PropertyResourceBundle
.
It does so by matching the name of the requested resource bundle (first parameter in the getBundle()
method)
against the class names of a ListResourceBundle
first, and if none found, against a property file resource bundle.
Both ListResourceBundle
and PropertyResourceBundle
are covered in more detail
in the following sections.
Property Files as ResourceBundle
You can use standard property files for storing localized texts. You can load these properties via
the ResourceBundle
class. Here is an example:
Locale locale = new Locale("en", "US"); ResourceBundle labels = ResourceBundle.getBundle("i18n.MyBundle", locale); System.out.println(labels.getString("label1"));
For this example to work you should put a standard Java property file named MyBundle.properties
in a Java package named i18n
. Make sure this property file is available on your class
path when you run the above code, meaning the property file should be located among the classes
of your application, and in the i18n
package.
The name of a resource bundle is like
a class name. Thus, i18n.MyBundle
means a property file named MyBundle.properties
in the package (directory) i18n
.
Here is an example of what the content of the property file could look like:
label1 = Label 1 is done! label2 = Label 2 is through!
As is the standard with Java property files, it is a list of key and value pairs. The key is on the left side of the = , and the value is on the right side. The value is what you should localize, not the key.
Different Languages in Different Property Files
In order to provide strings in different languages, create a property file for each language, and suffix them with underscore (_) and then the language code. For instance:
MyBundle.properties MyBundle_da.properties MyBundle_de.properties MyBundle_fr.properties
All of these files should be located in the same package (directory).
The file without language suffix (e.g. MyBundle.properties
) is the default property file. In case no property file is available for
the language (Locale
) passed to the ResourceBundle.getBundle()
method, and the system has no
default Locale set (e.g. a German computer will have a German Locale as default), this file is
read and returned as a ResourceBundle
.
The other property files with the language code suffixes contain the same keys but with values in different languages. Thus, the danish property file could look like this:
label1 = Label 1 er klar! label2 = Label 2 er igennem!
Classes as ResourceBundle
You can also use a set of classes to contain your resources. Using classes you can use more than just string values.
Like with the property files, you create a set of classes with a bundle base name and language suffixes. For instance:
i18n.MyClassBundle i18n.MyClassBundle_da i18n.MyClassBundle_en i18n.MyClassBundle_de
Here is an example implementation of the default bundle class file:
package i18n; import java.util.ListResourceBundle; public class MyClassBundle extends ListResourceBundle { @Override protected Object[][] getContents() { return contents; } private Object[][] contents = { { "price" , new Double(10.00) }, { "currency", "EUR" }, }; }
And here is an implementation of the resource bundle for the danish language:
public class MyClassBundle_da extends ListResourceBundle { @Override protected Object[][] getContents() { return contents; } private Object[][] contents = { { "price" , new Double(75.00) }, { "currency", "DKK" }, }; }
Notice the contents
array. It consists of a 2-dimensional array of keys and values.
Thus, price
and currency
are keys, and the values to the right of them
are the localized values. These two examples contains a price in two different currencies.
You obtain an instance of a ListResourceBundle
the same way you get an instance
of a PropertyResourceBundle
. Here are two examples that obtain an instance of
both the default ResourceBundle
and the ResourceBundle
for the danish
language:
Locale locale = new Locale("de", "DE"); //no bundle for German -> default ResourceBundle bundle = ResourceBundle.getBundle("i18n.MyClassBundle", locale); System.out.println("price : " + bundle.getObject("price")); System.out.println("currency: " + bundle.getObject("currency")); locale = new Locale("da", "DK"); bundle = ResourceBundle.getBundle("i18n.MyClassBundle", locale); System.out.println("price : " + bundle.getObject("price")); System.out.println("currency: " + bundle.getObject("currency"));
The output printed from this code would be:
price : 10.0 currency: EUR price : 75.0 currency: DKK
The price obtained from the default ResourceBundle
is listed in EUR
,
and the price obtained from the danish ResourceBundle
is listed in DKK
.
Getting Values From a ResourceBundle
Once you have obtained a ResourceBundle
instance you can get localized values from
it using one of the methods:
getObject(String key); getString(String key); getStringArray(String key);
You can also obtain a set of all keys contained in the ResourceBundle
using the keySet()
method, like this:
Set<String> keys = bundle.keySet();
Additional ResourceBundle Methods
The ResourceBundle
class has a few more methods (e.g. getLocale()
). Check out the JavaDoc for more
information about these methods.
Tweet | |
Jakob Jenkov |