Browse Source

1、增加i18n国际化处理

rayson 1 year ago
parent
commit
127c6b1ecc
23 changed files with 531 additions and 62 deletions
  1. 38 1
      citu-framework/citu-common/src/main/java/com/citu/framework/common/util/string/StrUtils.java
  2. 48 0
      citu-framework/citu-spring-boot-starter-web/src/main/java/com/citu/framework/i18n/config/CituI18nAutoConfiguration.java
  3. 19 0
      citu-framework/citu-spring-boot-starter-web/src/main/java/com/citu/framework/i18n/config/I18nProperties.java
  4. 41 0
      citu-framework/citu-spring-boot-starter-web/src/main/java/com/citu/framework/i18n/config/LocaleInterceptor.java
  5. 6 0
      citu-framework/citu-spring-boot-starter-web/src/main/java/com/citu/framework/i18n/package-info.java
  6. 10 1
      citu-framework/citu-spring-boot-starter-web/src/main/java/com/citu/framework/swagger/config/CituSwaggerAutoConfiguration.java
  7. 17 9
      citu-framework/citu-spring-boot-starter-web/src/main/java/com/citu/framework/web/config/CituWebAutoConfiguration.java
  8. 63 19
      citu-framework/citu-spring-boot-starter-web/src/main/java/com/citu/framework/web/core/handler/GlobalExceptionHandler.java
  9. 1 0
      citu-framework/citu-spring-boot-starter-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
  10. 21 21
      menduner/menduner-system-api/src/main/java/com/citu/module/menduner/system/enums/ErrorCodeConstants.java
  11. 1 1
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/config/permission/CustomDataPermissionAutoConfiguration.java
  12. 1 1
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/config/permission/CustomDataPermissionRule.java
  13. 1 1
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/config/permission/CustomDataPermissionRuleCustomizer.java
  14. 3 6
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/controller/app/person/AppPersonController.java
  15. 39 0
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/controller/app/test/TestController.java
  16. 14 0
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/controller/app/test/TestReqVO.java
  17. 2 0
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/controller/app/user/AppMdeUserController.java
  18. 1 1
      menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/framework/datapermission/config/DataPermissionConfiguration.java
  19. 17 1
      menduner/menduner-system-biz/src/main/resources/application.yaml
  20. 1 0
      menduner/menduner-system-biz/src/main/resources/i18n/messages.properties
  21. 93 0
      menduner/menduner-system-biz/src/main/resources/i18n/messages_en_US.properties
  22. 93 0
      menduner/menduner-system-biz/src/main/resources/i18n/messages_zh_CN.properties
  23. 1 0
      menduner/menduner-system-biz/src/main/resources/i18n/messages_zh_HK.properties

+ 38 - 1
citu-framework/citu-common/src/main/java/com/citu/framework/common/util/string/StrUtils.java

@@ -64,7 +64,7 @@ public class StrUtils {
     /**
      * 移除字符串中,包含指定字符串的行
      *
-     * @param content 字符串
+     * @param content  字符串
      * @param sequence 包含的字符串
      * @return 移除后的字符串
      */
@@ -77,4 +77,41 @@ public class StrUtils {
                 .collect(Collectors.joining("\n"));
     }
 
+    /**
+     * 将数字转换成字符串
+     * 1100004002 转换后 1_100_004_002
+     * Integer的长度小于10 不转换
+     *
+     * @param number    数字
+     * @param minLength 长度小于多少不转换
+     * @return String
+     **/
+    public static String formatNumberWithUnderscores(int number, int minLength) {
+        // 将数字转换为字符串
+        String numberStr = Integer.toString(number);
+
+        // 如果数字字符串长度小于指定的最小长度,则直接返回原字符串
+        if (numberStr.length() < minLength) {
+            return numberStr;
+        }
+
+        // 使用StringBuilder来构建带有下划线的字符串
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < numberStr.length(); i++) {
+            sb.append(numberStr.charAt(i));
+
+            // 在第一个字符之后立即添加下划线
+            if (i == 0) {
+                sb.append('_');
+            }
+            // 之后每隔三位添加一个下划线
+            else if (i % 3 == 0 && i != 0 && i != numberStr.length() - 1) {
+                sb.append('_');
+            }
+        }
+
+        // 返回最终的字符串
+        return sb.toString();
+    }
+
 }

+ 48 - 0
citu-framework/citu-spring-boot-starter-web/src/main/java/com/citu/framework/i18n/config/CituI18nAutoConfiguration.java

@@ -0,0 +1,48 @@
+package com.citu.framework.i18n.config;
+
+import com.citu.framework.xss.config.XssProperties;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.MessageSource;
+import org.springframework.context.annotation.Bean;
+import org.springframework.validation.Validator;
+import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
+import org.springframework.web.servlet.LocaleResolver;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+import org.springframework.web.servlet.i18n.SessionLocaleResolver;
+
+import java.util.Locale;
+
+/**
+ * i18n 国际化配置
+ *
+ * @author rayson
+ **/
+@AutoConfiguration
+@EnableConfigurationProperties(I18nProperties.class)
+@ConditionalOnProperty(prefix = "citu.i18n", name = "enable", havingValue = "true", matchIfMissing = true)
+// 设置为 false 时,禁用
+public class CituI18nAutoConfiguration implements WebMvcConfigurer {
+
+    @Bean
+    public LocaleResolver localeResolver() {
+        SessionLocaleResolver localeResolver = new SessionLocaleResolver();
+        localeResolver.setDefaultLocale(Locale.SIMPLIFIED_CHINESE);
+        // Configure the locale resolver as needed
+        return localeResolver;
+    }
+
+    @Bean
+    public Validator validator(MessageSource messageSource) {
+        LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
+        validator.setValidationMessageSource(messageSource);
+        return validator;
+    }
+
+    @Override
+    public void addInterceptors(InterceptorRegistry registry) {
+        registry.addInterceptor(new LocaleInterceptor());
+    }
+}

+ 19 - 0
citu-framework/citu-spring-boot-starter-web/src/main/java/com/citu/framework/i18n/config/I18nProperties.java

