jee6 学习笔记 10: Internationalizing the web app

Making a web app to support multiple languages.

 

This is achieved in JSF2 by using message properties files (resource bundles) and load the correct key/value pair from these resource files, based on the current locale the web application is set.

 

One configuration is in the "faces-config.xml", to setup the default locale and the location of the messages files. JSF would load these resources once accessed.

 

Here's the relevant section in "faces-config.xml":

 

<application>
   	<locale-config>
   	   	<default-locale>en</default-locale>
   	   	<supported-locale>zh</supported-locale>
   	 </locale-config>
	 <resource-bundle>
		<base-name>com.jxee.messages</base-name>
		<var>msgs</var>
	</resource-bundle>
</application>

 

Note: According to the above configuration, the message resource bundle should reside in this directory: "web_application_classpath_root/com/jxee". This means that a valid place would be "WEB-INF/classes/com/jxee". Since we are supporting English and Chinese in this example, two resource files should be created, one for English and one for Chinese.

 

The following is the proejct directory screen shot for these two files:


jee6 学习笔记 10: Internationalizing the web app_第1张图片

 

The JSF pages need to set the current locale when rendering the pages. This can be done by the following code ( Since every page needs to set this property, the template is a good place to put it):

 

<f:view locale="#{langBean.appLocale}">

 

 

This example enables the web application user to choose the language, by using a Primefaces context menu. The backing bean of the context menu would set the current local for the web application.

 

Here's the context menu soruce (again, the template is a good place to include it):

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui">
    <h:form>
	<p:contextMenu>
	    <p:menuitem value="#{msgs.english}" 
	    	actionListener="#{langBean.change2English}" 
	    	rendered="#{langBean.appLocale.language != 'en'}" 
	    	immediate="true" ajax="false"/>
	    	
	    <p:menuitem value="#{msgs.chinese}" 
	    	action="#{langBean.change2Chinese}" 
	    	rendered="#{langBean.appLocale.language != 'zh'}" 
	    	immediate="true" ajax="false"/>
	    	
	    <p:separator/>
	    
	    <p:menuitem value="Primefaces Homepage" url="http://www.primefaces.org"/>  
	</p:contextMenu>
	</h:form>
</html>
 

One thing need to mention in the above code is that since we use Primefaces tags, we need to set attribute ajax="false" , in order to make the form submitted and re-rendered, after the backing bean change the current locale for the whole application. Otherwise it would only change the labels with a refresh/redirect.

 

Here's the backing bean for the above context menu to change the application locale:

 

package com.jxee.action;

import java.io.Serializable;
import java.util.Locale;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;

import org.apache.log4j.Logger;
 
@SessionScoped
@ManagedBean(name="langBean")
public class LocaleBean implements Serializable{
 
  private static Logger log = Logger.getLogger(LocaleBean.class);
  private Locale appLocale = Locale.ENGLISH;
  
  @PostConstruct
  public void init() {
    FacesContext.getCurrentInstance().getViewRoot().setLocale(this.appLocale);
    log.debug(">>> locale inited to: " + this.appLocale.getLanguage());
  }
  
  public Locale getAppLocale() {
    return appLocale;
  }

  public void setAppLocale(Locale appLocale) {
    this.appLocale = appLocale;
  }
  
  // as an action listener
  public void change2English(ActionEvent e) {
    this.appLocale = Locale.ENGLISH;
    FacesContext.getCurrentInstance().getViewRoot().setLocale(this.appLocale);
    log.debug(">>> locale changed to English: " + this.appLocale.getLanguage());
  }
  
  // as an action method
  public String change2Chinese() {
    this.appLocale = Locale.CHINESE;
    FacesContext.getCurrentInstance().getViewRoot().setLocale(this.appLocale);
    log.debug(">>> locale changed to Chinese: " + this.appLocale.getLanguage());
    return null;
  }
}

 

OK, looks like everything is setup. Now just need to change the "/template/template1.xhtml" to include the <f:view locale="..."/> and the language chooser context menu. Then in the JSF page sources, we need to change very hard coded labels to something like "#{msgs.label_key_name}".

 

