新增消息国际化配置功能

This commit is contained in:
tianfeng 2025-12-15 11:18:48 +08:00
parent f1d5e994fd
commit 77cdad58ed
11 changed files with 499 additions and 4 deletions

View File

@ -0,0 +1,64 @@
package com.red.circle.other.app.command.system.i18n;
import com.red.circle.other.domain.gateway.SystemI18nConfigGateway;
import com.red.circle.other.domain.system.i18n.SystemI18nConfig;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 国际化配置查询执行器
*
* @author Leo
* @date 2025-01-13
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class SystemI18nConfigQryExe {
private final SystemI18nConfigGateway systemI18nConfigGateway;
/**
* 获取单个配置值
*/
public String getValue(String i18nType, String countryCode, String i18nKey) {
SystemI18nConfig config = systemI18nConfigGateway.getByTypeCountryKey(i18nType, countryCode, i18nKey);
if (config != null) {
return config.getI18nValue();
}
// 降级到ALL通用配置
config = systemI18nConfigGateway.getByTypeCountryKey(i18nType, "ALL", i18nKey);
return config != null ? config.getI18nValue() : null;
}
/**
* 获取某业务类型下某国家的所有配置返回Map
*/
public Map<String, String> getConfigMap(String i18nType, String countryCode) {
List<SystemI18nConfig> configList = systemI18nConfigGateway.listByTypeAndCountry(i18nType, countryCode);
Map<String, String> configMap = new HashMap<>();
if (!CollectionUtils.isEmpty(configList)) {
for (SystemI18nConfig config : configList) {
configMap.put(config.getI18nKey(), config.getI18nValue());
}
}
// 降级补充ALL通用配置
List<SystemI18nConfig> allConfigList = systemI18nConfigGateway.listByTypeAndCountry(i18nType, "ALL");
if (!CollectionUtils.isEmpty(allConfigList)) {
for (SystemI18nConfig config : allConfigList) {
configMap.putIfAbsent(config.getI18nKey(), config.getI18nValue());
}
}
return configMap;
}
}

View File

@ -0,0 +1,35 @@
package com.red.circle.other.app.service.system;
import com.red.circle.other.app.command.system.i18n.SystemI18nConfigQryExe;
import com.red.circle.other.domain.system.i18n.I18nTypeEnum;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* 国际化配置服务
*
* @author Leo
* @date 2025-01-13
*/
@Service
@RequiredArgsConstructor
public class SystemI18nConfigService {
private final SystemI18nConfigQryExe systemI18nConfigQryExe;
/**
* 获取配置值
*/
public String getValue(I18nTypeEnum i18nType, String countryCode, String i18nKey) {
return systemI18nConfigQryExe.getValue(i18nType.getCode(), countryCode, i18nKey);
}
/**
* 获取配置Map
*/
public Map<String, String> getConfigMap(I18nTypeEnum i18nType, String countryCode) {
return systemI18nConfigQryExe.getConfigMap(i18nType.getCode(), countryCode);
}
}

View File

@ -0,0 +1,41 @@
package com.red.circle.other.domain.gateway;
import com.red.circle.other.domain.system.i18n.SystemI18nConfig;
import java.util.List;
/**
* 国际化配置领域网关
*
* @author Leo
* @date 2025-01-13
*/
public interface SystemI18nConfigGateway {
/**
* 查询单个配置
*
* @param i18nType 业务类型
* @param countryCode 国家代码
* @param i18nKey 配置key
* @return 配置对象
*/
SystemI18nConfig getByTypeCountryKey(String i18nType, String countryCode, String i18nKey);
/**
* 查询某业务类型下某国家的所有配置
*
* @param i18nType 业务类型
* @param countryCode 国家代码
* @return 配置列表
*/
List<SystemI18nConfig> listByTypeAndCountry(String i18nType, String countryCode);
/**
* 查询某业务类型的所有配置
*
* @param i18nType 业务类型
* @return 配置列表
*/
List<SystemI18nConfig> listByType(String i18nType);
}

