SpringBoot配置国际化

Java知识点总结:想看的可以从这里进入

2.8、国际化配置

2.8.1、配置文件

国际化为 Internationalization 简称 I18n ,国际化的配置需要在resource包内创建 i18n包,

  1. resource包内创建i18n包,在内部创建国际化资源文件(文件格式为:基本名_ 语言代码 _国家或地区代码),idea会自动识别,进行合并

    1. message.properties:默认的设置
    2. message_en_US.properties :英语时生效
    3. message_zh_CN.properties:中文时生效
  2. 创建完成后idea自动识别成如下情况

    image-20220921104925677

  3. 下载一个插件 Resource Bundle Editor

    image-20220920174512548

    下载完此插件后,左下角会出现2个按钮

    image-20220920175439513
  4. 点击 Resource Bundle 切换到可视化操作

    image-20220921104739995
  5. 可视化页面添加完毕后,会在配置文件中以 键=值的形式自动生成

    image-20220921104654219

  6. 在配置文件中设定国际化文件的位置

    spring:
      messages:
        basename: i18n/message
    

2.8.2、管理国际化

ResourceBundleMessageSource类用于管理国际化资源文件,Spring Boot 通过 MessageSourceAutoConfiguration 对 ResourceBundleMessageSource 提供了默认配置。

@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(name = AbstractApplicationContext.MESSAGE_SOURCE_BEAN_NAME, search = SearchStrategy.CURRENT)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Conditional(ResourceBundleCondition.class)
@EnableConfigurationProperties
public class MessageSourceAutoConfiguration {
    
    

    private static final Resource[] NO_RESOURCES = {
    
    };

    // Spring Boot 将 ResourceBundleMessageSource 以组件的形式添加到容器中,进而实现对国际化资源文件的管理。,(yml文件中配置的国际化文件的位置)
    @Bean
    @ConfigurationProperties(prefix = "spring.messages")
    public MessageSourceProperties messageSourceProperties() {
    
    
        return new MessageSourceProperties();
    }
 	//Spring Boot 从容器中获取 MessageSourceProperties 组件,并从中读取国际化资源文件的 basename(文件基本名)、encoding(编码)等信息,将它们封装到 ResourceBundleMessageSource 中;
    @Bean
    public MessageSource messageSource(MessageSourceProperties properties) {
    
    
        //资源包属性
        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
         //读取国际化资源文件的 基本名,并封装到 ResourceBundleMessageSource 中
        if (StringUtils.hasText(properties.getBasename())) {
    
    
            messageSource.setBasenames(StringUtils
                                       .commaDelimitedListToStringArray(StringUtils.trimAllWhitespace(properties.getBasename())));
        }
        //读取国际化资源文件的 编码,封装到 ResourceBundleMessageSource 中
        if (properties.getEncoding() != null) {
    
    
            messageSource.setDefaultEncoding(properties.getEncoding().name());
        }
      	//如果没有找到特定语言环境的文件,回退到系统语言环境
        messageSource.setFallbackToSystemLocale(properties.isFallbackToSystemLocale());
        //缓存持续时间
        Duration cacheDuration = properties.getCacheDuration();
        if (cacheDuration != null) {
    
    
            messageSource.setCacheMillis(cacheDuration.toMillis());
        }
        //设置始终使用消息格式
        messageSource.setAlwaysUseMessageFormat(properties.isAlwaysUseMessageFormat());
        //设置使用代码作为默认消息
        messageSource.setUseCodeAsDefaultMessage(properties.isUseCodeAsDefaultMessage());
        return messageSource;
    }

    //资源束条件
    protected static class ResourceBundleCondition extends SpringBootCondition {
    
    

        private static ConcurrentReferenceHashMap<String, ConditionOutcome> cache = new ConcurrentReferenceHashMap<>();

        //获取配置的国际化
        @Override
        public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
    
    
            String basename = context.getEnvironment().getProperty("spring.messages.basename", "messages");
            ConditionOutcome outcome = cache.get(basename);
            if (outcome == null) {
    
    
                outcome = getMatchOutcomeForBasename(context, basename);
                cache.put(basename, outcome);
            }
            return outcome;
        }

