Localization of Portlets Outside of Liferay
This wiki will explain how to localize non-Lifray dependent portlets outside of Liferay. You can use this method regardless of what framework you are using to build your portlets.
Some benefits of using resource bundles is efficiency in maintaining message bundles and the ability to localize or internationalize your messages from a centralized location. The centralized location is actually in your Language.properties files.
Localizing your portlets will require these steps:
- 1 Create Message Bundles
- 2 Configuring your portlets to load their language bundles
- 3 Loading your language bundles in your pages
- 4 Localize Messages
- 5 Titles and Category
- 6 Note: One WAR with multiple portlets
Create Message Bundles
Language files are .properties files.
hello-world=Hello World title-error=Please Enter A Valid Title Name
These files must be located in the classpath accessible by your portlet. A common location is within the portlet's WEB-INF/classes folder. The default message bundle is Language.properties, but can have any name, provided it is fully qualified (see Step 2 for details on this).
Your foreign language files will be named with the following syntax:
So if you were creating a Spanish message bundle, you would name it Language_es.properties. Sometimes a language will have different dialects from different regions. For example Chinese, you could have Chinese from China or Taiwan. In this case you would name your files Language_zh_CN.properties and Language_zh_TW.properties.
Had you decided to use a different name for your bundles, the above would be:
WEB-INF/classes/com/my/portlets/p1/Resource.properties WEB-INF/classes/com/my/portlets/p1/Resource_es.properties WEB-INF/classes/com/my/portlets/p1/Resource_zh_CN.properties WEB-INF/classes/com/my/portlets/p1/Resource_zh_TW.properties
Add More Locales
The language and country code combinations, or "locales" are found in portal.properties (Languages and Time Zones section). If you want to add more locales, you would need to look up the proper codes. Here are good places to start: http://ftp.ics.uci.edu/pub/ietf/http/related/iso639.txt http://userpage.chemie.fu-berlin.de/diverse/doc/ISO_3166.html
Java can only read Unicode characters or latin1 characters so what do you do when you have non-unicode characters such as Arabic or Japanese ? One way of dealing with this is to write a Language_*.properties.native file that uses the native language in the value. Afterwards, convert the native file using a native to ascii converter. A popular one is ascii2converter. http://java.sun.com/j2se/1.5.0/docs/tooldocs/solaris/native2ascii.html
Configuring your portlets to load their language bundles
In your portlet.xml, define your <resource-bundle> as you created it above.
Also in portlet.xml, define a <supported-locale> for each language you want to support. Example for Spanish and Chinese from China or Taiwan:
<supported-locale>es</supported-locale> <supported-locale>zh_CN</supported-locale> <supported-locale>zh_TW</supported-locale>
The end result for several portlets could be something like:
<portlet-app ...> <portlet> <portlet-name>p1</portlet-name> ... <supported-locale>es</supported-locale> <supported-locale>zh_CN</supported-locale> <supported-locale>zh_TW</supported-locale> <resource-bundle>com.my.portlets.p1.Resource</resource-bundle> ... </portlet> <portlet> <portlet-name>p2</portlet-name> ... <supported-locale>es</supported-locale> <supported-locale>zh_CN</supported-locale> <supported-locale>zh_TW</supported-locale> <resource-bundle>com.my.portlets.p2.Resource</resource-bundle> ... </portlet> ... <portlet> <portlet-name>pN</portlet-name> ... <supported-locale>es</supported-locale> <supported-locale>zh_CN</supported-locale> <supported-locale>zh_TW</supported-locale> <resource-bundle>com.my.portlets.pN.Resource</resource-bundle> ... </portlet> </portlet-app>
Loading your language bundles in your pages
Portlet Standard Way
The standard way of loading your language bundles in portlets is by accessing a couple of objects in the portlet context:
<%@ taglib uri="http://java.sun.com/portlet" prefix="portlet" %>
<%@ page import="java.util.Locale" %> <%@ page import="java.util.ResourceBundle" %>
<% // renderRequest and portletConfig are objects which, accoring to the // portlet spec, are required to be in context. So they should just be // there for you to use. Locale locale = renderRequest.getLocale(); ResourceBundle res = portletConfig.getResourceBundle(locale); %>
This method doesn't require you to know the actual name of the bundle. The portlet container should take care of setting that up for you (provided you configured your portlet.xml properly)
We can use the ResourceBundle to select which Language.properties files to use. The ResouceBundle requires two parameters to be passed including the locale codes; you could use the Locale class to retrieve the current locale.
Import these classes in your jsp:
<%@ page import="java.util.ResourceBundle" %> <%@ page import="java.util.Locale" %>
Also include the following in your jsp:
<% Locale locale = (Locale)request.getSession().getAttribute("org.apache.struts.action.LOCALE"); String language = locale.getLanguage(); String country = locale.getCountry(); // Remember, "Language" is the fully qualified name of a bundle in the classpath // // e.g. WEB-INF/classes/Language_*.properties ResourceBundle res = ResourceBundle.getBundle("Language", new Locale(language, country)); %>
In the above snippet you can see that we request a Locale object, which we then use to get the Language and Country codes. Those codes are then passed in as parameters in ResourceBundle.getBundle(String, new Locale(String, String)) to identify which bundle to use.
Use your messages with the following syntax:
If you have a hello world button, instead of making the button
<input type="button" value="Hello World" />
<input type="button" value="<%= res.getString("hello-world")" %>" />
Now you are set to use your localized/internationalized messages. When you change the Locale via the Language portlet, your localization should appear!
Titles and Category
There are three standard keys defined specifically for the localization of portlet info, including the title.
javax.portlet.title=My Portlet javax.portlet.short-title=MyPortlet javax.portlet.keywords=My,Portlet
Include these in your language bundles to localize those values and the portlet titles, displayed throughtout the portal (including the "Add Content" menu), will be localized.
(*4.3) Portlet Category/"Add Content" Menu
Suppose you create a new portlet category in which to group your portlets, and you configure the liferay-display.xml as such;
<display> <category name="my.new.category"> <category name="my.new.sub-category"> <portlet id="portlet_A" /> <portlet id="portlet_B" /> </category> <portlet id="portlet_C" /> <portlet id="portlet_D" /> </category> </display>
All you need to do to have the appropriate name appear in the "Add Content" menu of the portal is to add the keys to your localization files. For the above two categories, include the following in your language bundles:
my.new.category=This is My Category my.new.sub-category=My Sub-Category
Note: If for example you have the four portlets above defined in your portlet.xml, and each one has it's own language bundle, the first bundle found to contain the keys will be used. So to be safe, just copy the category keys to each bundle.
If using struts, in struts-config.xml, define the <message-resource>. If your files are in WEB-INF/classes/abc/123/Language.properties you would do this:
<message-resources parameter="abc.123.Language" />
Note: One WAR with multiple portlets
Remember, if you have more than one portlet in your war, they won't be able to share the same resource bundle. What does this mean? It means you can't do this (as is done in the portal war):
You can only do:
Use the method suggested above to separate your portlet resource bundles.