介绍
Spring Boot通过MessageSource接口来实现国际化,它可以加载不同的消息资源文件,通常是.properties格式。通过定义不同的语言文件(例如:messages_en.properties、messages_zh.properties等),可以根据用户的语言环境来自动选择对应的文件,提供不同的翻译和文本来实现业务的国际化操作。
效果
英文
java
{
"msg": "success",
"code": 200,
"data": null
}
中文
java
{
"msg": "操作成功",
"code": 200,
"data": null
}
其他语言也可以自行配置
配置文件
yml
spring:
messages:
# 国际化资源文件路径
basename: i18n/messages

messages表示匹配以messages开头的文件
创建语言文件
message.properties
公共的语言文件
yml
system.error.tip=请联系管理员操作
messages_en_US.properties
英文语言文件
yml
system.user.tip.name=Please enter the user name
system.user.tip.password=Please enter the user password
messages_zh_CN.properties
中文语言文件
yml
system.user.tip.name=请输入用户名
system.user.tip.password=请输入用户密码
多语言情况下请保持语言文件的格式和字段
拦截器配置
这个拦截器主要识别前端传递的语言字符串并根据字符串返回对应的语言
java
/**
* 该类是一个自定义的拦截器,用于从HTTP请求的头部获取语言参数,并根据该参数设置当前请求的语言。
* 它继承自Spring的`LocaleChangeInterceptor`,并重写了`preHandle`方法来实现自定义的语言切换逻辑。
*/
public class CustomLocaleChangeInterceptor extends LocaleChangeInterceptor {
// 设置请求头中获取语言的字段名
private static final String LANG_HEADER = "lang";
/**
* 这个方法会在每个请求处理之前被调用,用来获取请求头中的语言设置,
* 如果存在有效的语言参数,就会设置当前请求的语言环境。
* @param request 当前的HTTP请求对象
* @param response 当前的HTTP响应对象
* @param handler 当前请求的处理器(一般是控制器方法)
* @return 如果返回true,表示继续执行后续的处理器链,否则会中断请求的处理
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// 从请求头中获取指定的语言字段("lang")
String lang = request.getHeader(LANG_HEADER);
// 如果lang参数存在且不为空
if (lang != null && !lang.isEmpty()) {
// 按照"-"分割语言和地区信息
String[] parts = lang.split("_");
// 设置语言环境
// parts[0]是语言(例如:en、zh)
// parts[1]是地区(例如:US、CN),如果没有地区则使用空字符串
LocaleContextHolder.setLocale(new Locale(parts[0], parts.length > 1 ? parts[1] : ""));
}
// 返回true放行
return true;
}
}
还有一种方法可以从浏览器自带的:Accept-Language:zh-CN,zh;q=0.9 来获取但是各浏览器的参数有所不同所以没采用,好处就是可以自动识别用户的语言。
I18n配置类
java
/**
* 资源文件配置加载
* 该配置类用于设置国际化资源文件的加载和管理。它配置了语言环境解析器以及自定义的拦截器。
* 通过此配置,Spring Web应用能够根据用户的请求来切换不同的语言环境(Locale)。
*/
@Configuration
public class I18nConfig implements WebMvcConfigurer {
/**
* 定义一个 LocaleResolver bean,用于处理当前用户会话中的语言环境。
*
* LocaleResolver 用于解析当前请求的语言环境,通常会根据Session中的信息来判断。
* 在这里我们使用的是 SessionLocaleResolver,它会将用户选择的语言存储在Session中,
* 这样用户在后续请求中可以保持相同的语言环境。
*
* @return 返回配置好的 LocaleResolver
*/
@Bean
public LocaleResolver localeResolver() {
// 创建一个 SessionLocaleResolver 实例
SessionLocaleResolver slr = new SessionLocaleResolver();
// 设置默认的语言环境为简体中文 (zh_CN)
// 当用户没有明确设置语言时,应用默认使用简体中文
slr.setDefaultLocale(Locale.SIMPLIFIED_CHINESE);
return slr;
}
/**
* 配置国际化拦截器,用于监听用户请求中的语言切换参数。
*
* 该方法会添加一个自定义的拦截器 CustomLocaleChangeInterceptor,目的是监听用户请求中的语言切换请求,
* 并更新当前会话的语言环境。
*
* @param registry 拦截器注册器
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册自定义的语言环境切换拦截器
// 该拦截器会监听请求中是否包含语言参数(例如:?lang=zh_CN),
// 如果有,就会根据该参数改变当前用户的语言环境。
registry.addInterceptor(new CustomLocaleChangeInterceptor());
}
}
封装Bean工具类
该代码来着若依管理系统
java
/**
* spring工具类,方便在非Spring管理环境中获取bean
* 提供一些用于获取Spring上下文中的Bean,环境配置,AOP代理对象等功能的方法。
* 该类实现了 BeanFactoryPostProcessor 和 ApplicationContextAware 接口,
* 用于在非Spring管理环境中操作Spring容器中的bean。
*
* @author ruoyi
*/
@Component
public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware
{
/** Spring应用上下文环境的BeanFactory */
private static ConfigurableListableBeanFactory beanFactory;
/** Spring应用上下文环境 */
private static ApplicationContext applicationContext;
/**
* 实现 BeanFactoryPostProcessor 接口的 postProcessBeanFactory 方法
* 用于在Spring容器启动时获取Spring容器中的BeanFactory。
*
* @param beanFactory Spring的BeanFactory
* @throws BeansException 如果发生异常
*/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
{
SpringUtils.beanFactory = beanFactory; // 保存 BeanFactory 实例
}
/**
* 实现 ApplicationContextAware 接口的 setApplicationContext 方法
* 用于在Spring容器启动时获取Spring应用上下文环境。
*
* @param applicationContext Spring的应用上下文
* @throws BeansException 如果发生异常
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
{
SpringUtils.applicationContext = applicationContext; // 保存应用上下文实例
}
/**
* 根据bean名称获取Spring容器中的Bean实例
*
* @param name bean的名称
* @return 返回与给定名称相对应的bean实例
* @throws org.springframework.beans.BeansException 如果没有找到bean实例
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) throws BeansException
{
return (T) beanFactory.getBean(name); // 获取bean
}
/**
* 根据给定的bean类型获取Spring容器中的Bean实例
*
* @param clz bean的类型
* @return 返回与给定类型相对应的bean实例
* @throws org.springframework.beans.BeansException 如果没有找到bean实例
*/
public static <T> T getBean(Class<T> clz) throws BeansException
{
T result = (T) beanFactory.getBean(clz); // 根据类型获取bean
return result;
}
/**
* 检查BeanFactory中是否包含指定名称的Bean定义
*
* @param name bean的名称
* @return 如果包含该bean,返回true,否则返回false
*/
public static boolean containsBean(String name)
{
return beanFactory.containsBean(name); // 检查bean是否存在
}
/**
* 判断指定名称的bean是singleton类型还是prototype类型
* 如果指定名称的bean没有定义,将抛出NoSuchBeanDefinitionException异常。
*
* @param name bean的名称
* @return 如果是singleton类型返回true,prototype类型返回false
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException 如果没有找到该bean
*/
public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException
{
return beanFactory.isSingleton(name); // 判断bean类型
}
/**
* 获取指定名称bean的类型
* 如果没有找到bean,将抛出NoSuchBeanDefinitionException异常。
*
* @param name bean的名称
* @return 返回指定bean的类型
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException 如果没有找到该bean
*/
public static Class<?> getType(String name) throws NoSuchBeanDefinitionException
{
return beanFactory.getType(name); // 获取bean的类型
}
/**
* 获取指定名称bean的别名
* 如果该bean有别名,则返回所有别名,否则返回空数组。
*
* @param name bean的名称
* @return 返回该bean的所有别名
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException 如果没有找到该bean
*/
public static String[] getAliases(String name) throws NoSuchBeanDefinitionException
{
return beanFactory.getAliases(name); // 获取bean的别名
}
/**
* 获取当前bean的AOP代理对象
* 通过AOP上下文获取代理对象,并返回代理对象或原始bean实例。
*
* @param invoker 需要代理的bean实例
* @return 返回代理对象或者原始对象
*/
@SuppressWarnings("unchecked")
public static <T> T getAopProxy(T invoker)
{
Object proxy = AopContext.currentProxy(); // 获取当前的AOP代理
if (((Advised) proxy).getTargetSource().getTargetClass() == invoker.getClass())
{
return (T) proxy; // 如果是代理类,返回代理对象
}
return invoker; // 否则返回原始对象
}
/**
* 获取当前的激活环境配置
* 如果有多个激活环境配置,返回所有的配置。
*
* @return 返回当前的所有激活环境配置
*/
public static String[] getActiveProfiles()
{
return applicationContext.getEnvironment().getActiveProfiles(); // 获取当前环境配置
}
/**
* 获取配置文件中的某个key对应的值
* 从环境配置中获取指定的属性值,如果没有找到该key,会抛出异常。
*
* @param key 配置文件中的key
* @return 返回配置文件中指定key对应的值
*/
public static String getRequiredProperty(String key)
{
return applicationContext.getEnvironment().getRequiredProperty(key); // 获取配置项的值
}
}
封装语言工具类
java
/**
* 获取i18n资源文件
*/
public class MessageUtils
{
/**
* 根据消息键和参数 获取消息 委托给spring messageSource
*
* @param code 消息键
* @param args 参数
* @return 获取国际化翻译值
*/
public static String message(String code, Object... args)
{
MessageSource messageSource = SpringUtils.getBean(MessageSource.class);
return messageSource.getMessage(code, args, LocaleContextHolder.getLocale());
}
}
接口使用
java
@RequestMapping("/user")
public R user() {
return R.success(I18NUtils.message("system.user.tip.name"));
}
前端请求
lang:en_US
返回英文
lang:zh_CN
返回中文
在请求头中携带
传入参数
语言文件
system.user.tip.name=请输入用户名:{0}
后端使用
java
System.out.println(I18NUtils.message("system.user.tip.name","admin"));
输出结果
java
请输入用户名:admin