        //获取 Basename 的匹配结果
        private ConditionOutcome getMatchOutcomeForBasename(ConditionContext context, String basename) {
    
    
            ConditionMessage.Builder message = ConditionMessage.forCondition("ResourceBundle");
            for (String name : StringUtils.commaDelimitedListToStringArray(StringUtils.trimAllWhitespace(basename))) {
    
    
                for (Resource resource : getResources(context.getClassLoader(), name)) {
    
    
                    if (resource.exists()) {
    
    
                        return ConditionOutcome.match(message.found("bundle").items(resource));
                    }
                }
            }
            return ConditionOutcome.noMatch(message.didNotFind("bundle with basename " + basename).atAll());
        }

        //获取资源
        private Resource[] getResources(ClassLoader classLoader, String name) {
    
    
            String target = name.replace('.', '/');
            try {
    
    
                return new PathMatchingResourcePatternResolver(classLoader)
                    .getResources("classpath*:" + target + ".properties");
            }
            catch (Exception ex) {
    
    
                return NO_RESOURCES;
            }
        }
    }
}
  • Spring Boot 创建MessageSourceProperties保存基本信息,并作为组件配置到容器中

  • MessageSourceProperties 的属性与配置文件中以“spring.messages”开头的配置进行了绑定;

    所以当我们自己编写了国际化配置文件时, 需要在springboot的默认配置文件中指定spring.messages.basename的值用于解析国际化配置文件, 如果值不包含包限定, 那么将直接从classpath类路径下进行解析

  • Spring Boot 从容器中获取 MessageSourceProperties 组件,并从中读取国际化资源文件的 basename(文件基本名)、encoding(编码)等信息,将它们封装到 ResourceBundleMessageSource 中;

  • Spring Boot 将 ResourceBundleMessageSource 以组件的形式添加到容器中,进而实现对国际化资源文件的管理。

public class MessageSourceProperties {
    
    

   /**逗号分隔的基本名称列表(本质上是完全限定的类路径位置)*/
   private String basename = "messages";

   /**消息包编码。*/
   private Charset encoding = StandardCharsets.UTF_8;

   /**加载的资源包文件缓存持续时间 */
   @DurationUnit(ChronoUnit.SECONDS)
   private Duration cacheDuration;

   /**如果没有找到特定语言环境的文件,是否回退到系统语言环境*/
   private boolean fallbackToSystemLocale = true;

   /**是否始终应用 MessageFormat 规则,甚至解析没有参数的消息。*/
   private boolean alwaysUseMessageFormat = false;

   /**是否使用消息代码作为默认消息而不是抛出“NoSuchMessageException”*/
   private boolean useCodeAsDefaultMessage = false;

 .....get、set等方法..........

}

2.8.3、在HTML获取

  1. 配置LocaleResolver(用于切换国际化的不同配置,WebMvcAutoConfiguration中的localeResolver为国际化解析器)。

    @Configuration
    public class MyMessageConfig implements LocaleResolver {
          
          
    	//使用自定义LocaleResolver生效
        @Bean
        public LocaleResolver localeResolver(){
          
          
            return new MyMessageConfig();
        }
    	//用于解析路径中的配置的(l='zh_CN')
        @Override
        public Locale resolveLocale(HttpServletRequest request) {
          
          
            String l = request.getParameter("l");
            Locale locale = Locale.getDefault();
            if (!StringUtils.isEmpty(l)){
          
          
                String[] s = l.split("_");
                locale = new Locale(s[0],s[1]);
            }
            return locale;
        }
        @Override
        public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) 	   {
          
          
        }
    }
    
  2. HTML中获取国际化:

    在标签里面用:th:text="#{xxx.xxx}"

    在标签外面用:[[#{xxx.xxx}]]

  3. 切换中英文按钮

    <a class="btn btn-sm" th:href="@{/跳转到此页面的路径(l='zh_CN')}">中文</a>|
    <a class="btn btn-sm" th:href="@{/跳转到此页面的路径(l='en_US')}">English</a>
    
    image-20220921174233244

猜你喜欢

转载自blog.csdn.net/yuandfeng/article/details/129709701