springboot国际化多语言

1,新建国际化多语言文件

在resources目录下新建 messages.properties + 其他语言的文件

编辑messages.properties文件,下方从text切换到Resource Bundle ,即可对照着编辑多语言文件

(如果没有找到Resource Bundle,先在settings->plugins中安装Resource Bundle Editor)

2,配置文件添加配置

spring.messages.always-use-message-format=false

是否始终应用 MessageFormat 规则,甚至分析没有参数的消息。

默认是false

 

spring.messages.basename=messages

以逗号分隔的基名列表(实质上是完全限定的类路径位置),每个基名都遵循 ResourceBundle 约定,对基于斜杠的位置提供了宽松的支持。如果它不包含包限定符(例如“org. mypackage”),则将从类路径根目录解析它。

默认是messages,所以第一步中文件为messages.properties,也可根据实际定义其他名字。

 

spring.messages.cache-duration=1000

 加载的资源包文件缓存持续时间。如果未设置,捆绑包将永久缓存。如果未指定持续时间后缀,则将使用秒。

默认是null。

 

spring.messages.encoding=utf-8

 消息包编码。

默认是UTF-8

 

spring.messages.fallback-to-system-locale=true

 如果未找到特定区域设置的文件,是否回退到系统区域设置。如果关闭此功能,则唯一的回退将是默认文件(例如,basename “messages”的“messages. properties”)。

默认是true

 

spring.messages.use-code-as-default-message=false

 是否使用消息代码作为默认消息,而不是抛出“NoSuchMessageException”。建议仅在开发期间使用。

默认是false。

第一步中我们定义了一个参数叫test.i18n.message,如果我们使用的时候取名test.i18n.message123,只要是多语言文件中未定义的key,则该参数设置为false时,会报错。设置为true时,不会报错,由于找不到对应的key,则不替换该多语言字符。

3,设置上下文语言环境

在web请求中,两个地方会根据header中的参数设置语言环境:

org.springframework.web.filter.RequestContextFilter#initContextHolders

org.springframework.web.servlet.FrameworkServlet#initContextHolders

解析request中locale的地方:

org.apache.catalina.connector.Request#parseLocales

如果请求头中为携带语言参数的header为accept-language,则框架已自动帮我们做了解析,不用我们再写额外代码。

注意:参考了多个大公司国际化,没有公司将国际化相关的数据用accept-language传递(accept-language本身记录的是浏览器(我用的谷歌浏览器)的语言环境,可能是可以作为其他的业务数据,类似于收集用户数据等),而是存放在cookie中。

所以我们要定义一个参数,将国际化相关的数据存放在cookie中,请求后端时将该参数添加到header(单独定义一个header参数,或者将整个cookie传输)中传递到后端。

假设这里是单独定义了一个header参数:test-lang。

框架解析多语言环境时,使用的accept-language,所以我们要重写解析的方法,替换为我们自定义的header参数:test-lang。

新建一个request的包装类,在filter中包装原request,重写解析语言环境的方法。

import org.apache.tomcat.util.http.parser.AcceptLanguage;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.IOException;
import java.io.StringReader;
import java.util.*;/*** @Description i18n 国际化包装请求* @DATE 2024/4/6 22:45**/
public class I18nWrapperRequest extends HttpServletRequestWrapper {public I18nWrapperRequest(HttpServletRequest request) {super(request);}/*** Parse locales.*/protected boolean localesParsed = false;/*** The preferred Locales associated with this Request.*/protected final ArrayList<Locale> locales = new ArrayList<>();/*** The default Locale if none are specified.*/protected static final Locale defaultLocale = Locale.getDefault();@Overridepublic Locale getLocale() {if (!localesParsed) {parseLocales();}if (locales.size() > 0) {return locales.get(0);}return defaultLocale;}@Overridepublic Enumeration<Locale> getLocales() {if (!localesParsed) {parseLocales();}if (locales.size() > 0) {return Collections.enumeration(locales);}ArrayList<Locale> results = new ArrayList<>();results.add(defaultLocale);return Collections.enumeration(results);}/*** Parse request locales.*/protected void parseLocales() {localesParsed = true;// Store the accumulated languages that have been requested in// a local collection, sorted by the quality value (so we can// add Locales in descending order). The values will be ArrayLists// containing the corresponding Locales to be addedTreeMap<Double, ArrayList<Locale>> locales = new TreeMap<>();Enumeration<String> values = ((HttpServletRequest) getRequest()).getHeaders("test-lang");while (values.hasMoreElements()) {String value = values.nextElement();parseLocalesHeader(value, locales);}// Process the quality values in highest->lowest order (due to// negating the Double value when creating the key)for (ArrayList<Locale> list : locales.values()) {for (Locale locale : list) {addLocale(locale);}}}/*** Parse accept-language header value.** @param value   the header value* @param locales the map that will hold the result*/protected void parseLocalesHeader(String value, TreeMap<Double, ArrayList<Locale>> locales) {List<AcceptLanguage> acceptLanguages;try {acceptLanguages = AcceptLanguage.parse(new StringReader(value));} catch (IOException e) {// Mal-formed headers are ignore. Do the same in the unlikely event// of an IOException.return;}for (AcceptLanguage acceptLanguage : acceptLanguages) {// Add a new Locale to the list of Locales for this quality levelDouble key = Double.valueOf(-acceptLanguage.getQuality()); // Reverse the orderlocales.computeIfAbsent(key, k -> new ArrayList<>()).add(acceptLanguage.getLocale());}}/*** Add a Locale to the set of preferred Locales for this Request. The first added Locale will be the first one* returned by getLocales().** @param locale The new preferred Locale*/public void addLocale(Locale locale) {locales.add(locale);}}
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** @Description 国际化过滤器* @DATE 2024/4/6 23:00**/
@WebFilter("/**")
@Component
@Order(value = Ordered.HIGHEST_PRECEDENCE)
public class I18nFilter extends OncePerRequestFilter {@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {filterChain.doFilter(new I18nWrapperRequest(request), response);}
}

4,返回多语言

目前是在报错信息中需要返回多语言,报错分为两种:

1)手动抛出异常信息

2)validation框架抛出异常信息

