springboot国家化多语言实现

发布于:2025-05-08 ⋅ 阅读:(13) ⋅ 点赞:(0)

前言

公司在做国际化项目时需要匹配多语言环境,通过spring实现i18n国际化方便快捷

项目结构

src/
├── main/
│   ├── java/
│   │   └── com/example/i18ndemo/
│   │       ├── config/       # 配置类
│   │       ├── controller/   # 控制器
│   │       ├── service/      # 服务层
│   │       └── I18nDemoApplication.java # 启动类
│   └── resources/
│       ├── static/           # 静态资源
│       ├── templates/        # 模板文件
│       ├── messages.properties      # 默认语言文件
│       ├── messages_en.properties   # 英文
│       ├── messages_zh_CN.properties # 中文
│       └── application.properties   # 应用配置
└── test/                     # 测试代码

创建springboot项目

创建一个springboot项目。项目名称是I18nDemo

添加maven依赖

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.5</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- Thymeleaf (可选,用于前端模板) -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <!-- 验证支持 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

初始化语言文件

在 resources 目录下创建以下文件:

messages.properties (默认)

welcome.message=Welcome
user.greeting=Hello, {0}
login.title=Login

messages_zh_CN.properties

welcome.message=欢迎
user.greeting=你好, {0}
login.title=登录

messages_ja.properties

welcome.message=ようこそ
user.greeting=こんにちは, {0}
login.title=ログイン

配置国际化支持

应用配置 (application.properties)

# 国际化配置
spring.messages.basename=messages
spring.messages.encoding=UTF-8
spring.messages.fallback-to-system-locale=false

# Thymeleaf 配置 (如果使用)
spring.thymeleaf.cache=false
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.thymeleaf.mode=HTML
spring.thymeleaf.encoding=UTF-8

创建配置类

普通的配置类支持通过url参数切换语言

package com.example.i18ndemo.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.LocaleChangeInterceptor;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;

import java.util.Locale;

@Configuration
public class I18nConfig implements WebMvcConfigurer {

    @Bean
    public LocaleResolver localeResolver() {
        SessionLocaleResolver slr = new SessionLocaleResolver();
        slr.setDefaultLocale(Locale.ENGLISH); // 设置默认语言
        return slr;
    }

    @Bean
    public LocaleChangeInterceptor localeChangeInterceptor() {
        LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
        lci.setParamName("lang"); // 通过URL参数切换语言
        return lci;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(localeChangeInterceptor());
    }
}

优化过的配置类,支持通过url和head传递国际化参数,推荐使用head方便快捷

此种方式传递中文的时候需要用zh-CN

  • Spring的 LocaleContextHolder 能自动处理 zh_CN 和 zh-CN

  • 但底层 Locale.forLanguageTag() 仍然要求标准格式

  • 如果前端传的是zh_CN,则后端可以直接替换下

    localeStr = localeStr.replace('_', '-');

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.LocaleChangeInterceptor;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;

@Configuration
public class I18nConfig implements WebMvcConfigurer {

    @Bean
    public LocaleResolver localeResolver() {
        SmartLocaleResolver resolver = new SmartLocaleResolver();
        resolver.setDefaultLocale(Locale.ENGLISH);
        return resolver;
    }

    public class SmartLocaleResolver implements LocaleResolver {

        private Locale defaultLocale = Locale.ENGLISH;

        @Override
        public Locale resolveLocale(HttpServletRequest request) {
            // 1. 优先检查 URL 参数(如 ?lang=zh_CN)
            String langParam = request.getParameter("lang");
            if (langParam != null && !langParam.isEmpty()) {
                return Locale.forLanguageTag(langParam);
            }

            // 2. 如果没有 URL 参数,检查 Accept-Language 头
            String acceptLanguage = request.getHeader("Accept-Language");
            if (acceptLanguage != null && !acceptLanguage.isEmpty()) {
                return request.getLocale();
            }

            // 3. 返回默认语言
            return defaultLocale;
        }

        @Override
        public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
            // 如果需要动态修改语言,可以在这里实现
        }

        public void setDefaultLocale(Locale defaultLocale) {
            this.defaultLocale = defaultLocale;
        }
    }
}

创建测试控制器

package com.example.i18ndemo.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import java.util.Locale;

@Controller
public class HomeController {

    private final MessageSource messageSource;

    @Autowired
    public HomeController(MessageSource messageSource) {
        this.messageSource = messageSource;
    }

    @GetMapping("/")
    public String home(Model model) {
        // 通过代码获取消息
        String welcomeMsg = messageSource.getMessage(
            "welcome.message", 
            null, 
            LocaleContextHolder.getLocale()
        );
        
        model.addAttribute("welcomeMsg", welcomeMsg);
        return "home";
    }
}

创建 Thymeleaf 模板

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title th:text="#{login.title}">Login</title>
</head>
<body>
    <h1 th:text="${welcomeMsg}">Welcome</h1>
    
    <!-- 直接使用消息 -->
    <p th:text="#{user.greeting('John')}">Hello, User</p>
    
    <!-- 语言切换链接 -->
    <div>
        <a href="?lang=en">English</a> | 
        <a href="?lang=zh-CN">中文</a> | 
        <a href="?lang=ja">日本語</a>
    </div>
</body>
</html>

运行项目

  1. 启动主类 I18nDemoApplication

  2. 访问 http://localhost:8080

  3. 点击不同语言链接测试切换功能

扩展建议

  1. 数据库存储消息:对于大型项目,可以实现 MessageSource 接口从数据库加载消息

  2. 前端框架集成:如果使用 Vue/React,可以创建 API 端点返回语言包

  3. 自动化测试:编写测试验证所有语言包是否完整

  4. 本地化日期/数字:使用 Spring 的 Formatter 体系实现

这样你就完成了一个基本的支持国际化的 Spring Boot 项目!


网站公告

今日签到

点亮在社区的每一天
去签到