4 Replies Latest reply on Jul 20, 2010 9:11 AM by mstruk

    Portlet Locale & Internationalization

    llengcai

      I am trying to get the portlet to display the correct value from the resource bundle by setting the following (as per portlet jsr 168 spec) values in the portlet.xml and deployed it in GateIn 3.0.0-GA

       

           <supported-locale>en</supported-locale>
           <supported-locale>es</supported-locale>
           <supported-locale>zh</supported-locale>
           <resource-bundle>locale.portlet.gadget.GadgetPortlet</resource-bundle>

       

      one the of the jsp file contains the following taglib

       

           <fmt:setBundle basename="locale.portlet.gadget.GadgetPortlet"/>

           <fmt:message key="total.summary" />

       

      What I would expect is, once the use choose the language from the "Change Language" link on the top right of the portal page, the jsp will display the value of "total.summary" to the selected language. Unfortunately it doesn't work.

       

      After some digging around and tracing, I notice the PortletRequest.getLocale() eventually delegated the call to org.exoplatform.portal.webui.application.ExoUserContext.getLocale():

       

      public Locale getLocale() {
              return clientRequest != null ? clientRequest.getLocale()
                      : Locale.ENGLISH;

      }

       

      The clientRequest is the servlet request object from the catalina container. My guess is this servlet request object will just grep the locale value from the Accept-Language http request header sent by the browser. The Accept-Language header value doesn't seems to have any corelation with the "Change Language" action which actually update the locale setting in the portal by calling the

       

      org.exoplatform.portal.webui.workspace.UIPortalApplication.UIPortalApplication.setLocale()

       

      I am able to get the above scenario work if I replace the org.exoplatform.portal.webui.application.ExoUserContext.getLocale() method above with

       

      public Locale getLocale() {
              PortalRequestContext context = PortalRequestContext.getCurrentInstance();

              if(context != null) {
                 UIPortalApplication uiPortalApplication = (UIPortalApplication) context.getUIApplication();
                 Locale locale = uiPortalApplication.getLocale();
                 if (locale != null)    return locale;

              }

       

              return clientRequest != null ? clientRequest.getLocale()
                      : Locale.ENGLISH;

      }

       

      Can anyone, especially the core developers here verify if this is the correctly way of fixing the issue I stated above, assuming our intention is to read the locale based on the Change Language settings rather than browser's Accept-Language http header?

        • 1. Re: Portlet Locale & Internationalization
          theute

          I agree with your assumption and noticed that not long ago.

           

          The spec doesn't enforce to use the browser preference so I also think it would be better to return the preferred locale of a user for a particular portal.

          I forgot to open a Jira for this issue, do you mind creating it ?

          • 2. Re: Portlet Locale & Internationalization
            llengcai

            Thomas, thanks for the reply. I have created an issue on jira (https://jira.jboss.org/browse/GTNPORTAL-1306).

            • 3. Re: Portlet Locale & Internationalization
              theute

              Thanks !

              • 4. Re: Portlet Locale & Internationalization
                mstruk

                I'm playing with this issue a bit. So let me describe how I'm going about it, and maybe someone has some other ideas ...

                 

                There are currently three  layers of localization settings in GateIn.

                 

                1) Logged-in users  have a profile that can contain a locale (doesn't have to) - if  specified, this value is used for GateIn page localization, provided the  specified locale is supported.
                2) The first fallback value is  browser setting (used as first choice for anonymous users). If browser  language is supported, that's the locale used for GateIn page  localization.
                3) Every portal has a default locale which is the  ultimate fallback value.

                 

                UIPortalApplication.getLocale() reflects  this fallback configuration, which is executed once per user session - at UIPortalApplication creation time.

                 

                We could make the described algorithm pluggable. For example, if you come to a site as anonymous user from a cybecafe in Germany you'll see the site in German, and you may not speak enough German to  find language selector in the top right corner to  switch to a language you understand. So maybe to address this one might want to simply turn off browser language preference for anonymous users.

                 

                That requires some kind of plugability mechanism.

                 

                So I  put together one pluggability mechanism at the UIPortalApplication  configuration layer (fixed for the duration of user session unless set  via language selector component, or user profile update) through which one can override the forementioned three-layer config mechanism. That's at the level of portal and then naturally propagates to ExoUserContext.getLocale() and to PortletRequest.getLocale(). The mechanism works via portal scoped service, so the same mechanism is used for all the pages within a portal.

                 

                The logic that performs locale determination has until now been inside UIPortalApplication zero-arg constructor - where the initialization happens.
                I introduced LocalePolicy interface in component/resources module and DefaultLocalePolicyService implementation  in webui/portal module - added its registration to webui portal's conf/portal/configuration.xml
                I extracted the locale determination logic from UIPortalApplication into this new DefaultLocalePolicyService, and refactored it to make it very easy to understand, and very easy to extend. UIPortalApplication would now delegate to LocalPolicy implementation.
                The default behavior should be the same as it used to be.

                I know there are some other ideas to address this, and some other currently problematic use-cases, so maybe someone has a different approach in mind that would cover more of those use-cases ...