Seam通过提供几个内置部件来为UI提供多语言支持,从而使构建国际化的应用程序变得十分容易。
每一个用户登录会话都有一个相关的 java.util.Locale 实例(以名为 locale 的组件形式提供给应用程序)。 一般情况下,不需要做任何特别的配置设置locale,Seam 委托JSF来判断当前的活动locale:
通过Seam的以下几个配置属性来手工设置locale也是你 可能的: org.jboss.seam.international.localeSelector.language、 org.jboss.seam.international.localeSelector.country和 org.jboss.seam.international.localeSelector.variant,但是并不推荐这种做法。
然而,允许用户通过应用程序的用户界面来手工设置locale也是很有益处的。Seam提供了内置的功能来覆盖通过上述算法决定的locale。你所要做的只是 在JSP或Facelet的Form中增加以下代码段:
<h:selectOneMenu value="#{localeSelector.language}"> <f:selectItem itemLabel="English" itemValue="en"/> <f:selectItem itemLabel="Deutsch" itemValue="de"/> <f:selectItem itemLabel="Francais" itemValue="fr"/> </h:selectOneMenu> <h:commandButton action="#{localeSelector.select}" value="#{messages['ChangeLanguage']}"/>
或者,如果你想要一个 faces-config.xml 支持的所有locale的列表,就用:
<h:selectOneMenu value="#{localeSelector.localeString}"> <f:selectItems value="#{localeSelector.supportedLocales}"/> </h:selectOneMenu> <h:commandButton action="#{localeSelector.select}" value="#{messages['ChangeLanguage']}"/>
当在下拉列表中选择一项,并按下按钮后,随后会话中Seam和JSF的locale就被刷新了。
JSF 通过使用 <f:loadBundle /> 来支持用户界面标签和描述文本的国际化。这个方法同样可以用在Seam应用程序中。 或者,可以利用Seam的 messages 组件用内嵌的EL表达式来显示模板标签。
Seam提供了一个 java.util.ResourceBundle (以org.jboss.seam.core.resourceBundle 的名字提供给应用程序)。 你需要通过这个指定的资源包来使你的国际化标签可用。默认情况下,Seam 使用名为messages的资源包, 你需要在 messages.properties、messages_en.properties、messages_en_AU.properties 等文件中定义你的标签。这些文件通常在 WEB-INF/classes 目录下。
因此,在 messages_en.properties中:
Hello=Hello
和在 messages_en_AU.properties中:
Hello=G'day
你可以通过设置Seam的配置属性 org.jboss.seam.core.resourceLoader.bundleNames 为资源包选择一个不同的名字。 甚至可以指定一个资源包名称列表,以深度优先进行消息的搜索。
<core:resource-loader> <core:bundle-names> <value>mycompany_messages</value> <value>standard_messages</value> </core:bundle-names> </core:resource-loader>
如果想为一个特殊页定义消息,可在以一个和JSF View id同名的资源包中指定,去掉前置 / 和文件扩展名。 这样,如果我们只想在 /welcome/hello.jsp 中显示消息,就把它置于 welcome/hello_en.properties 中。
你还可以在 pages.xml 中指定一个显式的绑定名称:
<page view-id="/welcome/hello.jsp" bundle="HelloMessages"/>
这样,我们就可以在 /welcome/hello.jsp 中使用定义在 HelloMessages.properties 中的消息了。
如果使用Seam的资源包来定义标签,就不用每页再写 <f:loadBundle ... /> 了,可以使用这种简单的形式:
<h:outputText value="#{messages['Hello']}"/>
或者:
<h:outputText value="#{messages.Hello}"/>
更好的一点是,message自身可以包含EL表达式:
Hello=Hello, #{user.firstName} #{user.lastName}
Hello=G'day, #{user.firstName}
你也可以在代码中这样使用消息:
@In private Map<String, String> messages;
@In("#{messages['Hello']}") private String helloMessage;
facesMessages 组件是一个向用户显示成功或者失败消息的非常方便的途径。 我们之前描述的功能对Faces Messages同样有效:
@Name("hello") @Stateless public class HelloBean implements Hello { @In FacesMessages facesMessages; public String sayIt() { facesMessages.addFromResourceBundle("Hello"); } }
这将根据用户的locale显示 Hello, Gavin King 或者 G'day, Gavin。
Seam中还有一个session范围的 java.util.Timezone 实例,叫做 org.jboss.seam.international.timezone, 和一个名为 org.jboss.seam.international.timezoneSelector 的用于设置时区的组件。默认情况下,时区取服务器的默认时区。 不幸的是,JSF规范中讲所有的日期和时间都假设是UTC 的,并且显示为UTC,除非使用 <f:convertDateTime> 明确地为其指定时区。 这是一个非常不方便的默认行为。
Seam覆写了这个行为,默认所有的日期和时间都是Seam的时区。另外,Seam提供了 <s:convertDateTime> 标签,用来处理Seam 时区的转化。
Seam应用程序可以很方便地改变皮肤。Theme API和本地化API非常相似,但是它们二者的关注点截然不同,一些应用同时支持本地化和主题。
首先,配置所支持的主题集合:
<theme:theme-selector cookie-enabled="true"> <theme:available-themes> <value>default</value> <value>accessible</value> <value>printable</value> </theme:available-themes> </theme:theme-selector>
注意,第一个是默认的主题。
主题定义在一个和该主题同名的属性文件中。例如,default 主题定义在default.properties中。 default.properties可能是这样定义的:
css ../screen.css template /template.xhtml
通常主题资源包的内容是CSS样式或图片的路径和facelet模板(不像本地化资源包那样通常是文本)。
现在我们可以在JSP或者Facelet页面中使用这些内容了。例如,一个Facelet页的风格可以这样:
<link href="#{theme.css}" rel="stylesheet" type="text/css" />
或者,当页面定义在一个子目录中时可以这样:
<link href="#{facesContext.externalContext.requestContextPath}#{theme.css}" rel="stylesheet" type="text/css" />
最强大的是,Facelet让我们通过 <ui:composition> 把模板主题化:
<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" template="#{theme.template}">
正如locale选择器一样,有一个内置的主题选择器允许用户在各主题间自由地切换:
<h:selectOneMenu value="#{themeSelector.theme}"> <f:selectItems value="#{themeSelector.themes}"/> </h:selectOneMenu> <h:commandButton action="#{themeSelector.select}" value="Select Theme"/>
locale选择器、主题选择器和时区选择器全都支持持久化,把参数保存到cookie中。仅需要在components.xml中设置 cookie-enabled 配置属性:
<theme:theme-selector cookie-enabled="true"> <theme:available-themes> <value>default</value> <value>accessible</value> <value>printable</value> </theme:available-themes> </theme:theme-selector> <international:locale-selector cookie-enabled="true"/>