相关文章推荐
大力的勺子  ·  python ...·  3 天前    · 
满身肌肉的充值卡  ·  python基础—re模块下的函数及匹配对象 ...·  3 天前    · 
礼貌的机器人  ·  javax.net.ssl.SSLExcep ...·  昨天    · 
犯傻的铅笔  ·  Spring WebClient使用 - ...·  昨天    · 
睿智的松鼠  ·  HTTP客户端之Spring ...·  昨天    · 
率性的水煮鱼  ·  Pandas加速方式的研究 - 简书·  1 年前    · 
买醉的吐司  ·  管理员如何对密码相关策略进行集中管理_应用身 ...·  1 年前    · 
暴走的橡皮擦  ·  Django Rest Framework ...·  2 年前    · 
跑龙套的手链  ·  300美元平替ChatGPT!斯坦福130亿 ...·  2 年前    · 
侠义非凡的红金鱼  ·  android ...·  2 年前    · 
Code  ›  Spring boot国际化开发者社区
bundle string
https://cloud.tencent.com/developer/article/1193338
爱听歌的松树
2 年前
作者头像
JadePeng
0 篇文章

Spring boot国际化

前往专栏
腾讯云
开发者社区
文档 意见反馈 控制台
首页
学习
活动
专区
工具
TVP
文章/答案/技术大牛
发布
首页
学习
活动
专区
工具
TVP
返回腾讯云官网
社区首页 > 专栏 > JadePeng的技术博客 > Spring boot国际化

Spring boot国际化

作者头像
JadePeng
发布 于 2018-08-22 17:44:27
957 0
发布 于 2018-08-22 17:44:27
举报

国际化主要是引入了MessageSource,我们简单看下如何使用,以及其原理。

1.1 设置资源文件

在 properties新建i18n目录

新建message文件:

messages.properties

error.title=Your request cannot be processed

messages_zh_CN.properties

error.title=您的请求无法处理

1.2 配置

修改properties文件的目录:在application.yml或者application.properties中配置 spring.message.basename

spring:
    application:
        name: test-worklog
    messages:
        basename: i18n/messages
        encoding: UTF-8

1.3 使用

引用自动注解的MessageSource,调用 messageSource.getMessage 即可,注意,需要通过 LocaleContextHolder.getLocale() 获取当前的地区。

@Autowired
private MessageSource messageSource;
 * 国际化
 * @param result
 * @return
