Saturday, July 9, 2011

How to read arabic message from ressource bundles with JSF


In this article we assume that you already have an idea about configuring ressource bundles in JSF, how to use it in your pages and also how to configure jsf pages encoding ...

This blog entry is realy independante from JSF version, and it works for both JSF1 and JSF2 ;-)

We suppose that you want to write "Arabic" like "loginBean.username.label = اسم المستخدم " in the message resource bundle (properties) file and you try to save it you will get this error:
"Save couldn't be completed Some characters cannot be mapped using "ISO-85591-1" character encoding. Either change encoding or remove the character ..." because the default mechanism loading of properties files is in "ISO-8559-1-1".

If you change the file encoding to UTF-8, you will be able to save the file but you can not print your messages correctly in JSF !!

To get it work you have to change the default mechanism loading to UTF-8 by implementing a custom ressource bundle class using UTF-8 Control

public class I18nRessourceBundle extends ResourceBundle {

protected static final String BUNDLE_EXTENSION = "properties";
protected static final String CHARSET = "UTF-8";
public static final Control UTF8_CONTROL = new UTF8Control();

public I18nRessourceBundle() {
setParent(ResourceBundle.getBundle("Propety_File_Ressource",
FacesContext.getCurrentInstance().getViewRoot().getLocale(), UTF8_CONTROL));
}

@Override
protected Object handleGetObject(String key) {
return parent.getObject(key);
}

@Override
public Enumeration getKeys() {
return parent.getKeys();
}

public static class UTF8Control extends Control {
public ResourceBundle newBundle
(String baseName, Locale locale, String format, ClassLoader loader, boolean reload)
throws IllegalAccessException, InstantiationException, IOException
{
// The below code is copied from default Control#newBundle() implementation.
// Only the PropertyResourceBundle line is changed to read the file as UTF-8.

String bundleName = toBundleName(baseName, locale);
String resourceName = toResourceName(bundleName, BUNDLE_EXTENSION);
ResourceBundle bundle = null;
InputStream stream = null;
if (reload) {
URL url = loader.getResource(resourceName);
if (url != null) {
URLConnection connection = url.openConnection();
if (connection != null) {
connection.setUseCaches(false);
stream = connection.getInputStream();
}
}
} else {
stream = loader.getResourceAsStream(resourceName);
}
if (stream != null) {
try {
bundle = new PropertyResourceBundle(new InputStreamReader(stream, CHARSET));
} finally {
stream.close();
}
}
return bundle;
}
}
}


We assume that you have a properties file Propety_File_Ressource in your ressource folder

So in JSF configuration you should use:



...


package_name.I18nRessourceBundle
msgBlog

Insted of


...


Propety_File_Ressource
msgBlog




Enjoy it!

2 comments:

  1. Hi badr,
    I did exactly as in the blog but it give me "java.util.MissingResourceException: Can't find bundle for base name com.upnormal.aflete.backEnd.util.bundles.I18nRessourceBundle" exception any ideas ?

    ReplyDelete