@@ -0,0 +1,19 @@
+package com.citu.framework.i18n.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+
+@Data
+@ConfigurationProperties(prefix = "citu.i18n")
+public class I18nProperties {
+
+    /**
+     * 是否开启,默认为 false
+     */
+    private boolean enable = false;
+
+
+
+
+}

+ 41 - 0
citu-framework/citu-spring-boot-starter-web/src/main/java/com/citu/framework/i18n/config/LocaleInterceptor.java

@@ -0,0 +1,41 @@
+package com.citu.framework.i18n.config;
+
+import org.springframework.context.i18n.LocaleContextHolder;
+import org.springframework.http.HttpHeaders;
+import org.springframework.util.StringUtils;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Locale;
+
+/**
+ * 国际化切换拦截
+ * @author rayson
+ **/
+public class LocaleInterceptor implements HandlerInterceptor {
+
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
+        String language = request.getHeader(HttpHeaders.ACCEPT_LANGUAGE);
+        Locale locale =  Locale.getDefault();
+
+        if (StringUtils.hasText(language)
+                && !language.trim().equals(Locale.SIMPLIFIED_CHINESE.toString())
+        ) {
+            String[] langParts = language.split("_");
+            if (langParts.length == 2) {
+                locale = new Locale(langParts[0], langParts[1]);
+            }
+        }
+
+        LocaleContextHolder.setLocale(locale);
+
+        return true;
+    }
+
+    @Override
+    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
+        LocaleContextHolder.resetLocaleContext();
+    }
+}

+ 6 - 0
citu-framework/citu-spring-boot-starter-web/src/main/java/com/citu/framework/i18n/package-info.java

@@ -0,0 +1,6 @@
+/**
+ * 基于 Swagger + Knife4j 实现 API 接口文档
+ *
+ * @author 芋道源码
+ */
+package com.citu.framework.i18n;

+ 10 - 1
citu-framework/citu-spring-boot-starter-web/src/main/java/com/citu/framework/swagger/config/CituSwaggerAutoConfiguration.java

@@ -121,7 +121,8 @@ public class CituSwaggerAutoConfiguration {
                 .pathsToMatch("/admin-api/" + path + "/**", "/app-api/" + path + "/**")
                 .addOperationCustomizer((operation, handlerMethod) -> operation
                         .addParametersItem(buildTenantHeaderParameter())
-                        .addParametersItem(buildSecurityHeaderParameter()))
+                        .addParametersItem(buildSecurityHeaderParameter())
+                        .addParametersItem(buildI18nHeaderParameter()))
                 .build();
     }
 
@@ -153,5 +154,13 @@ public class CituSwaggerAutoConfiguration {
                 .schema(new StringSchema()._default("Bearer test1").name(HEADER_TENANT_ID).description("认证 Token")); // 默认:使用用户编号为 1
     }
 
+    private static Parameter buildI18nHeaderParameter() {
+        return new Parameter()
+                .name(HttpHeaders.ACCEPT_LANGUAGE) // header 名
+                .description("语言") // 描述
+                .in(String.valueOf(SecurityScheme.In.HEADER)) // 请求 header
+                .schema(new StringSchema()._default("zh_CN").name(HEADER_TENANT_ID).description("默认中文")); // 默认:使用用户编号为 1
+    }
+
 }
 

+ 17 - 9
citu-framework/citu-spring-boot-starter-web/src/main/java/com/citu/framework/web/config/CituWebAutoConfiguration.java

@@ -2,6 +2,7 @@ package com.citu.framework.web.config;
 
 import com.citu.framework.apilog.core.service.ApiErrorLogFrameworkService;
 import com.citu.framework.common.enums.WebFilterOrderEnum;
+import com.citu.framework.i18n.config.I18nProperties;
 import com.citu.framework.web.core.filter.CacheRequestBodyFilter;
 import com.citu.framework.web.core.filter.DemoFilter;
 import com.citu.framework.web.core.handler.GlobalExceptionHandler;
@@ -15,6 +16,7 @@ import org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfigu
 import org.springframework.boot.context.properties.EnableConfigurationProperties;
 import org.springframework.boot.web.client.RestTemplateBuilder;
 import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.MessageSource;
 import org.springframework.context.annotation.Bean;
 import org.springframework.util.AntPathMatcher;
 import org.springframework.web.bind.annotation.RestController;
