This tutorial JSF 2 internationalization example shows how you make an web based application in different languages. I will show here how you can switch in different languages like Bengali, Hindi, English, Dutch and French. You don’t need to change the language settings from the browser for switching to different languages. I have given user an option to choose a language in a dropdown where the languages are displayed in Bengali, Hindi, English, Dutch and French.
If you want you can add more languages and accordingly you need to create separate properties file for each language and configure the supported-locale in faces-config.xml file.
This application shows title, welcome message, choose language option and copyright information in Bengali, Hindi, English, Dutch and French languages. By default the selected language is English. You can also set the default language as per your choice, for that you have to configure in the LocaleSwitcher.java managed bean.
Related Posts:
Final Output
Choose language

English

Bengali

Hindi

Dutch

French

Prerequisites
Java at least 1.8, Gradle 6.5.1, Maven 3.6.3, JSF 2.2.20
Project Setup
Create a gradle or maven based project in Eclipse. The name of the project is jsf-2-internationalization-i18n.
If you creating gradle based project then use below build.gradle script:
plugins {
id 'war'
id 'java-library'
}
repositories {
jcenter()
}
dependencies {
implementation 'com.sun.faces:jsf-api:2.2.20'
implementation 'com.sun.faces:jsf-impl:2.2.20'
implementation 'javax.enterprise:cdi-api:2.0.SP1'
}
If you are creating maven based project then use below pom.xml file:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.roytuts</groupId>
<artifactId>jsf-2-internationalization-i18n</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>2.2.20</version>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-impl</artifactId>
<version>2.2.20</version>
</dependency>
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>2.0.SP1</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>jsf2-immediate-attribute</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>12</source>
<target>12</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Deployment Descriptor – web.xml
I have modified the deployment descriptor file for jsf support and welcome file rendered as home page once the application starts up.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>JSF 2 i18n - Internationalization</display-name>
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>index.jsf</welcome-file>
</welcome-file-list>
</web-app>
In the above web.xml file there are several properties as shown below:
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
This context-param tells which environment you will use. Environments can be Development, SystemTest, UnitTest, Extension and Production.
So I will use here Development because I want to get all the benefits for debugging, testing, error reporting etc. for developing the application.
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
The above configuration uses FacesServlet which is related to Java Server Faces. All requests and responses from the client route through this FacesServlet.
You have also <load-on-startup/> for loading the FacesServlet
at the same time when the application starts up.
You can have any value from 0 to 127 for <load-on-startup/>.
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>
You need to map the URL pattern for each request/response coming from the client. We can have *.jsf, *.faces and *.xhtml for <url-pattern/>.
Remember you cannot have multiple URL pattern for JSF application but other applications, such as, Struts can have multiple pattern for client requests.
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
The above configuration is required only if are going to use http session for putting some objects in session like login based application.
<welcome-file-list>
<welcome-file>index.jsf</welcome-file>
</welcome-file-list>
This holds a list of welcome files but remember only one of them will be used – the first one which matches with the URL pattern and file is found in the root directory.
Notice that file extension has .jsf
because it should match with the URL pattern otherwise it will give you 404 – page not found.
Resource Bundle or Properties Files
Now I will create properties files for each language. The below properties files are kept under classpath folder src/main/resources.
Bengali – Messages_bn.properties
i18n=JSF 2.2 এ আন্তর্জাতিকায়ন উদাহরণ
welcome=বাংলা ভাষা স্বাগতম
chooseLang=আপনার ভাষা চয়ন করুন
copyright=কপিরাইট
2014=2014-2020
Hindi – Messages_hi.properties
i18n=JSF 2.2 में अंतर्राष्ट्रीयकरण उदाहरण
welcome=हिन्दी भाषा में आपका स्वागत है
chooseLang=अपनी भाषा चुनें
copyright=सर्वाधिकार
2014=2014-2020
English – Messages.properties
i18n=Internationalization Example in JSF 2.2
welcome=Welcome to English Language
chooseLang=Choose your language
copyright=Copyright
2014=2014-2020
Dutch – Messages_nl.properties
i18n=Internationalisering Voorbeeld in JSF 2.2
welcome=Welkom bij Nederlandse Taal
chooseLang=Kies uw taal
copyright=Auteursrecht
2014=2014-2020
French – Messages_fr.properties
i18n=Internationalisation exemple dans JSF 2.2
welcome=Bienvenue à la langue française
chooseLang=Choisissez votre langue
copyright=Droit d'auteur
2014=2014-2020
JSF Managed Bean
Now look at the below JSF Managed Bean LocaleSwitcher.java. Default locale is set to English language.
package com.roytuts.jsf.internationalization.i18n;
import java.io.Serializable;
import java.util.Locale;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ValueChangeEvent;
@ViewScoped
@ManagedBean
public class LocaleSwitcher implements Serializable {
private static final long serialVersionUID = 1L;
/**
* Creates a new instance of LocaleSwitcher
*/
public LocaleSwitcher() {
}
// default language - english(en)
private String language = "en";
// get the current locale from facescontext
private Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
public Locale getLocale() {
return locale;
}
public void setLocale(Locale locale) {
this.locale = locale;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
// when dropdown value gets changed - so the language and locale
public void onLanguageChange(ValueChangeEvent vce) {
if (vce != null) {
String l = vce.getNewValue().toString();
setLanguage(l);
locale = new Locale(l);
FacesContext.getCurrentInstance().getViewRoot().setLocale(locale);
} else {
FacesContext.getCurrentInstance().getViewRoot().setLocale(Locale.ENGLISH);
}
}
}
Locale Configuration
Create face-config.xml file and put it under WEB-INF with the below source code.
<?xml version='1.0' encoding='UTF-8'?>
<faces-config version="2.2"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd">
<application>
<!-- locale configuration -->
<locale-config>
<!-- default locale and supported locales -->
<default-locale>en</default-locale>
<supported-locale>bn</supported-locale>
<supported-locale>hi</supported-locale>
<supported-locale>nl</supported-locale>
<supported-locale>fr</supported-locale>
</locale-config>
<!-- resource bundle configuration -->
<resource-bundle>
<!-- properties file base name with full package -->
<base-name>
Messages
</base-name>
<!-- properties file key will be accessed using this variable #{msg.keyName},
where keyName is the property file key -->
<var>msg</var>
</resource-bundle>
</application>
</faces-config>
JSF Template Files
I will use template so that you don’t need to copy common code like header/footer and most importantly here is <f:view locale=””/> tag in every page.
So put the template file under WEB-INF/template so that it cannot be tempered from outside the world.
main.xhtml
Look at the below template file with <ui:insert/> tag whose content can be overridden by template client file.
<?xml version='1.0' encoding='UTF-8' ?>
<!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:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
lang="#{localeSwitcher.language}">
<f:view locale="#{localeSwitcher.locale}">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<h:outputStylesheet library="css" name="default.css" />
<h:outputStylesheet library="css" name="cssLayout.css" />
<title><ui:insert name="title" /></title>
</h:head>
<h:body>
<div id="top">
<!-- header part -->
<ui:insert name="top">
<ui:include src="header.xhtml" />
</ui:insert>
</div>
<div id="content" class="center_content">
<ui:insert name="content"></ui:insert>
</div>
<div id="bottom">
<ui:insert name="bottom">
<ui:include src="footer.xhtml" />
</ui:insert>
</div>
</h:body>
</f:view>
</html>
header.xhtml
<?xml version='1.0' encoding='UTF-8' ?>
<!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://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<body>
<ui:composition>
<h:form prependId="false">
<h:panelGrid columns="3">
<h:outputText value="#{msg.i18n}" />
<h:outputLabel> | </h:outputLabel>
<h:panelGroup>
<h:outputText value="#{msg.chooseLang}" />
<h:selectOneMenu value="#{localeSwitcher.language}"
onchange="submit()" style="margin-left:5px;"
valueChangeListener="#{localeSwitcher.onLanguageChange}">
<f:selectItem itemValue="bn" itemLabel="বাংলা" />
<f:selectItem itemValue="hi" itemLabel="हिंदी" />
<f:selectItem itemValue="en" itemLabel="English" />
<f:selectItem itemValue="nl" itemLabel="Nederlands" />
<f:selectItem itemValue="fr" itemLabel="Français" />
</h:selectOneMenu>
</h:panelGroup>
</h:panelGrid>
</h:form>
</ui:composition>
</body>
</html>
footer.xhtml
<?xml version='1.0' encoding='UTF-8' ?>
<!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://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<body>
<ui:composition>
<p style="text-align: left; width: 100%;">
<h:outputText value="#{msg.copyright} © 2014-2020" escape="false" />
</p>
</ui:composition>
</body>
</html>
Now I will look into the index.xhtml file. This is a template client file.
<?xml version='1.0' encoding='UTF-8' ?>
<!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://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<body>
<ui:composition template="./WEB-INF/template/main.xhtml">
<ui:define name="title">
#{msg.i18n}
</ui:define>
<ui:define name="content">
<h:outputText value="#{msg.welcome}"></h:outputText>
</ui:define>
</ui:composition>
</body>
</html>
Styles
Simple css styling under wepapp/resources/css directory.
cssLayout.css
#top {
position: relative;
background-color: #036fab;
color: white;
padding: 5px;
margin: 0px 0px 10px 0px;
}
#bottom {
position: relative;
background-color: #c2dfef;
padding: 5px;
margin: 10px 0px 0px 0px;
}
#left {
float: left;
background-color: #ece3a5;
padding: 5px;
width: 150px;
}
#right {
float: right;
background-color: #ece3a5;
padding: 5px;
width: 150px;
}
.center_content {
position: relative;
background-color: #dddddd;
padding: 5px;
}
.left_content {
background-color: #dddddd;
padding: 5px;
margin-left: 170px;
}
.right_content {
background-color: #dddddd;
padding: 5px;
margin: 0px 170px 0px 170px;
}
#top a:link, #top a:visited {
color: white;
font-weight: bold;
text-decoration: none;
}
#top a:link:hover, #top a:visited:hover {
color: black;
font-weight: bold;
text-decoration: underline;
}
default.css
body {
background-color: #ffffff;
font-size: 12px;
font-family: Verdana, "Verdana CE", Arial, "Arial CE",
"Lucida Grande CE", lucida, "Helvetica CE", sans-serif;
color: #000000;
margin: 10px;
}
h1 {
font-family: Arial, "Arial CE", "Lucida Grande CE", lucida,
"Helvetica CE", sans-serif;
border-bottom: 1px solid #AFAFAF;
font-size: 16px;
font-weight: bold;
margin: 0px;
padding: 0px;
color: #D20005;
}
a:link, a:visited {
color: #045491;
font-weight: bold;
text-decoration: none;
}
a:link:hover, a:visited:hover {
color: #045491;
font-weight: bold;
text-decoration: underline;
}
That’s all. Hope you got idea how to internationalize JSF 2 application.
Source Code
Thanks for reading.
In jsf 2.2 we don’t use faces-config.xml anymore isn’t it? so how to do ? Thans
even in jsf 2.2 you can use faces-config.xml file