Here's the updated template1.xhtml:

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
   	xmlns:ui="http://java.sun.com/jsf/facelets"
   	xmlns:p="http://primefaces.org/ui">
   	
  <f:view locale="#{langBean.appLocale}">
	  <h:head>
	    <title>
	      <ui:insert name="title">Title</ui:insert>
	    </title> 
	  </h:head>
	  
	  <h:body>  
	     <ui:insert name="menu">
	     	<ui:include src="menubar.xhtml"/>
	     	<ui:include src="contextmenu.xhtml"/>
	     </ui:insert>
	     
	     <p:spacer height="20"/>
	     	
	     <ui:insert name="content"/>
	  </h:body> 
  </f:view>
</html>
 

The updated JSF page "/tst/testSingleton.xhtml" (also updated main menu and studentSearch.xhtml):

 

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
   				xmlns:h="http://java.sun.com/jsf/html"
      			xmlns:f="http://java.sun.com/jsf/core"
      			xmlns:ui="http://java.sun.com/jsf/facelets"
      			xmlns:p="http://primefaces.org/ui"
   				template="/template/template1.xhtml">

<ui:define name="title">Test EJB3.1 @Singleton</ui:define>

<ui:define name="content">
	<h:form>
    <p:panel header="#{msgs.testSingletonHeader}" toggleable="true" style="width:60%">
    	<h:panelGrid columns="1">
        	Click "Test" to see if it's the same instance:
        	<h:outputText id="out" value="#{st.message}" escape="false"/>
        </h:panelGrid>
        <p:separator/>
        <p:commandButton value="#{msgs['test']}" action="#{st.test}" update="out"/>
        <p:spacer width="7"/>
        <p:commandButton value="#{msgs.clear}" actionListener="#{st.reset}" update="out"/>
    </p:panel>
    </h:form>
</ui:define>
</ui:composition>

 

 

Here's the "com.jxee.messages_zh.properties" (with Eclipse 3.7 "Indigo", it translated to unicode while i inputing Chinese, that cool! Othewise, you might want use JDK tool "native2ascii" to translate the Chinese characters to unicode):

 

### main menu labels
student=\u5B66\u751F
studentSearch=\u5B66\u751F\u67E5\u8BE2
studentNew=\u8F93\u5165\u65B0\u751F
blah=blah and blah

ajaxTest=Ajax \u8BD5\u9A8C
getParamTest=Get Param \u8BD5\u9A8C
ejbTest=EJB \u8BD5\u9A8C
asyncEjbTest=Asnyc EJB \u8BD5\u9A8C
singletonEjbTest=Singleton EJB \u8BD5\u9A8C

username=\u7528\u6237\u540D
password=\u53E3\u4EE4
login=\u829D\u9EBB\u5F00\u95E8
logout=\u79BB\u5F00

search=\u67E5\u8BE2

### context menu labels: for Chinese locale, shows English labels
english=English
chinese=Chinese

### test Singleton ejb labels
test=\u8BD5\u9A8C
clear=\u518D\u6765\u4E00\u904D\u5E7F\u64AD\u4F53\u64CD (-;
testSingletonHeader=\u8BD5\u9A8C EJB3.1 @Singleton

### student search screen
name=\u59D3\u540D
mobile=\u624B\u673A
createdDate=\u8F93\u5165\u65E5\u671F
studentFound=\u67E5\u8BE2\u5230\u7684\u5B66\u751F
addNewStudent=\u6DFB\u52A0\u5B66\u751F
 

 

Now take a look at what we've got:

 

ss1: The language chooser context menu, before switching to Chinese:


jee6 学习笔记 10: Internationalizing the web app_第2张图片

 

ss2: The language chooser context menu, after switched to Chinese:


jee6 学习笔记 10: Internationalizing the web app_第3张图片

 

ss3: The i18Ned screen "/student/studentSearch.jsf":


jee6 学习笔记 10: Internationalizing the web app_第4张图片

 

not too bad!

你可能感兴趣的:(locale,jsf2,i18n,primefaces)