public String getMessage(String result, Object[] params) {
    String message = "";
    try {
        Locale locale = LocaleContextHolder.getLocale();
        message = messageSource.getMessage(result, params, locale);
    } catch (Exception e) {
        LOGGER.error("parse message error! ", e);
    return message;
}

如何设置个性化的地区呢? forLanguageTag 即可

 Locale locale = Locale.forLanguageTag(user.getLangKey());

1.4 原理分析

MessageSourceAutoConfiguration 中,实现了autoconfig

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

该类一方面读取配置文件,一方面创建了MessageSource的实例:

@Bean
    public MessageSource messageSource() {
        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
        if (StringUtils.hasText(this.basename)) {
            messageSource.setBasenames(StringUtils.commaDelimitedListToStringArray(
                    StringUtils.trimAllWhitespace(this.basename)));
        if (this.encoding != null) {
            messageSource.setDefaultEncoding(this.encoding.name());
        messageSource.setFallbackToSystemLocale(this.fallbackToSystemLocale);
        messageSource.setCacheSeconds(this.cacheSeconds);
        messageSource.setAlwaysUseMessageFormat(this.alwaysUseMessageFormat);
        return messageSource;
    }

因此,默认是加载的 ResourceBundleMessageSource ,该类派生与于AbstractResourceBasedMessageSource

enter description here
enter description here
@Override
    public final String getMessage(String code, Object[] args, String defaultMessage, Locale locale) {
        String msg = getMessageInternal(code, args, locale);
        if (msg != null) {
            return msg;
        if (defaultMessage == null) {
            String fallback = getDefaultMessage(code);
            if (fallback != null) {
                return fallback;
        return renderDefaultMessage(defaultMessage, args, locale);
    }

最终是调用resolveCode来获取message,通过ResourceBundle来获取message

    @Override
    protected MessageFormat resolveCode(String code, Locale locale) {
        // 遍历语言文件路径
        Set<String> basenames = getBasenameSet();
        for (String basename : basenames) {
            ResourceBundle bundle = getResourceBundle(basename, locale);
            if (bundle != null) {
                MessageFormat messageFormat = getMessageFormat(bundle, code, locale);
                if (messageFormat != null) {
                    return messageFormat;
        return null;
// 获取ResourceBundle 
protected ResourceBundle getResourceBundle(String basename, Locale locale) {
        if (getCacheMillis() >= 0) {
            // Fresh ResourceBundle.getBundle call in order to let ResourceBundle
            // do its native caching, at the expense of more extensive lookup steps.
            return doGetBundle(basename, locale);
        else {
            // Cache forever: prefer locale cache over repeated getBundle calls.
            synchronized (this.cachedResourceBundles) {
                Map<Locale, ResourceBundle> localeMap = this.cachedResourceBundles.get(basename);
                if (localeMap != null) {
                    ResourceBundle bundle = localeMap.get(locale);
                    if (bundle != null) {
                        return bundle;
                try {
                    ResourceBundle bundle = doGetBundle(basename, locale);
                    if (localeMap == null) {
                        localeMap = new HashMap<Locale, ResourceBundle>();
                        this.cachedResourceBundles.put(basename, localeMap);
                    localeMap.put(locale, bundle);
                    return bundle;
                catch (MissingResourceException ex) {
                    if (logger.isWarnEnabled()) {
                        logger.warn("ResourceBundle [" + basename + "] not found for MessageSource: " + ex.getMessage());
                    // Assume bundle not found
                    // -> do NOT throw the exception to allow for checking parent message source.
                    return null;
//  ResourceBundle  
protected ResourceBundle doGetBundle(String basename, Locale locale) throws MissingResourceException {
        return ResourceBundle.getBundle(basename, locale, getBundleClassLoader(), new MessageSourceControl());
}

最后来看getMessageFormat:

/**
     * Return a MessageFormat for the given bundle and code,
     * fetching already generated MessageFormats from the cache.
     * @param bundle the ResourceBundle to work on
     * @param code the message code to retrieve
     * @param locale the Locale to use to build the MessageFormat
     * @return the resulting MessageFormat, or {@code null} if no message
     * defined for the given code
     * @throws MissingResourceException if thrown by the ResourceBundle
    protected MessageFormat getMessageFormat(ResourceBundle bundle, String code, Locale locale)
            throws MissingResourceException {
        synchronized (this.cachedBundleMessageFormats) {
            // 从缓存读取
            Map<String, Map<Locale, MessageFormat>> codeMap = this.cachedBundleMessageFormats.get(bundle);
            Map<Locale, MessageFormat> localeMap = null;
            if (codeMap != null) {
                localeMap = codeMap.get(code);
                if (localeMap != null) {
                    MessageFormat result = localeMap.get(locale);
                    if (result != null) {
                        return result;
            // 缓存miss,从bundle读取
            String msg = getStringOrNull(bundle, code);
            if (msg != null) {
                if (codeMap == null) {
                    codeMap = new HashMap<String, Map<Locale, MessageFormat>>();
                    this.cachedBundleMessageFormats.put(bundle, codeMap);
                if (localeMap == null) {
                    localeMap = new HashMap<Locale, MessageFormat>();
                    codeMap.put(code, localeMap);
                MessageFormat result = createMessageFormat(msg, locale);
                localeMap.put(locale, result);
                return result;
            return null;
 
推荐文章
大力的勺子  ·  python re.match函数的使用_python re.match
3 天前
满身肌肉的充值卡  ·  python基础—re模块下的函数及匹配对象的属性与方法(re.match()/re.search()...等)
3 天前
礼貌的机器人  ·  javax.net.ssl.SSLException: SSLEngine已关闭,SSLEngine已在webclient中关闭(Springboot)开发者社区
昨天
犯傻的铅笔  ·  Spring WebClient使用 - 大坑水滴
昨天
睿智的松鼠  ·  HTTP客户端之Spring WebClient - 钟小嘿
昨天
率性的水煮鱼  ·  Pandas加速方式的研究 - 简书
1 年前
买醉的吐司  ·  管理员如何对密码相关策略进行集中管理_应用身份服务 (IDaaS)(IDaaS)-阿里云帮助中心
1 年前
暴走的橡皮擦  ·  Django Rest Framework 教程及API向导_天天向上goto的技术博客_51CTO博客
2 年前
跑龙套的手链  ·  300美元平替ChatGPT!斯坦福130亿参数「小羊驼」诞生-51CTO.COM
2 年前
侠义非凡的红金鱼  ·  android HierarchyViewer查看视图层级关系_android 查看视图层级_skycnlr的博客-CSDN博客
2 年前
今天看啥   ·   Py中国   ·   codingpro   ·   小百科   ·   link之家   ·   卧龙AI搜索
删除内容请联系邮箱 2879853325@qq.com
Code - 代码工具平台
© 2024 ~ 沪ICP备11025650号