首先,我们需要

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Lumos学习王佩丰Excel第二讲:单元格格式设置

今天学会GIF录制了&#xff0c;分享知识会更简便一些&#xff0c;话不多说&#xff0c;开始吧~ 一、美化表格 1、设置单元格格式的路径 从菜单栏进入&#xff1a; 选中区域&#xff08;单元格&#xff09;- 右键“设置单元格格式”&#xff1a; 2、合并单元格 合并一行 批量…

5.3 用栈翻转数组,动态规划求斐波那契数列

5.3 用栈翻转数组&#xff0c;动态规划求斐波那契数列 1. 用栈翻转数组 assume cs:code,ds:data,ss:stack data segmentarr dw 1111h,2222h,3333h,4444h,5555h,6666h,7777h,8888hres db 800 dup(0) data endsstack segmentdb 100 dup(0) stack endscode segmentstart:mov ax,…

YOLOv8模型剪枝实战:Network Slimming网络瘦身方法

课程链接&#xff1a;YOLOv8模型剪枝实战&#xff1a;Network Slimming网络瘦身方法_在线视频教程-CSDN程序员研修院 YOLOv8是一个当前非常流行的目标检测器&#xff0c;本课程使用Network Slimming&#xff08;网络瘦身&#xff09;剪枝方法对YOLOv8进行模型剪枝&#xff0c;…

力扣347. 前 K 个高频元素

思路&#xff1a;记录元素出现的次数用map&#xff1b; 要维护前k个元素&#xff0c;不至于把所有元素都排序再取前k个&#xff0c;而是新建一个堆&#xff0c;用小根堆存放前k个最大的数。 为什么是小根堆&#xff1f;因为堆每次出数据时只出堆顶&#xff0c;每次把当前最小的…

手动实现Tomcat底层机制+自己设计Servlet

文章目录 1.Tomcat整体架构分析自己理解 2.第一阶段1.实现功能2.代码1.TomcatV1.java 3.调试阶段1.阻塞在readLine导致无法返回结果 4.结果演示 3.第二阶段1.实现功能2.代码1.RequestHander.java2.TomcatV2.java 3.调试阶段1.发现每次按回车会接受到两次请求 4.结果演示 4.第三…

[dvwa] Command Injection

命令注入 0x01 low 没有过滤&#xff0c;直接利用 127.0.0.1 && ip a 函数 php_uname(mode) 动态地检查服务器的操作系统 ‘s’&#xff1a;操作系统名称 ‘n’&#xff1a;网络主机名 ‘r’&#xff1a;操作系统发行版本号 ‘v’&#xff1a;操作系统版本 ‘m’&…

书籍《笔记的方法》读后感

读完《笔记的方法》有几周的时间&#xff0c;书里有些记录的内容&#xff0c;觉得非常有价值的&#xff0c;自己的观点&#xff0c;当下读书&#xff0c;其实并没有那么高大尚&#xff0c;就是存粹陶冶下情操&#xff0c;读书还是有一定作用的&#xff0c;毕竟看书只能慢慢来&a…

淘宝API接口详解:如何高效利用API进行电商开发

淘宝API接口详解&#xff1a;如何高效利用API进行电商开发 请求示例&#xff0c;API接口接入Anzexi58 在电商行业蓬勃发展的今天&#xff0c;淘宝作为国内最大的电商平台之一&#xff0c;为商家和开发者提供了丰富的API接口。这些接口使得电商开发变得更加高效和便捷。本文将详…

