Resource Bundles in JSF 2.0 Applications
Join the DZone community and get the full member experience.
Join For FreeSetting up resource message bundles in
JSF to provide multilingal messages and captions is often overlooked
when first creating an application. Leaving it till later in the project
means you will have to go back and manually change the constants over
to resource based values. Resource bundles JSF 1.2 were far from perfect
but fortunately, using resource bundles in JSF 2.0 is very easy and
this tutorial will show you how to add bundles and use them in your JSF
2.0 pages.
For this example, we’ll create a new application using the jee6-servlet-basic-archetype Knappsack Maven archetype. The full source can be downloaded and run using mvn clean jetty:run from the command line.
Message resources are stored in properties files which consist of name value pairs that binds a message key string with the message value. We’ll use the following example
firstName=First Name
lastName=Last Name
forgotPassword=Forgot Password?
usernameTaken={0} is already taken
This file needs to be saved and referenced in a package, which would normally be in the same place as your source code, but Maven provides a separate area for resources. Save the file in the src/main/resources/org/fluttercode/resourcedemo/with the name MessageResources.properties. Open up the faces-config file and add the following XML :
<application>
<resource-bundle>
<base-name>org.fluttercode.resourcedemo.MessageResources</base-name>
<var>msgs</var>
</resource-bundle>
</application>
Here, we have told JSF about the resource bundle and assigned a variable name to it. Now we will go and add a reference to one of the messages in our home page. Open home.xhtml and replace the initial message with the following :
<h:outputText value="#{msgs.firstName}"/>
This is a JSF output text component that gets its value from the resource bunde, in this case, the firstName value. If you are using JBoss Tools, you will see that it can perform autocompletion for you on both the msgs value and the actual property keys on the msgs resources. It also displays the actual property value in the preview window for the page. If you run the app now by typing mvn jetty:run in the command line, you will see that the word First Name appears in the page.
Access Resources From Code
Typically, in your application you will generate messages for the user that also needs to be obtained from the resource bundle. To do this, we will create a bean that can fetch the resource bundle for us and extract strings from it.
public class MessageProvider {
private ResourceBundle bundle;
public ResourceBundle getBundle() {
if (bundle == null) {
FacesContext context = FacesContext.getCurrentInstance();
bundle = context.getApplication().getResourceBundle(context, "msgs");
}
return bundle;
}
public String getValue(String key) {
String result = null;
try {
result = getBundle().getString(key);
} catch (MissingResourceException e) {
result = "???" + key + "??? not found";
}
return result;
}
}
In our home.jsf page, we display our message by adding
Message = #{someBean.message}
Which results in the following phrase being displayed :
Message = SomeValue is not valid
Having just the one default properties file in place is the bare minimum for using string resource bundles in your applications, and I would recommend using that for any application, even if it is never going to be multi-lingual. At the very least, it keeps your string constants in one place and at best, it makes it really easy to support multiple languages at a later date.
Handling JSF Locale Information
If you go multi-lingual you will need to provide multiple versions of
the resource file for different locales, and list the supported locales
in your faces-config.xml file.
To test this, create multiple copies of the MessageResources file in the same directory with different names such as MessageResources_de.properties or MessageResources_fr.properties and in the content for each, use the same values, but add the locale on the end.
MessageResources_fr.properties
firstName=First Name(fr)
lastName=Last Name(fr)
forgotPassword=Forgot Password?(fr)
someMessage={0} is not valid(fr)
In the faces-config.xml file you can add the supported locales and set the default locale to use.
<application>
<locale-config>
<default-locale>en_US</default-locale>
<supported-locale>de</supported-locale>
<supported-locale>en_GB</supported-locale>
<supported-locale>fr</supported-locale>
</locale-config>
<resource-bundle>
<base-name>org.fluttercode.resourcedemo.MessageResources</base-name>
<var>msgs</var>
</resource-bundle>
</application>
Now, depending on where you are in the world, and your browser
locale, if you plan on following along, you'll have to substitute your
own locale for en_US. Since we have a MessageProperties
file without a locale in the file name, if it cannot find a matching
locale, it will use this default bundle. If the default locale is
specified in faces-config,then that locale will be used instead of the non-specific default.
Play around with renaming some of the resource files, especially the
file that matches your own locale. If the file exists, but it is not
included in the list of supported locales in faces-config it won't be used. You can also change the default-locale value to one other than your own locale and see how the locale would be selected.
JSF will also select a locale that matches based on the language if not the specific region. In my case, having a locale of en_US means that if available, JSF will select the MessageResources_en bundle if there is no bundle specifically for en_US.
Download the Maven source code for this project and run it locally by unzipping it into a folder and typing mvn clean jetty:run and going to http://localhost:8080/resourcedemo/.
From http://www.andygibson.net/blog/article/resource-bundles-in-jsf-2-0-applications/
Opinions expressed by DZone contributors are their own.
Trending
-
Security Challenges for Microservice Applications in Multi-Cloud Environments
-
How Web3 Is Driving Social and Financial Empowerment
-
How To Scan and Validate Image Uploads in Java
-
A Data-Driven Approach to Application Modernization
Comments