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