If your portlets target an international audience, you can localize the user
interface. Localizing your portlet’s language is done using language keys for
each language you wish to support. You can translate these manually or use a web
service to translate them for you. Conveniently, all existing translated
messages in the portal core are accessible from plugin projects. You can check
for the presence of specific language keys in the core Language.properties
file found in portal-impl/src/content
. Leveraging portal’s core language keys
saves you time, since these keys always have up to date translations for
multiple languages. Additionally, your portlet blends better into Liferay’s UI
conventions.
You can use a language key in your JSP via a <liferay-ui:message />
tag.
<liferay-ui:message key="message-key" />
You specify the message key corresponding to the language key in the
Language.properties
file you want to display. For example, to welcome a user
in their language, specify the message key named welcome
.
<liferay-ui:message key="welcome" />
This key maps to the of the word “Welcome”, in your translation of it to the
user’s locale. Here is the welcome
language key from Liferay’s
Language.properties
file.
welcome=Welcome
Let’s add the welcome
language key in front of our greeting in the
view.jsp
file of the my-greeting-portlet
we created earlier. Replace its
current greeting paragraph with this:
<p><liferay-ui:message key="welcome" />! <%= greeting %></p>
Revisit the page to see the word “Welcome”, from Language.properties
, now
precedes your greeting!
Note, in order to use the <liferay-ui:message />
tag, or any of the
liferay-ui
tags, you must include the following line in your JSP. It imports
the liferay-ui
tag library.
<%@ taglib uri="http://liferay.com/tld/ui" prefix="liferay-ui" %>
The <liferay-ui:message />
tag also supports passing strings as arguments to
a language key. For example, the welcome-x
key expects one argument. Here is
welcome-x
key from the Language.properties
file:
welcome-x=Welcome{0}!
It references {0}
, which denotes the first argument of the argument list. An
arbitrary number of arguments can be passed in via message tag, but only those
arguments expected by the language key are used. The arguments are referenced in
order as {0}
, {1}
, etc. Let’s pass in the user’s screen name as an argument
to the welcome-x
language key in the “My Greeting” portlet.
-
Open the
view.jsp
file. -
Add the following lines near the top of the JSP, just above the
<portlet:defineObjects />
tag. The first line imports theliferay-theme
tag library. The second line defines the library’s objects, providing access to theuser
object holding the user’s screen name.<%@ taglib uri="http://liferay.com/tld/theme" prefix="liferay-theme"%> <liferay-theme:defineObjects />
-
Replace the current welcome message tag and exclamation point,
<liferay-ui:message key="welcome" />!
, in the JSP with the following:<liferay-ui:message arguments="<%= user.getScreenName() %>" key="welcome-x" />
When you refesh your page, your “My Greeting” portlet greets you by your screen name!
Other message tags you’ll want to use are the <liferay-ui:success />
and
<liferay-ui:error />
tags. The <liferay-ui:success />
helps you give
positive feedback, marked up in a pleasant green background. The
<liferay-ui:error />
tag helps you warn your users of invalid input or
exceptional conditions. The error messages are marked up in an appropriate red
background.
The <liferay-ui:success />
tag is triggered when its key value is found in the
SessionMessages
object. Earlier in our MyGreetingPortlet
class, we triggered
the success message <liferay-ui:success key="success" ... />
by adding its key
to the SessionMessages
object with the following call:
SessionMessages.add(actionRequest, "success");
Similarly, the <liferay-ui:error />
tag is triggered when its key value is
found in the SessionErrors
object. Likewise, in our MyGreetingPortlet
class,
we triggered the error message <liferay-ui:error key="error" ... />
by adding
its key to the SessionErrors
object with the following call:
SessionErrors.add(actionRequest, "error");
That’s all you need to do to leverage Liferay’s core localization keys. If you need to add localization keys, follow the instructions below to deliver locally tailored portlets to your customers.
Your Localization Plan
First consider some questions that will make our life easier as we develop your localization:
- Does my plugin contain more than one portlet? This is very important if portlets share the same UI elements and messages; you don’t want to maintain the same data in ten places.
- Do my portlets need localized titles in portlet headers and administrative tools?
- Do my portlets have to be accessible in the Control Panel? This is important if you want to provide your customers fancy Title and Description features like the majority of core liferay portlets.
We’ll cover these different cases in the following sections.
Create Resource Bundles
First, let’s create a resource bundle for providing textual translations of three related fictional portlets named My Finances, Asset Ticker and Portfolio Manager. All three portlets share some attributes:
- They use existing Liferay core messages to handle standard UI cases.
- They use common financial terms, so we don’t want to repeat them for each portlet.
Let’s explore sharing translated text between these portlets.
Assuming you already created a plugin project and added portlets, let’s start:
-
Create a
content
package in yoursrc
plugin project folder. -
Create the
Language.properties
file to define all the keys our portlets need. -
For each portlet, update its
<portlet>
node inportlet.xml
to refer to the resource bundle correctly:<portlet> <portlet-name>finances</portlet-name> ... <resource-bundle>content/Language</resource-bundle> <portlet-info>...</portlet-info> ... </portlet> <portlet> <portlet-name>portfolio</portlet-name> ... <resource-bundle>content/Language</resource-bundle> <portlet-info>...</portlet-info> ... </portlet> <portlet> <portlet-name>ticker</portlet-name> ... <resource-bundle>content/Language</resource-bundle> <portlet-info>...</portlet-info> ... </portlet>
Make sure to put each
resource-bundle
element in its proper place in theportlet
element. See theportlet.xml
file’s schema http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd for details.
At this point our portlets are ready to deliver a localized UI.
Please note: It’s best to use the Liferay naming convention for language bundles so your portlets can share properties, and the Plugins SDK Ant task used to build the translations works.
In order for a user to see a message in his own locale, the message value must
be specified in a resource bundle file with a name ending in his locale’s two
character code. For example, a resource bundle file named
Language_es.properties
containing a message property with key welcome
must
be present with a Spanish translation of the word “Welcome”. Good news, Plugins
SDK provides a means for you to get translations for your default resource
bundle.
The Plugins SDK uses the Bing Translator service http://www.microsofttranslator.com/ to translate all of the resources in your Language.properties file to multiple languages. It provides a base translation for you to start with. To create base translations using the Bing Translator service, you’ll need to do the following:
-
Signup for an Azure Marketplace account and register your application. Be sure to write down your ID and secret given to you for your application.
-
Edit the
portal-ext.properties
file in your Liferay Home directory by adding the following two lines replaced with your values:microsoft.translator.client.id=your-id microsoft.translator.client.secret=your-secret
-
In Developer Studio, right-click on the
Language.properties
file → Liferay → Build Languages.If prompted, choose the option to force Eclipse to accept the
Language.properties
file as UTF-8. Make sure you are connected to the Internet when you execute this.
When the build completes, you’ll find the generated files with all of the
translations, in the same folder as your Language.properties
file.
By using Studio’s language building capability, you can keep all created
translations synchronized with your default Language.properties
. You can run
it any time during development. It significantly reduces the time spent on the
maintanance of translations. Of course, you’ll want to have someone fluent in
that language review the translation before deploying the translation to a
Production environment.
Now that you know how to create a shared resource bundle, let’s consider a case in which you must use separate resource bundles for each portlet. In order to localize messages used in the Control Panel for a Control Panel-enabled portlet, you must use separate resource bundles. We’ll show you how to implement them.
Portlet Title and Description In Control Panel
You may have noticed that your Control Panel-enabled portlets are missing that
super-fancy must-have portlet title and description in the Control Panel. To
make your portlet look cool within the Control Panel, create specially tailored
description and title keys in separate Language.properties
files for each
portlet in your project. You’ll use the javax.portlet.title
and
javax.portlet.description
language keys.
For demonstration purposes, let’s consider a project that has one portlet named
eventlisting
and another portlet named locationlisting
. We’ll need to create
a resource bundle for each of them to specify their localized title and
description values.
Here’s what you’d do to localize the title and description for each portlet in the project:
-
If you haven’t done so already, configure each portlet to display in the Control Panel. For our example, we would display them in the Content portion and give them an arbitrary weight value for determining where they’re to be placed in the column with respect to the other portlets. Here’s a sample of how to specify this in our project’s
liferay-portlet.xml
file:<portlet> <portlet-name>eventlisting</portlet-name> <icon>/icon.png</icon> <control-panel-entry-category>content</control-panel-entry-category> <control-panel-entry-weight>1.5</control-panel-entry-weight> .... </portlet> <portlet> <portlet-name>locationlisting</portlet-name> <icon>/icon.png</icon> <control-panel-entry-category>content</control-panel-entry-category> <control-panel-entry-weight>1.6</control-panel-entry-weight> .... </portlet>
-
Create a namespaced folder to hold each portlet’s resource bundle. It’s a best practice to name each resource bundle folder based on the name of its portlet.
For example, you could create a resource bundler folder
content/eventlisting
for theeventlisting
portlet and a foldercontent/locationlisting
for thelocationlisting
portlet. -
Create a
Language.properties
file in the resource bundle folders you just created. Specify thejavax.portlet.title
andjavax.portlet.description
language key/values in each of theseLanguage.properties
files.The
eventlisting
portlet could have the following key/value pairs in itscontent/eventlisting/Language.properties
file:javax.portlet.title=Event Listing Portlet javax.portlet.description=Lists important upcoming events.
And the
locationlisting
portlet could have these key/value pairs in itscontent/locationlisting/Language.properties
file:javax.portlet.title=Location Listing Portlet javax.portlet.description=Lists event locations.
-
Specify the resource bundles for the portlets in the project’s
portlet.xml
file. The exampleportlet.xml
file code snippet below demonstrates specifying the resource bundles for theeventlisting
andlocationlisting
example portlets:<portlet> <portlet-name>eventlisting</portlet-name> ... <resource-bundle>content.eventlisting.Language</resource-bundle> <portlet-info>...</portlet-info> ... </portlet> <portlet> <portlet-name>locationlisting</portlet-name> ... <resource-bundle>content.locationlisting.Language</resource-bundle> <portlet-info>...</portlet-info> ... </portlet>
-
Redeploy your plugin project.
-
Go to the Control Panel and select the Event Locations portlet.
-
Add
en
to your portal context in your URL to interface with the portal in Spanish. For example, your URL would start like this:http://localhost:8080/es/group/control_panel/...
Portal’s Control Panel displays your portlet’s localized title and description.
You’re becoming an expert localizer!
Now that you’re comfortable localizing portlet content, you may want to learn how to make translations available throughout the portal or how to override an existing translation. For instructions on doing that, refer to Chapter 7 of this guide, specifically the Overriding a Language.properties File section. It describes how to use a hook to override existing Liferay translations. You can share your keys with other portlets, as well as override existing Liferay translations.
Next, let’s learn how to configure your portlets’ preferences using configuration actions.