springBoot3 项目实战国际化
1 创建国际化资源文件
messages.properties (默认)
messages_en_US.properties (英文)
messages_zh_CN.properties (中文)
# {}是参数引用,用于拼接传参
user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定{1}分钟
2 配置 application.yml
spring:
messages:
basename: i18n/messages
encoding: UTF-8
3 维护 i8n 配置类
package com.okyun.framework.config;
@Configuration
public class I18nConfig implements WebMvcConfigurer
{
@Bean
public LocaleResolver localeResolver()
{
SessionLocaleResolver slr = new SessionLocaleResolver();
slr.setDefaultLocale(Constants.DEFAULT_LOCALE);
return slr;
}
@Bean
public LocaleChangeInterceptor localeChangeInterceptor()
{
LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
lci.setParamName("lang");
return lci;
}
@Override
public void addInterceptors(InterceptorRegistry registry)
{
registry.addInterceptor(localeChangeInterceptor());
}
}
4 封装消息工具
package com.okyun.common.utils;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import com.okyun.common.utils.spring.SpringUtils;
public class MessageUtils
{
public static String message(String code, Object... args)
{
MessageSource messageSource = SpringUtils.getBean(MessageSource.class);
return messageSource.getMessage(code, args, LocaleContextHolder.getLocale());
}
}
5 后台业务中使用
AjaxResult.error(MessageUtils.message("user.password.retry.limit.exceed",new Object[] { retryLimitCount, lockTime }))
6 前端切换语言
@GetMapping("/changeLanguage")
public AjaxResult changeLanguage(String lang)
{
return AjaxResult.success();
}
7 特殊国际化处理 - 参数校验注解
@Size(max = 30, message = "编码最大长度30个字符")
@Pattern(regexp = "^[^+-].*", message = "编码不能以 + 或 - 开头")
private String productNo;
# Spring 会自动从 `messages.properties` 加载对应的消息
size.between.valid=长度必须在{min}到{max}个字符之间
size.max.valid=长度不能超过{max}个字符
size.min.valid=长度不能少于{min}个字符
8 特殊国际化处理 - Excel列名
8.1 Excel注解添加i18n字段
package com.okyun.common.annotation;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Excel{
...
public String i18nKey() default "";
...
}
8.2 ExcelUtil 方法添加获取国际化逻辑
package com.okyun.common.utils.poi;
public class ExcelUtil<T>{
...
private static final MessageSource messageSource = SpringUtils.getBean(MessageSource.class);
private String getI18nHeader(Excel excelAttr) {
if (StringUtils.isNotEmpty(excelAttr.i18nKey())) {
return messageSource.getMessage(
excelAttr.i18nKey(),
null,
LocaleContextHolder.getLocale()
);
}
return excelAttr.name();
}
public Cell createHeadCell(Excel attr, Row row, int column){
...
cell.setCellValue(getI18nHeader(attr));
...
}
public Cell addCell(Excel attr, Row row, T vo, Field field, int column){
......
else if (StringUtils.isNotEmpty(dictType) && StringUtils.isNotNull(value)) {
String label = DictUtils.getDictLabel(
dictType,
Convert.toStr(value),
separator,
LocaleContextHolder.getLocale()
);
cell.setCellValue(label);
}
......
}
...
}
8.3 字典数据国际化
package com.okyun.common.utils;
public class DictUtils{
......
public static String getDictLabel(String dictType, String dictValue, String separator, Locale locale) {
String i18nKey = "dict." + dictType + "." + dictValue;
MessageSource messageSource = SpringUtils.getBean(MessageSource.class);
String i18nLabel = messageSource.getMessage(i18nKey, null, null, locale);
if (i18nLabel == null || i18nKey.equals(i18nLabel)) {
return getDictLabel(dictType, dictValue, separator);
}
return i18nLabel;
}
......
}
8.4 项目实战中使用
8.4.1 @Excel注解
@Excel(name = "商品状态", dictType = "product_status", i18nKey = "product.product.status")
private Integer productStatus;
@Excel(name = "编码", i18nKey = "product.product.code")
private String productNo;
8.4.2 维护映射文件
product.product.code=商品编码
product.product.status=商品状态
dict.product_status.0=启售
dict.product_status.1=停售