引文
假如我们开发了一个在中文环境下运行的页面,代码如下:
<html>
<head>
<title>欢迎</title>
</head>
<body>
<h1>
欢迎到来!
</h1>
</body>
</html>
之后又假如,有一天我们公司的业务扩展到了日本,和美国,那么我们必须要订制另外的两张不同的页面,代码为:
<html>
<head>
<title>Welcome</title>
</head>
<body>
<h1>
Welcome Here!
</h1>
</body>
</html>
和
<html>
<head>
<title>ようこそ</title>
</head>
<body>
<h1>
ようこそ!
</h1>
</body>
</html>
也许你已经看到了,上述代码只有文字内容不相同,除此之外完全相同。也许你已经猜到了,现实的代码绝对不是这样的。那么是怎么处理的呢?
基本概念
引用
Internationalization and localization are means of adapting
products such as publications, hardware or software for non-native
environments, especially other nations and cultures.
国际化(internationalization i18n)和本地化(localization l10n)指让产品(出版物,软件,硬件等)能够适应非本地环境,特别是其他的语言和文化。
针对计算机来说就是让一个既可以在中文环境下运行也可以在英语,甚至是日语的环境下运行。
Java中如何实现国际化(仅限语言层面)
Java中国际化通过两步来完成,
第一, 通过将文字内容以特定的方式存放在特定的文件中,
特定的文件:方便管理,另外可以将文件明和特定的语言管理起来
特定的方式:有些时候有些环境不支持某些语言,例如通常英文环境不支持中文,所以要将中文改变为英文可以识别的形式,在使用的时候在转变回来。
第二,在运行时根据当前的语言环境决定从哪个文件中读取文字内容。
第一步,特定的文件,特定的格式
特殊的文件明通过语言和国家来定义,例如:
中文中国 zh_CN
日文日本 ja_JP
英语美国 en_US
Java中国际化的概念是将不同国家的语言描述的相同的东西放在各自对应的属性文件中,
如果这个文件的名字叫做Message,那么对应语言的文件分别为:
中文中国 Message_zh_CN.properties
日文日本 Message_ja_JP.properties
英文美国 Message_en_US.properties
特殊的方式使用替换ascii的方式,java中提供了一个native2ascii.exe的工具(在JAVA_HOME\bin目录下),这个工具专门用来把某种特定的文字内容转变为特殊的格式。
例如Message_zh_CN.properties中的内容为:
Msg1 = 欢迎
Msg2 = 欢迎到这里!
经过命令native2ascii Message_zh_CN.properties之后输出:
Msg1 = \u6b22\u8fce
Msg2 = \u6b22\u8fce\u5230\u8fd9\u91cc\uff01
这里\u6b22等的数字是对应汉字(或者其他非英语字符)的unicode表示
第二步,通过当前的运行环境确定使用的文件的名字
例如存在上述的三个文件:
中文中国 Message_zh_CN.properties
日文日本 Message_ja_JP.properties
英文美国 Message_en_US.properties
可以使用java.util.ResouceBundle 类来取得当前的资源文件,代码为:
ResourceBundle rb = ResourceBundle.getBundle("Message");
也可以指语言与国家特征来获得想要的文件的内容,例如:
ResourceBundle rb = ResourceBundle.getBundle("Message", Locale.JAPAN);
Struts2中如何实现国际化(仅限语言层面)
Struts2中使用国际化的几个方法:
1) UI标签
例如:
<s:i18n name="struts.action.test.i18n.Shop">
<s:text name="main.title"/>
</s:i18n>
从指定资源文件struts.action.test.i18n.Shop中找到main.title对应的消息内容。
<!-- Second Example -->
<s:text name="main.title" />
从对应的文件中找到main.title对应的消息内容。
<!-- Third Examlpe -->
<s:text name="i18n.label.greetings">
<s:param >Mr Smith</s:param>
</s:text>
从对应的文件中找到i18n.label.greetings对应的消息内容,其中的{0}参数将会被Mr Smith替换。
2) ActionSupport的getText方法
例如:<s:text name="%{getText("i18n.label.greetings")}">
或者在Action中直接使用。
在没有指定资源文件的情况下,资源文件的查找按如下的顺序:
1)ActionClass.properties
2)BaseClass.properties
3)Interface.properties
4)ModelDriven’s Model
5)package.properties
6)search up the i18n message key hierarchy itself
7)global resource properties
例如有如下结构:
com/
acme/
package.properties
actions/
package.properties
FooAction.java
FooAction.properties
如果FooAction.properties文件不存在,将使用com/acme/action
/package.properties,如果com/acme/action/package.properties文件不存在,将使用com
/acme/ package.properties,如果还不存在,将使用com/ package.properties等等。
可以通过getText方法,text标签或者i18n标签来访问资源文件。
可以在struts.properties中通过struts.custom.i18n.resources来指定global的资源绑定。
相关参考I18n Intercepter
关于类型转换的国际化支持参看【第七章 Type Convertion】部分