当前位置: 首页 > news >正文

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框架抛出异常信息

首先,我们需要

相关文章:

springboot国际化多语言

1,新建国际化多语言文件 在resources目录下新建 messages.properties 其他语言的文件 编辑messages.properties文件,下方从text切换到Resource Bundle ,即可对照着编辑多语言文件 (如果没有找到Resource Bundle,先在settings->plugins中安装Resource Bundle Editor) 2,配…...

set和map

这里是目录标题 setinsertfinderasecountlower_boundupper_boundmultisetset的应用 mappairinsertinsert的pair map的遍历map对[ ]的重载(重点)multimap set set的普通迭代器和const迭代器都不支持修改。(这点可以根据源代码看出来&#xff0c;都是对const iterator进行了type…...

Open CASCADE学习|求曲面的参数空间

在三维空间中&#xff0c;任意的曲面都可以通过特定的方法映射到一个二维参数平面上&#xff0c;从而对其进行详细的几何分析和处理。首先&#xff0c;我们需要从三维模型中提取出特定的曲面&#xff0c;这通常被称为“Face”。一个face可以被视为三维空间中的一个封闭区域&…...

代码随想录阅读笔记-二叉树【总结】

二叉树的理论基础 代码随想录 (programmercarl.com)&#xff1a;二叉树的种类、存储方式、遍历方式、定义方式 二叉树的遍历方式 深度优先遍历 代码随想录阅读笔记-二叉树【递归遍历】-CSDN博客&#xff1a;递归三部曲初次亮相代码随想录阅读笔记-二叉树【迭代遍历】-CSDN博…...

【SpringBoot整合系列】SpringBoot整合FastDFS(二)

目录 SpringBoot整合FastDFSJava客户端/依赖常用api接口解释1.uploadFile参数返回值 2.uploadSlaveFile参数返回值 3.getMetadata参数返回值 4.overwriteMetadata参数&#xff1a;返回值&#xff1a;无 5.mergeMetadata参数&#xff1a;返回值&#xff1a;无 6.queryFileInfo参…...

L2-2 巴音布鲁克永远的土(二分+并查集)

思路&#xff1a;我们可以二分答案&#xff0c;然后判断当前答案合不合理。 对于判断答案合理&#xff0c;可以用并查集&#xff0c;看mid能否把所有检查点连进一个集合中&#xff0c;枚举每个结点&#xff0c;如何当前结点周围的四个方向可以连的话&#xff0c;就加进同一个集…...

Spring Cloud学习笔记:Eureka简介,Eureka简单样例

这是本人学习的总结&#xff0c;主要学习资料如下 - 马士兵教育 [TOC](目录)1、Eureka 1.1、架构 Eureka是SpringCloud Nexflix的核心子模块&#xff0c;其中包含Server和Client。 Server提供服务注册&#xff0c;存储所有可用服务节点。 Client用于简化和Server的通讯复杂…...

【漏洞复现】WordPress Welcart 任意文件读取漏洞(CVE-2022-4140)

0x01 产品简介 Welcart 是一款免费的 WordPress 电子商务插件。Welcart 具有许多用于制作在线商店的功能和自定义设置。您可以轻松创建自己的原始在线商店。 0x02 漏洞概述 Welcart存在任意文件读取漏洞&#xff0c;未授权的攻击者可以通过该漏洞读取任意文件&#xff0c;获…...

快速排序:深入解析其原理、实现与性能特性

快速排序&#xff0c;以其名字所示&#xff0c;是一种追求速度的高效排序算法。作为分治法在排序问题上的典型应用&#xff0c;快速排序凭借其平均情况下近乎理想的O(n log n)时间复杂度和简洁的实现逻辑&#xff0c;在实际编程与数据处理中占据着重要地位。本篇博客将详细解析…...

一文看懂Mac地址

一、Mac地址是什么&#xff1f; 虽然IP地址已经成为一个家喻户晓的术语&#xff0c;但还有一个同样重要的数字标识符值得我们关注——MAC地址。在本文中&#xff0c;我们旨在阐明网络中这个经常被忽视的方面。加入我们&#xff0c;深入研究 MAC 地址的世界&#xff0c;了解它们…...

2024.4.10作业

#include "widget.h" #include "ui_widget.h" Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { ui->setupUi(this); } Widget::~Widget() { delete ui; } //显示时间 void Widget::timerEvent(QTimerEvent *e) { QT…...

python - Django创建项目

项目运行命令 根目录下运行命令:   python manage.py runserver win环境创建项目 直接使用 Pycharm 创建项目 在 cmd 或 Linux 命令行环境下创建 Django 项目 django-admin startproject mysite 这样就会在当前目录下创建一个叫做 mysite 的Django项目。   可以看到Djang…...

WPF —— 动画缩放变换

ScaleTransform:在二维x-y坐标系统内缩放对象; 在故事板中依赖的属性为RenderTransform.ScaleX或RenderTransform.ScaleY,这要根据你要沿哪个轴进行缩放,X代表x轴,Y代表y轴; key属性当我们使用静态资源访问时候--> <!--TargetType"{x:Type Button} 直接应用…...

SQL注入---盲注

文章目录 目录 一.盲注概述 布尔盲注&#xff1a; 时间盲注&#xff1a; 一.盲注概述 注是一种SQL注入攻击的形式&#xff0c;在这种攻击中&#xff0c;攻击者向目标应用程序发送恶意注入代码&#xff0c;然后通过观察应用程序的响应来推断出数据库中的信息。与常规的SQL注入…...

PlanUML和Mermaid哪个好?

引言 在当今信息化快速发展的时代&#xff0c;数据可视化和图表工具不仅对于程序员&#xff0c;也对于非技术背景的人士至关重要。绘图工具可以帮助我们更好地理解和表达复杂的概念或数据流。PlantUML和Mermaid是两款被广泛使用的绘图语言&#xff0c;它们都能够通过简洁的文本…...

leetcode 343. 整数拆分

题目 给定一个正整数 n &#xff0c;将其拆分为 k 个 正整数 的和&#xff08; k > 2 &#xff09;&#xff0c;并使这些整数的乘积最大化。 返回 你可以获得的最大乘积 。 示例 1: 输入: n 2 输出: 1 解释: 2 1 1, 1 1 1。 示例 2: 输入: n 10 输出: 36 解释: 1…...

【MATLAB源码-第180期】基于matlab的PTS,SLM,CPFilter三种降低OFDM系统的PAPR仿真。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 1. 限幅和滤波&#xff08;Clipping and Filtering&#xff09; 原理简介 限幅和滤波是一种基础且直观的方法&#xff0c;用于降低OFDM信号的PAPR。在限幅阶段&#xff0c;信号的幅度在达到设定阈值时会被削减&#xff0c;…...

学透Spring Boot — 004. Spring Boot Starter机制和自动配置机制

如果你项目中一直用的是 Spring Boot&#xff0c;那么恭喜你没有经历过用 Spring 手动集成其它框架的痛苦。 都说 Spring Boot 大大简化了 Spring 框架开发 Web 应用的难度&#xff0c;这里我们通过配置 Hibernate 的两种方式来深刻体会这一点&#xff1a; 使用 Spring 框架集…...

面试算法-170-二叉树的最大深度

题目 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;3 解 class Solution {public int maxDepth(TreeNod…...

【数据结构】哈希

文章目录 1. 哈希概念2. 哈希冲突3. 哈希函数4. 哈希冲突解决4.1 闭散列4.2 开散列 unordered 系列的关联式容器之所以效率比较高&#xff0c;是因为其底层使用了哈希结构。 1. 哈希概念 顺序结构以及平衡树中&#xff0c;元素关键码与其存储位置之间没有对应的关系&#xff…...

UE5 学习系列(三)创建和移动物体

这篇博客是该系列的第三篇&#xff0c;是在之前两篇博客的基础上展开&#xff0c;主要介绍如何在操作界面中创建和拖动物体&#xff0c;这篇博客跟随的视频链接如下&#xff1a; B 站视频&#xff1a;s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

Cinnamon修改面板小工具图标

Cinnamon开始菜单-CSDN博客 设置模块都是做好的&#xff0c;比GNOME简单得多&#xff01; 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

自然语言处理——Transformer

自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效&#xff0c;它能挖掘数据中的时序信息以及语义信息&#xff0c;但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN&#xff0c;但是…...

AI书签管理工具开发全记录(十九):嵌入资源处理

1.前言 &#x1f4dd; 在上一篇文章中&#xff0c;我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源&#xff0c;方便后续将资源打包到一个可执行文件中。 2.embed介绍 &#x1f3af; Go 1.16 引入了革命性的 embed 包&#xff0c;彻底改变了静态资源管理的…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式

今天是关于AI如何在教学中增强学生的学习体验&#xff0c;我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育&#xff0c;这并非炒作&#xff0c;而是已经发生的巨大变革。教育机构和教育者不能忽视它&#xff0c;试图简单地禁止学生使…...

9-Oracle 23 ai Vector Search 特性 知识准备

很多小伙伴是不是参加了 免费认证课程&#xff08;限时至2025/5/15&#xff09; Oracle AI Vector Search 1Z0-184-25考试&#xff0c;都顺利拿到certified了没。 各行各业的AI 大模型的到来&#xff0c;传统的数据库中的SQL还能不能打&#xff0c;结构化和非结构的话数据如何和…...

mac:大模型系列测试

0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何&#xff0c;是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试&#xff0c;是可以跑通文章里面的代码。训练速度也是很快的。 注意…...

在 Visual Studio Code 中使用驭码 CodeRider 提升开发效率:以冒泡排序为例

目录 前言1 插件安装与配置1.1 安装驭码 CodeRider1.2 初始配置建议 2 示例代码&#xff1a;冒泡排序3 驭码 CodeRider 功能详解3.1 功能概览3.2 代码解释功能3.3 自动注释生成3.4 逻辑修改功能3.5 单元测试自动生成3.6 代码优化建议 4 驭码的实际应用建议5 常见问题与解决建议…...