分享
 
 
 

Struts应用的国际化

王朝java/jsp·作者佚名  2006-01-31
窄屏简体版  字體: |||超大  

Struts应用的国际化

万维网(World Wide Web)的迅猛发展推动了跨国业务的发展,它成为一种在全世界范围内发布产品信息、吸引客户的有效手段。为了使企业Web应用能支持全球客户,软件开发者应该开发出支持多国语言、国际化的Web应用。

1 本地化与国际化的概念

国际化(简称为I18N)指的是软件设计阶段,就应该使软件具有支持多种语言和地区的功能。这样,当需要在应用中添加对一种新的语言和国家的支持时,不需要对已有的软件返工,无需修改应用的程序代码。

本地化意味着针对不同语言的客户,开发出不同的软件版本;国际化意味着同一个软件可以面向使用各种不同语言的客户。

如果一个应用支持国际化,它应该具备以下特征:

· 当应用需要支持一种新的语言时,无需修改应用程序代码。

· 文本、消息和图片从源程序代码中抽取出来,存储在外部。

·

应该根据用户的语言和地理位置,对与特定文化相关的数据,如日期、时间和货币,进行正确的格式化。

·

支持非标准的字符集。

·

可以方便快捷地对应用作出调整,使它适应新的语言和地区。

在对一个Web应用进行国际化时,除了应该对网站上的文本、图片和按钮进行国际化外,还应该对数字和货币等根据不同国家的标准进行相关的格式化,这样才能保证各个国家的用户都能顺利地读懂这些数据。

Locale(本地)指的是一个具有相同风俗、文化和语言的区域。如果一个应用没有事先把I18N作为那前的功能,那么当这个应用需要支持新的Locale时,开发人员必需对嵌入在源代码中的文本、图片和消息进行修改,然后重新编译源代码。每当这个应用需要支持新的Locale时,就必需重复这些繁琐的步骤,这种做法显然大大降低了软件开发效率。

2 Web应用的中文本地化

无论时对Web应用的本地化还是国际化,都会涉及字符编码转换问题。当数据流的源与目的地使用不同的字符编码时,就需要对字符编码进行正确的转换。

2.1 处理HTTP请求数据编码

默认情况下,IE浏览器发送请求时采用“ISO-8859-1”字符编码,如果Web应用程序要正确地读取用户发送的中文数据,则需要进行编码转换。

一种方法是在处理请求前,先设置HttpServletRequest对象的字符编码:

request.setCharacterEncoding(“gb2312”);

还有一种办法是对用户输入的请求数据进行编码转换:

String clientData =

request.getParameter(“clientData”);

if(clientData != null)

clientData = new

String(clientData.getBytes(“ISO-8859-1”),

“GB2312”);

2.2 处理数据库数据编码

如果数据库系统的字符编码为“GB2312”,那么可以直接读取数据库中的中文数据,而无需进行编码转换。如果数据库字符编码为“ISO-8859-1”,那么必需先对来自数据库的数据进行编码转换,然后才能使用。

2.3 处理XML配置文件编码

如果在XML文件中包含中文,可以将XML文件的字符编码为“GB2312”。这样,当Java程序加载和解析XML文件时无需再进行编码转换。

<?xml version=’1.0’ encoding=”GB2312”?>

2.4 处理响应结果的编码

可以通过以下方式来设置响应结果的编码:

·

在Servlet中

response.setContentType(“text/html;charset=GB2312”);

·

在JSP中

<%@ page contentType=”text/html;charset=GB2312” %>

·

在HTML中

<head>

<META HTTP-EQUIV=”Content-Type”

CONTENT=”text/html; charset=GB2312”>

</head>

3 Java对I18N的支持

Java在其核心库中提供了支持I18N的类和接口。Struts框架依赖于这些Java I18N组件来实现对I18N的支持,因此,掌握Java I18N组件的使用方法有助于理解Struts应用的国际化机制。

3.1 Locale类

java.util.Locale类时最重要的Java I18N类,在Java语言中,几乎所有对国际化和本地化的支持都依赖于这个类。

Locale类的实例代表一种特定的语言和地区。如果Java类库中的某个类在运行时需要根据Locale对象来调整其功能,那么就称这个类是本地敏感的(Locale-Sensitive)。例如,java.text.DateFormat类就是本地敏感的,因为它需要依照特定的Locale对象来对日期进行相关的格式化。

