Open feng-dan opened 9 months ago
/**
* @author fengdan
*/
@Slf4j
@RequiredArgsConstructor(onConstructor_ = {@Autowired})
public abstract class AbstractI18nServiceImpl<T extends I18nEntity> implements I18nService<T> {
protected final Class<T> entityClass;
protected final JdbcTemplate jdbcTemplate;
protected final TmsServiceApi tmsServiceApi;
protected final I18nInfoMapper i18nInfoMapper;
String enUsValue = I18nLanguageEnum.EN_US.getValue();
protected abstract T saveEntity(T entity);
protected abstract T getEntityById(Long entityId);
protected abstract Long getEntityId(T entity);
@Override
public T getEntityByIdWithI18n(Long entityId, String language) {
T entity = getEntityById(entityId);
if (entity != null) {
fillI18nInfo(entity, language);
}
return entity;
}
// 可以在保存实体时调用此方法自动添加国际化信息
@Override
public T saveWithI18n(T entity, String language) {
// 调用子类提供的保存实体的方法
T savedEntity = saveEntity(entity);
Field[] fields = entity.getClass().getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(I18nField.class)) {
try {
field.setAccessible(true);
Object fieldValue = field.get(savedEntity);
if (fieldValue != null && (!savedEntity.isI18nConfigured() || "zh_CN".equals(language))) {
addI18nInfo(savedEntity, field.toString(), fieldValue.toString(), language);
}
} catch (IllegalAccessException e) {
log.error("ex:{}", e.getMessage(), e);
}
}
}
return savedEntity;
}
private void fillI18nInfo(T entity, String language) {
Long entityId = getEntityId(entity);
Field[] fields = entityClass.getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(I18nField.class)) {
try {
field.setAccessible(true);
I18nInfo i18nInfo = findI18nValue(field.getName(), language, entityId);
if (i18nInfo != null) {
field.set(entity, i18nInfo.getValue());
}
} catch (IllegalAccessException e) {
log.error("ex:{}", e.getMessage(), e);
}
}
}
}
private I18nInfo findI18nValue(String fieldName, String language, Long entityId) {
I18nInfoMapper mapper = new I18nInfoMapperImpl(jdbcTemplate);
return mapper.findByEntityTypeAndFieldAndLanguage(fieldName, language, entityId).stream().findFirst().orElse(null);
}
/**
* defaultTranslationToEnglish
*
* @param entity 对象
* @param field 字段
* @param value 内容
*/
protected void defaultTranslationToEnglish(T entity, String field, String value) {
String valueEnglish = new I18nTranslationService(tmsServiceApi).translateToEnglish(value);
Long entityId = getEntityId(entity);
I18nInfo i18nInfo = builder18nInfo(field, valueEnglish, entityId);
I18nInfoMapper mapper = new I18nInfoMapperImpl(jdbcTemplate);
mapper.insertI18nInfo(i18nInfo);
}
protected void addI18nInfo(T entity, String field, String value, String language) {
Long entityId = getEntityId(entity);
I18nInfo i18nInfo = builder18nInfo(field, value, language, entityId);
I18nInfoMapper mapper = new I18nInfoMapperImpl(jdbcTemplate);
mapper.insertI18nInfo(i18nInfo);
}
protected I18nInfo builder18nInfo(String field, String valueEnglish, Long entityId) {
returnbuilder18nInfo(field, valueEnglish, enUsValue, entityId);
}
protected I18nInfo builder18nInfo(String field, String value, String language, Long entityId) {
I18nInfo i18nInfo = new I18nInfo();
i18nInfo.setField(field);
i18nInfo.setValue(value);
i18nInfo.setI18n(language);
i18nInfo.setEntityId(entityId);
return i18nInfo;
}
}
目前实现核心代码,集成方改动点较大
您好,我想请教关于业务数据国际化的一个实现方案(需支持12种语言)。目前我面临的情况是,业务表中的某些属性需要支持国际化显示。我考虑采用注解结合AOP的方式,在读写这些属性时动态处理其对应的国际化信息。
具体设想是通过自定义注解(如@I18nField)标记需要国际化的字段,并使用AOP在业务数据的读取和写入过程中自动从数据库的国际化字典表中获取或更新对应的语言版本内容。
但在实际操作中,如何确保在插入、更新业务数据的同时,关联的国际化记录也能够正确创建和更新?另外,在查询业务数据时,如何高效地利用AOP拦截并填充相应的国际化值?
请问您是否有类似的实践案例或者对这种基于注解+AOP实现国际化属性读写的优化建议?非常期待与您交流这一主题,共同探讨可能的最佳实践方法。
config_i18n_message 表