真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

SpringBoot如何實現(xiàn)國際化

這篇文章主要介紹“Spring Boot如何實現(xiàn)國際化”,在日常操作中,相信很多人在Spring Boot如何實現(xiàn)國際化問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Spring Boot如何實現(xiàn)國際化”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

創(chuàng)新互聯(lián)公司堅持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:網(wǎng)站制作、做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時代的陽東網(wǎng)站設(shè)計、移動媒體設(shè)計的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!

i18n 國際化

在開發(fā)中,國際化(Internationalization),也叫本地化,指的是一個網(wǎng)站(或應(yīng)用)可以支持多種不同的語言,即可以根據(jù)用戶所在的語言類型和國家/地區(qū),顯示不同的文字。能夠讓不同國家,不同語種的用戶方便使用,提高用戶體驗性。

實現(xiàn)國際化,比較簡單的實現(xiàn)方案就是根據(jù)不同的國家和語言開發(fā)不同的程序,分別用相應(yīng)的語言文字顯示,例如Oracle英文官網(wǎng)地址:https://www.oracle.com/index.html,中文官網(wǎng)地址:https://www.oracle.com/cn/index.html。

一般比較大型的公司會使用這種根據(jù)不同的國家和語言開發(fā)不同的程序的形式實現(xiàn)國家化,其一人家公司有資源投入開發(fā),其二可以根據(jù)不同國家,不同語種用戶習(xí)慣開發(fā)更加符合當(dāng)?shù)厝说牟季謽邮?,交互等?/p>

還有另外一種國家化實現(xiàn)方案,就是開發(fā)一套程序,可以根據(jù)用戶所在區(qū)域顯示不同的語言文字,但是網(wǎng)站/應(yīng)用的布局樣式等不會發(fā)生很大變化。這個方案也是我們要將的i18n國際化實現(xiàn),i18n其實就是英文單詞Internationalization(國際化)的縮寫,i和n代表單詞首尾字母,18代表中間的18個字母。

i18n 實現(xiàn)

在Java中,通過java.util.Locale類表示本地化對象,它通過語言類型和國家/地區(qū)等元素來確定創(chuàng)建一個本地化對象 。Locale對象表示具體的地理,時區(qū),語言,政治等。

我們可以通過以下方法,獲取本地系統(tǒng)的語言,國家等信息;以及獲取代表指定地區(qū)的語言,國家信息Local對象。當(dāng)然你也可以調(diào)用 Locale.getAvailableLocales() 方法查看所有可用的Local對象。

package com.nobody;

import java.util.Locale;

/**
 * @Description
 * @Author Mr.nobody
 * @Date 2021/4/15
 * @Version 1.0
 */
public class LocalTest {
    public static void main(String[] args) {
        Locale defaultLocale = Locale.getDefault();
        Locale chinaLocale = Locale.CHINA;
        Locale usLocale = Locale.US;
        Locale usLocale1 = new Locale("en", "US");
        System.out.println(defaultLocale);
        System.out.println(defaultLocale.getLanguage());
        System.out.println(defaultLocale.getCountry());
        System.out.println(chinaLocale);
        System.out.println(usLocale);
        System.out.println(usLocale1);
    }
}

// 輸出結(jié)果
zh_CN
zh
CN
zh_CN
en_US
en_US

我們一般會將不同的語言的屬性值存放在不同的配置文件中,ResourceBundle類可以根據(jù)指定的baseName和Local對象,就可以找到相應(yīng)的配置文件,從而讀取到相應(yīng)的語言文字,從而構(gòu)建出ResourceBundle對象,然后我們可以通過ResourceBundle.getString(key)就可以取得key在不同地域的語言文字了。

Properties配置文件命名規(guī)則:baseName_local.properties

假如baseName為i18n,則相應(yīng)的配置文件應(yīng)該命名為如下:

  • 中文的配置文件:i18n_zh_CN.properties

  • 英文的配置文件:i18n_en_US.properties

Spring Boot如何實現(xiàn)國際化

然后在兩個配置文件中,存放著鍵值對,對應(yīng)不同的語言文字

# 在i18n_zh_CN.properties文件中
userName=陳皮

# 在i18n_en_US.properties文件中
userName=Peel

我們通過如下方式,就可以獲取相應(yīng)語言環(huán)境下的信息了,如下:

Locale chinaLocale = Locale.CHINA;
ResourceBundle resourceBundle = ResourceBundle.getBundle("i18n", chinaLocale);
String userName = resourceBundle.getString("userName");
System.out.println(userName);

Locale usLocale = Locale.US;
resourceBundle = ResourceBundle.getBundle("i18n", usLocale);
userName = resourceBundle.getString("userName");
System.out.println(userName);

// 輸出結(jié)果
陳皮
Peel

對于不同地域語言環(huán)境的用戶,我們是如何處理國際化呢?其實原理很簡單,假設(shè)客戶端發(fā)送一個請求到服務(wù)端,在請求頭中設(shè)置了鍵值對,“Accept-Language”:“zh-CN”,根據(jù)這個信息,可以構(gòu)建出一個代表這個區(qū)域的本地化對象Locale,根據(jù)配置文件的baseName和Locale對象就可以知道讀取哪個配置文件的屬性,將要顯示的文字格式化處理,最終返回給客戶端進(jìn)行顯示。

