Localization

Describe the advantages of localizing an application

Internationalization is the process of designing an application so that it can be adapted to various languages and regions without engineering changes.

Localization is the process of adapting the content of a product to a specific region or language. Translating words is the best-known part of this process, but it is not the only part. Localization usually includes:

  • Numbers
  • Dates
  • Currencies
  • Images and sounds
  • Layouts

Even in countries with the same languages, you can find differences, for example, American English vs. British English.

So the benefits of localization are:

  • With the addition of localized data, the same executable can run worldwide.
  • Textual elements, such as status messages and the GUI component labels, are not hardcoded 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.

 

Read and set the locale by using the Locale object

Here's the javadoc for the Locale class.

The four ways to create a Locale object are:

  • Locale.Builder Class

    For example:

    Locale loc = new Locale.Builder().setLanguage("fr").setRegion("FR").build();
    
  • Locale Constructors

    There are three constructors available in the Locale class:

    • Locale(String language)
    • Locale(String language, String country)
    • Locale(String language, String country, String variant)

    For example:

    Locale l1 = new Locale("es", "ES");
    Locale l2 = new Locale("en");
    
  • Locale.forLanguageTag Factory Method

    For example:

    Locale loc = Locale.forLanguageTag("ja-JP");
    
  • Locale Constants

    For example:

    Locale loc1 = Locale.ITALIAN;
    Locale loc2 = Locale.CHINA;
    

To find out which types of Locale definitions a locale-sensitive class recognizes, you invoke the getAvailableLocales() method. For example, to find out which Locale definitions are supported by the NumberFormat class:

public class Test {
    static public void main(String[] args) {
        Locale locales[] = NumberFormat.getAvailableLocales();
        for (Locale l : locales) {
            System.out.println(l.toString());
        }
    }
}

The output can be something like this:

ms_MY
ar_QA
is_IS
fi_FI
pl
en_MT

If we change fromSystem.out.println(l.toString()) to System.out.println(l.getDisplayName ()) the output would be:

Malay (Malaysia)
Arabic (Qatar)
Icelandic (Iceland)
Finnish (Finland)
Polish
English (Malta)

You can assign a different Locale to every locale-sensitive object in your program. However, locale-sensitive objects rely on the default Locale set by the Java Virtual Machine. You can use the Locale.getDefault() method to get it and the Locale.setDefault(Locale) to set it.

 

Create and read a Properties file

Properties are files with string key/value pairs that store configuration data or settings:

# A comment
user=amtg
passw=changeme
language=java

To use them, you create instances of java.util.Properties. The following example, loads the file config.properties from project classpath and read its properties:

public class Test {
  public static void main(String[] args) {
        Properties prop = new Properties();
        InputStream input = null;

        try {
            input = Test.class.getClassLoader().getResourceAsStream("config.properties");
            //load the properties file from class path
            prop.load(input);

        //get a property value and print it out
        System.out.println(prop.getProperty("user"));

        //get all properties
        Enumeration<?> e = prop.propertyNames();
            while (e.hasMoreElements()) {
                String key = (String) e.nextElement();
                String value = prop.getProperty(key);
                System.out.println("Key : " + key + ", Value : " + value);
            }

        } catch (IOException ex) {
            ex.printStackTrace();
      } finally {
            input.close();
            }
    }
}

 

Build a resource bundle for each locale and load a resource bundle in an application

java.util.ResourceBundle class is used to store texts in key/pair values and components that are locale sensitive.

Resource bundles can share a common base name, but names can also have additional components that identify their locales. For example, if the base name of resource bundles is "MyBundle", we can have a "MyBundle_en" for the English locale and "MyBundle_es" for a Spanish locale. We can even have different resources for different countries, for example, "MyBundle_fr_CA" for Canadian French:

MyBundle.properties
MyBundle_en.properties
MyBundle_es.properties
MyBundle_fr_CA.properties

These files should be located in the same directory. If no locale is found for a resource bundle, the default bundle ("MyBundle.properties") will be used.

To load the resource bundle MyBundle.properties for an English locale, we use the following code:

Locale locale = new Locale("en", "US");
ResourceBundle rb = ResourceBundle.getBundle("MyBundle", locale);
System.out.println(rb.getString("label"));

Although we only use the ResourceBundle class, it actually has two subclasses, PropertyResourceBundle and ListResourceBundle.

The PropertyResourceBundle class stores localized texts in standard Java property files.

The ListResourceBundle class uses classes to contain the resources. Using classes, you can use more than just String values.

Here's an example implementation:

public class MyBundle_en extends ListResourceBundle {

    @Override
    protected Object[][] getContents() {
        return labels;
    }

    private Object[][] labels = {
            { "value1"   , new Integer(100) },
            { "label1", "MILES" },
    };
}

To get an object value, we use rb.getObject(key) or rb.getStringArray(key) (which is just a shortcut to (String[])getObject(key)) instead of rb.getString(key)

You can also obtain a set of all the keys contained in the ResourceBundle by using:

Set<String> keys = rb.keySet();

 

Content