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();     
} 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM