第 14 章 国际化

目录

地域
px_preferred_locale会话属性
请求拦截器
时区
px_preferred_time_zone 会话属性
请求拦截器
标签
本地文件
浏览器和本地URI
在Java中定位浏览器与本地资源
消息
主题
改变字体大小和/或样式
使用自制主题
主题提供者

本章描述了如何使ZK应用程序足够简单的运行在任何地域(in any locale)。

首先,ZK允许开发人员以任何喜欢的方式嵌入Java代码或EL表达式。你可以使用国际化(Internationalization)方法,例如java.util.ResourceBundle

但是,ZK对于国际化有一些内置(built-in)的支持,你或许会发现它们很有用。

地域

地域(locale)用于处理请求和事件,默认情况下,由浏览器的首选项(preferences)(通过使用javax.servlet.ServletRequestgetLocale方法)决定。

但是,这是可以配置的。例如,你或许想为所有的用户使用相同的地域(locale),而不管浏览器是如何配置的。另一个例子,若在服务器端维护用户的profiles,你或许想使用用户在他或她的profile内指定的首选(preferred)地域(locale)。

px_preferred_locale会话属性

在检查浏览器的首选项之前,ZK会首先检查是否定义了一个名为px_preferred_locale的会话属性。若定义了,ZK会使用它作为会话默认的地域(locale),同时代替浏览器的首选项。因此,通过为此属性中的首选 locale排序,你可以控制一个会话的地域(locale)。

例如,当用户登录时你可以这样做。

void login(String username, String password) {
   //check password
   ...
   Locale preferredLocale = ...; //decide the locale (from, say, database)
   session.setAttribute("px_preferred_locale", preferredLocale);
   ...
}

[提示]:为避免typo,你饿可以使用定义在org.zkoss.web.Attributes类内的PREFERRED_LOCALE常量。

请求拦截器

在用户登录之后才决定地域(locale),对于一些应用程序已经有些晚了。例如,在用户登录之前,你或许想使用与前一个会话相同的地域(locale)。对于一个Web应用程序,这通常由cookies处理。使用ZK,你可以注册一个请求拦截器,并且当拦截器被调用时维护cookies。

请求拦截器被用于拦截由ZK加载器和ZK更新引擎处理的每个请求。它必须实现org.zkoss.zk.ui.util.RequestInterceptor接口。例如,

public class MyLocaleProvider implements org.zkoss.zk.ui.util.RequestInterceptor {
   public void request(org.zkoss.zk.ui.Session sess,
   Object request, Object response) {
      final Cookie[] cookies = ((HttpServletRequest)request).getCookies();
      if (cookies != null) {
         for (int j = cookies.length; --j >= 0;) {
            if (cookies[j].getName().equals("my.locale")) {
               //determine the locale
               String val = cookies[j].getValue();
               Locale locale = org.zkoss.util.Locales.getLocale(val);
               sess.setAttribute(Attributes.PREFERRED_LOCALE, locale);
               return;
            }
         }
      }
   }
}

为使其生效,你必须按如下方式在WEB-INF/zk.xml内进行注册。一旦注册,每次ZK加载器或ZK更新引擎接收一个请求时都会调用request方法。关于配置的详细信息,请参考the Developer's Reference的附录B(Appendix B)。

<listener>
   <listener-class>MyLocaleProvider</listener-class>
</listener>

[注]:当注册时,一个拦截器的实例会被初始化。然后,相同应用程序内的所有请求会共享此拦截器。因此,你必须确保拦截器可以被同时访问(也就是说,线程安全)。

[注]: request方法会在很早的阶段被调用,在请求参数被解析之前。因此,推荐在此方法中访问它们,除非你为请求合适的配置了地域(locale)和字符编码。