Java国际化编程
目录
java支持的国家与语言
我们可以通过下面程序的运行结果知道Java支持的国家与语言。
public class LocaleList {
public static void main(String[] args) {
// 返回Java所支持的全部国家的语言
Locale[] localesList = Locale.getAvailableLocales();
// 便利数组的每个元素,依次获取所支持国家的语言
for (int i = 0; i < localesList.length; i++) {
// 输出所支持国家的语言
System.out.println(localesList[i].getDisplayCountry()
+ "=" + localesList[i].getCountry() + " "
+ localesList[i].getDisplayLanguage()
+ "=" + localesList[i].getLanguage());
}
}
}
最简单的hello World程序
对于一个最简单的Hello World程序
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
对于这个最简单的Hello World程序,现在需要这个程序在不同国家的电脑上都能实现一个简单的打招呼。当然要与本国语言相同。
这里需要提供几个文件:
base.propertise
文件内容如下:
hello=你好!
base_zh_CN.properties
文件的内容如下:
hello=你好!
base_en_US.properties
文件的内容如下:
hello=Welcome you!
对于包含非ASCII码的文件需要使用Java提供的工具native2ascii来转化。
这个工具可以在%JAVA_HOME%/bin下找到,当然用的使用只需要在命令提示窗口像编译Java程序一样使用。
具体的用法如下:
native2ascii 原资源文件 目标资源文件
例如:
native2ascii base.properties base_zh_US.properties
当然如果使用IDE时可以使用一些插件(有些插件是自带的)。
这里以idea为例:在Setting->Preferences–>Editor–>FileCodings中将Preferences–>Editor–>FileCodings勾上
只是因为编码不同,idea一般设置的编码是utf-8,而资源文件是ascii。
具体用法也很简单
参见idea官网英文的可以翻译看看。
下面是这个程序的代码:
public class ReHello
{
public static void main(String[] args)
{
// 取得系统默认的国家/语言环境
Locale myLocale = Locale.getDefault(Locale.Category.FORMAT);
// 根据指定国家/语言环境加载资源文件
ResourceBundle bundle = ResourceBundle
.getBundle("Java基础库类.base" , myLocale);
// 打印从资源文件中取得的消息
System.out.println(bundle.getString("hello"));
}
}
需要注意的是:如果此程序在某个包下,必须在hello前加包名。
测试
英文时可以将系统语言调成美国的。
但是也可以通过下面的程序完成。
public class ReHello
{
public static void main(String[] args)
{
// 取得系统默认的国家/语言环境
Locale myLocale = new Locale("en", "US");
// 根据指定国家/语言环境加载资源文件
ResourceBundle bundle = ResourceBundle
.getBundle("Java基础库类.base" , myLocale);
// 打印从资源文件中取得的消息
System.out.println(bundle.getString("hello"));
}
}
下面是API中对这些方法的解释
Enum Locale.Category
枚举地区类别。 这些区域设置类别用于获取/设置由类别表示的特定功能的默认语言环境。
public static Locale getDefault(Locale.Category category)获取Java虚拟机的此实例的指定类别的默认语言环境的当前值。
Java虚拟机根据主机环境在启动期间设置默认语言环境。 如果没有显式指定区域设置,则会被许多区域设置敏感的方法使用。 它可以使用setDefault(Locale.Category,Locale)方法更改。
public static final Locale.Category FORMAT用于表示格式化日期,数字和/或货币的默认区域设置的类别。
getBundle
public static final ResourceBundle getBundle(String baseName, Locale locale)使用指定的基本名称、语言环境和调用者的类加载器获取资源包。
getString
public final String getString(String key)从此资源包或它的某个父包中获取给定键的字符串。
更多内容请自行阅读API文档。
使用MessageFormat处理包占位符的字符串
如果需要输入的东西是可变的
比如说要输出一个
你好 xxx!今天是 xxxx-xx-xx x午 xx:xx。
需要准备的文件是:
mess.properties文件的内容是:
你好 {0}!今天是 {1}。
mess_en_US.properties文件的内容是:
Hello {0}! Today is {1}.
public class HelloAre {
public static void main(String[] args) {
Locale currentlocale = null;
if(args.length == 2) {
currentlocale = new Locale(args[0], args[1]);
}
else {
currentlocale = Locale.getDefault(Locale.Category.FORMAT);
}
ResourceBundle bundle = ResourceBundle.getBundle("Java基础库类.mess", currentlocale);
String msg = bundle.getString("msg");
System.out.println(MessageFormat.format(msg, "Peter", new Date())
);
}
}
public final StringBuffer format(Object arguments,
StringBuffer result,
FieldPosition pos)格式化一个对象数组,并将 MessageFormat 的模式添加到所提供的 StringBuffer,用格式化后的对象替换格式元素。这等效于
使用类来代替资源文件
条件是:
1. 类名必须是baseName_language_country,与文件的命名相似。
2. 该类必须继承 ListResourceBundle,并且重写getContents()方法,该方法返回Object数组,该数组的每一项都是key-value。
例如:
import java.util.*;
public class myMess_zh_CN extends ListResourceBundle {
private final Object[][] myDate = {
{"msg", "{0},你好,今天的日期是{1}"}
};
public Object[][] getContents() {
return myDate;
}
}
ResourceBundle搜索资源的顺序是(以中国为例):
1. baseName_zh_CN.class
2. baseName_zh_CN.properties
3. baseName_zh.class
4. baseName_zh.properties
5. baseName.class
6. baseName.properties
使用NumberFormat格式化数字
MessageFromat 是抽象类Fromat的子类,Fromat抽象类还有两个子类:NumberFromat和DateFromat,他们分别实现数值、日期装换成字符串。
NumberFromat也是有个抽象类,无法透过构造器来创建NumberFromat对象,但可以通过类方法来创建。
1. getCurrencyInstance() : 返回默认的Locale的货币格式器。也可以调用该方法时传入指定的Locale,则获取指定的Local货币格式器。
2. getPercentInstance() : 返回默认locale的百分数格式器。也可以指定。
3. getIntegerInstance() : 返回默认整数格式器。也可以指定。
4. getNumberInstance() : 返回默认的通用数值格式器。也可以指定。
import java.text.NumberFormat;
import java.util.*;
public class NumberFormatDemo {
public static void main(String[] args) {
double a = 12334.00;
Locale[] locales = {Locale.CHINA, Locale.JAPAN, Locale.US, Locale.UK};
NumberFormat[] numberFormats = new NumberFormat[12];
for (int i = 0; i < locales.length; i++) {
numberFormats[i*3] = NumberFormat.getNumberInstance(locales[i]);
numberFormats[i*3 + 1] = NumberFormat.getPercentInstance(locales[i]);
numberFormats[i*3 + 2] = NumberFormat.getCurrencyInstance(locales[i]);
}
for (int i = 0; i < locales.length; i++) {
String str = i == 0 ? "中国的格式:" : i == 1 ? "日本的格式:" :
i == 2 ? "美国的格式:" : "英国得格式";
System.out.println(str);
System.out.println("通用格式:" + numberFormats[i*3].format(a));
System.out.println("百分格式:" + numberFormats[i*3 + 1].format(a));
System.out.println("货币数值格式格式:" + numberFormats[i*3 + 2].format(a));
}
}
}
使用DateFromat
DateFormat与NumbeFormat相似。
getDateFormat() : 返回一个日期格式器,格式化后的字符串只有日期。
getTimeFormat() : 返回一个时间格式器,格式化后的字符串只有时间,没有日期。
getDateTime() : 返回一个日期时间格式器,格式化后的字符串有日期、时间。
以上的方法都可以传入多个参数,用于指定日期的样式、时间的样式和Locale等参数。如果不指定就使用默认参数。
import static java.text.DateFormat.*;
import java.text.DateFormat;
import java.util.*;
public class DateFormatDemo {
public static void main(String[] args) {
Date date = new Date();
Locale[] locales = {Locale.CHINA, Locale.US};
DateFormat[] dateFormats = new DateFormat[16];
for (int i = 0; i < locales.length; i++) {
dateFormats[i*8] = DateFormat.getTimeInstance(SHORT, locales[i]);
dateFormats[i*8 + 1] = DateFormat.getTimeInstance(MEDIUM, locales[i]);
dateFormats[i*8 + 2] = DateFormat.getTimeInstance(LONG, locales[i]);
dateFormats[i*8 + 3] = DateFormat.getTimeInstance(FULL, locales[i]);
dateFormats[i*8 + 4] = DateFormat.getDateInstance(SHORT, locales[i]);
dateFormats[i*8 + 5] = DateFormat.getDateInstance(MEDIUM, locales[i]);
dateFormats[i*8 + 6] = DateFormat.getDateInstance(LONG, locales[i]);
dateFormats[i*8 + 7] = DateFormat.getDateInstance(FULL, locales[i]);
}
for (int i = 0; i < locales.length; i++) {
String str = i == 0 ? "中国的格式" : "美国格式";
System.out.println(str);
System.out.println("SHORT时间格式器:" + dateFormats[i*8].format(date));
System.out.println("MEDIUM时间格式器:" + dateFormats[i*8 + 1].format(date));
System.out.println("LONG时间格式器:" + dateFormats[i*8 + 2].format(date));
System.out.println("FULL时间格式器:" + dateFormats[i*8 + 3].format(date));
System.out.println("SHORT日期格式器:" + dateFormats[i*8 + 4].format(date));
System.out.println("MEDIUM日期格式器:" + dateFormats[i*8 + 5].format(date));
System.out.println("LONG日期格式器:" + dateFormats[i*8 + 6].format(date));
System.out.println("FULL日期格式器:" + dateFormats[i*8 + 7].format(date));
}
}
}