понедельник, 23 апреля 2012 г.

Locale in Grails. How to use it with cookies.

If you are developing multilingual project, you are definately know about i18n plugin in grails. It provides an interface to spring-i18n.
In the project root you can see grails-app/i18n folder and there are "messages.properties" files. What are they for? Every file is a standard Java Property file with message code as a key and localized message as a value. Grails picks messages accroding to locale. For example, if current locale are set to "pl", grails will use text from messages_pl.properties. By default grails analyze Accept-Language HTTP header and render response according it. But what should you do if you want to store the locale in cookies? In the Internationalization chapter in grails docs you can find these words:
You can provide users the capability to switch locales by simply passing a parameter called lang to Grails as a request parameter:/book/list?lang=esGrails will automatically switch the user's locale and store it in a cookie so subsequent requests will have the new header.
Yeah, that's great but when you try to do this, you will realize that there grails don't store locale in cookie. There is an open issue 8655 with this problem. On grails 2.0.3 this issue isn't solved. And now I will show you how to resolve this issue using custom Spring bean.
Let's look at the theory now. Spring-i18n using LocaleResolver interface to detect and store locale. It has two methods:
  • resolveLocale()
  • setLocale()
So we need to implement this interface and register it as a LovaleResolver bean. Ok, grails did most of work for us: when you have "lang" parameter in request, grails will execute setLocale() method. Create a file in src/groovy folder. Below you can see full code listing with all imports:

package com.buysomegames.i18n
 
import org.springframework.web.servlet.LocaleResolver
import javax.servlet.http.HttpServletResponse
import org.codehaus.groovy.grails.web.util.WebUtils
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.Cookie
import org.apache.commons.lang.LocaleUtils
 
class BSGLocaleResolver implements LocaleResolver {
 
    // declaring default locale
    private static final Locale defaultLocale = Locale.US
 
    Locale resolveLocale(HttpServletRequest httpServletRequest) {
        // retrieving locale from cookie
        def localeString = WebUtils.getCookie(httpServletRequest, "locale")?.value
        if (!localeString)
            return defaultLocale
        // using LocaleUtils from apache commons to parse locale string
        return LocaleUtils.toLocale(localeString)
    }
 
    void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
        def cookie = new Cookie("locale", locale.toString())
        // setting cookie path according your servlet context path. Setting "/" if it's empty
        cookie.path = httpServletRequest.servletContext.contextPath.empty ? "/" : httpServletRequest.servletContext.contextPath
        httpServletResponse.addCookie(cookie)
    }
}

Now you need to register this bean. Open grails-app/conf/spring/resources.groovy file and insert these lines:

 
beans = {
    localeResolver(com.buysomegames.i18n.BSGLocaleResolver)
}
 
Of course, you need to change class name :)
That's all. User locale will store in "locale" cookie now.

Комментариев нет:

Отправить комментарий

Постоянные читатели