国际化:i18n(其来源是英文单词 internationalization的首末字符i和n,18为中间的字符数)是"国际化"的简称。
我们通过三个实例进行讲解:
新建一个com.i18.com包,包下面建立一个类Test1:
package com.i18n; import java.util.Locale; public class Test1 { public static void main(String[] args) { Locale[] locales = Locale.getAvailableLocales(); for(Locale locale: locales) { System.out.println(locale.getDisplayCountry() + " : " + locale.getCountry()); } } } /*output: 日本 : JP 秘鲁 : PE : 日本 : JP 巴拿马 : PA 波斯尼亚和黑山共和国 : BA : 危地马拉 : GT 阿拉伯联合酋长国 : AE 挪威 : NO 阿尔巴尼亚 : AL : 伊拉克 : IQ 也门 : YE : 葡萄牙 : PT 塞浦路斯 : CY 卡塔尔 : QA 马其顿王国 : MK : 瑞士 : CH 美国 : US 芬兰 : FI : : 马耳他 : MT 斯洛文尼亚 : SI 斯洛伐克 : SK : 土耳其 : TR : : 沙特阿拉伯 : SA : 英国 : GB 塞尔维亚及黑山 : CS : : 新西兰 : NZ 挪威 : NO 立陶宛 : LT 尼加拉瓜 : NI : 爱尔兰 : IE 比利时 : BE 西班牙 : ES 黎巴嫩 : LB : 加拿大 : CA 爱沙尼亚 : EE 科威特 : KW 塞尔维亚 : RS 美国 : US 墨西哥 : MX 苏丹 : SD 印度尼西亚 : ID : : 乌拉圭 : UY 拉脱维亚 : LV : 巴西 : BR 叙利亚 : SY : : 多米尼加共和国 : DO 瑞士 : CH 印度 : IN 委内瑞拉 : VE 巴林 : BH 菲律宾 : PH 突尼斯 : TN : 奥地利 : AT : 荷兰 : NL 厄瓜多尔 : EC 台湾地区 : TW 约旦 : JO : 冰岛 : IS 哥伦比亚 : CO 哥斯达黎加 : CR 智利 : CL 埃及 : EG 南非 : ZA 泰国 : TH 希腊 : GR 意大利 : IT : 匈牙利 : HU : 爱尔兰 : IE 乌克兰 : UA 波兰 : PL 卢森堡 : LU 比利时 : BE 印度 : IN 西班牙 : ES 摩洛哥 : MA 玻利维亚 : BO 澳大利亚 : AU : 新加坡 : SG : : 萨尔瓦多 : SV 俄罗斯 : RU 韩国 : KR : 阿尔及利亚 : DZ 越南 : VN 黑山 : ME : 利比亚 : LY : 中国 : CN 白俄罗斯 : BY 香港 : HK : 以色列 : IL 保加利亚 : BG : 马耳他 : MT 巴拉圭 : PY : 法国 : FR 捷克共和国 : CZ 瑞士 : CH 罗马尼亚 : RO 波多黎哥 : PR 加拿大 : CA 德国 : DE : 卢森堡 : LU : 阿根廷 : AR : 马来西亚 : MY 克罗地亚 : HR 新加坡 : SG : : : 阿曼 : OM : 泰国 : TH : : 瑞典 : SE 丹麦 : DK 洪都拉斯 : HN */
继续,在包下面建立一个Test2:
package com.i18n; import java.util.Locale; import java.util.ResourceBundle; public class Test2 { public static void main(String[] args) { Locale locale = Locale.US; // Locale.CHINESE ResourceBundle bundle = ResourceBundle.getBundle("hellofile", locale); String value = bundle.getString("hello"); System.out.println(value); } }
在src下面建立两个文件:hellofile_en_US.properties,add一个name为"hello",value为"hello world"的键值对;hellofile_zh_CN.properties,add一个name为"hello",value为"你好"的键值对。运行这个程序,它会根据我们注释部分的代码的不同输出hello world或是你好。
最后,继续在该包下建立一个类Test3:
package com.i18n; import java.text.MessageFormat; import java.util.Locale; import java.util.ResourceBundle; public class Test3 { public static void main(String[] args) { Locale locale = Locale.US; // Locale.CHINESE ResourceBundle bundle = ResourceBundle.getBundle("hellofile", locale); String value = bundle.getString("hello"); String message = MessageFormat.format(value, new Object[]{"中国"}); // 把对应的占位符({0})给替换掉 System.out.println(message); } }
把hellofile_en_US.properties中的值改为"hello world:{0}",hellofile_zh_CN.properties中name的值改为"你好:{0}",运行程序,根据Locale.US或是Locale.CHINESE的不同输出信息为:
hello world:中国 或者 你好:中国
最后,我们使用struts2包装好的工具来实现国际化:
我们仍然使用register.jsp:
<body> <s:actionerror cssStyle="color:red"/><%--actionerror中增加的所有信息显示到页面上 --%> <s:form action="register"> <s:textfield name="username" label="username"></s:textfield> <s:password name="password" label="password"></s:password> <s:password name="repassword" label="repassword"></s:password> <s:textfield name="age" label="age"></s:textfield> <s:textfield name="birthday" label="birthday"></s:textfield> <s:textfield name="graduation" label="graduation"></s:textfield> <s:submit value="submit"></s:submit> </s:form> </body>
写好它的处理类RegisterAction:
package com.test.action; import java.util.Calendar; import java.util.Date; import com.opensymphony.xwork2.ActionSupport; public class RegisterAction extends ActionSupport { private String username; private String password; private String repassword; private int age; private Date birthday; private Date graduation; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getRepassword() { return repassword; } public void setRepassword(String repassword) { this.repassword = repassword; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public Date getGraduation() { return graduation; } public void setGraduation(Date graduation) { this.graduation = graduation; } @Override public String execute() throws Exception { System.out.println("execute invoked"); return SUCCESS; } @Override public void validate() { System.out.println("validate~~~~~~~~~~~~~~~~"); if(null == username || username.length() < 6 || username.length() > 10) { // 进行错误信息的输出 // this.addActionError("username invalid"); this.addActionError(this.getText("username.invlalid", new String[]{username})); } } }
然后再该Action对应的包com.test.action下,建立两个文件:RegisterAction_en_US.properties(name为"username.invalid",value为"user:{0} invalid")、RegisterAction_zh_CN.properties(name为"username.invalid",value为"用户:{0}无效")。
然后,在浏览器中访问:http://localhost:8080/struts2/register.jsp;下面是其输出样例(可以在浏览器的Internet首选项中将英语(美国)[en-US]添加到第一个位置,这样请求对象就会封装相关的信息,可以得到英文的错误提示):
它是如何实现的?其实底层的实现正如我们在Test3中讲述的那样。