Locale对象本身病不执行和I18N相关的格式化或解析工作。Locale对象仅仅负责向本地敏感的类提供本地化信息。例如,DateFormat类依据Locale对象来确定日期的格式,然后对日期进行语法分析和格式化。

创建Locale对象时,需要明确地指定其语言和国家代码。如:

Locale

usLocale = new Locale(“en”, “US”);

Locale

chLocale = new Locale(“ch”, “CH”);

构造方法的第一个参数是语言代码。语言代码由两个小写字母组成,遵从ISO-639规范。可以从http://www.unicode.org/unicode/onlinedat/languages.html中获得完整的语言代码列表。

构造方法的第二个参数是国家代码,它由两个大写字母组成,遵从ISO-3166规范。可以从http://www.unicode.org/unicode/onlinedat/countries.html中获得完整的国家代码列表。

Locale类提供了几个静态常量,他们代表一些常用的Locale实例。例如,如果要获得Japanese

Locale实例,可以使用如下两种方法之一:

Locale

locale1 = Locale.JAPAN;

Locale

locale2 = new Locale(“ja”, “JP”);

3.1.1 Web容器中Locale对象的来源

Java虚拟机在启动时会查询操作系统,为运行环境设置默认的Locale。Java程序可以调用java.util.Locale类的静态方法getLocale()来获得默认的Locale:

Locale

defaultLocale = Locale.getDefault();

Web容器在其本地环境中通常会使用以上默认的Locale;而对于特定的中断用户,Web容器会从HTTP请求中获取Locale信息。

3.1.2 在Web应用中访问Locale对象

在创建Locale对象时应该把语言和国家代码两个参数传递给构造方法。对于Web应用程序,通常不必创建自己的Locale实例,因为Web容器会负责创建所需的Locale实例。在应用程序中,可以调用HttpServletRequest对象的以下两个方法,来取得包含Web客户的Locale信息的Locale实例:

public

java.util.Locale getLocale();

public

java.util.Enumeration getLocales();

着两个方法都会访问HTTP请求中的Accept-Language头信息。getLocale()方法返回客户优先使用的Locale,而getLocales()方法返回一个Enumeration集合对象,它包含了按优先级降序排列的所有Locale对象。如果客户没有配置任何Locale,getLocale()方法将会返回默认的Locale。

3.1.3 在Struts应用中访问Locale对象

有序Web服务器并不和客户浏览器保持长期的连接,因此每个发送到Web容器的HTTP请求中都包含了Locale信息。Struts配置文件的<controller>元素的locale属性指定是否把Locale对象保存在session范围中,默认值为true,表示会把Locale对象保存在session范围中。在处理每一个用户请求时,RequestProcessor类都会调用它的processLocale()方法。

尽管每次发送的HTTP请求都包含Locale信息,processLocale()方法把Locale对象存储在session范围中必需满足以下条件:

· Struts配置文件的<controller>元素的locale属性为true。

· 在session范围内Locale对象还不存在。

processLocale()方法把Locale对象存储在session范围中时,属性key为Globals.LOCALE_KEY,这个常量的字符串值为“org.apache.struts.action.LOCALE”。

如果应用程序允许用户在同一个会话中改变Locale,那么应该对每一个新的HttpServletRequest调用其getLocale()方法,来判断用户是否改变了Locale,如果Locale发生改变,就把新的Locale对象保存在session范围内。

在Struts应用程序中可以很方便地获取Locale信息。例如,如果在Action类中访问Locale信息,可以调用在Struts Action基类中定义的getLocale()方法。

Action类的getLocale()方法调用RequestUtils.getUserLocale()方法。

getUserLocale()方法先通过HttpServletRequest参数获得HttpSession对象,然后再通过HttpSession对象来读取Locale对象。如果存在HttpSession对象并且HttpSession中存储了Locale对象,就返回该Locale对象,否则就直接调用HttpServletRequest的getLocale()方法取得Locale对象,并降它返回。

在Web应用程序的其他地方也可以直接调用RequestUtils类的getUserLocale()方法来获取Locale对象。

3.2

ResourceBundle类

java.util.ResourceBundle类提供存放和管理与Locale相关的资源的功能。这些资源包括文本域或按钮的Label、状态信息、图片名、错误信息和网页标题等。