【算法篇】三道题理解算法思想——认识BFS

BFS&#xff08;宽搜&#xff09; 宽度优先遍历和深度优先遍历组成了大家熟悉的搜索算法&#xff0c;这两种算法也是蓝桥杯之类竞赛题的常考思想&#xff0c;正巧马上蓝桥杯临近&#xff0c;博主也是刷了很多BFS相关的题型&#xff0c;在这篇文章中会从力扣上选取三道简单的宽搜…

一键无痕清理:高效删除Mac文件夹,释放宝贵存储空间

在当今重视隐私的时代&#xff0c;当转让或出借Mac电脑时&#xff0c;确保个人文件和敏感信息彻底清除至关重要。常规删除Mac上的文件和文件夹仅使数据看似消失&#xff0c;实际上它们仍驻留在硬盘上&#xff0c;存在被数据恢复软件找回的风险。为实现不可逆的删除效果&#xf…

【Linux】指令

1. 简单指令 whoami 显示当前登入账号名 ls /home 现在有的用户名 adduser 用户名 新加用户&#xff08;必须在root目录下&#xff09; passwd 用户名 给这个用户设置密码 userdel -r 用户名 删除这个用户 pwd 显示当前所处路径 stat 文件名 / 文件夹名 显示文件状…

五分钟快速搭建五金行业小程序商城教程解析

作为五金行业的从业者&#xff0c;你可能想要拓展线上业务&#xff0c;提供更方便快捷的购物体验给顾客。而小程序商城成为了一种非常受欢迎的方式。但是&#xff0c;你可能觉得不懂代码无法实现这样的小程序商城。现在&#xff0c;我将通过以下步骤&#xff0c;教你如何在五分…

TikTok防关联封号及操作需注意什么?

现在Tiktok对账户的管控一直非常严格。在运营Tiktok账户时&#xff0c;应该注意哪些方面来减少账户损失&#xff1f;以下是几个账户可能出现问题的原因。 网络环境问题 1.Tiktok账户对账户有严格的控制。我们经营Tiktok账户&#xff0c;手机应该模拟海外环境。一旦平台发现我…

全网短剧搜索前端源码开源分享可改自己的接口

全网短剧搜索前端源码 内含7000短剧资源(不支持在线播放&#xff09; 源码全开源&#xff0c;可以修改成自己的接口 178、226、347行修改 源码免费下载地址抄笔记 (chaobiji.cn)https://chaobiji.cn/

linux 文件提权|属性修改

文章目录 suid&#xff08;set uid&#xff09;添加文件属性查看文件属性i &#xff08;immutable&#xff09; umask suid&#xff08;set uid&#xff09; 让文件在执行的时候具有属主&#xff08;对应文件 user &#xff09;的权限 chmod 7744 temp.txt 第一位的7表示权限位…

数据库的基本使用

一、数据库的简介 RDBMS简介&#xff1a; Relational Database Management System,通过表来表示关系类型。当前主要使用两种类型的数据库:关系型数据库和非关系型数据库。所谓的关系型数据库RDBMS是建立在关系模型基础上的数据库&#xff0c;借助于集合代数等数学概念和方法来…

蓝桥杯第十三届省赛C++B组(未完)

目录 刷题统计 修剪灌木 X进制减法 【前缀和双指针】统计子矩阵 【DP】积木画 【图DFS】扫雷 李白打酒加强版 DFS (通过64%&#xff0c;ACwing 3/11&#xff09;; DFS(AC) DP&#xff08;AC&#xff09; 砍竹子(X) 刷题统计 题目描述 小明决定从下周一开始努力刷题准…

《QT实用小工具·十八》高亮发光按钮控件

1、概述 源码放在文章末尾 该项目实现了高亮发光按钮控件 可设置文本&#xff0c;居中显示。可设置文本颜色。可设置外边框渐变颜色。可设置里边框渐变颜色。可设置背景色。可直接调用内置的设置 绿色、红色、黄色、黑色、蓝色 等公有槽函数。可设置是否在容器中可移动&#…

git应用场景(进阶)

Git场景运用-CSDN博客 专有名词 Workspace&#xff1a;工作区 Index / Stage&#xff1a;暂存区 Repository&#xff1a;仓库区&#xff08;或本地仓库&#xff09; Remote&#xff1a;远程仓库HEAD HEAD&#xff0c;指向当前分支最新提交点。所处分支变化&#xff0c;或产生新…

Open CASCADE学习|旋转变换

物体在三维空间中的旋转变换操作通常可以通过三种不同的方式来表示&#xff1a;矩阵&#xff08;Matrix&#xff09;、欧拉角&#xff08;Euler Angles&#xff09;和四元数&#xff08;Quaternion&#xff09;。下面详细解释这三种表示方法。 矩阵&#xff08;Matrix&#xf…