在Grails应用程序的主页中更改用户的区域设置

时间:2015-04-01 12:14:41

标签: grails locale

登录后我一直试图更改用户区域设置(我使用的是Spring Security)。

我尝试在Spring Security的成功事件处理程序(onInteractiveAuthenticationSuccessEvent)中更改语言环境,并创建自己的localeResolver并在resources.groovy上注册它。

除主页外,它似乎适用于所有页面。

这是MyLocaleResolver

class MyLocaleResolver implements LocaleResolver {

    def springSecurityService

    private Locale defaultLocale = null;

    @Override
    Locale resolveLocale(HttpServletRequest httpServletRequest) {
        User user = User.findByEmail(springSecurityService.authentication.principal.username)
        if (user && !defaultLocale) {
            if (user.lang) {
                this.defaultLocale = new Locale(user.lang)
            } else {
                this.defaultLocale = Locale.ENGLISH
            }
        }
        println "defaultLocale = $defaultLocale"
        return this.defaultLocale
    }

    @Override
    void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
        this.defaultLocale = locale;
    }
}

和resources.groovy部分

localeResolver(MyLocaleResolver){
    springSecurityService = ref("springSecurityService")
}

更新(2015年4月7日): 我已经尝试扩展CookieLocaleResolver,并且因为它设置了cookie值,所以在所有情况下它都可以正常工作,除了在第一个主页加载中设置了默认语言而不是我在resolveLocale中设置的那个。

class MyLocaleResolver extends CookieLocaleResolver{

def springSecurityService

@Override
Locale resolveLocale(HttpServletRequest httpServletRequest) {
    super.resolveLocale(httpServletRequest)

    User user = User.findByEmail(springSecurityService.authentication.principal.username)
    Locale locale
    if (user) {
        if (user.lang) {
            locale = new Locale(user.lang)
        } else {
            locale = Locale.ENGLISH
        }
        httpServletRequest.setAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME, locale != null?locale:this.determineDefaultLocale(request));
    }
    return (Locale)httpServletRequest.getAttribute(LOCALE_REQUEST_ATTRIBUTE_NAME);
}

}

我尝试了一种不同的方法,尽管我认为尝试覆盖localeResolver会更好。我尝试在用户登录时更改语言环境,更改MongoUserDetailsS​​ervice的方法loadUserByUsername中的defaultLocale。它与以前的方法相同,除了在登录后的第一个主页加载时,它运行良好。

def localeResolver

@Override
public UserDetails loadUserByUsername(String username)
        throws UsernameNotFoundException {
            User.withTransaction { status ->
               User user = User.findByEmail(username)
               if (!user) throw new UsernameNotFoundException(
                            'User not found', username)

                try {
                    localeResolver.setDefaultLocale(user.lang ? new Locale(user.lang) : Locale.ENGLISH)
                } catch (Exception e){
                    e.printStackTrace()
                }

               def authorities = user.authorities.collect {
                   new SimpleGrantedAuthority(it.authority)
               }

               return new MyUserDetails(user.username, user.password, user.enabled,
                  !user.accountExpired, !user.passwordExpired,
                  !user.accountLocked, authorities ?: MongoUserDetailsService.NO_ROLES, user.id, user.client, user.email,
                    user.dateCreated)
            }
}

和resources.groovy

userDetailsService(net.ds.batto.MongoUserDetailsService){
    localeResolver = ref("localeResolver")
}

另外,我认为grails默认使用CookieLocaleResolver,但我看到我引用的localeResolver是SessionLocaleResolver。这是正确的行为还是可能出现配置错误的原因?

1 个答案:

答案 0 :(得分:0)

对我来说,defaultLocale是整个应用程序的全局配置(或者至少不适用于特定的用户会话)

http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/i18n/SessionLocaleResolver.html

  

自定义控制器可以通过在解析程序上调用#setLocale(Context)来覆盖用户的区域设置和时区

所以也许你可以尝试替换

localeResolver.setDefaultLocale(user.lang ? new Locale(user.lang) : Locale.ENGLISH)

通过

class MyLocaleChangeInterceptor extends LocaleChangeInterceptor {
        ...
    @Override
    boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        localeResolver.setLocale(user.lang ? new Locale(user.lang):Locale.ENGLISH)
    }
}

直接在LocaleChangeInterceptor中,我想当服务器到达“LocaleResolver”时已经太晚了已经处理过请求,只有在请求后才会受到Locale更改的影响。