View File

@ -0,0 +1,35 @@
package com.red.circle.other.domain.system.i18n;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 国际化配置业务类型枚举
*
* @author Leo
* @date 2025-01-13
*/
@Getter
@AllArgsConstructor
public enum I18nTypeEnum {
/**
* 靓号相关
*/
BEAUTIFUL_NUMBER("BEAUTIFUL_NUMBER", "靓号"),
/**
* 道具券相关
*/
PROP_COUPON("PROP_COUPON", "道具券");
/**
* 类型代码
*/
private final String code;
/**
* 类型名称
*/
private final String name;
}

View File

@ -0,0 +1,75 @@
package com.red.circle.other.domain.system.i18n;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 通用国际化配置领域实体
*
* @author Leo
* @date 2025-01-13
*/
@Data
public class SystemI18nConfig {
/**
* 主键
*/
private Long id;
/**
* 业务类型(BEAUTIFUL_NUMBER/PROP_COUPON等)
*/
private String i18nType;
/**
* 国家代码(CN/US/SA/ALL等)
*/
private String countryCode;
/**
* 配置项key(content/title/subtitle等)
*/
private String i18nKey;
/**
* 国际化文案内容
*/
private String i18nValue;
/**
* 排序号
*/
private Integer sortOrder;
/**
* 状态(0-禁用,1-启用)
*/
private Integer status;
/**
* 备注说明
*/
private String remark;
/**
* 创建人
*/
private String createdBy;
/**
* 创建时间
*/
private LocalDateTime createdTime;
/**
* 更新人
*/
private String updatedBy;
/**
* 更新时间
*/
private LocalDateTime updatedTime;
}

View File

@ -0,0 +1,23 @@
package com.red.circle.other.infra.convertor;
import com.red.circle.other.domain.system.i18n.SystemI18nConfig;
import com.red.circle.other.infra.database.rds.entity.system.SystemI18nConfigDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
/**
* 国际化配置转换器
*
* @author Leo
* @date 2025-01-13
*/
@Mapper
public interface SystemI18nConfigConvertor {
SystemI18nConfigConvertor INSTANCE = Mappers.getMapper(SystemI18nConfigConvertor.class);
/**
* DO转Domain
*/
SystemI18nConfig toDomain(SystemI18nConfigDO configDO);
}

View File

@ -0,0 +1,36 @@
package com.red.circle.other.infra.database.rds.dao.system;
import com.red.circle.framework.mybatis.dao.BaseDAO;
import com.red.circle.other.infra.database.rds.entity.system.SystemI18nConfigDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 国际化配置Mapper
*
* @author Leo
* @date 2025-01-13
*/
@Mapper
public interface SystemI18nConfigDAO extends BaseDAO<SystemI18nConfigDO> {
/**
* 查询单个配置
*/
SystemI18nConfigDO selectByTypeCountryKey(@Param("i18nType") String i18nType,
@Param("countryCode") String countryCode,
@Param("i18nKey") String i18nKey);
/**
* 查询某业务类型下某国家的所有配置
*/
List<SystemI18nConfigDO> selectByTypeAndCountry(@Param("i18nType") String i18nType,
@Param("countryCode") String countryCode);
/**
* 查询某业务类型的所有配置
*/
List<SystemI18nConfigDO> selectByType(@Param("i18nType") String i18nType);
}

View File

@ -0,0 +1,80 @@
package com.red.circle.other.infra.database.rds.entity.system;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 通用国际化配置表
*
* @author Leo
* @date 2025-01-13
*/
@Data
@TableName("system_i18n_config")
public class SystemI18nConfigDO {
/**
* 主键
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 业务类型
*/
private String i18nType;
/**
* 国家代码
*/
private String countryCode;
/**
* 配置项key
*/
private String i18nKey;
/**
* 国际化文案内容
*/
private String i18nValue;
/**
* 排序号
*/
private Integer sortOrder;
/**
* 状态
*/
private Integer status;
/**
* 备注说明
*/
private String remark;
/**
* 创建人
*/
private String createdBy;
/**
* 创建时间
*/
private LocalDateTime createdTime;
/**
* 更新人
*/
private String updatedBy;
/**
* 更新时间
*/
private LocalDateTime updatedTime;
}

