• 提升用户体验的利器:揭秘Spring框架中国际化的奇妙魔力


    国际化

    简单来说,国际化就是让应用(app、web)适应不同的语言和地区的需要,比如根据地区选择页面展示语言。

    i18n=internationalization,首末字符i和n,18为中间的字符数

    原理

    基于传入语言or地区标识进行判断,输出不同内容。伪代码如下:

    9877c8f1e14af2b52c69c69a106c89f1.jpeg

    原理简单,但是如何优雅的实现?spring是否已经提供了现成的轮子?答案是肯定的。基于原理可以认为,实现国际化主要分为2部分

    1. 输入语言or地区标识
    2. 输出不同语言or地区的内容文案

    输出

    通过MessageSource实现不同语言输出。

    在spring初始化refresh过程中,会初始化MessageSource。

    9f70a7a509daa12ccfd86a1145947df0.jpeg

    而springboot会初始化ResourceBundleMessageSource实例作为MessageSource的默认实现

    b4c9540a5a21636099f70669c0118c16.jpeg

    MessageSource内部则通过basename以及Locale定位到具体Resource Bundle文件,并基于code(properties key)读取对应的显示文本。

    其中涉及到的三个概念

    1. basename标识
    2. Locale
    3. Resource Bundle

    basename

    用于指定Resource Bundle文件位置,可以通过配置文件配置, 默认为messages

    spring.messages.basename=messages


    Locale

    Locale对象代表具体的地理,政治或文化地区,用来指定语言及地区。构造函数如下

    25941543201b15f6915be962c5ce559b.jpeg

    variant 变体值,用于指示变化的任意值Locale。 同时, Locale类内置了众多常用国家地区的常量实例,如

    c00f912445811984f61c163da939a615.jpeg

    Resource Bundle

    ResourceBundle类和Properties类似,都可以读取程序内的文件,不过ResourceBundle更强大,提供了诸如缓存、Locale区分一类的操作。

    所以MessageSource其实是对ResourceBundle的一种封装增加,优化了使用,并且托管与spring容器生命周期。这时就有一个很重要的选择:

    如果通过静态类封装了restful的接口返回,可以自己扩展ResourceBundle类,而不是将MessageSource的spring实例放置在静态类中。

    而idea中提供了Resource Bundle资源束的支持,方便用户添加管理国际化文案。



    输入

    看完输出的形式,可以知道,我们只需要确认Locale就可以实现国际化。所以我们再找一下Locale的轮子。

    accept-language

    servlet自带轮子,基于http协议,即通过header中的accept-language报文头,实现Locale的自动识别。

    代码见 org.apache.catalina.connector.Request

    d9efded8bf32e538ed235d0337bd27ed.jpeg

    spring提供的轮子

    1. LocaleResolver 实现次接口,用于自定义解析规则
    2. RequestContextUtils 基于request获取Locale,优先使用自定义LocaleResolver
    3. LocaleContextHolder通过ThreadLocal持有Locale对象,在FrameworkServlet支持servlet.service时执行初始化。
    4. LocaleChangeInterceptor通过Configuration配置Locale切换规则

    综上,只要请求方在header中增加了accept-language报文头,即可在代码中通过LocaleContextHolder获取Locale对象。

    02f32f73a23f31920bdbc6e9a8c87e98.jpeg

    lang

    除了accept-language外,常见在url中增加了国家及地区参数,如: https://twitter.com/?lang=zh

    通过lang配置国际化,需要通过LocaleChangeInterceptor进行配置,此配置的优先级高于accept-language

    8e56f970df1103c5389d85bc248eef88.jpeg

    Test Case

    8f210e6310142449521c383f3cbce7eb.jpeg

    LanguageTagCompliant

    Locale的命名规则为 lang-country, 如: zh-CN,有时会看到zh_CH这种写法,这是另一种规范,可以在CookieLocaleResolver了解规范定义

    ed2e1ffd9147f4ef6850e3fc224d9c90.jpeg

    需要在中LocaleChangeInterceptor开启兼容模式

    92398c59c9b78bce402af8a103dcc1fb.jpeg

    但是为了符合规范,不推荐zh_CH这种写法。

    倾向

    按照《Http参数格式约定》文中所述,通用&非业务参数,一般会选择放到header中,所以比较倾向于accept-language这种定义方法。

  • 相关阅读:
    数据库-sqlserver数据库迁移到mysql
    [工业自动化-5]:西门子S7-15xxx编程 - PLC系统初识别 :PLC概述与发展史
    基于Epoll的Reactor模式
    Windows server 2016——权限管理与数据恢复
    PHP cURL 函数
    正余弦(SCO)优化算法(附完整Matlab代码,可直接复制))
    索引的基础使用
    JavaWeb基础9——Filter&Listener&Ajax
    Dubbo+ZK入门使用
    IDEA报错:前言中不允许有内容
  • 原文地址:https://blog.csdn.net/m0_70952941/article/details/134032282