Java实现语言环境的适配
定义表结构
- language.sql
CREATE TABLE "pig"."language" (
"id" int8 NOT NULL DEFAULT nextval('"pig".language_id_seq'::regclass),
"language" varchar(20) COLLATE "pg_catalog"."default" NOT NULL,
"language_key" varchar(255) COLLATE "pg_catalog"."default",
"language_value" varchar(255) COLLATE "pg_catalog"."default" NOT NULL,
"status" int2 NOT NULL DEFAULT 1,
"create_time" timestamp(6) DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "language_pkey" PRIMARY KEY ("id"),
CONSTRAINT "idx_language" UNIQUE ("language", "language_key")
)
;
ALTER TABLE "pig"."language"
OWNER TO "cloud_dev_pg";
COMMENT ON COLUMN "pig"."language"."language" IS '语言类型';
COMMENT ON COLUMN "pig"."language"."language_key" IS '词条';
COMMENT ON COLUMN "pig"."language"."language_value" IS '对应语言的文字内容';
COMMENT ON COLUMN "pig"."language"."status" IS '状态【 0:无效、1:有效】 ';
COMMENT ON TABLE "pig"."language" IS '国际化语言表';
- LanguageController
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/language")
@Tag(name = "国际化信息模块")
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class LanguageController {
private final LanguageService languageService;
private final int status = 1;
@PostMapping("/add")
public R<Boolean> addLanguageMess(@RequestBody LanguageDTO languageDTO) {
languageDTO.setStatus(status);
languageDTO.setCreateTime(new Date());
return languageService.addLanguageMess(languageDTO);
}
@DeleteMapping("/delete")
public R<Boolean> deleteLanguageMess(@RequestParam Long id) {
LanguageDTO languageDTO = new LanguageDTO();
languageDTO.setId(id);
return languageService.deleteLanguageMess(languageDTO);
}
@PutMapping("/edit")
public R<Boolean> editLanguageMess(@RequestBody LanguageDTO languageDTO) {
return languageService.editLanguageMess(languageDTO);
}
@PostMapping("/select")
public R<Page<LanguageVO>> selectLanguageMessByPage(@RequestParam int current, @RequestParam int size, @RequestBody LanguageDTO languageDTO) {
Page<LanguageVO> pageR = languageService.selectLanguageMessByPage(current, size, languageDTO);
return R.ok(pageR);
}
@SysLog(module = LogMoudleConstants.LANGUAGE_MANAGEMENT, value = "清除国际化缓存")
@DeleteMapping("/cache")
public R clearLanguageCache() {
languageService.clearLanguageCache();
return R.ok();
}
@Inner
@GetMapping("/selectByLanguageAndKey")
public R<Language> selectByLanguageAndKey(@RequestParam(value = "language") String language, @RequestParam(value = "key") String key) {
Language languageVo = languageService.selectByLanguageAndKey(language, key);
if (languageVo != null){
return R.ok(languageVo);
}
return R.failed();
}
@Inner
@GetMapping("/selectByLanguageAndValue")
public R<Language> selectByLanguageAndValue(@RequestParam(value = "language") String language, @RequestParam(value = "value") String value) {
Language languageVo = languageService.selectByLanguageAndValue(language, value);
if (languageVo != null){
return R.ok(languageVo);
}
return R.failed();
}
}
- LanguageServiceImpl.java
@Slf4j
@Service
@RequiredArgsConstructor
public class LanguageServiceImpl extends ServiceImpl<LanguageMapper, Language> implements LanguageService {
private final LanguageMapper languageMapper;
//添加
@Override
public R<Boolean> addLanguageMess(LanguageDTO languageDTO) {
int count = languageMapper.selectCount(languageDTO);
if (count > 0) {
throw new AioException(SystemErrorEnum.EXIST_I18N_MESSAGE);
}
Boolean addBoolean = languageMapper.addLanguageMess(languageDTO);
return R.ok(addBoolean);
}
//删除
@Override
public R<Boolean> deleteLanguageMess(LanguageDTO languageDTO) {
Language language = languageMapper.selectById(languageDTO.getId());
if (language != null) {
Boolean deleteBoolean = languageMapper.deleteLanguageMess(languageDTO);
return R.ok(deleteBoolean);
}
throw new AioException(SystemErrorEnum.NOT_EXIST_I18N_MESSAGE);
}
//编辑
@Override
public R<Boolean> editLanguageMess(LanguageDTO languageDTO) {
if (languageDTO.getId() != null) {
Language language = languageMapper.selectById(languageDTO.getId());
if (language != null) {
int count = languageMapper.selectCount(languageDTO);
if (count > 0) {
throw new AioException(SystemErrorEnum.EXIST_I18N_MESSAGE);
}
Boolean editBoolean = languageMapper.editLanguageMess(languageDTO);
return R.ok(editBoolean);
}
throw new AioException(SystemErrorEnum.NOT_EXIST_I18N_MESSAGE);
} else {
throw new AioException(SystemErrorEnum.NOT_EXIST_I18N_MESSAGE);
}
}
//分页查询
@Override
public Page<LanguageVO> selectLanguageMessByPage(int current, int size, LanguageDTO languageDTO) {
Page<Language> languagePage = new Page<>(current, size);
LambdaQueryWrapper<Language> languageDTOLambdaQueryWrapper = Wrappers.lambdaQuery(Language.class);
languageDTOLambdaQueryWrapper.like(StringUtils.isNotEmpty(languageDTO.getKeyword()), Language::getLanguageKey, languageDTO.getKeyword()).or()
.like(StringUtils.isNotEmpty(languageDTO.getKeyword()), Language::getLanguageValue, languageDTO.getKeyword()).orderByDesc(Language::getCreateTime);
Page<Language> page = languageMapper.selectPage(languagePage, languageDTOLambdaQueryWrapper);
List<LanguageVO> records = page.getRecords()
.stream()
.map(data -> BeanUtil.copyProperties(data, LanguageVO.class))
.collect(Collectors.toList());
Page<LanguageVO> languageVOPage = new Page<>();
languageVOPage.setRecords(records);
languageVOPage.setSize(page.getSize());
languageVOPage.setCurrent(page.getCurrent());
languageVOPage.setTotal(page.getTotal());
return languageVOPage;
}
@Override
public Language selectByLanguageAndValue(String language, String value) {
LambdaQueryWrapper<Language> queryWrapper = Wrappers.lambdaQuery(Language.class);
queryWrapper.eq(Language::getLanguage, language)
.eq(Language::getLanguageValue, value);
List<Language> languages = baseMapper.selectList(queryWrapper);
if (CollectionUtil.isNotEmpty(languages)){
return languages.get(0);
}
return null;
}
@Override
public Language selectByLanguageAndKey(String language, String key) {
LambdaQueryWrapper<Language> queryWrapper = Wrappers.lambdaQuery(Language.class);
queryWrapper.eq(Language::getLanguage, language)
.eq(Language::getLanguageKey, key);
List<Language> languages = baseMapper.selectList(queryWrapper);
if (CollectionUtil.isNotEmpty(languages)){
return languages.get(0);
}
return null;
}
//清除缓存
@Override
@CacheEvict(value = {CacheConstants.LANGUAGE}, allEntries = true)
public void clearLanguageCache() {
}
}
定义系统错误码
- SystemCodeContant.java
public interface SystemCodeContant {
// 业务平台
String AIO_CLOUD = "10";
// 系统管理
String SYSTEM = AIO_CLOUD + "01";
// 其他
String OTHER = AIO_CLOUD + "99";
}
- EventErrorEnum.java
public enum EventErrorEnum implements IErrorCode {
//名称已存在
RULE_NAME_EXIST("000001"),
//数据源不能为空
ALARM_SOURCE_NOT_NULL("000002"),
;
EventErrorEnum(String code) {
this.code = code;
}
private String code;
@Override
public String getCode() {
return SystemCodeContant.SYSTEM + this.code;
}
@Override
public String getI18nMessage(Object... args) {
return MsgUtils.getDynamicMessage(getCode(), args);
}
}
定义资源i18n
配置目录
src/main/resources/i18n/messages.properties
src/main/resources/i18n/messages_en.properties
src/main/resources/i18n/messages_zh_CN.properties
内容配置
messages.properties
1004000001=rule name exist!
1004000002=alarm source not null!
1004000003=device has already bound organization {0} with the name of the alarm rule {1}!!
messages_en.properties
1004000001=rule name exist!
1004000002=alarm source not null!
1004000003=device has already bound organization {0} with the name of the alarm rule {1}!!
messages_zh_CN.properties
1004000001=名称已经存在,不允许重复!
1004000002=类型不能为空!
1004000003=关联设备已经绑定{0}相应配置了,名称为{1}的配置了!
定义业务类
- ILanguageService.java
public interface ILanguageService {
/**
* @param language 语种
* @author: kele
* @desc:
*/
void cacheData(String language);
/**
* @param key 词条
* @author: kele
* @desc: 根据词条和语言返回该语种的具体释义
*/
String getValueByKey(String key);
/**
* @author: kele
* @desc:
*/
void cleanCache();
}
- LanguageServiceImpl.java
@Slf4j
@RequiredArgsConstructor
public class LanguageServiceImpl implements ILanguageService {
private static final String LANGUAGE_KEY = "language_key";
private static final String LANGUAGE_VALUE = "language_value";
private static final String LANGUAGE_SQL = String.format("select %s,%s from pig.language where language = ? AND status = 1", LANGUAGE_KEY, LANGUAGE_VALUE);
private final DataSource dataSource;
private final ValueOperations<String, String> valueOperations;
private static ThreadLocal<JSONObject> localLanguage = new TransmittableThreadLocal<>();
@Override
public void cacheData(String language) {
//缓存对象注入为空,直接查库
if (valueOperations == null) {
localLanguage.set(JSON.parseObject(JSON.toJSONString(selectI18nData(language))));
return;
}
//查询缓存中是否已经有该语种的值
String value = valueOperations.get(String.format(CacheConstants.LANGUAGE_REDIS_KEY, language));
if (value != null) {
localLanguage.set(JSON.parseObject(value));
return;
}
//缓存中不存在该语种的值,去数据库查询
JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(selectI18nData(language)));
valueOperations.set(String.format(CacheConstants.LANGUAGE_REDIS_KEY, language), jsonObject.toJSONString());
localLanguage.set(jsonObject);
}
@Override
public String getValueByKey(String key) {
//缓存对象注入为空,直接查库
return localLanguage.get().getString(key);
}
@Override
public void cleanCache() {
localLanguage.remove();
}
/**
* @param language 语种
* @author: kele
* @desc: 查询该语种的国际化数据
*/
private Map<String, String> selectI18nData(String language) {
Map<String, String> result = new HashMap<>();
if (StringUtils.isEmpty(language)) {
return result;
}
Connection connection = null;
try {
//获取连接对象
connection = dataSource.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(LANGUAGE_SQL);
//设置语种
preparedStatement.setString(1, language);
ResultSet executeQuery = preparedStatement.executeQuery();
//循环取返回值
while (executeQuery.next()) {
result.put(executeQuery.getString(LANGUAGE_KEY), executeQuery.getString(LANGUAGE_VALUE));
}
} catch (Exception e) {
log.error("查询数据库失败", e);
} finally {
if (connection != null) {
try {
boolean closed = connection.isClosed();
if (!closed) {
connection.close();
}
} catch (Exception e) {
log.error("关闭连接异常", e);
}
}
}
return result;
}
}
定义处理注解
- DatabaseI18n.java
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DatabaseI18n {
/**
* 是否AOP统一处理
* @return false, true
*/
boolean value() default true;
/**
* @author: kele
* @desc: 有中文需要翻译
*/
boolean containsChinese() default false;
}
定义处理注解切面
- DatabaseI18nAspect.java
/**
* @author kele
* @description 数据国际化统一处理
*/
@Slf4j
@Aspect
@RequiredArgsConstructor
public class DatabaseI18nAspect {
private final ILanguageService iLanguageService;
@Around("@within(databaseI18n) || @annotation(databaseI18n)")
public Object around(ProceedingJoinPoint point, DatabaseI18n databaseI18n) throws Throwable {
// 实际注入的databaseI18n实体由表达式后一个注解决定,即是方法上的@DatabaseI18n注解实体,若方法上无@DatabaseI18n注解,则获取类上的
Object proceed = point.proceed();
try {
if (databaseI18n == null) {
Class<?> clazz = point.getTarget().getClass();
databaseI18n = AnnotationUtils.findAnnotation(clazz, DatabaseI18n.class);
}
//翻译业务类未注入,未获取到注解,返回值为空 直接返回不进行返回值解析
if (iLanguageService == null || databaseI18n == null || !databaseI18n.value() || proceed == null) {
return proceed;
}
//内部接口直接返回
if (innerRequest()) {
return proceed;
}
String requestLocalLanguage = RequestUtil.getRequestLocalLanguage();
//没有请求域或请求域没有指定语言的不翻译
if (requestLocalLanguage == null) {
return proceed;
}
iLanguageService.cacheData(requestLocalLanguage);
//判断是否是导出接口,导出接口数据必须保持原始的数据模型,不能转为JSON
try {
Class<?>[] parameterTypes = ((MethodSignature) point.getSignature()).getParameterTypes();
Method method = point.getTarget().getClass().getDeclaredMethod(point.getSignature().getName(), parameterTypes);
ResponseExcel responseExcel = AnnotationUtils.findAnnotation(method, ResponseExcel.class);
if (responseExcel != null) {
//导出的数据都是list 并且里面都是简单的数据模型
for (Object listDatum : (List) proceed) {
for (Field declaredField : listDatum.getClass().getDeclaredFields()) {
declaredField.setAccessible(true);
Object oldData = declaredField.get(listDatum);
//只有字符串需要进行国际化
Object i18nData = getI18nData(oldData, databaseI18n);
declaredField.set(listDatum, i18nData);
}
}
return proceed;
}
} catch (Exception e) {
log.error("判断是否导出接口异常", e);
}
//返回对象是否进行了包装 ,如果包装了获取其data值
try {
if (proceed instanceof R) {
R processR = (R) proceed;
Object processData = handleProcessData(processR.getData(), databaseI18n);
//由于返回值的模型不固定,统一进行了json替换,并非对象上进行修改,所以需要将新值赋予返回值对象
processR.setData(processData);
proceed = processR;
} else {
proceed = handleProcessData(proceed, databaseI18n);
}
} catch (Exception e) {
log.error("数据国际化失败", e);
}
return proceed;
} finally {
if (iLanguageService != null) {
iLanguageService.cleanCache();
}
}
}
private Object handleProcessData(Object proceed, DatabaseI18n databaseI18n) {
if (proceed == null) return proceed;
//简单类型直接返回
if (ClassUtil.isSimpleValueType(proceed.getClass())) {
return proceed;
}
//只处理数据记录
if (proceed instanceof IPage) {
IPage page = (IPage) proceed;
List processData = (List)handleProcessData(page.getRecords(), databaseI18n);
page.setRecords(processData);
return page;
}
//需要进行类型判断 否则不知道数据为列表还是对象
if (proceed instanceof List) {
JSONArray jsonArray = JSON.parseArray(JSON.toJSONStringWithDateFormat(proceed, JSON.DEFFAULT_DATE_FORMAT));
handleDataToI18n(jsonArray, databaseI18n);
return jsonArray;
} else {
JSONObject jsonObject = JSON.parseObject(JSON.toJSONStringWithDateFormat(proceed, JSON.DEFFAULT_DATE_FORMAT));
handleDataToI18n(jsonObject, databaseI18n);
return jsonObject;
}
}
private void handleDataToI18n(Object object, DatabaseI18n databaseI18n) {
//数据为空直接返回
if (object == null) return;
//数据为列表递归调用
if (object instanceof JSONArray) {
JSONArray jsonArray = (JSONArray) object;
jsonArray.forEach(data -> handleDataToI18n(data, databaseI18n));
return;
}
if (object instanceof JSONObject) {
JSONObject jsonObject = (JSONObject) object;
for (String key : jsonObject.keySet()) {
Object oldData = jsonObject.get(key);
//对象里面的属性为列表,递归调用
if (oldData instanceof JSONArray) {
//如果列表里面存在简单类型,需要替换返回值
long count = ((JSONArray) oldData).stream().filter(data -> ClassUtil.isSimpleValueType(data.getClass())).count();
if (count > 0) {
List<Object> list = ((JSONArray) oldData).stream().map(data -> {
if (data instanceof String) {
return getI18nData(data, databaseI18n);
} else {
handleDataToI18n(data, databaseI18n);
return data;
}
}).collect(Collectors.toList());
jsonObject.put(key, JSON.parseArray(JSON.toJSONString(list)));
} else {
handleDataToI18n(oldData, databaseI18n);
}
continue;
}
//属性值仍为对象,递归遍历
if (oldData instanceof JSONObject) {
handleDataToI18n(oldData, databaseI18n);
continue;
}
//替换词条为国际化数据
jsonObject.put(key, getI18nData(oldData, databaseI18n));
}
}
}
public Object getI18nData(Object oldData, DatabaseI18n databaseI18n) {
//非字符串的数据不进行国际化
if (!(oldData instanceof String)) {
return oldData;
}
String oldDataStr = String.valueOf(oldData);
String value = null;
if (databaseI18n.containsChinese() || oldDataStr.contains(StrUtil.DOT)) {
value = iLanguageService.getValueByKey(oldDataStr);
}
//根据词条和语言进行词条翻译
return value == null ? oldData : value;
}
/**
* @author: kele
* @desc: 是否内部请求
*/
private boolean innerRequest() {
HttpServletRequest request = RequestUtil.getRequest();
if (request == null) return false;
return StrUtil.isEmpty(request.getHeader(HttpHeaders.ACCEPT_LANGUAGE));
}
}
定义处理注解切面使用
- AioI18nAutoConfigration.java
/**
* @author kele
* @description
*/
public class AioI18nAutoConfigration {
@Bean
@ConditionalOnBean({DataSource.class})
public ILanguageService iLanguageService(DataSource dataSource, @Autowired(required = false) ValueOperations valueOperations) {
return new LanguageServiceImpl(dataSource, valueOperations);
}
@Bean
@ConditionalOnBean(ILanguageService.class)
public DatabaseI18nAspect databaseI18nAspect(ILanguageService iLanguageService) {
SerializeConfig serializeConfig = SerializeConfig.globalInstance;
serializeConfig.put(Long.class, ToStringSerializer.instance);
return new DatabaseI18nAspect(iLanguageService);
}
@Bean
@ConditionalOnBean(ILanguageService.class)
public AioI18nHeaderHandler aioI18nHeaderHandler(MessageSource messageSource, ILanguageService iLanguageService) {
return new AioI18nHeaderHandler(messageSource, iLanguageService);
}
}
国际化使用
Controller生效
@DatabaseI18n
public class AlarmTypeNotifyTemplateController {}
Controller下的方法生效
@GetMapping("/key/{key}")
@DatabaseI18n
public R<List<SysDictItem>> getDictByKey(@PathVariable String key) {
return R.ok();
}
Controller下的方法不生效
@GetMapping("/key/{key}")
@DatabaseI18n(value = false)
public R<List<SysDictItem>> getDictByKey(@PathVariable String key) {
return R.ok();
}
方法类单个生效使用
- 使用方式
@Resource
private ILanguageService iLanguageService;
GetMapping("/key/{key}")
@DatabaseI18n(value = false)
public R<List<SysDictItem>> getDictByKey(@PathVariable String key) {
iLanguageService.cacheData(RequestUtil.getRequestLocalLanguage());
String fileName = iLanguageService.getValueByKey(name);
alarmRecordService.asyncExportData(alarmRecord, task, fileName, head);
String taskStatusName = iLanguageService.getValueByKey(TaskStatusEnum.ABORNING.getName());
iLanguageService.cleanCache();
return R.ok();
}
- 工具类RequestUtil.java
import com.alibaba.ttl.TransmittableThreadLocal;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
/**
* @author kele
* @description
*/
public class RequestUtil {
private static ThreadLocal<ServletRequestAttributes> threadLocal = new TransmittableThreadLocal<>();
/**
* @author: kele
* @desc: 获取请求域
*/
public static HttpServletRequest getRequest() {
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
return servletRequestAttributes == null ? get() == null ? null : get().getRequest() : servletRequestAttributes.getRequest();
}
/**
* @author: kele
* @desc: 获取请求域
*/
public static String getRequestLocalLanguage() {
HttpServletRequest request = getRequest();
return request == null ? null : request.getLocale().getLanguage();
}
public static void set(ServletRequestAttributes servletRequestAttributes){
threadLocal.set(servletRequestAttributes);
}
public static ServletRequestAttributes get(){
return threadLocal.get();
}
public static void remove(){
threadLocal.remove();
}
public static void transfer() {
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
set(servletRequestAttributes);
}
}
Excel导出国际处理
- EasyExcelUtil.java
RequestUtil.transfer();
EasyExcelUtil.writeExcelLanguage(iLanguageService);
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dahua.alarm.api.model.vo.LocalDateTimeConverter;
import com.dahua.service.ILanguageService;
import com.dahua.util.RequestUtil;
import com.pig4cloud.plugin.excel.head.I18nHeaderCellWriteHandler;
import lombok.extern.slf4j.Slf4j;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.regex.Matcher;
@Slf4j
public class EasyExcelUtil {
private static ILanguageService iLanguageService;
public static void writeExcelLanguage(ILanguageService languageService) {
iLanguageService = languageService;
}
public static <T> void writeExcel(File file, Class<T> head, Collection<T> data) {
EasyExcel.write(file, head).sheet(0).doWrite(data);
}
/**
* 分页写入excel
* @param path
* @param head
* @param page
* @param i18nHeaderCellWriteHandler
* @param pageHandler
* @param <T>
*/
public static <T> File writeExcel(
String path,
Class<T> head,
Page page,
I18nHeaderCellWriteHandler i18nHeaderCellWriteHandler,
PageHandler<T> pageHandler
) {
//构造文件、创建文件
File file = new File(path);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
ExcelWriter excelWriter = null;
try {
excelWriter = EasyExcel
.write(file, head)
.inMemory(false)
.registerWriteHandler(i18nHeaderCellWriteHandler)
.registerConverter(new LocalDateTimeConverter())
.build();
//当前页码
while (true) {
//分页读取数据
List<T> data = pageHandler.page(page);
if (data.isEmpty()) {
//数据为0的时候也需要写入,防止excel文件异常
excelWriter.write(data, EasyExcel.writerSheet("sheet1").head(head).build());
break;
}
//读取的而数据写入excel
setI18nData(data);
excelWriter.write(data, EasyExcel.writerSheet("sheet1").head(head).build());
//更新页码
page.setCurrent(page.getCurrent() + 1);
}
} catch (Exception e) {
e.printStackTrace();
log.error("writeExcel -> errorMsg:", e);
} finally {
//数据写入完毕关闭资源
if (excelWriter != null) {
excelWriter.finish();
}
iLanguageService.cleanCache();
}
return file;
}
private static <T> void setI18nData(List<?> data) {
iLanguageService.cacheData(RequestUtil.getRequestLocalLanguage());
Map<String, Map<String, Object>> map = null;
for (int i = 0; i < data.size(); i++) {
Object obj = data.get(i);
Class<?> clazz = obj.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
try {
field.setAccessible(true);
Object val = field.get(obj);
//只有字符串需要进行国际化
if (val instanceof String) {
String value = (String)val;
if (value.contains(StrUtil.DOT)) {
value = iLanguageService.getValueByKey(value);
field.set(obj, value);
} else {
ExcelProperty annotation = field.getAnnotation(ExcelProperty.class);
if (Objects.nonNull(annotation)) {
if (Objects.nonNull(annotation.converter())) {
if (!annotation.converter().getName().contains("AutoConverter")) {
if (null == map) {
Class<?> clss = Class.forName(annotation.converter().getName());
Object convert = clss.getDeclaredConstructor().newInstance();
Method method = convert.getClass().getDeclaredMethod("getDictMap");
map = (Map<String, Map<String, Object>>)method.invoke(convert);
}
//对类属性上注解@ExcelProperty的value进行处理 eg:export.device_status
// String[] words = annotation.value()[0].split("\\.")[1].split("_");
//String key = words[0] + words[1].substring(0, 1).toUpperCase() + words[1].substring(1);
String key = convertToCamelCase(annotation.value()[0].split("\\.")[1]);
Map<String, Object> map0 = map.getOrDefault(key, new HashMap<>());
String v = map0.getOrDefault(value, "").toString();
value = v.contains(StrUtil.DOT) ? iLanguageService.getValueByKey(v) : v;
field.set(obj, value);
}
}
}
}
}
} catch (IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException | ClassNotFoundException e) {
log.error("writeExcel -> setI18nData -> errorMsg:", e);
}
}
}
}
/**
* 下划线转驼峰
*/
public static String convertToCamelCase(String input) {
StringBuilder camelCaseStr = new StringBuilder();
boolean nextUpperCase = false;
for (char c : input.toCharArray()) {
if (c == '_') {
nextUpperCase = true;
} else {
if (nextUpperCase) {
camelCaseStr.append(Character.toUpperCase(c));
nextUpperCase = false;
} else {
camelCaseStr.append(Character.toLowerCase(c));
}
}
}
return camelCaseStr.toString();
}
}
国际化测试
在其controller或者方法添加注解@DatabaseI18n即可
方式实现
错误码演示
-
错误码英文
-
错误码中文
词条业务演示
-
词条英文
-
词条中文
*