Springboot 集成 i18n

在Springboot中,我們會使用到一個MessageSource接口,用于訪問國際化信息,此接口定義了幾個重載的方法。code即國際化資源的屬性名(鍵);args即傳遞給格式化字符串中占位符的運(yùn)行時參數(shù)值;local即本地化對象;resolvable封裝了國際化資源屬性名,參數(shù),默認(rèn)信息等。

  • String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale)

  • String getMessage(String code, @Nullable Object[] args, Locale locale)

  • String getMessage(MessageSourceResolvable resolvable, Locale locale)

Springboot提供了國際化信息自動配置類MessageSourceAutoConfiguration,它可以生成MessageSource接口的實現(xiàn)類ResourceBundleMessageSource,注入到Spring容器中。MessageSource配置生效依靠ResourceBundleCondition條件,從環(huán)境變量中讀取spring.messages.basename的值(默認(rèn)值messages),這個值就是MessageSource對應(yīng)的資源文件名稱,資源文件擴(kuò)展名是.properties,然后通過PathMatchingResourcePatternResolver從classpath*:目錄下讀取對應(yīng)的資源文件,如果能正常讀取到資源文件,則加載配置類。源碼如下:

package org.springframework.boot.autoconfigure.context;

@Configuration
@ConditionalOnMissingBean(value = MessageSource.class, search = SearchStrategy.CURRENT)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Conditional(ResourceBundleCondition.class)
@EnableConfigurationProperties
public class MessageSourceAutoConfiguration {

    private static final Resource[] NO_RESOURCES = {};

    // 我們可以在application.properties文件中修改spring.messages前綴的默認(rèn)值,比如修改basename的值
    @Bean
    @ConfigurationProperties(prefix = "spring.messages")
    public MessageSourceProperties messageSourceProperties() {
        return new MessageSourceProperties();
    }

    // 生成ResourceBundleMessageSource實例,注入容器中
    @Bean
    public MessageSource messageSource(MessageSourceProperties properties) {
        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
        if (StringUtils.hasText(properties.getBasename())) {
            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 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;
        }

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

        // 讀取classpath*:路徑下的配置文件
        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國際化處理的屬性配置類,我們可以在application.properties文件中自定義修改這些默認(rèn)值,例如:spring.messages.basename=i18n。

package org.springframework.boot.autoconfigure.context;

/**
 * Configuration properties for Message Source.
 *
 * @author Stephane Nicoll
 * @author Kedar Joshi
 * @since 2.0.0
 */
public class MessageSourceProperties {

    /**
  * Comma-separated list of basenames (essentially a fully-qualified classpath
  * location), each following the ResourceBundle convention with relaxed support for
  * slash based locations. If it doesn't contain a package qualifier (such as
  * "org.mypackage"), it will be resolved from the classpath root.
  */
    private String basename = "messages";

    /**
  * Message bundles encoding.
  */
    private Charset encoding = StandardCharsets.UTF_8;

    /**
  * Loaded resource bundle files cache duration. When not set, bundles are cached
  * forever. If a duration suffix is not specified, seconds will be used.
  */
    @DurationUnit(ChronoUnit.SECONDS)
    private Duration cacheDuration;

    /**
  * Whether to fall back to the system Locale if no files for a specific Locale have
  * been found. if this is turned off, the only fallback will be the default file (e.g.
  * "messages.properties" for basename "messages").
  */
    private boolean fallbackToSystemLocale = true;

    /**
  * Whether to always apply the MessageFormat rules, parsing even messages without
  * arguments.
  */
    private boolean alwaysUseMessageFormat = false;

    /**
  * Whether to use the message code as the default message instead of throwing a
  * "NoSuchMessageException". Recommended during development only.
  */
    private boolean useCodeAsDefaultMessage = false;

    // 省略get/set
}

我們在類路徑下創(chuàng)建好國際化配置文件之后,就可以注入MessageSource實例,進(jìn)行國際化處理了:

i18n.properties文件是默認(rèn)文件,當(dāng)找不到語言的配置的時候,使用該文件進(jìn)行展示。

@Autowired
private MessageSource messageSource;

@GetMapping("test")
public GeneralResult test() {
    // 獲取客戶端的語言環(huán)境Locale對象,即取的請求頭Accept-Language鍵的值來判斷,我們也可以自定義請求頭鍵,來獲取語言標(biāo)識
    Locale locale = LocaleContextHolder.getLocale();
    String userName = messageSource.getMessage("userName", null, locale);
    System.out.println(userName);
    return GeneralResult.genSuccessResult(userName);
}

上面我們是利用Spirng自帶的LocaleContextHolder來獲取本地對象Locale,它是取的請求頭Accept-Language鍵的語言值來判斷生成相應(yīng)Locale對象。我們也可以根據(jù)其他方式,例如請求頭中自定義鍵的值,來生成Locale對象,然后再通過messageSource.getMessage()方法來實現(xiàn)最終的國家化。

到此,關(guān)于“Spring Boot如何實現(xiàn)國際化”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>
新聞名稱:SpringBoot如何實現(xiàn)國際化
文章URL:http://weahome.cn/article/gdchgd.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部