1

我必须使用 JSF2 实现基于域的 I18N。

例如,如果域是

www.bookstore.com      --> it should go to english site
www.bookstore.com.cn   --> it should go to chinese site
www.bookstore.co.jp    --> it should go to japanese site

我们拥有所有经过适当翻译的属性文件。当我更改浏览器语言/区域设置时,我可以看到翻译后的内容。但我们实际上并不需要这种行为。我在过滤器中根据域设置语言环境,它似乎不起作用。这是我的代码,这段代码有什么问题,问题出在哪里?

AuthenticationFilter.java

public class AuthenticationFilter implements Filter {

    private static Log log = LogFactory.getLog(AuthenticationFilter.class); 

    @Override
    public void init(FilterConfig config) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {

        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");

        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        FacesContext facesContext = FacesUtil.getFacesContext(httpRequest, httpResponse);
        facesContext.getExternalContext().setResponseCharacterEncoding("UTF-8");        

        Locale requestLocale = LocaleUtil.getLocaleFromDomain(httpRequest);         
        if(requestLocale == null){
            requestLocale = LocaleUtil.getDefault();
        }

        facesContext.getViewRoot().setLocale(requestLocale);
        chain.doFilter(httpRequest, httpResponse);
    }

    @Override
    public void destroy() {
    }

}

FacesUtil.java

public class FacesUtil {

  public static FacesContext getFacesContext(HttpServletRequest request, HttpServletResponse response) {
    FacesContext facesContext = FacesContext.getCurrentInstance();
    if (facesContext == null) {
      LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
      Lifecycle lifecycle = lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
      FacesContextFactory contextFactory = (FacesContextFactory) FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
      facesContext = contextFactory.getFacesContext(request.getSession().getServletContext(), request, response, lifecycle);
      UIViewRoot view = facesContext.getApplication().getViewHandler().createView(facesContext, "");
      facesContext.setViewRoot(view);
      FacesContextWrapper.setCurrentInstance(facesContext);
    }
    return facesContext;
  }

  // Wrap the protected FacesContext.setCurrentInstance() in a inner class.
  private static abstract class FacesContextWrapper extends FacesContext {
    protected static void setCurrentInstance(FacesContext facesContext) {
      FacesContext.setCurrentInstance(facesContext);
    }
  }

}

LocaleUtil.java

public class LocaleUtil {

    public static Locale getLocaleFromDomain(HttpServletRequest request){

           Locale locale=Locale.getDefault();

           String domain = request.getHeader("HOST");

           if(domain.contains(".com.cn"))
           {
               locale = new Locale(Locale.SIMPLIFIED_CHINESE.getLanguage(), Locale.CHINA.getCountry());

           }else if(domain.contains(".co.jp"))
           {
               locale = new Locale(Locale.JAPANESE.getLanguage(), Locale.JAPAN.getCountry());

           }else if(domain.contains(".co.kr"))
           {
               locale = new Locale(Locale.KOREAN.getLanguage(), Locale.KOREA.getCountry());

           }else if(domain.contains(".com.tw"))
           {
              locale = new Locale(Locale.CHINESE.getLanguage(), Locale.TAIWAN.getCountry());              
           }
           return locale;
        }        

    public static Locale getDefault() {
        Locale defaultLocale = new Locale("en", "US");
        return defaultLocale;
    }

    }

面孔-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<faces-config version="2.0" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd">

    <application>
        <locale-config>
            <default-locale>en</default-locale>
            <supported-locale>en_US</supported-locale>
            <supported-locale>zh</supported-locale>
            <supported-locale>zh_CN</supported-locale>
            <supported-locale>zh_TW</supported-locale>
            <supported-locale>ja</supported-locale>
            <supported-locale>ja_JP</supported-locale>
        </locale-config>
        <resource-bundle>
            <base-name>com.bookstore.component.BookStoreTextHandler</base-name>
            <var>msg</var>
        </resource-bundle>
    </application>

</faces-config> 

BookStoreTextHandler.java

public class BookStoreTextHandler extends ResourceBundle {

    protected static final String BUNDLE_NAME = "/var/app/conf/bookstore";
    protected static final String BUNDLE_EXTENSION = "properties";
    protected static final Control UTF8_CONTROL = new UTF8Control();

    public BookStoreTextHandler() {
        Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
        setParent(ResourceBundle.getBundle(BUNDLE_NAME, locale, UTF8_CONTROL));
    }

    @Override
    protected Object handleGetObject(String key) {
        return parent.getObject(key);
    }

    @Override
    public Enumeration<String> getKeys() {
        return parent.getKeys();
    }

    protected static class UTF8Control extends Control {
        @Override
        public ResourceBundle newBundle(String baseName, Locale locale, String format, ClassLoader loader, boolean reload)
                throws IllegalAccessException, InstantiationException, IOException {

            String bundleName = toBundleName(baseName, locale);
            String resourceName = toResourceName(bundleName, BUNDLE_EXTENSION);
            ResourceBundle bundle = null;

            InputStreamReader reader = null;
            FileInputStream fis = null;
            try {
                File file = new File(resourceName);

                if (file.isFile()) { // Also checks for existance
                    fis = new FileInputStream(file);
                    reader = new InputStreamReader(fis, Charset.forName("UTF-8"));
                    bundle = new PropertyResourceBundle(reader);
                }
            } finally {
                IOUtils.closeQuietly(reader);
                IOUtils.closeQuietly(fis);
            }
            return bundle;
        }
    }

}

我有bookstore.properties, bookstore_en.properties, bookstore_en_US.properties, bookstore_zh.properties, bookstore_zh_CN.properties, bookstore_zh_TW.properties, bookstore.properties_ja, bookstore_ja_JP.properties/var/app/conf/ 位置的文件。

介绍页.xhtml

<ui:composition lang="en" xmlns="http://www.w3.org/1999/xhtml"
                xmlns:f="http://java.sun.com/jsf/core"
                xmlns:h="http://java.sun.com/jsf/html"
                xmlns:c="http://java.sun.com/jsp/jstl/core"
                xmlns:fn="http://java.sun.com/jsp/jstl/functions"
                xmlns:ui="http://java.sun.com/jsf/facelets">

    <div class="frame">
        <h1>#{msg['bookstore.intro.title']}</h1>        
    </div>

    <div>
        <p style="line-height: 1.6em; font-family: Verdana, Arial, sans-serif;">
            <h:outputText value="#{msg['bookstore.intro.paragraph.1']}" escape="false"/>
        </p>
        <p style="line-height: 1.6em; font-family: Verdana, Arial, sans-serif;">
            <h:outputText value="#{msg['bookstore.intro.paragraph.2']}" escape="false"/>
        </p>
        <p style="line-height: 1.6em; font-family: Verdana, Arial, sans-serif; font-weight: bold;">
            <h:outputText value="#{msg['bookstore.intro.paragraph.3']}" escape="false"/>
        </p>
    </div>

</ui:composition>

当我从不同的域尝试[我已经在本地更改了我的主机文件]时,当我调试过滤器代码时,它会根据域提供正确的区域设置。但不知道为什么总是得到英文内容。但是如果我更改浏览器语言,我可以看到翻译后的内容。这段代码有什么问题?

4

0 回答 0