View File

@ -0,0 +1,50 @@
package com.red.circle.other.infra.gateway;
import com.red.circle.other.domain.gateway.SystemI18nConfigGateway;
import com.red.circle.other.domain.system.i18n.SystemI18nConfig;
import com.red.circle.other.infra.convertor.SystemI18nConfigConvertor;
import com.red.circle.other.infra.database.rds.dao.system.SystemI18nConfigDAO;
import com.red.circle.other.infra.database.rds.entity.system.SystemI18nConfigDO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.stream.Collectors;
/**
* 国际化配置网关实现
*
* @author Leo
* @date 2025-01-13
*/
@Component
@RequiredArgsConstructor
public class SystemI18nConfigGatewayImpl implements SystemI18nConfigGateway {
private final SystemI18nConfigDAO systemI18NConfigDAO;
@Override
public SystemI18nConfig getByTypeCountryKey(String i18nType, String countryCode, String i18nKey) {
SystemI18nConfigDO configDO = systemI18NConfigDAO.selectByTypeCountryKey(i18nType, countryCode, i18nKey);
if (configDO == null) {
configDO = systemI18NConfigDAO.selectByTypeCountryKey(i18nType, "EN", i18nKey);
}
return SystemI18nConfigConvertor.INSTANCE.toDomain(configDO);
}
@Override
public List<SystemI18nConfig> listByTypeAndCountry(String i18nType, String countryCode) {
List<SystemI18nConfigDO> configDOList = systemI18NConfigDAO.selectByTypeAndCountry(i18nType, countryCode);
return configDOList.stream()
.map(SystemI18nConfigConvertor.INSTANCE::toDomain)
.collect(Collectors.toList());
}
@Override
public List<SystemI18nConfig> listByType(String i18nType) {
List<SystemI18nConfigDO> configDOList = systemI18NConfigDAO.selectByType(i18nType);
return configDOList.stream()
.map(SystemI18nConfigConvertor.INSTANCE::toDomain)
.collect(Collectors.toList());
}
}

View File

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.red.circle.other.infra.database.rds.dao.system.SystemI18nConfigDAO">
<resultMap id="BaseResultMap" type="com.red.circle.other.infra.database.rds.entity.system.SystemI18nConfigDO">
<id column="id" property="id"/>
<result column="i18n_type" property="i18nType"/>
<result column="country_code" property="countryCode"/>
<result column="i18n_key" property="i18nKey"/>
<result column="i18n_value" property="i18nValue"/>
<result column="sort_order" property="sortOrder"/>
<result column="status" property="status"/>
<result column="remark" property="remark"/>
<result column="created_by" property="createdBy"/>
<result column="created_time" property="createdTime"/>
<result column="updated_by" property="updatedBy"/>
<result column="updated_time" property="updatedTime"/>
</resultMap>
<select id="selectByTypeCountryKey" resultMap="BaseResultMap">
SELECT * FROM system_i18n_config
WHERE i18n_type = #{i18nType}
AND country_code = #{countryCode}
AND i18n_key = #{i18nKey}
AND status = 1
LIMIT 1
</select>
<select id="selectByTypeAndCountry" resultMap="BaseResultMap">
SELECT * FROM system_i18n_config
WHERE i18n_type = #{i18nType}
AND country_code = #{countryCode}
AND status = 1
ORDER BY sort_order ASC, id ASC
</select>
<select id="selectByType" resultMap="BaseResultMap">
SELECT * FROM system_i18n_config
WHERE i18n_type = #{i18nType}
AND status = 1
ORDER BY country_code ASC, sort_order ASC, id ASC
</select>
</mapper>

