Internationalized Program Implementation Principles

Posted by Haraldur1234 on Sat, 29 Feb 2020 04:40:17 +0100

Article Directory


An internationalized program means that the same program code can be described in different languages for different countries, but the core business that the program handles is the same

Introduction to Internationalization

Now assuming that there is a world-recognized enterprise management platform, the owner of this enterprise decides to promote this product to all the large listed companies in the world, so these companies may come from: China, the United States, Germany and so on. In such circumstances, what is the first thing to consider?

After analysis, you can find that if you want to achieve international program development, the problem to be solved is the following two points:

  • How to define file information to save text
  • How specified resource information can be read based on the encoding of different regional languages

Locale Class

From the analysis, you can see that if you want to internationalize, the first thing you need to solve is the regional and language coding of users from different countries. In the java.util package, there is a class that specifically describes regional and language coding: Locale, which can then be instantiated using two construction methods in the Locale class.

Locale class construction method:

  • Construction method: public Locale(String language)
  • Construction method: public Locale(String language, String country)

What's needed is country and language code, while Chinese code: zh_CN, American English code is en_US

Example: (instantiating a Locale class object)

package com.java.springtest.international;

import java.util.Locale;

/**
 * @author Woo_home
 * @create by 2020/1/30
 */
public class JavaAPIDemo {
    public static void main(String[] args) {
        // Chinese environment
        Locale locale = new Locale("zh","CN");
        System.out.println(locale);
    }
}

Output:

But this is a manual choice of languages, and if you want to get the current running environment automatically now, you can instantiate it using the default method of the Locale class itself

  • Read the local default environment: public static Locale getDefault()
package com.java.springtest.international;

import java.util.Locale;

/**
 * @author Woo_home
 * @create by 2020/1/30
 */
public class JavaAPIDemo {
    public static void main(String[] args) {
        // Get Default Environment
        Locale locale = Locale.getDefault();
        System.out.println(locale);
    }
}

Output:

In the actual development process, many people may not care about country and language codes, so to simplify development, the Locale class also sets codes as constants for some of the world's more famous countries.

package com.java.springtest.international;

import java.util.Locale;

/**
 * @author Woo_home
 * @create by 2020/1/30
 */
public class JavaAPIDemo {
    public static void main(String[] args) {
        // Using constants of the Locale class
        Locale locale = Locale.CHINA;
        System.out.println(locale);
    }
}


Why can I get it from a constant?Open Locale's Source Discovery, which is also self-defined

static public final Locale CHINA = SIMPLIFIED_CHINESE;
static public final Locale SIMPLIFIED_CHINESE = createConstant("zh", "CN");

The advantage of using constants is that you can avoid the tedious coding of some area information

Read resource file: ResourceBundle

Read operation of resource file mainly depends on java.util.ResourceBundle class, which is defined as follows:

public abstract class ResourceBundle extends Object

You can see that ResourceBundle is an abstract class, and if you want to instantiate such an object now, you can do it directly using a static method provided in that class:

  • Gets the ResourceBundle class object: public static final ResourceBundle getBundle(String baseName)
    • -baseName: Describes the name of the resource file without a suffix (com.java.springtest.message.Message)
  • Read resource content (read by key): public final String getString(String key)

Example: Read content using the ResourceBundle class

Start by writing a simple resource file, as follows (note that the resource file needs to be placed under the resource path classpath path path):

Code implementation:

package com.java.springtest.international;

import java.util.ResourceBundle;

/**
 * @author Woo_home
 * @create by 2020/1/30
 */
public class JavaAPIDemo {
    public static void main(String[] args) {
    	// Message does not require a suffix, if the resource is not in the package, write the resource name directly
        ResourceBundle resourceBundle = ResourceBundle.getBundle("Message");
        // Get content by key
        String info = resourceBundle.getString("info");
        // Print Output
        System.out.println(info);
    }
}


The data key must exist when reading resources. If it does not exist, the following exception information will appear, as follows:

package com.java.springtest.international;

import java.util.ResourceBundle;