Struts框架并没有直接使用Java语言提供的ResourceBundle类。在Struts框架中提供了两个类:

· org.apache.struts.util.MessageResources

· org.apache.struts.util.PropertyMesasgeResources

这两个类具有和ResourceBundle相似的功能,其中PropertyMessageResources是MessageResources类的子类。

3.3 MessageFormat类和符合消息。

Java的ResourceBundle和Struts的MessageResources类都允许使用静态和动态的文本。静态文本指定的是实现就已经具有明确内容的文本。动态文本指的是只有在运行时才能确定内容的文本。

通常把包含可变数据的消息成为符合消息。符合消息允许在程序运行时把动态数据加入到消息文本中。着能够减少Resource Bundle中的静态消息数量,从而减少把静态消息文本翻译成其他Locale版本所花费的时间。

当然,在Resource Bundle中使用符合信息会使文本的翻译变得更加困难。因为文本包含了直到运行时才知道的替代值,而把包含替代值的消息文本翻译成不同的语言时,往往要对语言做适当调整。

Struts框架封装了MessageFormat类的功能,支持复合消息文本,该功能的实现对于Struts的其他组件是透明的。

4 Struts框架对国际化的支持

Struts框架对国际化的支持体现在能够输出何用户Locale相符合的文本何图片上。当Struts配置文件的<controller>元素的locale属性为true时,Struts框架把用户的Locale实例保存在session范围内,这样,Struts框架能自动根据这一Lcoale实例来从Resource Bundle中选择合适的资源文件。当用户的Locale为英文时,Struts框架就会向用户返回来自于application_en.properties文件的文本内容:当用户的Locale为中文时,Struts框架就会向用户返回来自于appcation_ch.properties文件的文本内容。

4.1 创建Struts的Resource Bundle

对于多应用模块的Struts应用,可以为每个子应用配置一个或多个Resource Bundle,应用模块中的Action、ActionForm

Bean、JSP页和客户化标签都可以访问这些Bundle。Struts配置文件中的每个<message-resources>元素定义了一个Resource Bundle。当应用中包含多个Resource Bundle时,它们通过<message-resources>元素的key属性来区别。

Resource Bundle的持久化消息文本存储在资源文件中,其扩展名为“.properties”,这一文件中消息的格式为:key=value。

在创建Resource Bundle的资源文件时,可以先提供一个默认的资源文件,默认资源文件应该取名为application.properties。如果应用程序需要支持中文用户,可以再创建一个包含中文消息的资源文件,文件名为:application_ch_CH.properties或application_ch.properties。

当Struts框架处理Locale为中文的用户请求时,Struts框架首先在WEB-INF/classes/目录下寻找application_ch_CH.properties文件,如果存在该文件,就从该文件中获取文本消息,否则再一次寻找application_ch.properties和application.properties文件。

应该总是为Resource Bundle提供默认的资源文件,这样,当不存在和某个Locale对应的资源文件时,就可以使用默认的资源文件。

应该把Resource Bundle的资源文件放在能被定位并加载的位置。对于Web应用程序,资源文件的存放目录为WEB-INF/classes目录。如果在配置Resource Bundle时还给定了包名,那么包名应该和资源文件所在的子目录对应。

4.2 访问 Resource Bundle

Struts应用的每个Resource Bundle和org.apache.struts.util.MessageResources类(实际上是其子类PropertyMessageResources)的一个实例对应。MessageResources对象中存放了来自资源文件的文本。当应用程序初始化时,这些MessageResources实例被存储在ServletContext中(即application范围内),因此任何一个Web组件都可以访问它们。一个MessageResources对象可以包含多种本地化版本的资源文件的数据。

Struts应用、子应用模块、Resource Bundle和资源文件之间存在以下关系:

·

一个Struts应用可以有多个子应用模块,必须有且只有一个默认子应用模块。

·

一个子应用模块可以有多个Resource Bundle,必须有且只有一个默认的Resource Bundle。

·

一个Resource Bundle可以有多个资源文件,必须有且只有一个默认资源文件。

下面介绍在Struts应用中访问Resource

Bundle的途径。

1.

通过编程来访问Resource Bundle

