您当前的位置: 首页 > 学无止境 > 心得笔记 网站首页心得笔记
【第11章:Java常用类库】_国际化程序
发布时间:2020-12-23 18:59:22编辑:雪饮阅读()
一个简单的国际化程序
国际化依赖于properties后缀的资源文件,建立一个资源文件
Message.properties:
info=HELLO
资源文件中的定义格式是key=val的格式
定义了资源文件,使用多语言支持的时候则需要加载对应资源,加载资源的方法提供于ResourceBundle类中ResourceBundle类需要额外导包,非java核心中自带。
则一个简单的java多语言程序如:
import java.util.ResourceBundle;
public class Hello{
public static void main(String args[]){
//获取资源文件
ResourceBundle rb=ResourceBundle.getBundle("Message");
//获取指定key的语言值
System.out.println("内容:"+rb.getString("info"));
}
}
D:\>javac Hello.java
D:\>java Hello
内容:HELLO
加载不同区域的资源包
不同区域的资源包定义如:
Message_zh_CN.properties:
info=cn info
Message_en_US.properties:
info=en info
Message_fr_FR.properties:
info=fr info
加载不同区域的资源包依赖于Locale类,也需要额外导包,实现如:
import java.util.ResourceBundle;
import java.util.Locale;
public class Hello{
public static void main(String args[]){
Locale zhLoc=new Locale("zh","CN");
Locale enLoc=new Locale("en","US");
Locale frLoc=new Locale("fr","FR");
ResourceBundle zhrb=ResourceBundle.getBundle("Message",zhLoc);
ResourceBundle enrb=ResourceBundle.getBundle("Message",enLoc);
ResourceBundle frrb=ResourceBundle.getBundle("Message",frLoc);
System.out.println("中文:"+zhrb.getString("info"));
System.out.println("英文:"+enrb.getString("info"));
System.out.println("法文:"+frrb.getString("info"));
}
}
D:\>java Hello
中文:cn info
英文:en info
法文:fr info
native2ascii.exe
在C:\Program Files (x86)\Java\jdk1.6.0_11\bin目录(jdk环境目录)中有native2ascii.exe
可用于对中文字符转码为ascii编码的工具,这在解决中文乱码的情况比较方便。运行程序输入对应中文就可以自动转换成为ascii输出。
在语言包资源文件中配置的键值对中对于英文语言值兼容性不必说,但是对于中文语言值则可能会有乱码等风险。
那么此时将转码之后的ascii编码复制到中文资源文件上如:
Message_zh_CN.properties:
info=cn info\u4f60\u597d
然后重新运行上面的java程序如:
D:\>javac Hello.java
D:\>java Hello
中文:cn info你好
英文:en info
法文:fr info
可以看到ascii编码自动在控制台中被转换了。
MessageFormat.format
MessageFormat.format方法可用于解析资源包中语言值的动态配置(占位符)
比如中文语言包中定义如:
Message_zh_CN.properties:
info=cn info\u4f60\u597d{0}
这里末尾定义了一个占位符0
那么给该语言包的占位符0传递参数则如:
import java.util.ResourceBundle;
import java.util.Locale;
import java.text.*;
public class Hello{
public static void main(String args[]){
Locale zhLoc=new Locale("zh","CN");
Locale enLoc=new Locale("en","US");
Locale frLoc=new Locale("fr","FR");
ResourceBundle zhrb=ResourceBundle.getBundle("Message",zhLoc);
ResourceBundle enrb=ResourceBundle.getBundle("Message",enLoc);
ResourceBundle frrb=ResourceBundle.getBundle("Message",frLoc);
System.out.println("中文:"+MessageFormat.format(zhrb.getString("info"),"kasumi"));
System.out.println("英文:"+enrb.getString("info"));
System.out.println("法文:"+frrb.getString("info"));
}
}
MessageFormat在java.text.*中包含的,所以把这个导入。
则执行结果如;
D:\>java Hello
中文:cn info你好kasumi
英文:en info
法文:fr info
MessageFormat.format解析资源包语言值模板时支持可变参数,且占位符的值与可变参数的参数索引一致,比如占位符为0,则对应可变参数的第一个参数,占位符为1则对应可变参数第二个参数,与占位符在资源包语言值模板中的位置无关。
如中文语言包中定义多个占位符如:
Message_zh_CN.properties:
info=cn info\u4f60\u597d{0},{2},{1}
而MessageFormat.format实现时候的可变参数传参如:
import java.util.ResourceBundle;
import java.util.Locale;
import java.text.*;
public class Hello{
public static void main(String args[]){
Locale zhLoc=new Locale("zh","CN");
Locale enLoc=new Locale("en","US");
Locale frLoc=new Locale("fr","FR");
ResourceBundle zhrb=ResourceBundle.getBundle("Message",zhLoc);
ResourceBundle enrb=ResourceBundle.getBundle("Message",enLoc);
ResourceBundle frrb=ResourceBundle.getBundle("Message",frLoc);
System.out.println("中文:"+MessageFormat.format(zhrb.getString("info"),"kasumi","hayabusa","snowDrink"));
System.out.println("英文:"+enrb.getString("info"));
System.out.println("法文:"+frrb.getString("info"));
}
}
则结果如:
D:\>javac Hello.java
D:\>java Hello
中文:cn info你好kasumi,snowDrink,hayabusa
英文:en info
法文:fr info
可变参数
参数个数不确定的时候可以用可变参数,形参可以直接用Object类型声明,参数名前面用”…”代表可变参数,则方法体接收到该参数则是一个对象数组。
public class Hello{
public static void main(String args[]){
fun("kasumi","hayabusa","ayani");
fun("kasumi");
}
public static void fun(Object ...args){
for(int i=0;i<args.length;i++){
System.out.print(args[i]+"\t");
}
System.out.println();
}
}
D:\>javac Hello.java
D:\>java Hello
kasumi hayabusa ayani
kasumi
可变参数也可以直接接收数组
public class Hello{
public static void main(String args[]){
Object[] arg1={"kasumi","hayabusa","ayani"};
Object[] arg2={"kasumi"};
Object[] arg3={};
fun(arg1);
fun(arg2);
fun(arg3);
}
public static void fun(Object ...args){
for(int i=0;i<args.length;i++){
System.out.print(args[i]+"\t");
}
System.out.println();
}
}
D:\>javac Hello.java
D:\>java Hello
kasumi hayabusa ayani
kasumi
用类来定义资源包
据说是为了照顾一些什么都喜欢用类来定义的一片玩家,所以存在一种可以用类来定义资源包的方式。
由于用类定义资源包的方式与之前通过properties后缀定义资源包的方式之间有优先级的情况,就是当这两种都出现的情况谁优先,所以这里就先把上面通过properties定义的所有资源包都删除了。
则用定义一个类的资源包如:
Message_zh_CN.java:
import java.util.ListResourceBundle;
public class Message_zh_CN extends ListResourceBundle{
private final Object data[][]={
{"info","hello ,{0}!{2}?{1}"}
};
public Object[][] getContents(){
return data;
}
}
然后对于资源包的调用还是和之前一样
import java.util.ResourceBundle;
import java.util.Locale;
import java.text.*;
public class Hello{
public static void main(String args[]){
Locale zhLoc=new Locale("zh","CN");
ResourceBundle zhrb=ResourceBundle.getBundle("Message",zhLoc);
System.out.println("中文:"+MessageFormat.format(zhrb.getString("info"),"kasumi","hayabusa","ayani"));
}
}
只是编译的时候就比较麻烦了,定义的这个类的资源包也要先编译下
D:\>javac Message_zh_CN.java
D:\>javac Hello.java
D:\>java Hello
中文:hello ,kasumi!ayani?hayabusa
语言资源包的优先级
对于同样的语言包使用方式:
import java.util.ResourceBundle;
import java.util.Locale;
import java.text.*;
public class Hello{
public static void main(String args[]){
Locale zhLoc=new Locale("zh","CN");
ResourceBundle zhrb=ResourceBundle.getBundle("Message",zhLoc);
System.out.println("中文:"+MessageFormat.format(zhrb.getString("info"),"kasumi","hayabusa","ayani"));
}
}
此时语言包定义优先级有这样的顺序:
Message_zh_CN.class
Message_zh_CN.properties
Message.properties
那么假定Message_zh_CN.class定义这里就先不变化了
恢复原来的Message_zh_CN.properties文件并变更内容为:
info=Message zh CN properties {0},{2},{1}
恢复原来的Message.properties文件并变更内容为:
info=message properties {0},{2},{1}
则此时输出如:
D:\>java Hello
中文:hello ,kasumi!ayani?hayabusa
可见此时Message_zh_CN.class最优先
然后此时删除掉Message_zh_CN.class
此时又输出的是:
D:\>java Hello
中文:Message zh CN properties kasumi,ayani,hayabusa
可见次优先的是Message_zh_CN.properties
然后再干掉Message_zh_CN.properties
此时输出的是
D:\>java Hello
中文:message properties kasumi,ayani,hayabusa
可见最后优先的就是
Message.properties
关键字词:java,国际化