提升用户体验的利器:揭秘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这种定义方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/103271.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

BC v1.2充电规范

1 JEITA Reference to https://www.mianbaoban.cn/blog/post/169964 符合 JEITA 规范的锂离子电池充电器解决方案 2 Battery Fuel Gauge 2.1 Cycle Count(充放电循环次数) 此指令回传一只读字段,代表电芯组已经历的完整充放电循环数。当放电容…

CSS常见选择器总结

1.简单选择器 简单选择器是开发中使用最多的选择器,包含: 元素选择器,使用元素的名称 类选择器,使用.类名 id选择器,使用#id id注意事项: 一个HTML文档里面的id值 是唯一的,不能重复 id值如…

震坤行亮相2023工博会,并荣获第23届中国工博会“CIIF信息技术奖”

震坤行亮相2023工博会,并荣获第23届中国工博会“CIIF信息技术奖” 2023年9月19日,2023年第23届中国国际工业博览会CIIF(以下简称“工博会”)在上海国家会展中心盛大开幕。震坤行紧跟智能制造产业发展步伐,携数字化解决…

STM32 invalid UTF-8 in comment 警告解决办法

这里写自定义目录标题 STM32 invalid UTF-8 in comment 警告解决办法问题描述解决办法 STM32 invalid UTF-8 in comment 警告解决办法 问题描述 …/…/libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x\stm32f10x.h(18): warning: invalid UTF-8 in comment [-Winvalid-utf8]…

软件工程第七周

内聚 耦合 (Coupling): 描述的是两个模块之间的相互依赖程度。控制耦合是耦合度的一种,表示一个模块控制另一个模块的流程。高度的耦合会导致软件维护困难,因为改变一个模块可能会对其他模块产生意外的影响。 内聚 (Cohesion): 描述的是模块内部各个元素…

操作教程|如何注册成为Moonbeam社区代表参与治理

社区代表是高度参与社区治理的社区成员,其主要职责是将社区成员委托给他们的投票权参与社区投票,并确保链上治理稳健发展和活跃参与度。本文将向您展示如何快速注册成为社区代表。 首先,前往Moonbeam委托网站,点击网页右上角的“…

【AI视野·今日Robot 机器人论文速览 第五十八期】Thu, 19 Oct 2023

AI视野今日CS.Robotics 机器人学论文速览 Thu, 19 Oct 2023 Totally 25 papers 👉上期速览✈更多精彩请移步主页 Daily Robotics Papers InViG: Benchmarking Interactive Visual Grounding with 500K Human-Robot Interactions Authors Hanbo Zhang, Jie Xu, Yuch…

nginx配置负载均衡--实战项目(适用于轮询、加权轮询、ip_hash)

👨‍🎓博主简介 🏅云计算领域优质创作者   🏅华为云开发者社区专家博主   🏅阿里云开发者社区专家博主 💊交流社区:运维交流社区 欢迎大家的加入! 🐋 希望大家多多支…

021-Qt 配置GitHub Copilot

Qt 配置GitHub Copilot 文章目录 Qt 配置GitHub Copilot项目介绍 GitHub Copilot配置 GitHub CopilotQt 前置条件升级QtGitHub Copilot 前置条件激活的了GitHub Copilot账号安装 Neovim 启用插件,重启Qt配置 GitHub Copilo安装Nodejs下载[copilot.vim](https://gith…

计算机网络文章荟萃

脑残式网络编程入门(二):我们在读写Socket时,究竟在读写什么?-网络编程/专项技术区 - 即时通讯开发者社区! 1.什么是 socket - 掘金2.socket 的实现原理 - 掘金本文讲述了 socket 在 linux 操作系统下的数据结构,以及阻塞 IO 利用…

Linux网络编程:IP协议

目录 一. IP协议的功能 二. IP协议报头 2.1 IP报头的格式 2.2 IP报头各部分含义 三. IP报文的分片问题 3.1 什么是分片 3.2 分片的原理 3.3 合并报文 四. 网段划分 4.1 网络号和主机号 4.2 网络号和主机号的划分策略 4.3 特殊的IP地址 4.4 IP地址数量不足问题 五.…

Git常用的命令有哪些?

一、前言 git 的操作可以通过命令的形式如执行,日常使用就如下图6个命令即可 实际上,如果想要熟练使用,超过60多个命令需要了解,下面则介绍下常见的的git 命令 二、有哪些 配置 Git 自带一个 git config 的工具来帮助设置控制…

初识Java篇

1.介绍Java语言 1.1Java是什么 Java是一种优秀的程序设计语言,它具有令人赏心悦目的语法和易于理解的语义。 不仅如此,Java还是一个有一系列计算机软件和规范形成的技术体系,这个技术体系提供了完整的用于软件开发和跨平台部署的支持环境&am…

JoySSL证书买二送一买三送二特别活动

数字安全对于网站运营和用户信任至关重要。JoySSL作为一家知名的SSL证书品牌,为了回馈广大用户,推出了买二送一和买三送二的特别活动。 超值优惠:买二送一、买三送二 JoySSL的买二送一和买三送二活动非常有吸引力。在买二送一的活动中&#…

安装docker ,更换docker版本

docker dockerd & containerd Dockerd(Docker 守护进程)在其底层使用 Containerd 来管理容器。Containerd 是一个开源的容器运行时管理器,由 Docker 公司于2017年开发并开源,它负责实际的容器生命周期管理。 以下是 Docker 守…

简化通知基础设施:开源的消息通知服务 | 开源专题 No.41

novuhq/novu Stars: 22.9k License: MIT Novu 是一个开源的通知基础设施项目,它提供了统一的 API 来通过多个渠道发送通知,包括应用内、推送、电子邮件、短信和聊天。主要功能有: 为所有消息提供商 (应用内、电子邮件、短信、推送和聊天) 提…

javaEE -8(9000字详解网络编程)

一:网络编程基础 1.1 网络资源 所谓的网络资源,其实就是在网络中可以获取的各种数据资源,而所有的网络资源,都是通过网络编程来进行数据传输的。 用户在浏览器中,打开在线视频网站,如优酷看视频&#xff…

解决 Element-ui中 表格(Table)使用 v-if 条件控制列显隐时数据展示错乱的问题

本文 Element-ui 版本 2.x 问题 在 el-table-column 上需根据不同 v-if 条件来控制列显隐时&#xff0c;就会出现列数据展示错乱的情况&#xff08;要么 A 列的数据显示在 B 列上&#xff0c;或者后端返回有数据的但是显示的为空&#xff09;&#xff0c;如下所示。 <tem…

反射的作用( 越过泛型检查 和 可以使用反射保存所有对象的具体信息 )

1、绕过 编译阶段 为集合添加数据 反射是作用在运行时的技术&#xff0c;此时集合的泛型将不能产生约束了&#xff0c;此时是可以 为集合存入其他任意类型的元素的 。泛型只是在编译阶段可以约束集合只能操作某种数据类型&#xff0c;在 编译成Class文件进入 运行阶段 的时候&a…

使用adobe font style 工具绘制的艺术字,请鉴赏。

Adobe Fireflyhttps://firefly.adobe.com/generate/font-styles