View File

@ -6,8 +6,13 @@ import com.red.circle.external.inner.model.enums.message.OfficialNoticeTypeEnum;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.core.response.CommonErrorCode;
import com.red.circle.framework.dto.PageResult;
import com.red.circle.other.domain.gateway.SystemI18nConfigGateway;
import com.red.circle.other.domain.gateway.user.ability.UserRegionGateway;
import com.red.circle.other.domain.system.i18n.I18nTypeEnum;
import com.red.circle.other.domain.system.i18n.SystemI18nConfig;
import com.red.circle.other.infra.database.mongo.entity.user.profile.UserSpecialId;
import com.red.circle.other.infra.database.mongo.service.user.profile.UserSpecialIdService;
import com.red.circle.other.infra.database.rds.dao.system.SystemI18nConfigDAO;
import com.red.circle.other.infra.database.rds.entity.user.user.UserBeautifulNumberApply;
import com.red.circle.other.infra.database.rds.service.user.user.UserBeautifulNumberApplyService;
import com.red.circle.other.infra.database.rds.service.user.user.UserBeautifulNumberService;
@ -18,6 +23,7 @@ import com.red.circle.other.inner.model.cmd.user.UserBeautifulNumberCmd;
import com.red.circle.other.inner.model.dto.user.BeautifulNumberDTO;
import com.red.circle.other.inner.model.dto.user.UserBeautifulNumberApplyDTO;
import com.red.circle.other.app.inner.service.user.user.UserBeautifulNumberClientService;
import com.red.circle.other.inner.model.dto.user.reigon.UserRegionDTO;
import com.red.circle.tool.core.date.TimestampUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@ -42,6 +48,8 @@ public class UserBeautifulNumberClientServiceImpl implements
private final UserBeautifulNumberApplyService userBeautifulNumberApplyService;
private final UserSpecialIdService userSpecialIdService;
private final OfficialNoticeClient officialNoticeClient;
private final SystemI18nConfigGateway systemI18nConfigGateway;
private final UserRegionGateway userRegionGateway;
@Override
public PageResult<UserBeautifulNumberApplyDTO> pageBeautifulNumberApply(
@ -59,6 +67,10 @@ public class UserBeautifulNumberClientServiceImpl implements
userBeautifulNumberApplyService.handleApply(id, state);
UserRegionDTO userRegion = userRegionGateway.getUserRegion(beautifulNumberApply.getApplyUser());
String regionCode = userRegion.getRegionCode();
SystemI18nConfig applyContent;
String content;
if (state == 1) {
UserSpecialId userSpecialId = userSpecialIdService.getByUserId(beautifulNumberApply.getApplyUser());
@ -75,11 +87,11 @@ public class UserBeautifulNumberClientServiceImpl implements
specialIdCmd.setExpiredTime(TimestampUtils.dateTimePlusDays(TimestampUtils.now(),365 * 3));
userSpecialIdService.add(specialIdCmd);
content = String.format("Your application for exclusive lD 【%s】has been approved and has been applied to both you user lD and room lD.",
beautifulNumberApply.getApplyAccount());
applyContent = systemI18nConfigGateway.getByTypeCountryKey(I18nTypeEnum.BEAUTIFUL_NUMBER.getCode(), regionCode, "apply_content");
content = String.format(applyContent.getI18nValue(),beautifulNumberApply.getApplyAccount());
} else {
content = String.format("Your application for exclusive lD 【%s】wasn't approved for reason 【%s】",
applyContent = systemI18nConfigGateway.getByTypeCountryKey(I18nTypeEnum.BEAUTIFUL_NUMBER.getCode(), regionCode, "audit_result_content");
content = String.format(applyContent.getI18nValue(),
beautifulNumberApply.getApplyAccount(),
remark);
}