浏览代码

自动扫描classpath*:i18n/**下的messages

zhou-hao 3 年之前
父节点
当前提交
8a140bc853

+ 0 - 20
hsweb-authorization/hsweb-authorization-api/src/main/java/org/hswebframework/web/authorization/configuration/AuthorizationI18nConfiguration.java

@@ -1,20 +0,0 @@
-package org.hswebframework.web.authorization.configuration;
-
-import org.springframework.context.MessageSource;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.support.ResourceBundleMessageSource;
-
-@Configuration
-public class AuthorizationI18nConfiguration {
-
-    @Bean
-    public MessageSource authorizationMessageSource(){
-        ResourceBundleMessageSource messageSource=new ResourceBundleMessageSource();
-        messageSource.setDefaultEncoding("UTF-8");
-        messageSource.setBundleClassLoader(AuthorizationI18nConfiguration.class.getClassLoader());
-        messageSource.setBasenames("i18n/authentication/messages");
-        return messageSource;
-    }
-
-}

+ 0 - 20
hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/configuration/Commons18nConfiguration.java

@@ -1,20 +0,0 @@
-package org.hswebframework.web.crud.configuration;
-
-import org.springframework.context.MessageSource;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.support.ResourceBundleMessageSource;
-
-@Configuration
-public class Commons18nConfiguration {
-
-    @Bean
-    public MessageSource commonsMessageSource(){
-        ResourceBundleMessageSource messageSource=new ResourceBundleMessageSource();
-        messageSource.setDefaultEncoding("UTF-8");
-        messageSource.setBundleClassLoader(Commons18nConfiguration.class.getClassLoader());
-        messageSource.setBasenames("i18n/commons/messages");
-        return messageSource;
-    }
-
-}

+ 2 - 2
hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/entity/factory/MapperEntityFactory.java

@@ -124,7 +124,7 @@ public class MapperEntityFactory implements EntityFactory, BeanFactory {
         if (realType == null) {
             if (!Modifier.isInterface(beanClass.getModifiers()) && !Modifier.isAbstract(beanClass.getModifiers())) {
                 realType = beanClass;
-            }else {
+            } else {
                 mapper = defaultMapperFactory.apply(beanClass);
             }
         }
@@ -172,7 +172,7 @@ public class MapperEntityFactory implements EntityFactory, BeanFactory {
             return (T) new HashSet<>();
         }
 
-        throw new NotFoundException("can not create instance:"+beanClass);
+        throw new NotFoundException("error.cant_create_instance", beanClass);
     }
 
     @Override

+ 0 - 7
hsweb-commons/hsweb-commons-crud/src/main/java/org/hswebframework/web/crud/web/CommonWebFluxConfiguration.java

@@ -8,17 +8,10 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.context.MessageSource;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
-import org.springframework.context.i18n.LocaleContext;
-import org.springframework.context.support.ReloadableResourceBundleMessageSource;
-import org.springframework.context.support.ResourceBundleMessageSource;
 import org.springframework.core.ReactiveAdapterRegistry;
 import org.springframework.http.codec.ServerCodecConfigurer;
 import org.springframework.web.reactive.accept.RequestedContentTypeResolver;
-import org.springframework.web.server.ServerWebExchange;
 import org.springframework.web.server.WebFilter;
-import org.springframework.web.server.WebFilterChain;
-import org.springframework.web.server.i18n.LocaleContextResolver;
-import reactor.core.publisher.Mono;
 
 @Configuration
 @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)

+ 4 - 0
hsweb-core/src/main/java/org/hswebframework/web/exception/I18nSupportException.java

@@ -28,6 +28,10 @@ public class I18nSupportException extends RuntimeException {
         this.code = code;
     }
 
+    @Override
+    public String getMessage() {
+        return code;
+    }
 
     @Override
     public String getLocalizedMessage() {

+ 10 - 1
hsweb-core/src/main/java/org/hswebframework/web/exception/ValidationException.java

@@ -16,6 +16,8 @@ import java.util.*;
 @ResponseStatus(HttpStatus.BAD_REQUEST)
 public class ValidationException extends I18nSupportException {
 
+    private static final boolean propertyI18nEnabled = Boolean.getBoolean("i18n.validation.property.enabled");
+
     private List<Detail> details;
 
     public ValidationException(String message) {
@@ -42,8 +44,15 @@ public class ValidationException extends I18nSupportException {
         } else {
             setCode("validation.property_validate_failed");
         }
+        String property = first.getPropertyPath().toString();
+
         //{0} 属性 ,{1} 验证消息
-        setArgs(new Object[]{first.getPropertyPath().toString(), first.getMessage()});
+        //property也支持国际化?
+        String resolveMessage = propertyI18nEnabled ?
+                LocaleUtils.resolveMessage(first.getRootBeanClass().getName() + "." + property, property)
+                : property;
+
+        setArgs(new Object[]{resolveMessage, first.getMessage()});
 
         details = new ArrayList<>(violations.size());
         for (ConstraintViolation<?> violation : violations) {

+ 1 - 1
hsweb-core/src/main/java/org/hswebframework/web/i18n/LocaleUtils.java

@@ -25,7 +25,7 @@ public class LocaleUtils {
 
     private static final ThreadLocal<Locale> CONTEXT_THREAD_LOCAL = new ThreadLocal<>();
 
-    static MessageSource messageSource;
+    static MessageSource messageSource = UnsupportedMessageSource.instance();
 
     /**
      * 获取当前的语言地区,如果没有设置则返回系统默认语言

+ 1 - 1
hsweb-core/src/main/java/org/hswebframework/web/i18n/MessageSourceInitializer.java

@@ -5,7 +5,7 @@ import org.springframework.context.MessageSource;
 public class MessageSourceInitializer {
 
     public static void init(MessageSource messageSource) {
-        if (LocaleUtils.messageSource == null) {
+        if (LocaleUtils.messageSource == null || LocaleUtils.messageSource instanceof UnsupportedMessageSource) {
             LocaleUtils.messageSource = messageSource;
         }
     }

+ 31 - 0
hsweb-core/src/main/java/org/hswebframework/web/i18n/UnsupportedMessageSource.java

@@ -0,0 +1,31 @@
+package org.hswebframework.web.i18n;
+
+import org.springframework.context.MessageSource;
+import org.springframework.context.MessageSourceResolvable;
+import org.springframework.context.NoSuchMessageException;
+
+import java.util.Locale;
+
+public class UnsupportedMessageSource implements MessageSource {
+
+    private static final UnsupportedMessageSource INSTANCE = new UnsupportedMessageSource();
+
+    public static MessageSource instance() {
+        return INSTANCE;
+    }
+
+    @Override
+    public String getMessage(String code, Object[] args, String defaultMessage, Locale locale) {
+        return defaultMessage;
+    }
+
+    @Override
+    public String getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException {
+        return code;
+    }
+
+    @Override
+    public String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException {
+        return resolvable.getDefaultMessage();
+    }
+}

+ 1 - 1
hsweb-core/src/main/resources/i18n/core/messages_en_US.properties

@@ -1,4 +1,4 @@
 error.not_found=The data does not exist
 error.cant_create_instance=Unable to create instance:{0}
 validation.parameter_does_not_exist_in_enums=Parameter {0} does not exist in option
-validation.property_validate_failed=Parameter '{0}' {1}
+validation.property_validate_failed={0} {1}

+ 1 - 1
hsweb-core/src/main/resources/i18n/core/messages_zh_CN.properties

@@ -2,4 +2,4 @@ error.not_found=数据不存在
 error.cant_create_instance=无法创建实例:{0}
 
 validation.parameter_does_not_exist_in_enums=参数[{0}]在选择中不存在
-validation.property_validate_failed=参数'{0}'{1}
+validation.property_validate_failed={0}{1}

+ 22 - 6
hsweb-starter/src/main/java/org/hswebframework/web/starter/i18n/I18nConfiguration.java

@@ -1,6 +1,7 @@
 package org.hswebframework.web.starter.i18n;
 
-import org.hswebframework.web.exception.BusinessException;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
 import org.hswebframework.web.i18n.MessageSourceInitializer;
 import org.springframework.beans.factory.ObjectProvider;
 import org.springframework.boot.autoconfigure.AutoConfigureOrder;
@@ -10,20 +11,35 @@ import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Primary;
 import org.springframework.context.support.ResourceBundleMessageSource;
 import org.springframework.core.Ordered;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+import org.springframework.util.StringUtils;
 
 import java.util.stream.Collectors;
 
 @Configuration(proxyBeanMethods = false)
 @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
+@Slf4j
 public class I18nConfiguration {
 
-
     @Bean
-    public MessageSource coreMessageSource(){
-        ResourceBundleMessageSource messageSource=new ResourceBundleMessageSource();
+    @SneakyThrows
+    public MessageSource autoResolveI18nMessageSource() {
+
+        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
         messageSource.setDefaultEncoding("UTF-8");
-        messageSource.setBundleClassLoader(BusinessException.class.getClassLoader());
-        messageSource.setBasenames("i18n/core/messages");
+        Resource[] resources = new PathMatchingResourcePatternResolver().getResources("classpath*:i18n/**");
+
+        for (Resource resource : resources) {
+            String path = resource.getURL().getPath();
+            if (StringUtils.hasText(path) && (path.endsWith(".properties") || path.endsWith(".xml"))) {
+                String name = path.substring(path.lastIndexOf("i18n"),path.indexOf("_"));
+
+                log.info("register i18n message resource {} -> {}", path,name);
+
+                messageSource.addBasenames(name);
+            }
+        }
         return messageSource;
     }