How to use the localized input field in Liferay 6.2

Blog posts

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 i18n, liferay 6.2, localized, Utility by Charalampos Chrysikopoulos


I'm curious about something in your code. I can see a line where you call a getXmlFromMap function which presumably generates the xml that we can plug into the xml attribute for the tag. Where is this method from? I have searched the Portal Code Base and I can find any such method -- is this something you wrote? It's a pretty critical piece to the example.

Hi Andrew, thanks for your comment. I have updated the article with the missing method. You can see also the class LocalizationUtil for an appropriate method.

Hey -- I actually found a different way while waiting for your reply. I actually was able to use the Liferay LocalizationUtil to generate the XML. The method is poorly named (which surprised me.. normally I find Liferay's naming conventions excellent) but I was able to do it with one line of code and without the static strings. xml = LocalizationUtil.updateLocalization(localizedMap, xml, "Title", Locale.US.toString()); .. and that did it for me. Thanks for getting back to me all the same.

Add new comment

You must have Javascript enabled to use this form.