还是直接上代码
目前实现了 中英文 返回 别的语言 都差不多
主要用spring boot 自带的 类实现的 不用引入任何 依赖
使用的就是下面的类
org.springframework.context.MessageSource 是 Spring Framework 中用于支持国际化(Internationalization,简称 i18n)的接口之一。它提供了一种统一的方式来获取文本信息,使得应用程序能够根据不同的语言和区域设置展示对应的文本内容。
具体来说,MessageSource 接口定义了一组方法,可以根据指定的消息代码(message code)和可选的参数获取相应的本地化文本消息。这些消息通常存储在配置文件中,通过配置管理器(如 ApplicationContext)加载并提供给应用程序使用。
在 Spring 应用中,通常会将不同语言版本的文本消息存储在不同的 properties 文件中,然后通过 MessageSource 接口来动态加载并根据当前用户的语言环境提供相应的文本信息,从而实现国际化功能。
第一步 配置文件
package com.xx.init.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
import java.util.Locale;
/**
* User:Json
* Date: 2024/4/20
**/
@Configuration
public class LocaleConfig {
//这里的配置文件 也可以写在 application.yml 中
@Bean
public ResourceBundleMessageSource messageSource() {
Locale.setDefault(Locale.CHINA);
ResourceBundleMessageSource source = new ResourceBundleMessageSource();
//设置国际化文件存储路径和名称
// i18n目录,messages文件名
//Spring Boot 会根据不同的语言环境自动加载对应的资源文件,
// 例如 messages_zh_CN.properties 或 messages_en_US.properties
source.setBasenames("i18n/messages");
//设置根据key如果没有获取到对应的文本信息,则返回key作为信息
source.setUseCodeAsDefaultMessage(true);
//设置字符编码
source.setDefaultEncoding("UTF-8");
return source;
}
}
一般项目 都会装这个插件 不解释了
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
创建中英文配置文件之前 看一下编辑器有没有 设置UTF-8 防止乱码
创建 这个后缀的文件 .properties
中英文:
messages_zh_CN.properties 或 messages_en_US.properties
最后样子
第二步创建 枚举类 定义 项目使用了哪些语言
package com.xx.init.language;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* User:Json
* Date: 2024/4/20
**/
@Getter
@AllArgsConstructor
public enum LanguageEnum {
ZH_CN("zh_CN", "中文/中国"),
EN("en_US", "英语/美国"),
;
/**
* 格式 是 语言_国家 缩写
* 更多国家 java.util.Locale; 可以查看这个类里的
*/
private String name;
/**
* 描述
*/
private String desc;
}
第三步 编写工具类
package com.xx.init.utils;
import cn.hutool.extra.spring.SpringUtil;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.springframework.context.MessageSource;
import org.springframework.util.StringUtils;
import java.util.Locale;
/**
* User:Json
* Date: 2024/4/20
**/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class LanguageUtil {
/**
* 根据key信息获取对应语言的内容
*
* @param key 消息key值
* @param language 语言_国家
* @return
*/
public static String get(String key, String language) {
if (!StringUtils.isEmpty(language)) {
String[] arrs = language.split("_");
if (arrs.length == 2) {
return get(key, new Locale(arrs[0], arrs[1]));
}
}
//使用默认的国际化语言
return get(key, Locale.getDefault());
}
/**
* 根据key信息获取对应语言的内容
*
* @param key 消息key值
* @param params 需要替换到占位符中的参数 占位符下标重0开始 格式如: {0} {1}
* @param language 语言_国家
* @return
*/
public static String get(String key, Object[] params, String language) {
if (!StringUtils.isEmpty(language)) {
String arrs[] = language.split("_");
if (arrs.length == 2) {
return get(key, params, new Locale(arrs[0], arrs[1]));
}
}
return get(key, params, Locale.getDefault());
}
private static String get(String key, Locale language) {
return get(key, new String[0], language);
}
private static String get(String key, Object[] params, Locale language) {
return getInstance().getMessage(key, params, language);
}
private static MessageSource getInstance() {
return Lazy.messageSource;
}
/**
* 使用懒加载方式实例化messageSource国际化工具
*/
private static class Lazy {
private static final MessageSource messageSource = SpringUtil.getBean(MessageSource.class);
}
}
第四步 编写测试配文文件
在中英文配置文件中 写两句 话 {0} 占位符 不需要就不写
第五步 拦截器获取前端 语言类型 这个大家哪获得都行
LanguageType.setLanguage 我定义的存储方式
// 用的是 ThreadLocal 用完 别忘了 释放
//如果ThreadLocal存放的数据不释放,当用户量大的时候会导致系统出现OOM问题
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
LanguageType.setLanguage(StringUtils.isEmpty(request.getHeader("language")) ? LanguageEnum.ZH_CN.getName() : request.getHeader("language"));
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
//会话结束移除线程缓存
LanguageType.removeLanguage();
}
第六步 :ThreadLocal 存储前端发来的 语言类型
package com.xx.init.language;
/**
* User:Json
* Date: 2024/4/20
**/
public class LanguageType{
private static ThreadLocal<String> language = new ThreadLocal<String>();
public static void setLanguage(String lang) {
language.set(lang);
}
public static String getLanguage() {
return language.get();
}
public static void removeLanguage() {
language.remove();
}
}
测试控制器
@GetMapping("index15")
@ApiOperation(value = "中文/英文测试")
@PassToken
public R index15(){
String s = LanguageUtil.get("test",new Object[]{"JAVA"}, LanguageType.getLanguage());
return R.success(s);
}
// LanguageType.getLanguage() 这个方法 我是从 拦截器 请求头里 获取 前端传入的语言类型
// 比如前端传个 zh_CN 就是 中文 en_US 就是英文
// 建议前端传的这个 和 LanguageEnum 枚举类里定义的 一样
// test 就是对应配置文件的 key
结果输出