本章的内容是:国际化!
1、Java默认的UTF-8编码为国际化提供了可能。国际化不止是编码、文本,还包括日期、货币等方面。
2、Locale类表示一个地区(的国际化情况),它包括:一种语言、一个位置和一个变量。
如美国:language=English, location=United States
如果只指定了语言,有时候将无法处理货币、时间等。因为语言可能被多个公家共用,但各地的时间、货币表示符号又不同。
3、Java对于语言使用ISO标准的ISO-639-1,每个国家使用2字母的代号表示,想了解的猛击这里。注意中国是zh不是cn哦~
Java对于国家,使用ISO-3166-1,每个国家一般也是两个字母,但多数为大写,猛击这里,例如中国是CN。
4、java.util.Locale有两个参数的构造函数:
Locale(String language, String country)
很明显第一个要写语言,如zh,第二个是国家,如CN
5、为了方便,Java预定义了上述Locale对象的常量:
如Locale.CHINA
Locale.US等,这些都是语言+位置(国家)。
也定义了只有语言没有位置的,如Locale.CHINESE,但这个不常用。
6、对于本机支持的所有Locale,可以列出:
import java.util.Locale; public class TestLocale { public static void main(String [] args) { Locale [] ls = Locale.getAvailableLocales(); for(Locale l:ls) { System.out.println(l.getLanguage()+" "+l.getCountry()); } } }
我得机器结果如下:
ja JP es PE en ja JP es PA sr BA mk es GT ar AE no NO sq AL bg ar IQ ar YE hu pt PT el CY ar QA mk MK sv de CH en US fi FI is cs en MT sl SI sk SK it tr TR zh th ar SA no en GB sr CS lt ro en NZ no NO lt LT es NI nl ga IE fr BE es ES ar LB ko fr CA et EE ar KW sr RS es US es MX ar SD in ID ru lv es UY lv LV iw pt BR ar SY hr et es DO fr CH hi IN es VE ar BH en PH ar TN fi de AT es nl NL es EC zh TW ar JO be is IS es CO es CR es CL ar EG en ZA th TH el GR it IT ca hu HU fr en IE uk UA pl PL fr LU nl BE en IN ca ES ar MA es BO en AU sr zh SG pt uk es SV ru RU ko KR vi ar DZ vi VN sr ME sq ar LY ar zh CN be BY zh HK ja iw IL bg BG in mt MT es PY sl fr FR cs CZ it CH ro RO es PR en CA de DE ga de LU de es AR sk ms MY hr HR en SG da mt pl ar OM tr th TH el ms sv SE da DK es HN
7、Locale的各种Get方法就不赘述了,自己查JavaDoc吧。
8、单纯的Locale只是一个标示,而表现层(同样的数字,格式化为不同地区的货币),则是通过Fomartter完成的。
例如:java.text.NumberFormat提供了数字的解析和格式化。
格式化步骤:
(1)getXXXInstance()
(2)format完成从int/double到对应string的过程,如下:
import java.text.NumberFormat; import java.util.Locale; public class TestNumFormat { public static void main(String [] args) { // Default formart NumberFormat fmt = NumberFormat.getInstance(Locale.CHINA); System.out.println(fmt.format(8888888.33333)); //8,888,888.333 // Currency format NumberFormat fmt2 = NumberFormat.getCurrencyInstance(Locale.CHINA); System.out.println(fmt2.format(88.33)); // ¥88.33 // Integer format NumberFormat fmt3 = NumberFormat.getIntegerInstance(Locale.CHINA); System.out.println(fmt3.format(8888888.3333)); // 8,888,888 } }
9、 解析步骤:
例如从String中抽出人民币多少元:
try { // Get format NumberFormat fmt4 = NumberFormat.getCurrencyInstance(Locale.CHINA); // Parse Number num = fmt4.parse("¥88.33"); System.out.println(num.doubleValue()); // 88.33 } catch(Exception e){ e.printStackTrace(); }
10、NumberFormat可以通过set/getMax/MinIntegerDigit等设置最多多少位小数。
11、如上,NumberFormat.getCurrencyInstance()用于获取货币格式刷。
NumberFormat.getCurrency()返回货币符号,例如人民币的¥。
12、日期格式化是另外一个重头戏,通过java.text.DateFormat完成。
步骤也是类似的,先getXXXInstance(),然后format,不过参数是java.util.Date。
注意instance多了一个参数style,短、中、长。
DateFormat getDateInstance(int style, Locale aLocale)
例子如下:
import java.text.DateFormat; import java.util.*; public class TestDateFormat { public static void main(String [] args) { // Now Date now = new Date(); // Dateformart DateFormat fmt = DateFormat.getDateInstance(DateFormat.LONG, Locale.CHINA); System.out.println(fmt.format(now)); // 2012年3月21日 // DateTimeformart DateFormat fmt2 = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, Locale.CHINA); System.out.println(fmt2.format(now)); // 2012年3月21日 下午09时47分42秒 } }
13、其实更多的时候,我们想要自己控制日期输出,比如2012-03-01 13:33:33这种,这有两种方法,一是之前提到的format大法(见《Java格式化日期字符串》),另外就是通过SimpleDateFormat完成:
import java.text.SimpleDateFormat; import java.util.*; class TestSimpleDateFormat { public static void main(String [] args) { // Now Date now = new Date(); // Make date format SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S"); System.out.println(fmt.format(now)); // 2012-03-21 22:01:04.124 } }
14、其实排序中也隐藏这国际化的风险,因为Java默认是用unicode排序的,这样很多顺序是错误的。。例如中文,我们习惯首字母拼音排序,而Java确实按照code的先后。。
这种排序需要java.util.Collator完成,同样也是用Locale获得当地的Collator,然后将它应用于sort时候就可以了~
下面的第二部分,就是按照首字母排序啦!
import java.text.Collator; import java.util.*; class TestCollator { public static void main(String [] args) { // Get Collator Collator coll = Collator.getInstance(Locale.CHINA); // Sort ArrayList<String> names = new ArrayList<String>(); names.add("计算所"); names.add("中科院"); names.add("米国"); // Default sort (按照Unicode编码排序) Collections.sort(names); for(String name: names) { System.out.println(name); } // Sort 1 (首字母排序!!) System.out.println(); Collections.sort(names, coll); for(String name: names) { System.out.println(name); } } }
15、还可以设置“排序强度”,多语种时候比较有用,需要时候再了解吧。。
16、java.text.MessageFormat用于格式化文本。
它支持占位符,例如:"My name is {2}, work at {0}, my number is {1}",然后后面可以用3个变量替代:
// MessageFormat String msg = MessageFormat.format("My name is {2}, work at {0}, my number is {1}", "ICT", "Coder4", 100); System.out.println(msg); // My name is 100, work at ICT, my number is Coder4
这个{}的格式是{idx, type, stype}。
idx就是下标。
type可以是number、time、date、choice。
如果number,则style可以是integer、currency、percent。如果time
如果time/date,style可以是short、medium、long、full或者模板yyyy-MM-dd等。
choice这种是用于a变成an这种小的根据实际语言的改变。
String msg = MessageFormat.format("My name is {2}, now is {0, date, full}, my number is {1} ", new Date(), "Coder4", 100); System.out.println(msg); // My name is 100, now is 2012年3月21日 星期三, my number is Coder4
17、Java内部是UTF-8编码,但系统不一定是,文件更不一定是。
用其他编码打开文件:
out = new FileWriter(filename, "iso-8859-1");
注意:文件编码名和Locale中定义的没有关联!!
18、.java文件的编码建议用ascii或者utf-8,如果有特殊字符,可以用naitive2ascii工具搞定。
19、本地化应用时,可能需要翻译大量的UI,此时我们可以用资源包搞定!
一个项目可以对应若干资源包
资源包命名为:
包名_语言_地区。例如:
Msg_de_DE
Msg_zh_CN
20、加载包:
ResourceBundle res =ResourceBuilde.getBundel("Msg", Locale.CHINA);
第一个参数是包名,第二个是Locale
它将先尝试匹配语言、国家和变量。如果失败,放弃语言,根据国家查找,如果都失败就用默认的locale了。
21、对字符串进行包国际化很简单:
MyMsg_zh_CN.properties:
注意这些字符串文件必须是ascii编码的,如果你要中文需要用naive2ascii编译!
下面是一个编译好的例子:
Button = \u6309\u6211
需要加载字符串的时候:
ResourceBundle bundle = ResourceBundle.getBundle("Msg", Locale.CHINA); String btn_str = bundle.getString("Button"); // 按我
22、如果对字符串之外的资源包,就需要扩展类了:
拓展ListResourceBundle
或者拓展ResourceBundle但是需要实现getKeys()和handleObject(String key)方法。
本章完毕。
eqwqw