zoukankan      html  css  js  c++  java
  • 12. SpringBoot国际化

    1)、编写国际化配置文件;

    2)、使用ResourceBundleMessageSource管理国际化资源文件

    3)、在页面使用fmt:message取出国际化内容  


    步骤
    1)、编写国际化配置文件,抽取页面需要显示的国际化消息

    国际化文件是peroperties文件  

     自动识别国际化视图

     通过国际化视图创建国际化配置文件

     同时对比编辑多个配置文件

     

     配置国际化文件路径:

    spring.messages.basename=static.i18n.login
    @Configuration
    @ConditionalOnMissingBean(
        value = {MessageSource.class},
        search = SearchStrategy.CURRENT
    )
    @AutoConfigureOrder(-2147483648)
    @Conditional({MessageSourceAutoConfiguration.ResourceBundleCondition.class})
    @EnableConfigurationProperties
    public class MessageSourceAutoConfiguration {
        private static final Resource[] NO_RESOURCES = new Resource[0];
    
        public MessageSourceAutoConfiguration() {
        }
    
        @Bean
        @ConfigurationProperties(
            prefix = "spring.messages"
        )
        public MessageSourceProperties messageSourceProperties() {
            return new MessageSourceProperties();
        }
    
        @Bean
        public MessageSource messageSource(MessageSourceProperties properties) {
            ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
            if (StringUtils.hasText(properties.getBasename())) {
           //设置国际化文件的基础名称(去掉语言_国家代{zh_CN})的):即默认是message.properties,上图中我们起的名称是login.properties messageSource.setBasenames(StringUtils.commaDelimitedListToStringArray(StringUtils.trimAllWhitespace(properties.getBasename()))); }
    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(); protected ResourceBundleCondition() { } public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
           //自定义的话就用此属性:spring.messages.basename来指定,默认叫message.propertie
           //我们上图的需要指定为:spring.messages.basename=login String basename
    = context.getEnvironment().getProperty("spring.messages.basename", "messages"); ConditionOutcome outcome = (ConditionOutcome)cache.get(basename); if (outcome == null) { outcome = this.getMatchOutcomeForBasename(context, basename); cache.put(basename, outcome); } return outcome; } private ConditionOutcome getMatchOutcomeForBasename(ConditionContext context, String basename) { Builder message = ConditionMessage.forCondition("ResourceBundle", new Object[0]); String[] var4 = StringUtils.commaDelimitedListToStringArray(StringUtils.trimAllWhitespace(basename)); int var5 = var4.length; for(int var6 = 0; var6 < var5; ++var6) { String name = var4[var6]; Resource[] var8 = this.getResources(context.getClassLoader(), name);//类路径 int var9 = var8.length; for(int var10 = 0; var10 < var9; ++var10) { Resource resource = var8[var10]; if (resource.exists()) { return ConditionOutcome.match(message.found("bundle").items(new Object[]{resource})); } } } return ConditionOutcome.noMatch(message.didNotFind("bundle with basename " + basename).atAll()); } private Resource[] getResources(ClassLoader classLoader, String name) { String target = name.replace('.', '/'); try {
              //类路径下的 message.properties 和 messages_zh_CN.properties 或 自己指定的xxxx.properties 、xxxx.preperties
    return (new PathMatchingResourcePatternResolver(classLoader)).getResources("classpath*:" + target + ".properties"); } catch (Exception var5) { return MessageSourceAutoConfiguration.NO_RESOURCES; } } } }
    public class MessageSourceProperties {
        private String basename = "messages";//我们的配置文件可以直接放在类路径下,默认名称叫message.properties
        private Charset encoding;
        @DurationUnit(ChronoUnit.SECONDS)
        private Duration cacheDuration;
        private boolean fallbackToSystemLocale;
        private boolean alwaysUseMessageFormat;
        private boolean useCodeAsDefaultMessage;
    
        public MessageSourceProperties() {
            this.encoding = StandardCharsets.UTF_8;
            this.fallbackToSystemLocale = true;
            this.alwaysUseMessageFormat = false;
            this.useCodeAsDefaultMessage = false;
        }
    
        public String getBasename() {
            return this.basename;
        }
    
        public void setBasename(String basename) {
            this.basename = basename;
        }
    ......
    }

     <!-- 中英文切换链接 -->

    <a class="btn btn-sm" th:href="@{/index.html(l='zh_CN'}">中文</a>
    <a class="btn btn-sm" th:href="@{/index.html(l='en_US')}">English</a>

     

     是根据浏览器的默认语言识别的

     不过取出来的中文有乱码

     IDEA中将UTF-8自动组转为ASSIC码

      

     File   ——》 settings 里的设置只是针对当前项目的设置,要想设置全局的

     

     Settins  ——》Other Settings ——》Default Settings  设置全局的默认设置

    然后重新编辑有乱码的properties文件

     根据浏览器的默认语言设置自动区分国际化字段的显示

     默认请求头里会有语言的信息

     切换默认的语言,请求头中排在第一位的也就变了

    实现原理:

    国际化Locale(区域信息对象);LocaleResolver(获取区域信息对象)

    public class WebMvcAutoConfiguration {
        public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer, ResourceLoaderAware {
    
    
            @Bean
            @ConditionalOnMissingBean  //当项目中没有区域解析器的时候,才执行这个SprigBoot默认的配置,所以可以自定义
            @ConditionalOnProperty(
                    prefix = "spring.mvc",
                    name = {"locale"}
            )
            //
            public LocaleResolver localeResolver() {
    
    
                //默认从配置文件中获取
                if (this.mvcProperties.getLocaleResolver() == org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties.LocaleResolver.FIXED) {
                    return new FixedLocaleResolver(this.mvcProperties.getLocale());
                } else {//如果配置文件中没有,则从HttpRequest的header中获取
                    AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
                    localeResolver.setDefaultLocale(this.mvcProperties.getLocale());
                    return localeResolver;
                }
            }
    
        }
    
    
    
        public class AcceptHeaderLocaleResolver implements LocaleResolver {
    
            public Locale resolveLocale(HttpServletRequest request) {
                Locale defaultLocale = this.getDefaultLocale();
                if (defaultLocale != null && request.getHeader("Accept-Language") == null) {
                    return defaultLocale;
                } else {
                    Locale requestLocale = request.getLocale();
                    List<Locale> supportedLocales = this.getSupportedLocales();
                    if (!supportedLocales.isEmpty() && !supportedLocales.contains(requestLocale)) {
                        Locale supportedLocale = this.findSupportedLocale(request, supportedLocales);
                        if (supportedLocale != null) {
                            return supportedLocale;
                        } else {//如果默认的区域解析器为空,则从requset请求头中获取
                            return defaultLocale != null ? defaultLocale : requestLocale;
                        }
                    } else {
                        return requestLocale;
                    }
                }
            }
    
        }

    自定义区域解析器,点击链接切换国际化

    public class MyLocaleResolver implements LocaleResolver {
        @Override
        public Locale resolveLocale(HttpServletRequest request) {
            String l = request.getParameter("l");
            Locale locale = Locale.getDefault();         
            if (!StringUtils.isEmpty(l)) {             
                String[] split = l.split("_");             
                locale = new Locale(split[0], split[1]);        
            }        
            return locale;
        }
    
        @Override
        public void setLocale(HttpServletRequest httpServletRequest, @Nullable HttpServletResponse httpServletResponse, @Nullable Locale locale) {
    
        }
    }
    //将自定义的区域解析器加入到容器中来
    @Bean     
    public LocaleResolver localeResolver(){         
        return new MyLocaleResolver();     
    } 
  • 相关阅读:
    双六游戏 扩展欧几里得
    线段上的格点 辗转相除法(GCD)
    POJ 2395 Out of Hay
    POJ 2377 Bad Cowtractors
    POJ 1258 Agri-Net
    POJ 3169 Layout
    POJ 3723 Conscription
    次最短路径 POJ 3255 Roadblocks
    最小生成树求法 Prim + Kruskal
    如何将页脚固定在页面底部,4中方法 转载自:W3CPLUS
  • 原文地址:https://www.cnblogs.com/guchunchao/p/9981791.html
Copyright © 2011-2022 走看看