在Action积累中定义了getResources(request)方法,它可以返回默认的Message Resources对象,代表当前应用模块使用的默认Resource Bundle。如果要活得特定的MessageResources对象,可以调用Action基类的getResources(request, key)方法,其中参数key和Struts配置文件中的<message-resources>元素的key属性对应。得到了MessageResources对象后,就可以通过它的方法来访问消息文本。

Org.apache.struts.util.MessageResources的getMessage()方法有好几种重载形式,下面列出常用的几种:

·

根据参数置顶的Locale检索对应的资源文件,然后返回和参数key对应的消息文本:

getMessage(java.util.Locale

locale, java.lang.String key)

·

根据参数指定的Locale检索对应的资源文件,然后返回和参数key对应的消息文本,args参数用于替换复合消息文本中的参数:

getMessage(java.util.Locale

locale, java.lang.String key, java.lang.Object[] args)

·

根据默认的Locale检索对应的资源文件,然后返回和参数key对应的消息文本:

getMessaeg(java.lang.String

key)

2.

使用和Resource Bundle绑定的Struts组件

Struts框架中的许多内在组件和Resource Bundle是绑定在一起的,如:

· ActionMessage类和<html:errors>标签。

每个ActionMessage实例代表Resource Bundle中的一条消息。在调用ActionMessage的构造方法时,需要传递消息key。

对于复合消息,在创建ActionMessage对象时,可以调用带两个参数的构造方法:ActionMessage(java.lang.String key, java.lang.Object[] values),values参数用户替换复合消息中的参数。

在JSP页面中,使用<html:errors>标签,就能读取并显示ActionErrors集合中所有ActionMessage对象包含的消息文本。

· Struts Bean标签库的<bean:message>标签。

Struts框架包含了一些可以访问应用的消息资源的客户化标签,其中使用最频繁的一个标签为<bean:message>标签。<bean:message>标签从应用的Resource Bundle中获取消息字符串。

<bean:message>有一个bundle属性,用于指定被访问的Resource Bundle,它和<message-resources>元素的key属性匹配。如果没有设置bundle属性,将访问默认的Resource

Bundle。

·

在Validator验证框架中访问Resource Bundle。

·

在声明型异常处理中访问Resource Bundle。

5 异常处理的国际化

在处理异常时,也应该考虑对I18N的支持。除非已经对应用抛出的异常消息做本地化,否则不应该直接向终端用户展示原始的异常消息。不懂Java语言的终端用户很难理解从Java虚拟机堆栈中抛出的Java异常消息,如果这些异常消息使用的不是用户的本地语言,那就更加会让用户困惑不解。

应该先把异常捕获,对异常消息进行本地化后,再把它展示给用户。Struts的Resource

Bundle和ActionMessage类可以完成这一功能。直接向终端用户显示Java异常绝对是不可取的。即使发生了无法恢复的系统错误,也应该向用户显示本地化的系统错误页。

6 小结

本文档介绍了软件的本地化与国际化的概念,然后消息介绍了对Struts应用实现国际化的原理和方法。与国际化密切相关的两个组件是Locale和Resource

Bundle:

· Locale:包含了用户的本地化信息,如语言和国家。

· Resource Bundle:包含了多个消息资源文件,每个消息资源文件存放和一种Locale相对应的本地化消息文本。

Struts框架的初始化时,把Resource

Bundle(即MessageResources对象)存储在application范围内;在响应用户请求时,把包装用户Locale信息的Locale实例存储在session范围内。Struts框架能自动根据这一Locale实例,从Resource Bundle中检索相应的资源文件,再从资源文件中读取本地化的消息文本。

对Struts应用实现国际化应该遵循以下原则:

·

尽量不在Servlet中使用含非英文字符的常量字符串。

·

对于JSP文件,应该对page指令中的charset属性进行相应的设置。

·

不要在JSP文件中直接包含本地化的消息资源,儿应该把消息资源存放在Resource Bundle的资源文件中。

·

不比在每个JSP或Servlet中设置HTTP请求的字符编码,可以在Servlet过滤器中设置编码:

HttpServletRequest.setCharaterEncoding(String encoding);

·

尽量使用“UTF-8”作为HTTP请求和响应的字符编码,而不是“GBK”或“GB2312”。

·

充分考虑底层数据库所使用的编码,它可能会给应用程序的移植带来麻烦。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有