跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava

SpringBoot 国际化 i18n 实战:配置文件与动态切换方案

介绍 SpringBoot 国际化(i18n)的实现方案。涵盖核心概念如 MessageSource、LocaleResolver。详细讲解基于配置文件的静态实现流程,包括多语言文件命名规则、application.yml 配置及中文乱码处理。同时提供自定义语言解析器与拦截器的代码示例,支持通过请求头或 Session 切换语言。最后封装了国际化工具类简化业务调用,并展示了控制器中的使用方式。

无尘发布于 2026/3/24更新于 2026/7/220K 浏览

前言

在全球化业务场景下,系统适配多语言已成为标配需求。SpringBoot 作为主流的 Java 开发框架,提供了完善的国际化(i18n)解决方案。本文将从实战角度出发,完整讲解两种企业级 i18n 实现方案:基于配置文件的静态实现(适配简体中文、繁体中文、英文)和基于数据库的动态实现(支持运行时修改语言配置),同时覆盖校验注解国际化、性能优化、常见问题排查等核心要点。

一、国际化基础认知

1.1 核心概念

i18n 的核心目标是让系统在不修改代码的前提下,通过配置适配不同语言和地区的使用习惯。SpringBoot 中实现 i18n 的核心依赖是:

  • MessageSource:消息源接口,负责加载和解析多语言消息,默认实现为 ResourceBundleMessageSource(基于配置文件)。
  • Accept-Language:语言地区标识,格式为 语言代码_国家/地区代码,如:
    • 简体中文:zh_CN
    • 繁体中文:zh_TW
    • 英文(美国):en_US
  • LocaleResolver:语言解析器,负责从请求中获取/设置当前 Locale。
  • LocaleChangeInterceptor:语言切换拦截器,用于拦截请求参数实现语言动态切换。

1.2 核心原理

SpringBoot 启动时,MessageSource 会加载指定路径下的多语言配置文件;当业务代码获取国际化消息时,框架会根据当前 Accept-Language 从对应配置文件/数据源中匹配消息键(Key),返回对应的消息值(Value)。

二、方式一:基于配置文件的 i18n 实现

2.1 环境准备

2.1.1 依赖配置

新建 SpringBoot 项目(推荐 2.7.x 或 3.2.x),核心依赖仅需 spring-boot-starter-web,无需额外依赖:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- 可选:简化配置文件编写(.yml) -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation
    

</artifactId>
</dependency>
</dependencies>
2.1.2 目录结构

在 resources 目录下创建 i18n 文件夹,用于存放多语言配置文件,最终目录结构:

resources/
├── application.yml          # 核心配置
└── i18n/                    # 国际化配置文件目录
    ├── messages.properties       # 默认配置(无语言标识)
    ├── messages_zh_CN.properties # 简体中文
    ├── messages_zh_TW.properties # 繁体中文
    └── messages_en_US.properties # 英文

2.2 多语言配置文件编写

2.2.1 命名规则

配置文件命名必须遵循 basename_语言代码_国家代码.properties 规则:

  • basename:自定义前缀(如 messages),需在 application.yml 中配置。
  • 无语言标识的 messages.properties 为默认配置,当匹配不到指定 Locale 的配置时,会使用该文件内容。
2.2.2 配置文件内容
  1. 默认配置(messages.properties):兜底使用,建议与默认语言(简体中文)保持一致
# 通用提示
common.submit=提交
common.cancel=取消
# 用户相关
user.name=用户名
user.age=年龄
# 校验提示
validate.required.id=主键不能为空
validate.required.name=姓名不能为空
  1. 简体中文(messages_zh_CN.properties):
# 通用提示
common.submit=提交
common.cancel=取消
# 用户相关
user.name=用户名
user.age=年龄
# 校验提示
validate.required.id=主键不能为空
validate.required.name=姓名不能为空
  1. 繁体中文(messages_zh_TW.properties):
# 通用提示
common.submit=提交
common.cancel=取消
# 用户相关
user.name=使用者名稱
user.age=年齡
# 校验提示
validate.required.id=主鍵不能為空
validate.required.name=姓名不能為空
  1. 英文(messages_en_US.properties):
# 通用提示
common.submit=Submit
common.cancel=Cancel
# 用户相关
user.name=Username
user.age=Age
# 校验提示
validate.required.id=Primary key cannot be empty
validate.required.name=Name cannot be empty

注意:properties 文件默认编码为 ISO-8859-1,直接写中文会乱码!需将 IDE 的 properties 文件编码设置为 UTF-8(IDEA:Settings → File Encodings → Properties Files → 勾选 Transparent native-to-ascii conversion)。

2.3 SpringBoot 核心配置

在 application.yml 中配置国际化相关参数,指定配置文件路径、默认语言、编码等:

spring:
  # 国际化配置
  messages:
    basename: i18n/messages      # 配置文件路径(无需写.properties 后缀)
    encoding: UTF-8              # 解决中文乱码
    fallback-to-system-locale: false  # 禁用系统语言回退
    default-locale: zh_CN        # 默认语言:简体中文
    cache-duration: 3600s        # 配置文件缓存时间(生产建议设置)
  # Web 配置(可选,用于请求参数解析)
  web:
    locale: zh_CN

2.4 自定义语言解析器与拦截器

默认情况下,SpringBoot 仅支持从请求头 Accept-Language 获取 Locale,为了方便通过请求参数(如 ?Accept-Language=en-US)切换语言,需自定义 LocaleResolver 并注册拦截器。

2.4.1 自定义 LocaleResolver

创建 config/I18nConfig.java,实现 LocaleResolver 接口:

package com.example.i18n.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
import org.springframework.web.servlet.handler.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;

/**
 * 国际化核心配置类(修改为 Header 拦截语言)
 */
@Configuration
public class I18nConfig implements WebMvcConfigurer {

    /**
     * 注册自定义 LocaleResolver(基于 Session 存储 Locale)
     * 替代默认的 AcceptHeaderLocaleResolver
     */
    @Bean
    public LocaleResolver localeResolver() {
        SessionLocaleResolver resolver = new SessionLocaleResolver();
        // 设置默认语言:简体中文(与 application.yml 中保持一致)
        resolver.setDefaultLocale(Locale.SIMPLIFIED_CHINESE);
        return resolver;
    }

    /**
     * 自定义拦截器:从 Accept-Language Header 解析并设置 Locale
     */
    @Bean
    public HandlerInterceptor localeHeaderInterceptor(LocaleResolver localeResolver) {
        return new HandlerInterceptor() {
            @Override
            public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
                // 1. 从请求头中获取语言标识(自定义 Header 名:Accept-Language,可根据需求修改)
                String acceptLanguage = request.getHeader("Accept-Language");
                // 2. 设置默认语言为空或者抛异常使用 Locale locale = Locale.SIMPLIFIED_CHINESE; // 默认语言// 默认:zh_CN
                Locale locale = Locale.SIMPLIFIED_CHINESE;
                // 3. 若 Header 中有值,则解析并设置 Accept-Language;无值则使用默认 Accept-Language
                if (acceptLanguage != null && !acceptLanguage.isEmpty()) {
                    try {
                        // 取第一个语言项(如 "zh-CN,en;q=0.8" → "zh-CN")
                        String primary = acceptLanguage.split(",")[0].trim();
                        // Spring 工具类能正确解析 "zh-CN"、"en" 等格式
                        locale = StringUtils.parseLocale(primary);
                    } catch (Exception e) {
                        // 解析失败则使用默认语言,不抛异常
                    }
                }
                // 使用容器中真实的 LocaleResolver 实例设置 Locale(存入 Session)
                localeResolver.setLocale(request, response, locale);
                return true;
            }
        };
    }

    /**
     * 注册拦截器到 Spring MVC 拦截器链
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(localeHeaderInterceptor(localeResolver()))
                .addPathPatterns("/**")
                .order(0); // 优先级最高
    }
}

关键说明:

  • SessionLocaleResolver:将 Locale 存储在 Session 中,一次切换后,后续请求无需重复传参。
  • localeHeaderInterceptor:拦截请求头 Header 中 Accept-Language 参数,自动更新当前 Locale(如 Accept-Language=zh-TW 会切换为繁体中文)。

2.5 国际化消息使用示例

2.5.1 工具类封装(推荐)

创建 utils/I18nUtils.java,封装获取国际化消息的方法,简化业务使用:

package com.example.i18n.utils;

import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Locale;

/**
 * 国际化工具类
 */
@Component
public class I18nUtils {

    @Resource
    private MessageSource messageSource;

    /**
     * 获取国际化消息(使用当前 Locale)
     * @param key 消息键
     * @return 消息值
     */
    public String getMessage(String key) {
        return getMessage(key, null, LocaleContextHolder.getLocale());
    }

    /**
     * 获取国际化消息(带参数)
     * @param key 消息键
     * @param args 参数数组(如消息为"你好{0}",args=new Object[]{"张三"})
     * @return 消息值
     */
    public String getMessage(String key, Object[] args) {
        return getMessage(key, args, LocaleContextHolder.getLocale());
    }

    /**
     * 手动指定 Locale 获取消息
     * @param key 消息键
     * @param args 参数数组
     * @param locale 语言标识
     * @return 消息值
     */
    public String getMessage(String key, Object[] args, Locale locale) {
        try {
            // 从 MessageSource 中获取消息,若未找到则返回 key 本身
            return messageSource.getMessage(key, args, locale);
        } catch (Exception e) {
            return key;
        }
    }
}

核心 API 说明:

  • LocaleContextHolder.getLocale():获取当前线程的 Locale(由 LocaleResolver 解析)。
  • messageSource.getMessage(key, args, locale):核心方法,参数说明:
    • key:消息键(如 user.name)。
    • args:消息参数(用于替换消息中的占位符,如 user.hello=你好{0})。
    • locale:指定语言标识。
2.5.2 控制器使用示例

创建 controller/I18nController.java,编写接口测试国际化效果:

package com.example.i18n.controller;

import com.example.i18n.utils.I18nUtils;
import org.springframework.web.bind.annotation.

目录

  1. 前言
  2. 一、国际化基础认知
  3. 1.1 核心概念
  4. 1.2 核心原理
  5. 二、方式一:基于配置文件的 i18n 实现
  6. 2.1 环境准备
  7. 2.1.1 依赖配置
  8. 2.1.2 目录结构
  9. 2.2 多语言配置文件编写
  10. 2.2.1 命名规则
  11. 2.2.2 配置文件内容
  12. 通用提示
  13. 用户相关
  14. 校验提示
  15. 通用提示
  16. 用户相关
  17. 校验提示
  18. 通用提示
  19. 用户相关
  20. 校验提示
  21. 通用提示
  22. 用户相关
  23. 校验提示
  24. 2.3 SpringBoot 核心配置
  25. 国际化配置
  26. Web 配置(可选,用于请求参数解析)
  27. 2.4 自定义语言解析器与拦截器
  28. 2.4.1 自定义 LocaleResolver
  29. 2.5 国际化消息使用示例
  30. 2.5.1 工具类封装(推荐)
  31. 2.5.2 控制器使用示例
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Ψ0 人形全身 VLA:基于人类视频与真实机器人数据的预训练与后训练方案
  • AI 办公实战指南:7 套书籍助你精准提效与职场进阶
  • ClawdBot 本地部署:零配置 Telegram AI 翻译机器人
  • 基于 Rokid AR 眼镜的 Android 喝水提醒应用开发
  • RTTR 与模板元编程:现代 C++ 反射技术解析
  • React 前端模拟内存溢出及 Chrome DevTools 内存泄漏排查
  • AI 零基础入门:从概念到实践指南
  • Python 量化入门:AKshare 获取股票基金期货全市场金融数据
  • OpenClaw 开源 AI 智能体框架:架构原理与部署方案
  • Qwen3-VL-WEBUI 部署与 AI 绘画使用指南
  • 使用 wechat-need-web 插件实现浏览器访问微信网页版
  • MCP 实战:利用 Figma AI Bridge 生成前端代码
  • Cogito-v1-preview-llama-3B 实战案例:SQL 生成与 API 文档编写
  • Python 技能变现:兼职实战与自动化办公指南
  • Web 开发中五种核心加密算法实战与原理
  • C++ 拷贝构造函数与赋值运算符重载详解
  • MySQL 索引原理:B+ 树结构与实战优化
  • 嵌入式开发中的 Git CI/CD 实践
  • 被工具定义的编程时代:VS Code 与 JetBrains 效率指南
  • 网络安全行业方向与学习路线详解

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online