Skip to content

区域解析 (Locale)

Spring 的架构全面支持国际化,DispatcherServlet 允许你根据客户端的区域设置(Locale)自动解析消息。这是通过 LocaleResolver 对象实现的。

常用 LocaleResolver 实现

实现类策略说明
AcceptHeaderLocaleResolver默认实现。检查请求头中的 accept-language。不支持修改 Locale。
CookieLocaleResolver检查客户端浏览器存储的 Cookie。如果存在则使用,支持通过代码修改并持久化到 Cookie。
SessionLocaleResolver将 Locale 存储在 HttpSession 中。设置是临时性的,会话结束即失效。

时区支持 (Time Zone)

LocaleContextResolver 接口扩展了 LocaleResolver,允许解析器提供包含时区信息的 LocaleContext。你可以通过 RequestContext.getTimeZone() 获取用户的时区。

区域拦截器 (LocaleChangeInterceptor)

你可以通过配置 LocaleChangeInterceptor 允许用户通过请求参数手动更改语言。

java
@Configuration
public class WebConfiguration implements WebMvcConfigurer {

    @Bean
    public LocaleResolver localeResolver() {
        return new CookieLocaleResolver(); // 使用 Cookie 存储
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
        lci.setParamName("lang"); // 参数名:?lang=zh_CN
        registry.addInterceptor(lci);
    }
}
kotlin
@Configuration
class WebConfiguration : WebMvcConfigurer {

    @Bean
    fun localeResolver(): LocaleResolver = CookieLocaleResolver()

    override fun addInterceptors(registry: InterceptorRegistry) {
        val lci = LocaleChangeInterceptor()
        lci.paramName = "lang"
        registry.addInterceptor(lci)
    }
}

补充教学

1. 国际化的“三剑客”

要实现完整的国际化,你需要三样东西:

  1. 资源文件 (Messages.properties):存储不同语言的文本。
  2. ResourceBundleMessageSource:用于加载这些资源文件的 Bean。
  3. LocaleResolver:决定当前请求该用哪种语言。
  • SessionLocaleResolver:用户关掉浏览器再进来,语言设置就丢了。且在集群环境下需要 Session 共享。
  • CookieLocaleResolver推荐做法。它可以设置有效期(如一年),这样用户下次访问时,依然能保持上次选择的预设语言,体验更好。

3. 如何在代码中获取 Locale?

不要直接从 Request 获取,因为那样可能拿不到拦截器修改后的 Locale。 正确方法

java
Locale locale = LocaleContextHolder.getLocale();

Spring 会在请求处理过程中将当前的 Locale 存入这个 ThreadLocal 变量中,方便你在 Service 层甚至任何地方随时获取。

Based on Spring Framework.