How do I create a Locale object using a variant?

Font differences may force you to use different characters on different platforms. You could then define the Locale objects with the variant codes to identify those differences. The variant codes conform to no standard. They are arbitrary and specific to your application. If you create Locale objects with variant codes only your application will know how to deal with them.

In this example instead of demonstrating to use a different font for different platform we simplify it to just print a different message. We create three different resource bundles for each platform, the Birthday_fr_FR_UNIX.properties, Birthday_fr_FR_MAC.properties and Birthday_fr_FR_WIN.properties. These files will contains different message for each platform.

package org.kodejava.util;

import java.util.Locale;
import java.util.ResourceBundle;

public class LocalePlatform {
    public static void main(String[] args) {
        ResourceBundle res;
        String language = "fr";
        String country = "FR";

        // Construct a locale from language, country, variant. Where the variant
        // can be a variant vendor and browser specific code.
        Locale unix = new Locale(language, country, "UNIX");
        res = ResourceBundle.getBundle("Birthday", unix);
        System.out.println("UNIX: " + res.getString("birthday"));

        Locale mac = new Locale(language, country, "MAC");
        res = ResourceBundle.getBundle("Birthday", mac);
        System.out.println("MAC : " + res.getString("birthday"));

        Locale windows = new Locale(language, country, "WIN");
        res = ResourceBundle.getBundle("Birthday", windows);
        System.out.println("WIN : " + res.getString("birthday"));
    }
}

Here are the contents of the resource bundle files:

Birthday_fr_FR_UNIX.properties

birthday=Unix, Joyeux anniversaire à vous!

Birthday_fr_FR_MAC.properties

birthday=Mac, Joyeux anniversaire à vous!

Birthday_fr_FR_WIN.properties

birthday=Windows, Joyeux anniversaire à vous!

How do I convert ResourceBundle to Properties?

package org.kodejava.util;

import java.util.*;

public class ResourceBundleToProperties {
    public static void main(String[] args) {
        // Load resource bundle Messages_en_GB.properties from the classpath.
        ResourceBundle resource = ResourceBundle.getBundle("Messages", Locale.UK);

        // Call the convertResourceBundleToProperties method to convert the resource
        // bundle into a Properties object.
        Properties properties = convertResourceBundleToProperties(resource);

        // Print the entire contents of the Properties.
        Enumeration<Object> keys = properties.keys();
        while (keys.hasMoreElements()) {
            String key = (String) keys.nextElement();
            String value = (String) properties.get(key);
            System.out.println(key + " = " + value);
        }
    }

    /**
     * Convert ResourceBundle into a Properties object.
     *
     * @param resource a resource bundle to convert.
     * @return Properties a properties version of the resource bundle.
     */
    private static Properties convertResourceBundleToProperties(ResourceBundle resource) {
        Properties properties = new Properties();
        Enumeration<String> keys = resource.getKeys();
        while (keys.hasMoreElements()) {
            String key = keys.nextElement();
            properties.put(key, resource.getString(key));
        }
        return properties;
    }
}

How do I convert ResourceBundle to Map?

The following code snippet will convert a resource bundle into a map object, a key-value mapping. It will read from a file called Messages_en_GB.properties which corresponding to the Locale.UK. For example the file contain the following string. This file should be placed under the resources directory.

welcome.message = Hello World!
package org.kodejava.util;

import java.util.*;

public class ResourceBundleToMap {
    public static void main(String[] args) {
        // Load resource bundle Messages_en_GB.properties from the classpath.
        ResourceBundle resource = ResourceBundle.getBundle("Messages", Locale.UK);

        // Call the convertResourceBundleTopMap method to convert the resource
        // bundle into a Map object.
        Map<String, String> map = convertResourceBundleToMap(resource);

        // Print the entire contents of the Map.
        for (String key : map.keySet()) {
            String value = map.get(key);
            System.out.println(key + " = " + value);
        }
    }

    /**
     * Convert ResourceBundle into a Map object.
     *
     * @param resource a resource bundle to convert.
     * @return Map a map version of the resource bundle.
     */
    private static Map<String, String> convertResourceBundleToMap(ResourceBundle resource) {
        Map<String, String> map = new HashMap<>();
        Enumeration<String> keys = resource.getKeys();
        while (keys.hasMoreElements()) {
            String key = keys.nextElement();
            map.put(key, resource.getString(key));
        }
        return map;
    }
}

How do I use ResourceBundle for i18n?

Creating an application for users in different regions can be hard in terms of the message format for the local region. Java provide a ResourceBundle class that help internationalize our application.

To create resources for i18n (there are 18 letters between the first i and the final n) we need to create a file for each locale our application supported. The file name must be ended in language_COUNTRY.properties. For instance a resource bundle for Locale.UK will be MessagesBundle_en_GB.properties.

When the bundle has been loaded we can use bundle.getString(key) to read specific message from our resource bundle file.

package org.kodejava.util;

import java.util.Locale;
import java.util.ResourceBundle;

public class InternationalizationDemo {

    public static void main(String[] args) {
        // Load resource bundle for Locale.UK locale. The resource 
        // bundle will load the MessagesBundle_en_GB.properties file.
        ResourceBundle bundle =
                ResourceBundle.getBundle("MessagesBundle", Locale.UK);
        System.out.println("Message in " + Locale.UK + ": " +
                bundle.getString("greeting"));

        // Change the default locale to Indonesian and get the default 
        // resource bundle for the current locale.
        Locale.setDefault(new Locale("in", "ID"));
        bundle = ResourceBundle.getBundle("MessagesBundle");
        System.out.println("Message in " + Locale.getDefault() + ": " +
                bundle.getString("greeting"));
    }
}

Below are some example of our resource bundle files, these files should be located in our application classpath to enable the ResourceBundle class to read it.

MessagesBundle_en_GB.properties

greeting=Hello, how are you?

MessagesBundle_in_ID.properties

greeting=Halo, apa kabar?