⚡ 拆分国际化starter
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>ballcat-extend-i18n</artifactId>
|
||||
<groupId>com.hccake</groupId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>ballcat-extend-i18n-annotation</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.hccake.common.i18n.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* i18n field annotation
|
||||
* @author Yakir
|
||||
*/
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface I18nField {
|
||||
|
||||
/**
|
||||
* 业务
|
||||
* @return 业务码
|
||||
*/
|
||||
String businessCode();
|
||||
|
||||
/**
|
||||
* 范围值 若指定 则对此范围内的值进行国际化 不在范围的则使用默认值
|
||||
* @return 范围值
|
||||
*/
|
||||
String[] rangeValue() default {};
|
||||
|
||||
/**
|
||||
* 默认值
|
||||
*/
|
||||
String defaultValue() default "";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>ballcat-extend-i18n</artifactId>
|
||||
<groupId>com.hccake</groupId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>ballcat-extend-i18n-core</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.hccake</groupId>
|
||||
<artifactId>ballcat-extend-i18n-annotation</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.hccake</groupId>
|
||||
<artifactId>ballcat-common-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.hccake</groupId>
|
||||
<artifactId>ballcat-spring-boot-starter-redis</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.hccake.common.i18n;
|
||||
|
||||
import com.hccake.common.i18n.model.I18nItem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* i18n 数据提供 主要负责从数据库中提取数据
|
||||
*
|
||||
* @author Yakir
|
||||
* @since 2021/3/30
|
||||
*/
|
||||
public interface I18nDataProvider {
|
||||
|
||||
/**
|
||||
* 指定业务 业务码 语言环境
|
||||
* @param systemName
|
||||
* @param businessCode
|
||||
* @param code
|
||||
* @param language
|
||||
* @return
|
||||
*/
|
||||
I18nItem selectOne(String systemName, String businessCode, String code, String language);
|
||||
|
||||
/**
|
||||
* 查询列表 指定code 查询出所有语言环境
|
||||
* @param systemName
|
||||
* @param businessCode
|
||||
* @param code
|
||||
* @return
|
||||
*/
|
||||
List<I18nItem> selectListByCode(String systemName, String businessCode, String code);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.hccake.common.i18n;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* i18n properties
|
||||
*
|
||||
* @author Yakir
|
||||
*/
|
||||
@Data
|
||||
@ConfigurationProperties(prefix = "ballcat.i18n")
|
||||
public class I18nProperties {
|
||||
|
||||
/**
|
||||
* 系统名称
|
||||
*/
|
||||
private String systemName = "test-item";
|
||||
|
||||
/**
|
||||
* 缓存空值标记
|
||||
*/
|
||||
private String nullValue = "N_V";
|
||||
|
||||
/**
|
||||
* 执行器 主要用来对数据做附加操作
|
||||
*/
|
||||
private String executor = "simple";
|
||||
|
||||
/**
|
||||
* 生成器
|
||||
*/
|
||||
private Generate generate = new Generate();
|
||||
|
||||
/**
|
||||
* 缓存设置
|
||||
*/
|
||||
private Cache cache = new Cache();
|
||||
|
||||
@Data
|
||||
public class Generate {
|
||||
|
||||
/**
|
||||
* 生成器定界符
|
||||
*/
|
||||
private String delimiter = ":";
|
||||
|
||||
}
|
||||
|
||||
@Data
|
||||
public class Cache {
|
||||
|
||||
/**
|
||||
* 缓存类型
|
||||
*/
|
||||
private String type = "local";
|
||||
|
||||
/**
|
||||
* 过期时间(s) -1 表示永不过期
|
||||
*/
|
||||
private Long expire = -1L;
|
||||
|
||||
}
|
||||
|
||||
public boolean isNullValue(String val) {
|
||||
return this.nullValue.equals(val);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.hccake.common.i18n.cache;
|
||||
|
||||
/**
|
||||
* 缓存服务 规范国际化的缓存
|
||||
*
|
||||
* @author Yakir
|
||||
*/
|
||||
public interface CacheService {
|
||||
|
||||
/**
|
||||
* 设置过期时间永不过期
|
||||
* @param cacheKey
|
||||
* @param cacheValue
|
||||
*/
|
||||
void put(String cacheKey, String cacheValue);
|
||||
|
||||
/**
|
||||
* 设置缓存
|
||||
* @param cacheKey 缓存key
|
||||
* @param cacheValue 值
|
||||
* @param expireTime 秒(S)为单位
|
||||
*/
|
||||
void put(String cacheKey, String cacheValue, Long expireTime);
|
||||
|
||||
/**
|
||||
* 根据key 得到数据
|
||||
* @param cacheKey 缓存key
|
||||
* @return string
|
||||
*/
|
||||
String get(String cacheKey);
|
||||
|
||||
/**
|
||||
* 根据key删除
|
||||
* @param cacheKey 缓存key
|
||||
*/
|
||||
void del(String cacheKey);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.hccake.common.i18n.cache;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* local cache
|
||||
*
|
||||
* @author Yakir
|
||||
*/
|
||||
public class LocalCacheService implements CacheService {
|
||||
|
||||
/**
|
||||
* 本地缓存 map
|
||||
*/
|
||||
private static final Map<String, String> CACHE_MAP = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void put(String cacheKey, String cacheValue) {
|
||||
put(cacheKey, cacheValue, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(String cacheKey, String cacheValue, Long expireTime) {
|
||||
CACHE_MAP.put(cacheKey, cacheValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String get(String cacheKey) {
|
||||
return CACHE_MAP.get(cacheKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void del(String cacheKey) {
|
||||
CACHE_MAP.remove(cacheKey);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.hccake.common.i18n.cache;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* redis 缓存
|
||||
*
|
||||
* @author Yakir
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class RedisCacheService implements CacheService {
|
||||
|
||||
private final StringRedisTemplate redisTemplate;
|
||||
|
||||
@Override
|
||||
public void put(String cacheKey, String cacheValue) {
|
||||
redisTemplate.opsForValue().set(cacheKey, cacheValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(String cacheKey, String cacheValue, Long expireTime) {
|
||||
if (expireTime <= 0) {
|
||||
this.put(cacheKey, cacheValue);
|
||||
}
|
||||
else {
|
||||
redisTemplate.opsForValue().set(cacheKey, cacheValue, expireTime, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String get(String cacheKey) {
|
||||
return redisTemplate.opsForValue().get(cacheKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void del(String cacheKey) {
|
||||
redisTemplate.delete(cacheKey);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package com.hccake.common.i18n.execute;
|
||||
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* abstract translate execute
|
||||
*
|
||||
* @author Yakir
|
||||
*/
|
||||
public abstract class AbstractTranslateExecute implements TranslateExecute {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void translateObject(Object source) {
|
||||
if (source == null) {
|
||||
return;
|
||||
}
|
||||
// 获取本地语言环境
|
||||
Locale locale = LocaleContextHolder.getLocale();
|
||||
String language = locale.toString();
|
||||
if (source instanceof List) {
|
||||
processObjects((List<Object>) source, language);
|
||||
}
|
||||
else if (source instanceof Set) {
|
||||
processObjects((Set) source, language);
|
||||
}
|
||||
else {
|
||||
processObject(source, language);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void translateObject(Object source, Map<String, String> params) {
|
||||
if (source == null) {
|
||||
return;
|
||||
}
|
||||
// 获取本地语言环境
|
||||
Locale locale = LocaleContextHolder.getLocale();
|
||||
String language = locale.toString();
|
||||
if (source instanceof List) {
|
||||
processObjects((List<Object>) source, language, params);
|
||||
}
|
||||
else if (source instanceof Set) {
|
||||
processObjects((Set<Object>) source, language, params);
|
||||
}
|
||||
else {
|
||||
processObject(source, language, params);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理对象 不带参数的
|
||||
* @param object 处理数据对象
|
||||
* @param language 语言环境
|
||||
*/
|
||||
public abstract void processObject(Object object, String language);
|
||||
|
||||
/**
|
||||
* 处理对象 不带参数
|
||||
* @param sources 元对象集合
|
||||
* @param language 语言环境
|
||||
*/
|
||||
public abstract <T extends Collection> void processObjects(T sources, String language);
|
||||
|
||||
/**
|
||||
* 处理对象带参数 一批对象公用一份参数
|
||||
* @param sources 元对象集合
|
||||
* @param language 语言环境
|
||||
* @param params 参数
|
||||
*/
|
||||
public abstract <T extends Collection> void processObjects(T sources, String language, Map<String, String> params);
|
||||
|
||||
/**
|
||||
* 处理对象单个 带参数
|
||||
* @param source 元对象
|
||||
* @param language 语言环境
|
||||
* @param params 参数
|
||||
*/
|
||||
public abstract void processObject(Object source, String language, Map<String, String> params);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
package com.hccake.common.i18n.execute;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.ClassUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.hccake.common.i18n.annotation.I18nField;
|
||||
import com.hccake.common.i18n.executor.ExecutorWrapper;
|
||||
import com.hccake.common.i18n.handler.TranslateHandler;
|
||||
import com.hccake.common.i18n.handler.TranslateHandlerHolder;
|
||||
import com.hccake.common.i18n.model.I18nValueItem;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 翻译执行器
|
||||
*
|
||||
* @author Yakir
|
||||
*/
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class DefaultTranslateExecute extends AbstractTranslateExecute {
|
||||
|
||||
private final ExecutorWrapper executorWrapper;
|
||||
|
||||
@Override
|
||||
public String translateText(String businessCode, String code) {
|
||||
String languageName = LocaleContextHolder.getLocale().toString();
|
||||
return translateText(businessCode, code, languageName, null, code);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String translateText(String businessCode, String code, String languageName) {
|
||||
return translateText(businessCode, code, languageName, null, code);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String translateText(String businessCode, String code, Map<String, String> params) {
|
||||
String languageName = LocaleContextHolder.getLocale().toString();
|
||||
return translateText(businessCode, code, languageName, params, code);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String translateText(String businessCode, String code, String languageName,
|
||||
Map<String, String> paramValues) {
|
||||
return translateText(businessCode, code, languageName, paramValues, code);
|
||||
}
|
||||
|
||||
public String translateText(String businessCode, String code, String languageName, Map<String, String> paramValues,
|
||||
String defaultValue) {
|
||||
I18nValueItem i18nValueItem = executorWrapper.selectLocaleLanguage(businessCode, code, languageName);
|
||||
if (i18nValueItem == null) {
|
||||
return code;
|
||||
}
|
||||
Integer type = i18nValueItem.getType();
|
||||
String tplValue = i18nValueItem.getTplValue();
|
||||
TranslateHandler translateHandler = TranslateHandlerHolder.getTranslateHandler(type);
|
||||
Assert.notNull(translateHandler, "translateHandler can not be Null");
|
||||
String resultValue = translateHandler.translateText(tplValue, paramValues);
|
||||
return StrUtil.isNotEmpty(resultValue) ? resultValue : defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Collection> void processObjects(T sources, String language, Map<String, String> params) {
|
||||
if (CollectionUtil.isEmpty(sources)) {
|
||||
return;
|
||||
}
|
||||
for (Object source : sources) {
|
||||
processObject(source, language, params);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Collection> void processObjects(T sources, String language) {
|
||||
this.processObjects(sources, language, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processObject(Object source, String language) {
|
||||
this.processObject(source, language, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processObject(Object source, String language, Map<String, String> params) {
|
||||
if (source == null) {
|
||||
return;
|
||||
}
|
||||
Class<?> sourceClass = source.getClass();
|
||||
// 若为基本类型 或string类中直接跳过
|
||||
if (isBaseTypeOrString(sourceClass)) {
|
||||
return;
|
||||
}
|
||||
for (Field field : sourceClass.getDeclaredFields()) {
|
||||
Class<?> fieldType = field.getType();
|
||||
// 若为排除类型直接跳过
|
||||
if (isExcludeFieldType(fieldType)) {
|
||||
continue;
|
||||
}
|
||||
if (List.class.isAssignableFrom(fieldType)) {
|
||||
// 防止实体对象里面防止list属性
|
||||
List<Object> elementsList = getFieldValue(field, source);
|
||||
if (CollectionUtil.isEmpty(elementsList)) {
|
||||
continue;
|
||||
}
|
||||
processObjects(elementsList, language);
|
||||
continue;
|
||||
}
|
||||
else if (Set.class.isAssignableFrom(fieldType)) {
|
||||
Set elementSet = getFieldValue(field, source);
|
||||
if (CollectionUtil.isEmpty(elementSet)) {
|
||||
continue;
|
||||
}
|
||||
processObjects(new ArrayList<>(elementSet), language);
|
||||
continue;
|
||||
}
|
||||
// 若不存在国际化注解 直接跳过
|
||||
if (!field.isAnnotationPresent(I18nField.class)) {
|
||||
continue;
|
||||
}
|
||||
// 设置字段为可进入
|
||||
String fieldValue = getFieldValue(field, source);
|
||||
// 若字段值为空 则直接跳过
|
||||
if (StrUtil.isEmpty(fieldValue)) {
|
||||
continue;
|
||||
}
|
||||
I18nField annotation = field.getAnnotation(I18nField.class);
|
||||
String[] rangeValue = annotation.rangeValue();
|
||||
String defaultValue = annotation.defaultValue();
|
||||
// rangeValue 不为空 并且当前元素 不在范围值内 直接跳过
|
||||
if (ArrayUtil.isNotEmpty(rangeValue) && !ArrayUtil.contains(rangeValue, fieldValue)) {
|
||||
continue;
|
||||
}
|
||||
String businessCode = annotation.businessCode();
|
||||
I18nValueItem i18nValueItem = executorWrapper.selectLocaleLanguage(businessCode, fieldValue, language);
|
||||
if (i18nValueItem == null) {
|
||||
continue;
|
||||
}
|
||||
String tplValue = i18nValueItem.getTplValue();
|
||||
Integer type = i18nValueItem.getType();
|
||||
TranslateHandler translateHandler = TranslateHandlerHolder.getTranslateHandler(type);
|
||||
if (translateHandler == null) {
|
||||
continue;
|
||||
}
|
||||
String afterValue = translateHandler.translateText(tplValue, params);
|
||||
if (StrUtil.isEmpty(afterValue)) {
|
||||
if (StrUtil.isEmpty(defaultValue)) {
|
||||
continue;
|
||||
}
|
||||
afterValue = defaultValue;
|
||||
}
|
||||
// 设置进字段
|
||||
setFieldValue(field, source, afterValue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为基础类型 或String 类型
|
||||
* @param sourceClass
|
||||
* @return
|
||||
*/
|
||||
private boolean isBaseTypeOrString(Class<?> sourceClass) {
|
||||
return ClassUtil.isBasicType(sourceClass) || String.class.isAssignableFrom(sourceClass);
|
||||
}
|
||||
|
||||
private <T> T getFieldValue(Field field, Object obj) {
|
||||
try {
|
||||
if (!field.isAccessible()) {
|
||||
field.setAccessible(true);
|
||||
}
|
||||
return (T) field.get(obj);
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
log.error("字段值获取失败", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置字段值
|
||||
* @param field 字段
|
||||
* @param obj 对象
|
||||
* @param val 新值
|
||||
*/
|
||||
private void setFieldValue(Field field, Object obj, String val) {
|
||||
try {
|
||||
if (!field.isAccessible()) {
|
||||
field.setAccessible(true);
|
||||
}
|
||||
field.set(obj, val);
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
log.error("国际化处理结果回填失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为排除字段类型
|
||||
* @param clazz string List map 保留
|
||||
* @return true 排除 false 进行翻译
|
||||
*/
|
||||
public boolean isExcludeFieldType(Class clazz) {
|
||||
if (String.class.isAssignableFrom(clazz) || List.class.isAssignableFrom(clazz)
|
||||
|| Set.class.isAssignableFrom(clazz)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.hccake.common.i18n.execute;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface TranslateExecute {
|
||||
|
||||
/**
|
||||
* 翻译文本使用默认语言环境
|
||||
* @param businessCode
|
||||
* @param code
|
||||
* @return
|
||||
*/
|
||||
String translateText(String businessCode, String code);
|
||||
|
||||
/**
|
||||
* 翻译文本 指定语言环境
|
||||
* @param businessCode
|
||||
* @param code
|
||||
* @param language
|
||||
* @return
|
||||
*/
|
||||
String translateText(String businessCode, String code, String language);
|
||||
|
||||
/**
|
||||
* 翻译文本使用当前语言环境
|
||||
* @param businessCode
|
||||
* @param code
|
||||
* @param params
|
||||
* @return
|
||||
*/
|
||||
String translateText(String businessCode, String code, Map<String, String> params);
|
||||
|
||||
/**
|
||||
* 翻译文本 指定语言环境
|
||||
* @param businessCode
|
||||
* @param code
|
||||
* @param language
|
||||
* @param params
|
||||
* @return
|
||||
*/
|
||||
String translateText(String businessCode, String code, String language, Map<String, String> params);
|
||||
|
||||
/**
|
||||
* 翻译对象 直接进行字段值更新
|
||||
* @param source
|
||||
*/
|
||||
void translateObject(Object source);
|
||||
|
||||
/**
|
||||
* 翻译单个对象 可以指定参数
|
||||
* @param source
|
||||
* @param params
|
||||
*/
|
||||
void translateObject(Object source, Map<String, String> params);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.hccake.common.i18n.execute;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 翻译执行包装器
|
||||
*
|
||||
* @author Yakir
|
||||
*/
|
||||
public class TranslateExecuteWrapper {
|
||||
|
||||
private static TranslateExecute translateExecute;
|
||||
|
||||
public static String translateText(String businessCode, String code) {
|
||||
return translateExecute.translateText(businessCode, code);
|
||||
}
|
||||
|
||||
public static String translateText(String businessCode, String code, String language) {
|
||||
return translateExecute.translateText(businessCode, code, language);
|
||||
}
|
||||
|
||||
public static String translateText(String businessCode, String code, Map<String, String> params) {
|
||||
return translateExecute.translateText(businessCode, code, params);
|
||||
}
|
||||
|
||||
public static String translateText(String businessCode, String code, String language, Map<String, String> params) {
|
||||
return translateExecute.translateText(businessCode, code, language, params);
|
||||
}
|
||||
|
||||
public static void translateObject(Object source) {
|
||||
translateExecute.translateObject(source);
|
||||
}
|
||||
|
||||
public static void translateObject(Object source, Map<String, String> params) {
|
||||
translateExecute.translateObject(source, params);
|
||||
}
|
||||
|
||||
public void setTranslateExecute(TranslateExecute translateExecute) {
|
||||
TranslateExecuteWrapper.translateExecute = translateExecute;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.hccake.common.i18n.executor;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.hccake.ballcat.common.util.JsonUtils;
|
||||
import com.hccake.common.i18n.I18nDataProvider;
|
||||
import com.hccake.common.i18n.I18nProperties;
|
||||
import com.hccake.common.i18n.cache.CacheService;
|
||||
import com.hccake.common.i18n.generate.KeyGenerate;
|
||||
import com.hccake.common.i18n.model.I18nItem;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 简单执行器 主要负责数据提取与缓存
|
||||
*
|
||||
* @author Yakir
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class CacheExecutor implements Executor {
|
||||
|
||||
private final I18nDataProvider i18nDataProvider;
|
||||
|
||||
private final I18nProperties i18nProperties;
|
||||
|
||||
private final KeyGenerate keyGenerate;
|
||||
|
||||
private final CacheService cacheService;
|
||||
|
||||
@Override
|
||||
public I18nItem selectOne(String systemName, String businessCode, String code, String language) {
|
||||
String key = keyGenerate.generateKey(systemName, businessCode, code, language);
|
||||
String cacheValue = cacheService.get(key);
|
||||
// 若为空值标记 则直接返回
|
||||
if (i18nProperties.isNullValue(cacheValue)) {
|
||||
return null;
|
||||
}
|
||||
if (StrUtil.isNotEmpty(cacheValue)) {
|
||||
return JsonUtils.toObj(cacheValue, I18nItem.class);
|
||||
}
|
||||
I18nItem i18nItem = i18nDataProvider.selectOne(systemName, businessCode, code, language);
|
||||
|
||||
cacheService.put(key,
|
||||
ObjectUtil.isNotEmpty(i18nItem) ? JsonUtils.toJson(i18nItem) : i18nProperties.getNullValue(),
|
||||
i18nProperties.getCache().getExpire());
|
||||
|
||||
return i18nItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<I18nItem> selectListByCode(String systemName, String businessCode, String code) {
|
||||
String key = keyGenerate.generateKey(systemName, businessCode, code);
|
||||
String cacheValue = cacheService.get(key);
|
||||
// 若为空值标记 则直接返回
|
||||
if (i18nProperties.isNullValue(cacheValue)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (StrUtil.isNotEmpty(cacheValue)) {
|
||||
return JsonUtils.toObj(cacheValue, List.class);
|
||||
}
|
||||
List<I18nItem> i18nItems = i18nDataProvider.selectListByCode(systemName, businessCode, code);
|
||||
|
||||
cacheService.put(key,
|
||||
ObjectUtil.isNotEmpty(i18nItems) ? JsonUtils.toJson(i18nItems) : i18nProperties.getNullValue(),
|
||||
i18nProperties.getCache().getExpire());
|
||||
|
||||
return i18nItems;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.hccake.common.i18n.executor;
|
||||
|
||||
import com.hccake.common.i18n.model.I18nItem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 执行器 主要负责数据提取与附加操作
|
||||
*
|
||||
* @author Yakir
|
||||
*/
|
||||
public interface Executor {
|
||||
|
||||
/**
|
||||
* 指定业务 业务码 语言环境
|
||||
* @param systemName 系统名称
|
||||
* @param businessCode 业务
|
||||
* @param code key
|
||||
* @param language 语言环境
|
||||
* @return 值
|
||||
*/
|
||||
I18nItem selectOne(String systemName, String businessCode, String code, String language);
|
||||
|
||||
/**
|
||||
* 查询列表 指定code 查询出所有语言环境
|
||||
* @param systemName 系统名称
|
||||
* @param businessCode 业务码
|
||||
* @param code key
|
||||
* @return 值列表
|
||||
*/
|
||||
List<I18nItem> selectListByCode(String systemName, String businessCode, String code);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.hccake.common.i18n.executor;
|
||||
|
||||
import com.hccake.common.i18n.I18nProperties;
|
||||
import com.hccake.common.i18n.model.I18nItem;
|
||||
import com.hccake.common.i18n.model.I18nValueItem;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* 执行者包装类 主要负责数据的处理转换
|
||||
*
|
||||
* @author Yakir
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class ExecutorWrapper {
|
||||
|
||||
private final I18nProperties i18nProperties;
|
||||
|
||||
private final Executor executor;
|
||||
|
||||
/**
|
||||
* 获取系统名
|
||||
* @return
|
||||
*/
|
||||
private String getSystemName() {
|
||||
return i18nProperties.getSystemName();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询区域项 语言
|
||||
* @param businessCode
|
||||
* @param code
|
||||
* @param language
|
||||
* @return {@link I18nValueItem} 对应处理后的国际化值
|
||||
*/
|
||||
public I18nValueItem selectLocaleLanguage(String businessCode, String code, String language) {
|
||||
I18nItem i18nItem = executor.selectOne(getSystemName(), businessCode, code, language);
|
||||
if (i18nItem == null) {
|
||||
return null;
|
||||
}
|
||||
return convertI18nValueItem(i18nItem);
|
||||
}
|
||||
|
||||
private I18nValueItem convertI18nValueItem(I18nItem e) {
|
||||
return new I18nValueItem().setTplValue(e.getValue()).setType(e.getType());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.hccake.common.i18n.executor;
|
||||
|
||||
import com.hccake.common.i18n.I18nDataProvider;
|
||||
import com.hccake.common.i18n.model.I18nItem;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 简单执行器 主要负责数据提取与缓存
|
||||
*
|
||||
* @author Yakir
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class SimpleExecutor implements Executor {
|
||||
|
||||
private final I18nDataProvider i18nDataProvider;
|
||||
|
||||
@Override
|
||||
public I18nItem selectOne(String systemName, String businessCode, String code, String language) {
|
||||
return i18nDataProvider.selectOne(systemName, businessCode, code, language);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<I18nItem> selectListByCode(String systemName, String businessCode, String code) {
|
||||
return i18nDataProvider.selectListByCode(systemName, businessCode, code);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package com.hccake.common.i18n.generate;
|
||||
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import com.hccake.common.i18n.I18nProperties;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* 默认key生成
|
||||
*
|
||||
* @author Yakir
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class DefaultKeyGenerate implements KeyGenerate {
|
||||
|
||||
private final I18nProperties i18nProperties;
|
||||
|
||||
@Override
|
||||
public String generateKey(String... params) {
|
||||
Assert.noNullElements(params, "params size must be greater than 0 ");
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
I18nProperties.Generate generate = i18nProperties.getGenerate();
|
||||
for (String param : params) {
|
||||
stringBuilder.append(param).append(generate.getDelimiter());
|
||||
}
|
||||
return stringBuilder.deleteCharAt(stringBuilder.length() - 1).toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.hccake.common.i18n.generate;
|
||||
|
||||
/**
|
||||
* 缓存key生成器
|
||||
*
|
||||
* @author Yakir
|
||||
*/
|
||||
public interface KeyGenerate {
|
||||
|
||||
/**
|
||||
* 缓存 key 生成
|
||||
* @param params 参数数组
|
||||
* @return 指定分隔符字符串
|
||||
*/
|
||||
String generateKey(String... params);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.hccake.common.i18n.handler;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* simple translate handler
|
||||
*
|
||||
* @author Yakir
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class SimpleTranslateHandler implements TranslateHandler {
|
||||
|
||||
@Override
|
||||
public String translateText(String originalText, Map<String, String> paramValues) {
|
||||
return originalText;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.hccake.common.i18n.handler;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* template translate handler
|
||||
*
|
||||
* @author Yakir
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class TemplateTranslateHandler implements TranslateHandler {
|
||||
|
||||
@Override
|
||||
public String translateText(String originalText, Map<String, String> paramValues) {
|
||||
return StrUtil.format(originalText, paramValues);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.hccake.common.i18n.handler;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 翻译处理器 具体执行处理逻辑
|
||||
*
|
||||
* @author Yakir
|
||||
*/
|
||||
public interface TranslateHandler {
|
||||
|
||||
/**
|
||||
* 翻译文本
|
||||
* @param originalText 原始文本
|
||||
* @param paramValues 参数值
|
||||
* @return 翻译后的值
|
||||
*/
|
||||
String translateText(String originalText, Map<String, String> paramValues);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.hccake.common.i18n.handler;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* translate handler holder
|
||||
*
|
||||
* @author Yakir
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class TranslateHandlerHolder {
|
||||
|
||||
/**
|
||||
* 处理器map元素
|
||||
*/
|
||||
private static final Map<Class<? extends TranslateHandler>, TranslateHandler> HANDLER_MAP = new HashMap<>();
|
||||
|
||||
/**
|
||||
* 枚举类型type标记 与类型的映射
|
||||
*/
|
||||
private static final Map<Integer, Class<? extends TranslateHandler>> TYPE_CLASS_MAP = new HashMap<>();
|
||||
|
||||
static {
|
||||
|
||||
TYPE_CLASS_MAP.put(1, SimpleTranslateHandler.class);
|
||||
TYPE_CLASS_MAP.put(2, TemplateTranslateHandler.class);
|
||||
|
||||
HANDLER_MAP.put(SimpleTranslateHandler.class, new SimpleTranslateHandler());
|
||||
HANDLER_MAP.put(TemplateTranslateHandler.class, new TemplateTranslateHandler());
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到处理器
|
||||
* @param clazz TranslateHandler的Class
|
||||
* @return @{code TranslateHandler实现}
|
||||
*/
|
||||
public static TranslateHandler getTranslateHandler(Class<? extends TranslateHandler> clazz) {
|
||||
return HANDLER_MAP.get(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加处理器
|
||||
* @param clazz TranslateHandler的Class
|
||||
* @param translateHandler TranslateHandler实现
|
||||
* @return @{code TranslateHandler实现}
|
||||
*/
|
||||
public static TranslateHandler addTranslateHandler(Class<? extends TranslateHandler> clazz,
|
||||
TranslateHandler translateHandler) {
|
||||
return HANDLER_MAP.put(clazz, translateHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到处理器 主要拓展 绑定type 与类的映射
|
||||
* @param type type
|
||||
* @return @{code TranslateHandler实现}
|
||||
*/
|
||||
public static TranslateHandler getTranslateHandler(Integer type) {
|
||||
return HANDLER_MAP.get(TYPE_CLASS_MAP.get(type));
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加处理器 主要拓展 绑定type 与类的映射
|
||||
* @param type 类型1.明文 2.模板
|
||||
* @param clazz TranslateHandler的Class
|
||||
* @param translateHandler TranslateHandler实现
|
||||
* @return @{code TranslateHandler实现}
|
||||
*/
|
||||
public static TranslateHandler addTranslateHandler(Integer type, Class<? extends TranslateHandler> clazz,
|
||||
TranslateHandler translateHandler) {
|
||||
TYPE_CLASS_MAP.put(type, clazz);
|
||||
return HANDLER_MAP.put(clazz, translateHandler);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.hccake.common.i18n.model;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* i18n item
|
||||
*
|
||||
* @author Yakir
|
||||
*/
|
||||
@Accessors(chain = true)
|
||||
@Data
|
||||
public class I18nItem {
|
||||
|
||||
/**
|
||||
* 系统名称
|
||||
*/
|
||||
private String systemName;
|
||||
|
||||
/**
|
||||
* 业务码
|
||||
*/
|
||||
private String businessCode;
|
||||
|
||||
/**
|
||||
* 分组code
|
||||
*/
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 语言环境
|
||||
*/
|
||||
private String language;
|
||||
|
||||
/**
|
||||
* 值
|
||||
*/
|
||||
private String value;
|
||||
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
private Integer type;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.hccake.common.i18n.model;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* i18n
|
||||
*
|
||||
* @author Yakir
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class I18nValueItem {
|
||||
|
||||
/**
|
||||
* 模板值
|
||||
*/
|
||||
private String tplValue;
|
||||
|
||||
/**
|
||||
* 类型 1.明文 2.模板
|
||||
*/
|
||||
private Integer type;
|
||||
|
||||
}
|
||||
18
ballcat-extends/ballcat-extend-i18n/pom.xml
Normal file
18
ballcat-extends/ballcat-extend-i18n/pom.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>ballcat-extends</artifactId>
|
||||
<groupId>com.hccake</groupId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>ballcat-extend-i18n</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<modules>
|
||||
<module>ballcat-extend-i18n-annotation</module>
|
||||
<module>ballcat-extend-i18n-core</module>
|
||||
</modules>
|
||||
</project>
|
||||
@@ -19,5 +19,6 @@
|
||||
<module>ballcat-extend-pay-virtual</module>
|
||||
<module>ballcat-extend-pay-ali</module>
|
||||
<module>ballcat-extend-pay-wx</module>
|
||||
<module>ballcat-extend-i18n</module>
|
||||
</modules>
|
||||
</project>
|
||||
Reference in New Issue
Block a user