Internationalization can be achieved by using i18n bundle approach in adobe CQ or AEM(Adobe Experience Manager). Based on our use-case/requirement their are different approaches to implement internationalization in adobe cq.
Lets see both the approaches to implement internationalization in Adobe CQ –
Granite.I18n.get("Letter created successfully.")
If we want to display certain text in different language based on URL,page language or region detected by browser. Then we should use internationalization feature of CQ.
Let’s understand how to implement it with an example:-
- Create a i18n node under /apps/<myapp>/ of type sling:Folder.
- Create a node with name as language code (fr) of type sling:Folder under i18n.
- Add property jcr:language and assign value of lang code or lang_COUNTRY.
- Add mixin type as mix:language.
Note:- By adding mixin type we enforced that along with sling:folder this node has addition behavior for mix languages.
- Select Language Node (fr) –> Right click and create new node of type sling:messageEntry and add below properties on this node.
- Name – sling:key Type – String Value – <our message in english>
- Name – sling:message Type – String Value – <our message in french>
Our directory structure would look similar to below structure where an example of key/value pairs for both English and French is shown:-
/apps/myapp/i18n +-- en (nt:folder, mix:language) | +-- jcr:language = "en" | +-- hello_world (sling:MessageEntry) | | +-- sling:key = "hello_world" | | +-- sling:message = "Hello world!" | +-- goodbye (sling:MessageEntry) | +-- sling:key - "goodbye" | +-- sling:message = "Goodbye!" +-- fr (nt:folder, mix:language) +-- jcr:language = "fr" +-- hello_world (nt:unstructured,sling:Message) | +-- sling:key = "hello_world" | +-- sling:message = "Bonjour tout le monde!" +-- goodbye (nt:unstructured,sling:Message) +-- sling:key - "goodbye" +-- sling:message = "Au revoir!"
Note:- If we create i18n at project level then it will be applicable for our entire project but if we require internationalization for specific component then we can create i18n node under our component
Now let’s write jsp code :
Detailed explanation of each method used in Below program.
When the <sling:defineObjects /> tag is used within a JSP page, the slingRequest value is created. The slingRequest implements the SlingHttpServletRequest interface and has couple of useful methods for internationalization: getLocale(), getLocales(), getResourceBundle(Locale), and getResourceBundle(String, Locale).
The getLocale() method gets the default Locale of the request. The getLocales() method gets all of the methods for a request. Typically the value for these come from the browser.
The method, getResourceBundle(Locale), gets a ResourceBundle instance that has all of the found key/value pairs for the locale. The method, getResourceBundle(String, Locale), gets a ResourceBundle with all of the key/value pairs for a base name and a locale.
The ResourceBundle interface has a method, getString(String), in which the argument is the key and the value of the key is returned. If the ResourceBundle does not have that key, the value returned is the key itself.
One thing to keep in mind is that a ResourceBundle is not the same thing as an OSGi bundle. They are two different concepts using the same name.
<%@page session="false"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %> <%@page import="java.util.Locale,java.util.ResourceBundle,com.day.cq.i18n.I18n"%> <%@include file="/libs/foundation/global.jsp"%> <cq:setContentBundle/> <% final Locale pageLocale = currentPage.getLanguage(false); final ResourceBundle resourceBundle = slingRequest.getResourceBundle(pageLocale); I18n i18n = new I18n(resourceBundle); %> <%= i18n.get("goodbye") %>
That’s it. Now this jsp page will be rendered according to page language or region detected by browser.
You can also see the list of all available dictionary available in aem here:- http://localhost:4502/libs/cq/i18n/translator.html
Note:- You can see that your training dictionary is also added to it. First priority goes to project dictionary if no match found then it looks in global dictionary available in aem.