/**
 * @author Woo_home
 * @create by 2020/1/30
 */
public class JavaAPIDemo {
    public static void main(String[] args) {
        ResourceBundle resourceBundle = ResourceBundle.getBundle("Message");
        String info = resourceBundle.getString("inFo");
        System.out.println(info);
    }
}
Exception in thread "main" java.util.MissingResourceException: 
Can't find resource for bundle java.util.PropertyResourceBundle, key inFo

Achieving Nationalization Procedures

That is to say, relying on resource files, Locale, ResourceBundle classes to achieve international processing operations, then the following for international program implementation (core key: reading resource information)

Example: (Code implementation)

1. Create a com.java.springtest.message.Message_zh_CN.properties under classpath (Chinese resource)

info =Welcome!

2. Create a com.java.springtest.message.Message_en_US.properties under classpath (English resource)

info = Welcome!

Now with a resource file without a default zone, there are three resource files defined

3. Loading resource information for a specified area through a program

package com.java.springtest.international;

import java.util.ResourceBundle;

/**
 * @author Woo_home
 * @create by 2020/1/30
 */
public class JavaAPIDemo {
    public static void main(String[] args) {
        ResourceBundle resourceBundle = ResourceBundle.getBundle("Message");
        String info = resourceBundle.getString("info");
        System.out.println(info);
    }
}

There is no explicit Locale object set when the ResourceBundle class is used to read the resource again at this time, but the file Message_zh_CN is found to be working. Why not Message?Because the default load in this method is the current local Local Resource:

// getBundle() method in Locale class
@CallerSensitive
    public static final ResourceBundle getBundle(String baseName)
    {
    	// Get current resources
        return getBundleImpl(baseName, Locale.getDefault(),
                             getLoader(Reflection.getCallerClass()),
                             getDefaultControl(baseName));
    }

4. If you need to modify the current Locale environment now, you can use the following methods in the ResourceBundle class:

  • Get ResourceBundle:public static final ResourceBundle getBundle(String baseName,
    Locale locale)
package com.java.springtest.international;

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

/**
 * @author Woo_home
 * @create by 2020/1/30
 */
public class JavaAPIDemo {
    public static void main(String[] args) {
        Locale locale = new Locale("en","US");
        ResourceBundle resourceBundle = ResourceBundle.getBundle("Message",locale);
        String info = resourceBundle.getString("info");
        System.out.println(info);
    }
}

Output:

If a resource file for the specified region exists now, the information for the resource file without the region set will not be read

Reading order of resource files: reading resource files in specified regions > Default local resources > public resources (no regions set)

Message Formatting

If a user has successfully logged in now, the message "XXX, Welcome", which means the user name will be displayed at this time, then if the content is saved in the resource file, it will need to be described by the placeholder, and the read data will also need to be processed by message formatting.

Examples: (modifying resource files)

Resource Name resource information
[Chinese Resource File] com.java.springtest.message.Message_zh_CN.properties info = Welcome to {0}, current date is {1}
[English Resource File] com.java.springtest.message.Message_en_US.properties info = Welcome{0},date: {1}

Continue to add {1}, {2} and so on, if necessary

The placeholder's information is read together if the resource is to be read, so the MessageFormat class is used for formatting.

A way to format text is provided in MesageFormat: public static String format(String pattern,
Object... arguments)

Examples: (Formatted text is internationalized)

package com.java.springtest.international;

import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.ResourceBundle;

/**
 * @author Woo_home
 * @create by 2020/1/30
 */
public class JavaAPIDemo {
    public static void main(String[] args) {
        Locale locale = new Locale("en","US");
        ResourceBundle resourceBundle = ResourceBundle.getBundle("Message",locale);
        String info = resourceBundle.getString("info");
        System.out.println(MessageFormat.format(info,"international",new SimpleDateFormat("yyyy-MM-dd").format(new Date())));
    }
}


If you encounter a resource file with {0}, {1} structures representing placeholders during development, this information must be formatted

192 original articles were published. 938 were praised. 170,000 visits+
Private letter follow

Topics: Java encoding