Friday, December 13, 2013

Multi-Lingual JSF





The default answer to having a multilingual page when developing an application is to develop two pages. This will usually add the complexity of managing the pages by resulting in the added effort of maintaining both pages/forms when having adding/amending a function. A simple solution to the problem is by considering the language to be as a separate function and manage it accordingly.

In-line with the function of multi-lingual, let us use the terminology of Function-Oriented application (as a sub-level of OO) where the function of presentation is isolated from the function of language and, as such, is isolated from the core function of the application. Within JSF, you can easily isolate the functionality of a multi lingual application. Let us start by a bundle two bundle files (This can be in a database if you prefer). Here I will use Arabic and English

BundleEn.bundle


dir=ltr 
Previous=Previous   
Next=Next  

BundleAr.bundle

dir=rtl 
Previous=سابق   
next=التالي  

Then Create a Managed Bean with the scope set as Session Scoped (This is to ensure you maintain the selected language)



UserSession.java

@ManagedBean   
@SessionScoped   
public class UserSession implements Serializable{
      private String lang;   
     FacesContext ctx;     
     public void setAr(){   
     lang="Ar";  
        try {  
            ExternalContext ctx = FacesContext.getCurrentInstance().getExternalContext();  
            ctx.redirect(ctx.getRequestContextPath());  
        } catch (IOException ex) {  
            Logger.getLogger(UserSession.class.getName()).log(Level.SEVERE, null, ex);  
        }  
    }  
    public void setEn(){  
        lang="En";  
        try {  
            ExternalContext ctx = FacesContext.getCurrentInstance().getExternalContext();  
            ctx.redirect(ctx.getRequestContextPath());  
        } catch (IOException ex) {  
            Logger.getLogger(UserSession.class.getName()).log(Level.SEVERE, null, ex);  
        }  
    }  
      
    public String getLabel(String label){  
        try{  
            return ResourceBundle.getBundle("/Bundle"+lang).getString(label);  
        } catch (Exception e){  
            return "No Label for " + label;  
        }  
    }  
      
    public String getLang() {  
        return lang;  
    }  
  
    public void setLang(String lang) {  
        this.lang = lang;  
    }  
}  


Finally, your JSF page. Depending on the label you need to retrieve, you may use the expression language in the following form:
<h:form dir="#{userSession.getLabel('dir')}">  
    <p:commandLink value="English" action="#{userSession.setEn()}" />  
    <p:commandLink value="عربي" action="#{userSession.setAr()}"  />  
    <h:outputText value="#{userSession.getLabel('next')}"/>  
    <h:outputText value="#{userSession.getLabel('Previous')}"/>  
</h:form>  


where dir while define the orientation of the page (left to right or right to left), next and previous will refer to the label title next and Previous respectively in the bundle bundle file based on the selected language. By implementing you code in the above manner, you open the opportunity to configure new languages as you feel free and it will require minimum maintenance from a technical perspective.