Wednesday, December 21, 2011

How to use multi language translation in JSP in CQ / WEM

Use Case: You want to display certain text in page based on page language


Solution: You can use i18n bundle approach for this

Suppose you want to display certain text for a component in different language based on page language or URL. Take an example of /apps/geometrixx/components/homepage component.

1) Create a i18n node under /apps/geometrixx/components/homepage of type sling:Folder
2) create a node of type sling:Folder under i18n of mixin type mix:language
3) Add a property called jcr:language and assign value of lang code or lang_COUNTRY

Structure would be like

+-- English (nt:folder, mix:language)
| +-- jcr:language = en
| +-- mx (sling:messageEntry)
| +-- sling:key = "msgXXX"
| +-- slign:message = "An Application Text"
+-- Deutsch (nt:folder, mix:language)
+-- jcr:language = de
+-- mx (sling:messageEntry)
+-- sling:key = "msgXXX"
+-- slign:message = "Ein Anwendungstext"

4) Then on jsp page use following code

Locale pageLocale = currentPage.getLanguage(false);
//If above bool is set to true. CQ looks in to page path rather than jcr:language property.
ResourceBundle resourceBundle = slingRequest.getResourceBundle(pageLocale);
I18n i18n = new I18n(resourceBundle);
I am printing using I18n <%=i18n.get("updateLocations") %>
I am printing using fmt:message now <fmt:message key="updateLocations"/>
I found page locale is <%=pageLocale.toString() %>

You can also test language using grid under http://localhost:4502/libs/cq/i18n/translator.html
More Info:

To change what languages are shown in the translator's grid, create a multi-value string property /etc/languages/languages (node structure must be created), containing the iso language codes (e.g. ["de", "fr", …]). The default is hard coded in the translator and maps the ootb CQ languages: ['de', 'fr', 'it', 'es', 'ja', 'zh-cn']

Some More Good blog Post on this:


  1. Hi Yogesh,

    thanks for this article. Could you please be more specific what needs to be done so I can see a different language in the cq translator? I tried to do the structure, but with no result, still have the hardcoded list.


    1. @Jan,



  2. Thanks - this was really useful

    Another point to note is that you may want to have separate bundles for different applications.

    To do this, place a property "sling:basename" under myApps/i18n/en of a value (e.g. "TEST")

    Then reference either by


    slingRequest.getResourceBundle("TEST", pageLocale);

    depending on the message you are using to access the bundle

    I'll write a blog post about this shortly

    1. Tim,

      Thanks for your feedback. For some reason I don't see [sling:Language] as registered mixin node type in CQ5.5 or in CQ5.6

      - sling:basename (string)
      - sling:basename (string) multiple

      Have you used this feature in CQ ?


    2. Hi Yogesh,

      We are implementing i18n feature using sightly(HTL) language, but when we try to access the property ex:"first-name"as a key from /myApps/i18n/en not getting the value associated to this key instead sightly outputing the key(first-name) itself.

      I see there is a resolution to add sling:basename for this issue but not sure where exactly we have to add this.

      Could you please provide the example of the node structure for one language with couple of dictionary entries.

      Thanks in advance for your help.


  3. Hi Yogesh,

    Thanks for the info you have provided. I have a question on using the below line of code.

    <%=i18n.get("updateLocations") %>

    It works if I use pass String literal to i18n.get() method but doesn't work when I pass object reference. Do you have any idea why?

    String gtBodyText = "Name";
    <%=i18n.get(gtBodyText) %>


    1. Stephen,

      That could be bug. Can you please work with daycare on this ?


  4. I have a component and try to print this fmt:message key="firstname"

    It works well for en,fr,de but not for en_UK and en_US.

    Is it needed to select the language for the parent path in page properties

    Ex: content/geometrixx/en/test.html - works fine
    content/geometrixx/en_UK/test.html - the key is returned as value and it is printed.

    1. I'm having the dame issue. How did you fix ir?

    2. Have you tried Locale pageLocale = currentPage.getLanguage(false) ?

  5. It is genuinely very useful for me.