Spring Boot i18n 国际化

Spring Boot i18n IDEA About 5,908 words

IDEA 插件

Resources Bundle Editor,方便查看和编辑多个i18n文件。

Accept-Language

Accept-Language请求头格式:

含义:,隔开,;后跟权重,q表示权重,取值范围:0-1,没有q表示q=1

浏览器默认会携带该请求头发起请求。

Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6

Java自带解析Accept-Language

List<Locale.LanguageRange> parse = Locale.LanguageRange.parse("zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6");

Tomcat中解析Accept-Language

// org.apache.tomcat.util.http.parser.AcceptLanguage
List<AcceptLanguage> parse = AcceptLanguage.parse(new StringReader("zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6"));

AcceptHeaderLocaleResolver

Spring Boot中自带的AcceptHeader解析器,默认注入:

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(WebProperties.class)
public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware {
    @Override
    @Bean
    @ConditionalOnMissingBean(name = DispatcherServlet.LOCALE_RESOLVER_BEAN_NAME) // LOCALE_RESOLVER_BEAN_NAME = "localeResolver";
    public LocaleResolver localeResolver() {
        if (this.webProperties.getLocaleResolver() == WebProperties.LocaleResolver.FIXED) {
            return new FixedLocaleResolver(this.webProperties.getLocale());
        }
        AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
        localeResolver.setDefaultLocale(this.webProperties.getLocale());
        return localeResolver;
    }
}

MessageSource

注入配置

@AutoConfiguration
@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 = {};

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

初始化流程:

public class DispatcherServlet extends FrameworkServlet {
    @Override
    protected void onRefresh(ApplicationContext context) {
        initStrategies(context);
    }

    protected void initStrategies(ApplicationContext context) {
        initMultipartResolver(context);
        initLocaleResolver(context);
        initThemeResolver(context);
        initHandlerMappings(context);
        initHandlerAdapters(context);
        initHandlerExceptionResolvers(context);
        initRequestToViewNameTranslator(context);
        initViewResolvers(context);
        initFlashMapManager(context);
    }

    private void initLocaleResolver(ApplicationContext context) {
        try {
            this.localeResolver = context.getBean(LOCALE_RESOLVER_BEAN_NAME, LocaleResolver.class);
            if (logger.isTraceEnabled()) {
                logger.trace("Detected " + this.localeResolver);
            }
            else if (logger.isDebugEnabled()) {
                logger.debug("Detected " + this.localeResolver.getClass().getSimpleName());
            }
        }
        catch (NoSuchBeanDefinitionException ex) {
            // We need to use the default.
            this.localeResolver = getDefaultStrategy(context, LocaleResolver.class);
            if (logger.isTraceEnabled()) {
                logger.trace("No LocaleResolver '" + LOCALE_RESOLVER_BEAN_NAME +
                        "': using default [" + this.localeResolver.getClass().getSimpleName() + "]");
            }
        }
    }
}

Locale

public static void main(String[] args) {
    System.out.println(Locale.getDefault().getCountry());
    System.out.println(Locale.getDefault().getDisplayCountry());
    System.out.println(Locale.getDefault().getLanguage());
    System.out.println(Locale.getDefault().getDisplayLanguage());
    System.out.println(Locale.getDefault().getDisplayName());
    System.out.println(Locale.getDefault().getScript());
    System.out.println(Locale.getDefault().getDisplayScript());
    System.out.println(Locale.getDefault().getVariant());
    System.out.println(Locale.getDefault().getDisplayVariant());
    System.out.println(Locale.getDefault().getISO3Country());
    System.out.println(Locale.getDefault().getISO3Language());
}

输出

CN
中国
zh
中文
中文 (简体,中国)
Hans
简体


CHN
zho

Locale中的常量:

public static void main(String[] args) {
    System.out.println(Locale.ENGLISH);
    System.out.println(Locale.UK);
    System.out.println(Locale.US);
    System.out.println(Locale.CHINA);
    System.out.println(Locale.PRC);
    System.out.println(Locale.TAIWAN);
    System.out.println(Locale.CHINESE);
    System.out.println(Locale.SIMPLIFIED_CHINESE);
    System.out.println(Locale.TRADITIONAL_CHINESE);
}

输出:

en
en_GB
en_US
zh_CN
zh_CN
zh_TW
zh
zh_CN
zh_TW

Spring Boot中获取Locale

RequestContext.getLoale()

LocaleContextHolder

参考文档

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Accept-Language

Views: 1,390 · Posted: 2023-03-05

————        END        ————

Give me a Star, Thanks:)

https://github.com/fendoudebb/LiteNote

扫描下方二维码关注公众号和小程序↓↓↓

扫描下方二维码关注公众号和小程序↓↓↓


Today On History
Browsing Refresh