所谓的国际化的程序指的是同一个程序代码可以根据不同的国家实现不同的语言描述,但是程序处理的核心业务是相同的。
国际化问题简介
现在假设有一款企业管理平台,决定推广到其他国家,首先要考虑的问题是什么?
通过上图可以发现,如果想要实现国际化的程序开发,那么要解决的问题就在于以下两点:
如何可以定义保存文字的文件信息;
如何可以根据不同区域语言的编码,读取指定的资源信息;
Locale类
如果想要实现国际化,那么首先需要解决的就是不同国家用户的区域和语言编码问题,而在java.util包中提供有专门描述区域和语言编码的类:Locale,而后主要可以使用Locale类中的两个构造方法进行实例化:
构造方法:public Locale(String language)
构造方法:
public Locale(String language, String country)
public class JavaAPIDemo {
public static void main(String[] args) {
Locale loc = new Locale("zh","CN");//中文环境
System.out.println(loc);
}
}
运行结果:
zh_CN
如果说现在想要自动获得当前的运行环境,那么现在就可以利用Locale类本身默认的方式进行实例化:
读取本地默认环境:
public static Locale getDefault();
public class JavaAPIDemo {
public static void main(String[] args) {
Locale loc = Locale.getDefault();//获取默认环境
System.out.println(loc);
}
}
运行结果:
zh_CN
在实际的开发过程中,很多人并不关心国家和语言的编码,所以为了简化开发,Locale也将世界上一些常用的国家编码设置为常量。
public class JavaAPIDemo {
public static void main(String[] args) {
Locale loc = Locale.CHINA;//中文环境
System.out.println(loc);
}
}
运行结果:
zh_CN
使用常量可以避免一些区域编码信息的繁琐。
读取资源文件:ResourceBundle
创建一个资源文件: Messages.properties,将这个配置文件放到src目录下
现在已经准备好了资源文件,那么随后就需要进行资源文件的读取操作了,而读取资源文件主要依靠的是java.util.ResourceBundle类完成,此类定义如下:
public abstract class ResourceBundle extends Object
ResourceBundle是一个抽象类,如果说想要进行此类对象的实例化可以直接利用该类中提供的一个静态方法完成:
获取ResourceBundle类对象: public static final ResourceBundle getBundle(String baseName); baseName:描述的是资源文件的名称,但是没有后缀;
根据key读取资源内容:public final String getString(String key)
范例:使用ResourceBundle类读取内容
import java.util.ResourceBundle;
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
ResourceBundle resource = ResourceBundle.getBundle("Message");
String val = resource.getString("info");
System.out.println(val);
}
}
运行结果:
你好
注意:使用的idea需要首先在file-settings-File Endodings中把properties的编码格式改为utf-8,不然会产生中文乱码
国际化程序开发实现
现在国际化程序的实现前期准备已经全部完成了,也就是说依靠资源文件、Locale、ResourceBundle类就可以实现国际化的处理操作,那么下面来进行国际化的程序实现(核心关键:读取资源信息)。
首先观察
代码不做任何更改,直接运行之后出现:你好啊,而不是你好,说明系统默认读取的是Message_zh_CN文件
此时在利用ResourceBundle类读取资源时并没有设置一个明确的Locale对象,但是发现“Messages_zh_CN”文件生效了,因为这个方法中默认加载的就是当前本地的Locale的资源:
public static final ResourceBundle getBundle(String baseName) {
return getBundleImpl(baseName, Locale.getDefault(), getLoader(Reflection.getCallerClass()), getDefaultControl(baseName));
}
如果现在有需要也可以修改当前的Locale环境,则可以使用ResourceBundle类中如下方法:
public static final ResourceBundle getBundle(String baseName, Locale locale);
范例:读取上述英文文件
import java.util.Locale;
import java.util.ResourceBundle;
public class JavaAPIDemo {
public static void main(String[] args) {
ResourceBundle resource = ResourceBundle.getBundle("Message",Locale.US);
String val = resource.getString("info");
System.out.println(val);
}
}
输出结果:
hello
如果现在有指定区域的组员文件存在时,那么没有设置区域的资源文件的信息将不会被读取。
资源读取顺序:读取指定区域的资源文件>默认的本地资源>公共的资源(没有区域设置的)
消息格式化
当用户登录成功后,一般都会显示这样的信息“XXX,欢迎您的光临!”,也就是这时会显示用户名,那么如果这些内容保存在资源文件里面,则需要通过占位符进行描述,同时对于读取出来的数据也需要进行消息格式化的处理。
范例:修改资源文件
【中文资源文件】Message_zh_CN.properties
info=你好啊,{0},今天的日期是:{1}
【英文资源文件】Message_en_US.properties
info=Hello,{0},data:{1}
如果有需要可以继续添加“{2}”、“{3}”之类的占位符;
此时如果直接读取资源文件,那么 会将占位符的信息一起读取出来 。
所以此时就需要利用MessageFormat类进行格式化处理。
在MessageFormat类中提供了一个格式化文本的方法:
public static String format(String pattern, Object... arguments);
范例:格式化文本实现国际化
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.ResourceBundle;
public class JavaAPIDemo {
public static void main(String[] args) {
ResourceBundle resource = ResourceBundle.getBundle("Message",Locale.US);
String val = resource.getString("info");
System.out.println(MessageFormat.format(val,"张三",new SimpleDateFormat("yyyy-MM-dd").format(new Date())));
}
}
运行结果:
Hello,张三,data:2020-07-10
如果再日后开发中见到资源文件中出现“{0}”、“{1}”的结构表示的都是占位符,该信息一定都需要格式化处理。