How to use the localized input field in Liferay 6.2

Posted on 03/10/2016 by Charalampos Chrysikopoulos

In liferay 6.2 (yes, it is alive), if you are working with a miltilingual site, you can use a very handy way to define multilingual fields, for example in the preferences of a custom portlet.

Lets assume, you have a custom portlet and you want to give the site administrator the option to edit the column title of a table. The table is dynamically generated with data from the database. A way to do it, is to create a configuration in the portlets menu options, and place an input field there. The value of the field will be saved in the portlet preferences, and so it can be used in the render phase of the portlet.

But, what if the portlet lives in a multilingual site. One solution is to create so many input fields as the locales of the site. Another, is to use the localized tag of the liferay tag library. In this case, the config.jsp would look like this:

<liferay-portlet:actionURL portletConfiguration="true"
    var="configurationURL" />

<aui:form action="<%=configurationURL%>" method="post" name="fm">

    <aui:input name="<%=com.liferay.portal.kernel.util.Constants.CMD%>"
        value="<%=com.liferay.portal.kernel.util.Constants.UPDATE%>" />

    <label class="control-label" for="title"> The is the fields description </label>
    <liferay-ui:input-localized id="title"  name="columnTitle"  xml='${ columnTitleXml }' />

        <aui:button type="submit" />

We use the liferay-ui:input-localize tag, and it is enough to define the name and the xml attribute.
Liferay likes to store the multilingual information (like in web contents for example) in an xml, and it has more or less the following structure:

<?xml version='1.0' encoding='UTF-8'?>
<root available-locales='el_GR,en_GB' default-locale='el_GR'>
    <Title language-id='el_GR'>Title in greek</Title>
    <Title language-id='en_GB'>Title in english</Title>

But, what is this xml? How can we generate it, and how can we read it to display the values we want, the way we want? There are some handy utility classes to do this.
On the submission of the values, the tag doesn't submit the xml, it submits the values with a locale prefix, like columnTitle_en_GB. You can see, that the tag generates some extra hidden fields, one for every locale.

So, how can you read the parameters and store the xml in the portlet preferences? Have a look at the following code:

    public void processAction(PortletConfig portletConfig, ActionRequest actionRequest, ActionResponse actionResponse)
        throws Exception {

        String portletResource = ParamUtil.getString(actionRequest, "portletResource");

        PortletPreferences preferences =
            Validator.isNotNull(portletResource) ? PortletPreferencesFactoryUtil.getPortletSetup(
                actionRequest, portletResource) : actionRequest.getPreferences();

        Map<Locale, String> columnTitleMap =
            LocalizationUtil.getLocalizationMap(actionRequest, "columnTitle");

        String columnTitleXml = getXmlFromMap(columnTitleMap);

        preferences.setValue("columnTitleXml", columnTitleXml);;

        super.processAction(portletConfig, actionRequest, actionResponse);

    public String render(PortletConfig config, RenderRequest request, RenderResponse response)
        throws Exception {

        String portletResource = ParamUtil.getString(request, "portletResource");

        PortletPreferences preferences =
            Validator.isNotNull(portletResource) ? PortletPreferencesFactoryUtil.getPortletSetup(
                request, portletResource) : request.getPreferences();

        String columnTitleXml = preferences.getValue("columnTitleXml", "");

        request.setAttribute("columnTitleXml", columnTitleXml);

        return "/html/example/config.jsp";

    public String getXmlFromMap(Map<Locale, String> contentMap) {

        StringBuilder sb = new StringBuilder();
        String comma = StringPool.BLANK;

        sb.append("<?xml version='1.0' encoding='UTF-8'?><root available-locales='");
        for (Locale l : contentMap.keySet()) {
            comma = StringPool.COMMA;
        sb.append("' default-locale='" + Constants.LOCALE_DEFAULT + "'>");

        for (Locale l : contentMap.keySet()) {
            sb.append("<Title language-id='");
        return sb.toString();

The method getXmlFromMap() gets a map Map<Locale, String> as a parameter and generates the xml, like it is described above. The render() method puts simply the xml in the request.

Now, how can we use this information in our custom portlet? This is easier:

        String columnTitleXml = renderRequest.getPreferences().getValue("columnTitleXml", "");

        Map<Locale, String> columnTitleMap = LocalizationUtil.getLocalizationMap(columnTitleXml, false);

        String columnTitle = columnTitleMap.get(themeDisplay.getLocale());

The LocalizationUtil class has many handy method to play, but as I experienced, the method getLocalizationMap(PortletPreferences prefs, String fieldName) doesn't return a thing, or to be more correct, it returns a map with the two locales (from the xml above), but without any value. I couldn't figure out why.

Place the columnTitle in the request, or use it the way you need to.

That's, all.

This entry was posted in Liferay and tagged liferay 6.2, localized, Utility, i18n by Charalampos Chrysikopoulos

Add new comment