Supporting multiple languages in ADF applications backed by resource bundles – and programmatically controlling the JSF locale
Java (Web) applications typically make use of a built in structure for centralizing (and internationalizing) boiler plate text; it is called Resource Bundle. Usually, resource bundles are implemented using property files – one per supported language – that contain key-value pairs; note that the XLIFF file format for resource bundles is gaining ground. The key is referred to in pages, code and wherever a boiler plate text element is required, the value is the language specific and centrally managed translation of the key.
In two previous articles, I have explained how to centralize the boilerplate text elements in ADF applications using resource bundles – either plain file based resource bundles (http://technology.amis.nl/2012/08/09/introduction-to-resource-bundles-in-adf-applications-for-centralizing-management-of-boilerplate-text) or resource bundles implemented using a database (http://technology.amis.nl/2012/08/10/implement-resource-bundles-for-adf-applications-in-a-database-table/). These two articles did not discuss how multiple languages can be supported and how the user can pick his or her favorite language. That is the purpose of this article.
In later articles I will discuss how to support not just different boilerplate text items for different languages but also different sets of boiler plate text for user groups that vary by location, role, department, age or personal preference. We will discuss how to refresh a resource bundle in running application and finally we will see how we can create an in-line resource bundle editing mechanism that allows users to manipulate the boiler plate text in context in a running application.
1. Specify supported locales in faces-config.xml
2. Create resource bundles per language
property file – create new files with the language as appendix to the file name, for example ApplicationBundle_en.properties and ApplicationBundle_nl.properties.
Java Class – the same approach: create a class per supported language and add _<language code> as suffix to the classname.
Additionally, the method getLocaleCode() needs to be defined in each of the classes:
3. Add entries for all supported languages to the resource bundle
Either the property files for the database table – depending on the implementation – needs to be extended with the proper key value pairs for the supported languages. Of course the keys are the same for all languages!
Here two new entries for the nl support (Dutch):
4. Run the page.
Try switching to a different preferred language. The default behavior for JSF is to take the locale set in the browser as the current locale. By changing the browser locale, you can instruct JSF therefore to change to a different language.
and the page renders like this:
5. Programmatically taking control of the locale in JSF
You may not always want to go with the locale defined in the browser. You may for example want to offer the user an option of selecting the language in the application itself. The JSF behavior can be overridden. One way of doing so is by explicitly setting the local on the f:view component using the locale attribute, that can either be static or set using an EL expression or by overriding the ViewHandler. I will discuss and implement this approach.
The ViewHandler in JSF takes care of determining the current locale, using the calculateLocale() method. The default implementation derives the locale from the browser setting. The default ViewHandler can be overridden with our own implementation. This is done by creating a class that extends from an existing ViewHandler implementation – overriding the calculateLocale() method – and by configuring the ViewHandler in faces-config.xml.
The LocaleSettingViewHandler is implemented like this:
The remainder of this class is quite important too, as it ensures that all normal operations by the ViewHandler still take place:
and there is the local utility method to evaluate EL expressions:
Here the calculateLocale() method refers in an EL expression to a managed bean. This bean has a language property, that can be manipulated by the user through a drop down component in the page:
The managed bean definition:
The ViewHandler is configured in faces-config.xml:
6. Run the page.
The default locale is still English – because the managed bean says so, not because of the browser setting.
Changing the selected language
and refreshing the page, using the newly selected language for retrieving the resource bundle entries:
Download the ADF application described in this article: ADFFacesWithResourceBundle_step3_multipleLanguagesAndLocaleControl.
Article on http://www.i-coding.de/www/en/jsf/application/locale.html describing how to set the locale.
Other articles in this series:
- Implement resource bundles for ADF applications in a database table
- Introduction to Resource Bundles in ADF applications for centralizing (management of) boilerplate text
- Context Sensitive Resource Bundle entries in JavaServer Faces applications – going beyond plain language, region & variant locales
- Personalize Resource Bundles in ADF applications with JHeadstart 10.3.2 run time
- Testing i18n features of JSF applications – Forcing a refresh of the Resource Bundle(s)
- Oracle ADF Virtual Developer Day 2013
- The AMIS Summary of Oracle OpenWorld 2013 is available for download – 60-page white paper
- On the integrity of data in Java applications – presentation from JFall 2013
- OOW13: summarizing one week and 2000 sessions in 3 hours and a bit – the yearly AMIS OOW Review session – 10th October
- OOW13 and JavaOne 13: Notes from a Conference – Part Two
- You consolidated your applications in one database, but now one application needs recovery…
- OOW13: Sneak Preview of the Major Announcements?! In-Memory Database, PaaS (Database and Java) and M6 big memory machine
- Case Study: A Case of Fusion Middleware
- Het Oracle OpenWorld Preview Evenement (5 september 2013) – 15 sprekers & sessies
- ADF 12c: Using WebSockets to implement client to client push (in a scalable manner)