@@ -40,6 +42,18 @@ public class CituWebAutoConfiguration implements WebMvcConfigurer {
     @Value("${spring.application.name}")
     private String applicationName;
 
+    @Resource
+    private I18nProperties i18nProperties;
+
+    @Resource
+    private MessageSource messageSource;
+
+    public static <T extends Filter> FilterRegistrationBean<T> createFilterBean(T filter, Integer order) {
+        FilterRegistrationBean<T> bean = new FilterRegistrationBean<>(filter);
+        bean.setOrder(order);
+        return bean;
+    }
+
     @Override
     public void configurePathMatch(PathMatchConfigurer configurer) {
         configurePathMatch(configurer, webProperties.getAdminApi());
@@ -60,7 +74,7 @@ public class CituWebAutoConfiguration implements WebMvcConfigurer {
 
     @Bean
     public GlobalExceptionHandler globalExceptionHandler(ApiErrorLogFrameworkService ApiErrorLogFrameworkService) {
-        return new GlobalExceptionHandler(applicationName, ApiErrorLogFrameworkService);
+        return new GlobalExceptionHandler(applicationName, ApiErrorLogFrameworkService, i18nProperties.isEnable(), messageSource);
     }
 
     @Bean
@@ -68,6 +82,8 @@ public class CituWebAutoConfiguration implements WebMvcConfigurer {
         return new GlobalResponseBodyHandler();
     }
 
+    // ========== Filter 相关 ==========
+
     @Bean
     @SuppressWarnings("InstantiationOfUtilityClass")
     public WebFrameworkUtils webFrameworkUtils(WebProperties webProperties) {
@@ -75,8 +91,6 @@ public class CituWebAutoConfiguration implements WebMvcConfigurer {
         return new WebFrameworkUtils(webProperties);
     }
 
-    // ========== Filter 相关 ==========
-
     /**
      * 创建 CorsFilter Bean,解决跨域问题
      */
@@ -111,12 +125,6 @@ public class CituWebAutoConfiguration implements WebMvcConfigurer {
         return createFilterBean(new DemoFilter(), WebFilterOrderEnum.DEMO_FILTER);
     }
 
-    public static <T extends Filter> FilterRegistrationBean<T> createFilterBean(T filter, Integer order) {
-        FilterRegistrationBean<T> bean = new FilterRegistrationBean<>(filter);
-        bean.setOrder(order);
-        return bean;
-    }
-
     /**
      * 创建 RestTemplate 实例
      *

+ 63 - 19
citu-framework/citu-spring-boot-starter-web/src/main/java/com/citu/framework/web/core/handler/GlobalExceptionHandler.java

@@ -4,16 +4,20 @@ import cn.hutool.core.exceptions.ExceptionUtil;
 import cn.hutool.core.map.MapUtil;
 import cn.hutool.core.util.StrUtil;
 import com.citu.framework.apilog.core.service.ApiErrorLogFrameworkService;
+import com.citu.framework.common.exception.ErrorCode;
 import com.citu.framework.common.exception.ServiceException;
 import com.citu.framework.common.pojo.CommonResult;
 import com.citu.framework.common.util.collection.SetUtils;
 import com.citu.framework.common.util.json.JsonUtils;
 import com.citu.framework.common.util.monitor.TracerUtils;
 import com.citu.framework.common.util.servlet.ServletUtils;
+import com.citu.framework.common.util.string.StrUtils;
 import com.citu.framework.web.core.util.WebFrameworkUtils;
 import com.citu.module.infra.api.logger.dto.ApiErrorLogCreateReqDTO;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.MessageSource;
+import org.springframework.context.i18n.LocaleContextHolder;
 import org.springframework.security.access.AccessDeniedException;
 import org.springframework.util.Assert;
 import org.springframework.validation.BindException;
@@ -56,12 +60,17 @@ public class GlobalExceptionHandler {
 
     private final ApiErrorLogFrameworkService apiErrorLogFrameworkService;
 
+    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
+    private final boolean enableI18n;
+
+    private final MessageSource messageSource;
+
     /**
      * 处理所有异常,主要是提供给 Filter 使用
      * 因为 Filter 不走 SpringMVC 的流程,但是我们又需要兜底处理异常,所以这里提供一个全量的异常处理过程,保持逻辑统一。
      *
      * @param request 请求
-     * @param ex 异常
+     * @param ex      异常
      * @return 通用返回
      */
     public CommonResult<?> allExceptionHandler(HttpServletRequest request, Throwable ex) {
@@ -98,26 +107,56 @@ public class GlobalExceptionHandler {
         return defaultExceptionHandler(request, ex);
     }
 
+
     /**
-     * 处理 SpringMVC 请求参数缺失
+     * 公共返回结果
      *
+     * @param code
+     * @param msg
+     * @return 公共结构
+     **/
+    private CommonResult<?> commonResult(Integer code, String msg) {
+        if (!enableI18n) {
+            // 国际化关闭
+            return CommonResult.error(code, msg);
+        }
+        // 国际化开启
+        String i18nMsg = messageSource.getMessage(StrUtils.formatNumberWithUnderscores(code, 10),
+                null, LocaleContextHolder.getLocale());
+        if (String.valueOf(code).equals(i18nMsg)) {
+            // 找不到国际化信息,则使用默认的错误提示
+            return CommonResult.error(code, msg);
+        } else {
+            return CommonResult.error(code, i18nMsg);
+        }
+    }
+
+    private CommonResult<?> commonResult(ErrorCode errorCode) {
+        return commonResult(errorCode.getCode(), errorCode.getMsg());
+    }
+
+    /**
+     * 处理 SpringMVC 请求参数缺失
+     * <p>
      * 例如说,接口上设置了 @RequestParam("xx") 参数,结果并未传递 xx 参数
      */
     @ExceptionHandler(value = MissingServletRequestParameterException.class)
     public CommonResult<?> missingServletRequestParameterExceptionHandler(MissingServletRequestParameterException ex) {
         log.warn("[missingServletRequestParameterExceptionHandler]", ex);
-        return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数缺失:%s", ex.getParameterName()));
+        // return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数缺失:%s", ex.getParameterName()));
+        return commonResult(BAD_REQUEST.getCode(), ex.getParameterName());
     }
 
     /**
      * 处理 SpringMVC 请求参数类型错误
-     *
+     * <p>
      * 例如说,接口上设置了 @RequestParam("xx") 参数为 Integer,结果传递 xx 参数类型为 String
      */
     @ExceptionHandler(MethodArgumentTypeMismatchException.class)
     public CommonResult<?> methodArgumentTypeMismatchExceptionHandler(MethodArgumentTypeMismatchException ex) {
         log.warn("[missingServletRequestParameterExceptionHandler]", ex);
-        return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数类型错误:%s", ex.getMessage()));
+        // return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数类型错误:%s", ex.getMessage()));
+        return commonResult(BAD_REQUEST.getCode(), ex.getMessage());
     }
 
     /**
@@ -128,7 +167,8 @@ public class GlobalExceptionHandler {
         log.warn("[methodArgumentNotValidExceptionExceptionHandler]", ex);
         FieldError fieldError = ex.getBindingResult().getFieldError();
         assert fieldError != null; // 断言,避免告警
-        return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数不正确:%s", fieldError.getDefaultMessage()));
+        // return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数不正确:%s", fieldError.getDefaultMessage()));
+        return commonResult(BAD_REQUEST.getCode(), fieldError.getDefaultMessage());
     }
 
     /**
@@ -139,7 +179,8 @@ public class GlobalExceptionHandler {
         log.warn("[handleBindException]", ex);
         FieldError fieldError = ex.getFieldError();
         assert fieldError != null; // 断言,避免告警
-        return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数不正确:%s", fieldError.getDefaultMessage()));
+        // return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数不正确:%s", fieldError.getDefaultMessage()));
+        return commonResult(BAD_REQUEST.getCode(), fieldError.getDefaultMessage());
     }
 
     /**
@@ -149,7 +190,8 @@ public class GlobalExceptionHandler {
     public CommonResult<?> constraintViolationExceptionHandler(ConstraintViolationException ex) {
         log.warn("[constraintViolationExceptionHandler]", ex);
         ConstraintViolation<?> constraintViolation = ex.getConstraintViolations().iterator().next();
-        return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数不正确:%s", constraintViolation.getMessage()));
+        // return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数不正确:%s", constraintViolation.getMessage()));
+        return commonResult(BAD_REQUEST.getCode(), constraintViolation.getMessage());
     }
 
     /**
@@ -159,12 +201,12 @@ public class GlobalExceptionHandler {
     public CommonResult<?> validationException(ValidationException ex) {
         log.warn("[constraintViolationExceptionHandler]", ex);
         // 无法拼接明细的错误信息,因为 Dubbo Consumer 抛出 ValidationException 异常时,是直接的字符串信息,且人类不可读
-        return CommonResult.error(BAD_REQUEST);
+        return commonResult(BAD_REQUEST);
     }
 
     /**
      * 处理 SpringMVC 请求地址不存在
-     *
+     * <p>
      * 注意,它需要设置如下两个配置项:
      * 1. spring.mvc.throw-exception-if-no-handler-found 为 true
      * 2. spring.mvc.static-path-pattern 为 /statics/**
@@ -172,35 +214,37 @@ public class GlobalExceptionHandler {
     @ExceptionHandler(NoHandlerFoundException.class)
     public CommonResult<?> noHandlerFoundExceptionHandler(NoHandlerFoundException ex) {
         log.warn("[noHandlerFoundExceptionHandler]", ex);
-        return CommonResult.error(NOT_FOUND.getCode(), String.format("请求地址不存在:%s", ex.getRequestURL()));
+        // return CommonResult.error(NOT_FOUND.getCode(), String.format("请求地址不存在:%s", ex.getRequestURL()));
+        return commonResult(NOT_FOUND.getCode(), ex.getRequestURL());
     }
 
     /**
      * 处理 SpringMVC 请求方法不正确
-     *
+     * <p>
      * 例如说,A 接口的方法为 GET 方式,结果请求方法为 POST 方式,导致不匹配
      */
     @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
     public CommonResult<?> httpRequestMethodNotSupportedExceptionHandler(HttpRequestMethodNotSupportedException ex) {
         log.warn("[httpRequestMethodNotSupportedExceptionHandler]", ex);
-        return CommonResult.error(METHOD_NOT_ALLOWED.getCode(), String.format("请求方法不正确:%s", ex.getMessage()));
+        // return CommonResult.error(METHOD_NOT_ALLOWED.getCode(), String.format("请求方法不正确:%s", ex.getMessage()));
+        return commonResult(METHOD_NOT_ALLOWED.getCode(), ex.getMessage());
     }
 
     /**
      * 处理 Spring Security 权限不足的异常
-     *
+     * <p>
      * 来源是,使用 @PreAuthorize 注解,AOP 进行权限拦截
      */
     @ExceptionHandler(value = AccessDeniedException.class)
     public CommonResult<?> accessDeniedExceptionHandler(HttpServletRequest req, AccessDeniedException ex) {
         log.warn("[accessDeniedExceptionHandler][userId({}) 无法访问 url({})]", WebFrameworkUtils.getLoginUserId(req),
                 req.getRequestURL(), ex);
-        return CommonResult.error(FORBIDDEN);
+        return commonResult(FORBIDDEN);
     }
 
     /**
      * 处理业务异常 ServiceException
-     *
+     * <p>
      * 例如说,商品库存不足,用户手机号已存在。
      */
     @ExceptionHandler(value = ServiceException.class)
@@ -209,7 +253,7 @@ public class GlobalExceptionHandler {
             // 不包含的时候,才进行打印,避免 ex 堆栈过多
             log.info("[serviceExceptionHandler]", ex);
         }
-        return CommonResult.error(ex.getCode(), ex.getMessage());
+        return commonResult(ex.getCode(), ex.getMessage());
     }
 
     /**
@@ -228,7 +272,7 @@ public class GlobalExceptionHandler {
         // 插入异常日志
         createExceptionLog(req, ex);
         // 返回 ERROR CommonResult
-        return CommonResult.error(INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg());
+        return commonResult(INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg());
     }
 
     private void createExceptionLog(HttpServletRequest req, Throwable e) {
@@ -240,7 +284,7 @@ public class GlobalExceptionHandler {
             // 执行插入 errorLog
             apiErrorLogFrameworkService.createApiErrorLog(errorLog);
         } catch (Throwable th) {
-            log.error("[createExceptionLog][url({}) log({}) 发生异常]", req.getRequestURI(),  JsonUtils.toJsonString(errorLog), th);
+            log.error("[createExceptionLog][url({}) log({}) 发生异常]", req.getRequestURI(), JsonUtils.toJsonString(errorLog), th);
         }
     }
 

+ 1 - 0
citu-framework/citu-spring-boot-starter-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

@@ -6,3 +6,4 @@ com.citu.framework.apilog.config.CituApiLogRpcAutoConfiguration
 com.citu.framework.banner.config.CituBannerAutoConfiguration
 com.citu.framework.errorcode.config.CituErrorCodeAutoConfiguration
 com.citu.framework.errorcode.config.CituErrorCodeRpcAutoConfiguration
+com.citu.framework.i18n.config.CituI18nAutoConfiguration

+ 21 - 21
menduner/menduner-system-api/src/main/java/com/citu/module/menduner/system/enums/ErrorCodeConstants.java

@@ -53,10 +53,10 @@ public interface ErrorCodeConstants {
     // ========== 证书 1_100_014_000 ==========
     ErrorCode MDE_CERTIFICATE_NOT_EXISTS = new ErrorCode(1_100_014_001, "证书不存在");
 
-    // ========== 证书 1_100_015_000 ==========
+    // ========== 访问量 1_100_015_000 ==========
     ErrorCode MDE_VISITS_NOT_EXISTS = new ErrorCode(1_100_015_001, "访问量不存在");
 
-    // ========== 门墩儿-用户登录 1_200_001_000 ==========
+    // ========== 用户登录 1_200_001_000 ==========
     ErrorCode MDE_USER_NOT_EXISTS = new ErrorCode(1_200_001_001, "用户不存在");
     ErrorCode MDE_USER_MOBILE_NOT_EXISTS = new ErrorCode(1_200_001_002, "手机号未注册用户");
     ErrorCode MDE_USER_MOBILE_USED = new ErrorCode(1_200_001_003, "修改手机失败,该手机号({})已经被使用");
@@ -82,54 +82,54 @@ public interface ErrorCodeConstants {
 
     // ========== 角色模块 1_200_003_000 ==========
     ErrorCode MDE_ROLE_NOT_EXISTS = new ErrorCode(1_200_003_001, "角色不存在");
-    ErrorCode MDE_ROLE_NAME_DUPLICATE = new ErrorCode(1_200_003_001, "已经存在名为【{}】的角色");
-    ErrorCode MDE_ROLE_CODE_DUPLICATE = new ErrorCode(1_200_003_002, "已经存在编码为【{}】的角色");
-    ErrorCode MDE_ROLE_CAN_NOT_UPDATE_SYSTEM_TYPE_ROLE = new ErrorCode(1_200_003_003, "不能操作类型为系统内置的角色");
-    ErrorCode MDE_ROLE_IS_DISABLE = new ErrorCode(1_200_003_004, "名字为【{}】的角色已被禁用");
-    ErrorCode MDE_ROLE_ADMIN_CODE_ERROR = new ErrorCode(1_200_003_005, "编码【{}】不能使用");
+    ErrorCode MDE_ROLE_NAME_DUPLICATE = new ErrorCode(1_200_003_002, "已经存在名为【{}】的角色");
+    ErrorCode MDE_ROLE_CODE_DUPLICATE = new ErrorCode(1_200_003_003, "已经存在编码为【{}】的角色");
+    ErrorCode MDE_ROLE_CAN_NOT_UPDATE_SYSTEM_TYPE_ROLE = new ErrorCode(1_200_003_004, "不能操作类型为系统内置的角色");
+    ErrorCode MDE_ROLE_IS_DISABLE = new ErrorCode(1_200_003_005, "名字为【{}】的角色已被禁用");
+    ErrorCode MDE_ROLE_ADMIN_CODE_ERROR = new ErrorCode(1_200_003_006, "编码【{}】不能使用");
 
-    // ========== 门墩儿-企业信息 1_200_004_000 ==========
+    // ========== 企业信息 1_200_004_000 ==========
     ErrorCode MDE_ENTERPRISE_NOT_EXISTS = new ErrorCode(1_200_004_001, "企业信息不存在");
 
-    // ========== 门墩儿-企业工商信息  1_200_005_001 ==========
+    // ========== 企业工商信息  1_200_005_001 ==========
     ErrorCode MDE_ENTERPRISE_BUSINESS_NOT_EXISTS = new ErrorCode(1_200_005_001, "企业工商信息不存在");
 
-    // ========== 门墩儿-企业注册申请 1_200_006_000 ==========
+    // ========== 企业注册申请 1_200_006_000 ==========
     ErrorCode MDE_ENTERPRISE_REGISTER_NOT_EXISTS = new ErrorCode(1_200_006_001, "企业注册申请不存在");
 
-    // ========== 门墩儿-企业地址 1_200_007_001 ==========
+    // ========== 企业地址 1_200_007_001 ==========
     ErrorCode MDE_ENTERPRISE_ADDRESS_NOT_EXISTS = new ErrorCode(1_200_007_001, "企业地址不存在");
 
-    // ========== 门墩儿-企业登录用户 1_200_008_000 ==========
+    // ========== 企业登录用户 1_200_008_000 ==========
     ErrorCode MDE_ENTERPRISE_USER_BIND_NOT_EXISTS = new ErrorCode(1_200_008_001, "企业登录用户不存在");
 
-    // ========== 门墩儿-企业岗位信息 1_200_009_000 ==========
+    // ========== 企业岗位信息 1_200_009_000 ==========
     ErrorCode ENTERPRISE_POST_NOT_EXISTS = new ErrorCode(1_200_009_001, "企业岗位信息不存在");
 
-    // ========== 门墩儿-招聘职位 1_200_010_000 ==========
+    // ========== 招聘职位 1_200_010_000 ==========
     ErrorCode MDE_JOB_ADVERTISED_NOT_EXISTS = new ErrorCode(1_200_010_001, "招聘职位不存在");
 
-    // ========== 门墩儿 - 企业招聘者浏览 1_200_011_000 ==========
+    // ========== 企业招聘者浏览 1_200_011_000 ==========
     ErrorCode ENTERPRISE_USER_LOOK_NOT_EXISTS = new ErrorCode(1_200_011_001, "企业招聘者浏览不存在");
 
-    // ========== 门墩儿-人才-企业关注订阅 1_200_012_000 ==========
+    // ========== 人才-企业关注订阅 1_200_012_000 ==========
     ErrorCode PERSON_ENTERPRISE_ATTENTION_NOT_EXISTS = new ErrorCode(1_200_012_001, "企业关注订阅不存在");
     ErrorCode PERSON_ENTERPRISE_ATTENTION_EXISTS = new ErrorCode(1_200_012_002, "企业已关注订阅,请勿重复点击");
 
-    // ========== 门墩儿-人才-浏览记录 1_200_013_000 ==========
+    // ========== 人才-浏览记录 1_200_013_000 ==========
     ErrorCode PERSON_BROWSE_RECORD_NOT_EXISTS = new ErrorCode(1_200_013_001, "浏览记录不存在");
 
-    // ========== 门墩儿-人才-招聘职位收藏 1_200_014_000 ==========
+    // ========== 人才-招聘职位收藏 1_200_014_000 ==========
     ErrorCode PERSON_JOB_COLLECTION_NOT_EXISTS = new ErrorCode(1_200_014_001, "招聘职位收藏不存在");
     ErrorCode PERSON_JOB_COLLECTION_EXISTS = new ErrorCode(1_200_014_002, "职位已收藏,请勿重复点击");
 
-    // ========== 门墩儿-培训经历 1_200_015_000 ==========
+    // ========== 培训经历 1_200_015_000 ==========
     ErrorCode TRAIN_EXP_NOT_EXISTS = new ErrorCode(1_200_015_001, "培训经历不存在");
 
-    // ========== 门墩儿-项目经历 1_200_016_000 ==========
+    // ========== 项目经历 1_200_016_000 ==========
     ErrorCode PROJECT_EXP_NOT_EXISTS = new ErrorCode(1_200_016_001, "项目经历不存在");
 
-    // ========== 门墩儿-职业技能 1_200_017_000 ==========
+    // ========== 职业技能 1_200_017_000 ==========
     ErrorCode SKILL_NOT_EXISTS = new ErrorCode(1_200_017_001, "职业技能不存在");
     ErrorCode SKILL_EXITS_CHILDREN = new ErrorCode(1_200_017_002, "存在存在子职业技能,无法删除");
     ErrorCode SKILL_PARENT_NOT_EXITS = new ErrorCode(1_200_017_003,"父级职业技能不存在");

+ 1 - 1
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/config/CustomDataPermissionAutoConfiguration.java → menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/config/permission/CustomDataPermissionAutoConfiguration.java

@@ -1,4 +1,4 @@
-package com.citu.module.menduner.system.config;
+package com.citu.module.menduner.system.config.permission;
 
 import cn.hutool.extra.spring.SpringUtil;
 import com.citu.framework.security.core.LoginUser;

+ 1 - 1
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/config/CustomDataPermissionRule.java → menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/config/permission/CustomDataPermissionRule.java

@@ -1,4 +1,4 @@
-package com.citu.module.menduner.system.config;
+package com.citu.module.menduner.system.config.permission;
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.text.CharSequenceUtil;

+ 1 - 1
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/config/CustomDataPermissionRuleCustomizer.java → menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/config/permission/CustomDataPermissionRuleCustomizer.java

@@ -1,4 +1,4 @@
-package com.citu.module.menduner.system.config;
+package com.citu.module.menduner.system.config.permission;
 
 /**
  * @author rayson

+ 3 - 6
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/controller/app/person/AppPersonController.java

@@ -13,10 +13,7 @@ import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
 
@@ -48,7 +45,7 @@ public class AppPersonController {
     }
 
     @PreAuthenticated
-    @GetMapping("/job/favorite")
+    @PostMapping("/job/favorite")
     @Operation(summary = "用户收藏职位")
     public CommonResult<Boolean> favorite(@RequestParam("jobId") Long jobId) {
         Boolean result = jobFavoriteService.favorite(jobId);
@@ -56,7 +53,7 @@ public class AppPersonController {
     }
 
     @PreAuthenticated
-    @GetMapping("/enterprise/subscribe")
+    @PostMapping("/enterprise/subscribe")
     @Operation(summary = "用户关注订阅企业")
     public CommonResult<Boolean> subscribe(@RequestParam("enterpriseId")Long enterpriseId) {
         Boolean result = enterpriseSubscribeService.subscribe(enterpriseId);

+ 39 - 0
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/controller/app/test/TestController.java

@@ -0,0 +1,39 @@
+package com.citu.module.menduner.system.controller.app.test;
+
+import com.citu.framework.common.pojo.CommonResult;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.MessageSource;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.validation.Valid;
+import java.util.Locale;
+
+import static com.citu.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static com.citu.module.menduner.system.enums.ErrorCodeConstants.MDE_AREA_HOT_EXISTS;
+
+@Tag(name = "用户端 - test")
+@RestController
+@RequestMapping("/menduner/system/test")
+@Validated
+@Slf4j
+public class TestController {
+
+    @Resource
+    MessageSource messageSource;
+
+
+    @PostMapping("/validation")
+    public CommonResult<String> test(@RequestBody @Valid TestReqVO reqVO) {
+        throw exception(MDE_AREA_HOT_EXISTS);
+    }
+
+
+    @GetMapping("/i18n")
+    public String hello(@RequestHeader(name = "Accept-Language", required = false) Locale locale) {
+        // return messageSource.getMessage("person.name", null, LocaleContextHolder.getLocale());
+        return messageSource.getMessage("1_100_001_001", null, locale);
+    }
+}

+ 14 - 0
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/controller/app/test/TestReqVO.java

@@ -0,0 +1,14 @@
+package com.citu.module.menduner.system.controller.app.test;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+@Schema(description = "test Request VO")
+@Data
+public class TestReqVO {
+
+    @NotBlank(message = "{person.name}")
+    private String name;
+}

+ 2 - 0
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/controller/app/user/AppMdeUserController.java

@@ -69,4 +69,6 @@ public class AppMdeUserController {
     }
 
 
+
+
 }

+ 1 - 1
menduner/menduner-system-biz/src/main/java/com/citu/module/menduner/system/framework/datapermission/config/DataPermissionConfiguration.java

@@ -1,7 +1,7 @@
 package com.citu.module.menduner.system.framework.datapermission.config;
 
 
-import com.citu.module.menduner.system.config.CustomDataPermissionRuleCustomizer;
+import com.citu.module.menduner.system.config.permission.CustomDataPermissionRuleCustomizer;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 

+ 17 - 1
menduner/menduner-system-biz/src/main/resources/application.yaml

@@ -3,6 +3,20 @@ spring:
     allow-circular-references: true # 允许循环依赖,因为项目是三层架构,无法避免这个情况。
     allow-bean-definition-overriding: true # 允许 Bean 覆盖,例如说 Feign 等会存在重复定义的服务
 
+  # 国际化
+  messages:
+    # 默认名称
+    basename: i18n/messages
+    encoding: UTF-8
+    # 找不到对应区域的语言时,是否回退到系统区域的语言,默认 true
+    fallback-to-system-locale: false
+    # 找不到code时,是否直接返回code值,而不是抛异常,默认false,抛异常
+    use-code-as-default-message: true
+    # 是否始终使用MessageFormat格式化国际化消息,即使没有国际化消息参数,默认false
+    always-use-message-format: false
+    # 加载国际化资源后的过期时间,不设置不过期,单位秒
+    cache-duration:
+
   # Servlet 配置
   servlet:
     # 文件上传相关配置项
@@ -105,10 +119,12 @@ citu:
     description: 提供管理员管理的所有功能
     version: ${citu.info.version}
     base-package: ${citu.info.base-package}
+  i18n:
+    enable: true
   captcha:
     enable: false # 验证码的开关,默认为 true;
   error-code: # 错误码相关配置项
-    enable: true
+    enable: false
     constants-class-list:
       - com.citu.module.menduner.system.enums.ErrorCodeConstants
   tenant: # 多租户相关配置项

+ 1 - 0
menduner/menduner-system-biz/src/main/resources/i18n/messages.properties

@@ -0,0 +1 @@
+person.name=3453453

+ 93 - 0
menduner/menduner-system-biz/src/main/resources/i18n/messages_en_US.properties

@@ -0,0 +1,93 @@
+# ========== 人员信息-个人档案 1_100_001_000 ==========
+1_100_001_001=Personal Profile Does Not Exist
+# ========== 行业信息 1_100_002_000 ==========
+1_100_002_001=Industry information does not exist
+# ========== 职位信息 1_100_003_000 ==========
+1_100_002_003=Position information does not exist
+# ========== 地区 1_100_004_000 ==========
+1_100_004_001=Region does not exist
+1_100_004_002=Popular regions already exist, please do not add them again
+# ========== 简历附件 1_100_005_000 ==========
+1_100_005_001=Resume attachment does not exist
+# ========== 教育经历 1_100_006_000 ==========
+1_100_006_001=Educational experience does not exist
+# ========== 求职意向 1_100_007_000 ==========
+1_100_007_001=Job search intention does not exist
+# ========== 专业 1_100_008_000 ==========
+1_100_008_001=Major does not exist
+# ========== 职位标签 1_100_009_000 ==========
+1_100_009_001=Position tag does not exist
+# ========== 学校 1_100_010_000 ==========
+1_100_010_001=School does not exist
+# ========== 人员证书 1_100_011_000 ==========
+1_100_011_001=Personnel certificate does not exist
+# ========== 工作经历 1_100_012_000 ==========
+1_100_012_001=Work experience does not exist
+# ========== 人员技能 1_100_013_000 ==========
+1_100_013_001=Personnel skill does not exist
+# ========== 证书 1_100_014_000 ==========
+1_100_014_001=Certificate does not exist
+# ========== 访问量 1_100_015_000 ==========
+1_100_015_001=The traffic does not exist
+# ========== 用户登录 1_200_001_000 ==========
+1_200_001_001=User does not exist
+1_200_001_002=Unregistered user with phone number
+1_200_001_003=Modifying phone failed, the phone number ({}) has already been used
+1_200_001_004=User account already exists
+1_200_001_005=Phone number already exists
+1_200_001_006=Email already exists
+1_200_001_008=Importing user data cannot be empty!
+1_200_001_009=User password verification failed
+1_200_001_010=The user named [{}] has been disabled
+1_200_001_011=User creation failed due to exceeding the maximum tenant quota ({}) for tenants!
+# ========== AUTH 模块 1_200_002_000 ==========
+1_200_002_001=Login failed, incorrect account and password
+1_200_002_002=Login failed, account disabled
+1_200_002_003=Login failed, unable to resolve third-party login information
+1_200_002_004=The phone number has already been used
+1_002_000_004=Incorrect verification code, reason: {}
+1_002_000_005=Account not bound, needs to be bound
+1_002_000_006=Token has expired
+1_002_000_007=Phone number does not exist
+# ========== 角色模块 1_200_003_000 ==========
+1_200_003_001=Character does not exist
+1_200_003_002=A role named [{}] already exists
+1_200_003_003=A role with code [{}] already exists
+1_200_003_004=Cannot operate on roles with built-in system types
+1_200_003_005=The character named [{}] has been disabled
+1_200_003_006=Encoding [{}] cannot be used
+# ========== 企业信息 1_200_004_000 ==========
+1_200_004_001=Enterprise information does not exist
+# ========== 企业工商信息  1_200_005_001 ==========
+1_200_005_001=Enterprise business information does not exist
+# ========== 企业注册申请 1_200_006_000 ==========
+1_200_006_001=The enterprise registration application does not exist
+# ========== 企业地址 1_200_007_001 ==========
+1_200_007_001=The company address does not exist
+# ========== 企业登录用户 1_200_008_000 ==========
+1_200_008_001=Enterprise login user does not exist
+# ========== 企业岗位信息 1_200_009_000 ==========
+1_200_009_001=Enterprise position information does not exist
+# ========== 招聘职位 1_200_010_000 ==========
+1_200_010_001=Recruitment position does not exist
+# ========== 企业招聘者浏览 1_200_011_000 ==========
+1_200_011_001=Enterprise recruiter browsing does not exist
+# ========== 人才-企业关注订阅 1_200_012_000 ==========
+1_200_012_001=Enterprise follow subscription does not exist
+1_200_012_002=Enterprise has followed and subscribed, please do not click again
+# ========== 人才-浏览记录 1_200_013_000 ==========
+1_200_013_001=Browsing history does not exist
+# ========== 人才-招聘职位收藏 1_200_014_000 ==========
+1_200_014_001=Recruitment position collection does not exist
+1_200_014_002=Position has been saved, please do not click again
+# ========== 培训经历 1_200_015_000 ==========
+1_200_015_001=Training experience does not exist
+# ========== 项目经历 1_200_016_000 ==========
+1_200_016_001=Project experience does not exist
+# ========== 职业技能 1_200_017_000 ==========
+1_200_017_001=Vocational skill does not exist
+1_200_017_002=There are sub profession skills that cannot be deleted
+1_200_017_003=Parent level vocational skill does not exist
+1_200_017_004=Unable to set oneself as a parent vocational skill
+1_200_017_005=There is already a vocational skill with the Chinese name for this skill
+1_200_017_006=Cannot set one's own child Skill as the parent Skill

+ 93 - 0
menduner/menduner-system-biz/src/main/resources/i18n/messages_zh_CN.properties

@@ -0,0 +1,93 @@
+# ========== 人员信息-个人档案 1_100_001_000 ==========
+1_100_001_001=人员信息-个人档案不存在
+# ========== 行业信息 1_100_002_000 ==========
+1_100_002_001=行业信息不存在
+# ========== 职位信息 1_100_003_000 ==========
+1_100_002_003=职位信息不存在
+# ========== 地区 1_100_004_000 ==========
+1_100_004_001=地区不存在
+1_100_004_002=热门地区已存在,请勿重复添加
+# ========== 简历附件 1_100_005_000 ==========
+1_100_005_001=简历附件不存在
+# ========== 教育经历 1_100_006_000 ==========
+1_100_006_001=教育经历不存在
+# ========== 求职意向 1_100_007_000 ==========
+1_100_007_001=求职意向不存在
+# ========== 专业 1_100_008_000 ==========
+1_100_008_001=专业不存在
+# ========== 职位标签 1_100_009_000 ==========
+1_100_009_001=职位标签不存在
+# ========== 学校 1_100_010_000 ==========
+1_100_010_001=学校不存在
+# ========== 人员证书 1_100_011_000 ==========
+1_100_011_001=人员证书不存在
+# ========== 工作经历 1_100_012_000 ==========
+1_100_012_001=工作经历不存在
+# ========== 人员技能 1_100_013_000 ==========
+1_100_013_001=人员技能不存在
+# ========== 证书 1_100_014_000 ==========
+1_100_014_001=证书不存在
+# ========== 访问量 1_100_015_000 ==========
+1_100_015_001=访问量不存在
+# ========== 用户登录 1_200_001_000 ==========
+1_200_001_001=用户不存在
+1_200_001_002=手机号未注册用户
+1_200_001_003=修改手机失败,该手机号({})已经被使用
+1_200_001_004=用户账号已经存在
+1_200_001_005=手机号已经存在
+1_200_001_006=邮箱已经存在
+1_200_001_008=导入用户数据不能为空!
+1_200_001_009=用户密码校验失败
+1_200_001_010=名字为【{}】的用户已被禁用
+1_200_001_011=创建用户失败,原因:超过租户最大租户配额({})!
+# ========== AUTH 模块 1_200_002_000 ==========
+1_200_002_001=登录失败,账号密码不正确
+1_200_002_002=登录失败,账号被禁用
+1_200_002_003=登录失败,解析不到三方登录信息
+1_200_002_004=手机号已经被使用
+1_002_000_004=验证码不正确,原因:{}
+1_002_000_005=未绑定账号,需要进行绑定
+1_002_000_006=Token 已经过期
+1_002_000_007=手机号不存在
+# ========== 角色模块 1_200_003_000 ==========
+1_200_003_001=角色不存在
+1_200_003_002=已经存在名为【{}】的角色
+1_200_003_003=已经存在编码为【{}】的角色
+1_200_003_004=不能操作类型为系统内置的角色
+1_200_003_005=名字为【{}】的角色已被禁用
+1_200_003_006=编码【{}】不能使用
+# ========== 企业信息 1_200_004_000 ==========
+1_200_004_001=企业信息不存在
+# ========== 企业工商信息  1_200_005_001 ==========
+1_200_005_001=企业工商信息不存在
+# ========== 企业注册申请 1_200_006_000 ==========
+1_200_006_001=企业注册申请不存在
+# ========== 企业地址 1_200_007_001 ==========
+1_200_007_001=企业地址不存在
+# ========== 企业登录用户 1_200_008_000 ==========
+1_200_008_001=企业登录用户不存在
+# ========== 企业岗位信息 1_200_009_000 ==========
+1_200_009_001=企业岗位信息不存在
+# ========== 招聘职位 1_200_010_000 ==========
+1_200_010_001=招聘职位不存在
+# ========== 企业招聘者浏览 1_200_011_000 ==========
+1_200_011_001=企业招聘者浏览不存在
+# ========== 人才-企业关注订阅 1_200_012_000 ==========
+1_200_012_001=企业关注订阅不存在
+1_200_012_002=企业已关注订阅,请勿重复点击
+# ========== 人才-浏览记录 1_200_013_000 ==========
+1_200_013_001=浏览记录不存在
+# ========== 人才-招聘职位收藏 1_200_014_000 ==========
+1_200_014_001=招聘职位收藏不存在
+1_200_014_002=职位已收藏,请勿重复点击
+# ========== 培训经历 1_200_015_000 ==========
+1_200_015_001=培训经历不存在
+# ========== 项目经历 1_200_016_000 ==========
+1_200_016_001=项目经历不存在
+# ========== 职业技能 1_200_017_000 ==========
+1_200_017_001=职业技能不存在
+1_200_017_002=存在存在子职业技能,无法删除
+1_200_017_003=父级职业技能不存在
+1_200_017_004=不能设置自己为父职业技能
+1_200_017_005=已经存在该技能中文名称的职业技能
+1_200_017_006=不能设置自己的子Skill为父Skill

+ 1 - 0
menduner/menduner-system-biz/src/main/resources/i18n/messages_zh_HK.properties

@@ -0,0 +1 @@
+person.name=88888888