Java ResourceBundle

Jakob Jenkov
Last update: 2019-08-18

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.
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.

Jakob Jenkov

Featured Videos

Java ConcurrentMap + ConcurrentHashMap

Java Generics

Java ForkJoinPool

P2P Networks Introduction

















Close TOC
All Tutorial Trails
All Trails
Table of contents (TOC) for this tutorial trail
Trail TOC
Table of contents (TOC) for this tutorial
Page TOC
Previous tutorial in this tutorial trail
Previous
Next tutorial in this tutorial trail
Next