Spingboot落地国际化需求,Springboot按照请求的地区返回信息

@TOC

一、国际化

1、概述

国际化(internationalization)是设计和制造领域适应不同区域要求的产品的一种方式。它要求从产品中抽离所有地域语言,国家/地区和文化相关的元素。换言之,应用程序的功能和代码设计考虑在不同地区运行的需要,其代码简化了不同本地版本的生产。开发这样的程序的过程,就称为国际化。

2、Spring国际化

Spring国际化详解,Spring国家化实例及源码详解

二、springboot简单使用国际化

1、定义MessageSource

java 复制代码
/**
 * 国际化相关
 * @return
 */
@Bean
public MessageSource messageSource() {
    ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
    messageSource.setBasename("messages/message");
    messageSource.setDefaultEncoding("UTF-8");
    return messageSource;
}

2、定义message配置文件

bash 复制代码
# message_en.properties
test=meiguo
test2=meiguo{0}

# message_zh.properties
test=中国

3、测试

java 复制代码
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    String message = applicationContext.getMessage("test", null, new Locale("zh"));
    System.out.println(message); // 中国

    String message2 = applicationContext.getMessage("test", null, new Locale("en"));
    System.out.println(message2); // meiguo

	String message3 = applicationContext.getMessage("test2", new String[]{"content"}, new Locale("en"));
    System.out.println(message3); // meiguocontent
}

我们发现,按照不同地区,根据配置文件获取到了不同的配置。

三、根据请求的地区获取信息

1、定义message配置文件

bash 复制代码
# message_en_US.properties
Success={0}success
Test=myTest

# message_zh_CN.properties
Success={0}成message功
Test=我的test内容

2、定义配置类

java 复制代码
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;

@Configuration
public class I18nConfig {

    /**
     * 国际化相关
     */
    @Bean
    public MessageSource messageSource() {
        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
        messageSource.setBasename("messages/message");
        messageSource.setDefaultEncoding("UTF-8");
        return messageSource;
    }
}

3、基础模板工具

java 复制代码
import org.springframework.context.NoSuchMessageException;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.support.RequestContextUtils;

import javax.servlet.http.HttpServletRequest;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

public interface I18nTemplateBase {


    String defaultMessage();

    String name();


    /**
     * 解析国际化模板
     */
    default String resolve(HttpServletRequest request, Object... args) {
        // 先解析参数
        List<Object> argResolveList = new ArrayList<>();
        if (args != null) {
            for (Object arg : args) {
                if (arg instanceof I18nTemplateBase) {
                    I18nTemplateBase i18nTemplateBase = (I18nTemplateBase) arg;
                    try {
                        argResolveList.add(resolveTemplate(request, i18nTemplateBase.name()));
                    } catch (NoSuchMessageException e) {
                        argResolveList.add(i18nTemplateBase.defaultMessage());
                    }
                }
            }
        }


        // 再解析最终的
        String resolveResult;
        try {
            resolveResult = resolveTemplate(request, name(), argResolveList.toArray());
        } catch (NoSuchMessageException e) {
            // 拿不到模板用默认模板
            resolveResult = MessageFormat.format(defaultMessage(), args);
        }
        return resolveResult;

    }


    /**
     * 根据key解析国际化模板
     */
    default String resolveTemplate(HttpServletRequest request, String code, Object... args) {
        Locale locale = RequestContextUtils.getLocale(request);
        WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(request.getServletContext());
        if (context != null) {
            return context.getMessage(String.valueOf(code), args, locale);
        } else {
            throw new NoSuchMessageException("WebApplicationContext not available");
        }
    }
}

4、消息模板定义枚举

java 复制代码
/**
 * 标准国际化消息模板
 */
public enum I18nTemplate implements I18nTemplateBase {

    Success("{0}成功"),
    Error("{0}失败"),

    Data("{0}"),

    // TODO - 定义更多消息模板
    Test("测试结果"),
    ;

    private final String defaultMessage;

    I18nTemplate(String defaultMessage) {
        this.defaultMessage = defaultMessage;
    }

    public String defaultMessage() {
        return defaultMessage;
    }

}

5、测试一下

java 复制代码
@GetMapping("/test1")
public String test1(HttpServletRequest request) {
    // 模板定制 + 参数定制
    String resolve1 = I18nTemplate.Success.resolve(request, I18nTemplate.Test);
    System.out.println(resolve1);

    // 模板定制 + 参数手输
    String resolve2 = I18nTemplate.Error.resolve(request, "手写的参数");
    System.out.println(resolve2);

    // 模板参数都手输
    String resolve3 = I18nTemplate.Data.resolve(request, "手写的参数");
    System.out.println(resolve3);
    return "success";
}
bash 复制代码
请求头:Accept-Language=en-US

结果:
myTestsuccess
手写的参数失败
手写的参数
bash 复制代码
请求头:Accept-Language=zh-CN

结果:
我的test内容成message功
手写的参数失败
手写的参数

可以实现模板消息、默认消息等。

6、总结

我们可以通过Spring的国际化,将每一个国家的语言模板都定义在配置文件中,这样就可以动态的解决数据返回的语言问题了。

真正生产环境还会将消息再进一步封装,配合httpcode码、返回的数据、请求成功状态、消息等等统一进行封装返回。此处就不进行详细分享了。

相关推荐
swipe44 分钟前
Neo4j + Graph RAG 医疗知识图谱工程实践:患者教育问答真正需要的是“关系可追溯”
后端·langchain·llm
源码宝2 小时前
MES系统源码:Java8 + SpringBoot2.7 + MySQL8 + Redis,后端源码清爽易扩展
java·后端·源码·springboot·mes系统·源码二开·mes源码
金銀銅鐵2 小时前
[Java] 如何理解 class 文件中方法的 descriptor?
java·后端
村口张大爷2 小时前
05 — 分层架构与依赖倒置
后端·架构·系统架构
Jasonakeke3 小时前
SpringBoot自动配置原理揭秘
java·spring boot·后端
IT_陈寒4 小时前
Vite热更新失灵?你可能漏了这个配置
前端·人工智能·后端
uzong5 小时前
面试官:如何做好架构设计
后端·架构
Cosolar5 小时前
QwenPaw Agent 实现原理深度剖析
后端·面试·架构
Sincerelyplz5 小时前
【AI会议纪要实践】mapReduce、RAG 与结构化输出
java·后端·agent
zavoryn5 小时前
后端接入 AI Agent:Tool Calling 网关、幂等与审计日志实战
后端·架构