spring-boot国际化i18n中英文实现

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

一、背景

接触到的项目使用国际化越来越多系统页面实现中英文环境记录下前端使用vue + vue-i8n

后端java自己封装

前端翻译对象页面涉及到的所有按钮包括新增、删除、导出、下载、导入、上一页、下一页等、文本所有弹框提示包括请输入内容、您确定要删除吗、新增修改列名、列表头名、提交、取消、必填项不能为空等总结为所有页面定义的中文内容 切换为英文环境时 页面需切换英文。

后端翻译对象因菜单采用动态菜单故菜单翻译放到后端字典数据接口返回提示信息操作成果、操作失败、原因

此处前端自行百度只记录后端部分

spring-boot  maven  此处只贴关键性代码  项目其他封装 代码 未粘贴

配置类



package com.cloud.framework.i18n;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;

@ConditionalOnProperty(name = {"spring.messages.basename"})
@EnableConfigurationProperties({TranslatorProperties.class})
@Configuration
public class InternationalConfiguration extends AcceptHeaderLocaleResolver implements WebMvcConfigurer {
    @Autowired
    private TranslatorProperties translatorProperties;

    public InternationalConfiguration() {
    }

    @Bean
    public ResourceBundleMessageSource messageSource() {
        ResourceBundleMessageSource rs = new ResourceBundleMessageSource();
        rs.setDefaultEncoding(this.translatorProperties.getEncoding());
        rs.setBasenames(new String[]{this.translatorProperties.getBasename()});
        rs.setUseCodeAsDefaultMessage(true);
        rs.setCacheSeconds(this.translatorProperties.getCacheSeconds());
        return rs;
    }

    @Bean
    public Translator myTranslator(ResourceBundleMessageSource messageSource) {
        Translator result = new Translator(messageSource);
        result.setDefaultLang(this.translatorProperties.getDefaultLang());
        return result;
    }
}

 


package com.cloud.framework.i18n;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix = "spring.messages")
public class TranslatorProperties {
    private String encoding;
    private String basename;
    private int cacheSeconds;
    private boolean isClientLang;
    private String defaultLang;
    public TranslatorProperties() {
    }
    public String getEncoding() {
        return this.encoding;
    }

    public String getBasename() {
        return this.basename;
    }

    public int getCacheSeconds() {
        return this.cacheSeconds;
    }

    public boolean isClientLang() {
        return this.isClientLang;
    }

    public String getDefaultLang() {
        return this.defaultLang;
    }

    public void setEncoding(String encoding) {
        this.encoding = encoding;
    }

    public void setBasename(String basename) {
        this.basename = basename;
    }

    public void setCacheSeconds(int cacheSeconds) {
        this.cacheSeconds = cacheSeconds;
    }

    public void setClientLang(boolean isClientLang) {
        this.isClientLang = isClientLang;
    }

    public void setDefaultLang(String defaultLang) {
        this.defaultLang = defaultLang;
    }


    protected boolean canEqual(Object other) {
        return other instanceof TranslatorProperties;
    }

    public TranslatorProperties(String encoding, String basename, int cacheSeconds, boolean isClientLang, String defaultLang) {
        this.encoding = encoding;
        this.basename = basename;
        this.cacheSeconds = cacheSeconds;
        this.isClientLang = isClientLang;
        this.defaultLang = defaultLang;
    }


}

翻译工具类


package com.cloud.framework.i18n;

import com.alibaba.fastjson.JSONObject;
import com.cloud.framework.cache.RedisUtils;
import com.cloud.framework.util.CodeStyleConvert;
import com.cloud.framework.web.SysContext;
import com.google.common.base.Preconditions;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.util.CollectionUtils;

public class Translator {
    private static final Logger log = LoggerFactory.getLogger(Translator.class);
    private static final String TIP = "mutli--lang--%s--%s";
    @Autowired
    private SysContext context;
    @Autowired
    private RedisUtils redisUtils;
    private ResourceBundleMessageSource messageSource;
    private String defaultLang;

    @Autowired
    Translator(ResourceBundleMessageSource messageSource) {
        this.messageSource = messageSource;
    }

    public String dataToLocale(String field, String msg) {
        String lang = this.initDefaultLang();
        String[] l = lang.split("_");
        Preconditions.checkArgument(l.length == 2, "error lang");
        String codeStyle = field.indexOf("i18n_") < 0 ? CodeStyleConvert.underscoreName(field) : field;
        log.info(String.format("mutli--lang--%s--%s", "CodeStyle", codeStyle));
        List<Object> items = this.redisUtils.lRange(String.format("language:%s", codeStyle), 0L, -1L);
        if (CollectionUtils.isEmpty(items)) {
            return msg;
        } else {
            Iterator var8 = items.iterator();

            JSONObject joItem;
            do {
                if (!var8.hasNext()) {
                    return msg;
                }

                Object item = var8.next();
                log.info(String.format("mutli--lang--%s--%s", "RedisItem", item.toString()));
                joItem = (JSONObject)item;
            } while(!joItem.containsKey("typeKey") || !joItem.get("typeKey").equals(msg + "_" + l[0]));

            return joItem.get("value").toString();
        }
    }

    private String initDefaultLang() {
        String lang = this.context.getLang();
        if (StringUtils.isEmpty(lang) && !StringUtils.isEmpty(this.defaultLang)) {
            lang = this.defaultLang;
        }

        return lang;
    }

    public String sysToLocale(String msg) {
        String lang = this.initDefaultLang();
        String[] l = lang.split("_");
        Preconditions.checkArgument(l.length == 2, "error lang");
        Locale locale = new Locale(l[0], l[1]);
        return this.messageSource.getMessage(msg, new Object[0], locale);
    }

    public String sysToLocale(String lang, String msg) {
        String[] l = lang.split("_");
        Preconditions.checkArgument(l.length == 2, "error lang");
        Locale locale = new Locale(l[0], l[1]);
        return this.messageSource.getMessage(msg, new Object[0], locale);
    }

    public String getDefaultLang() {
        return this.defaultLang;
    }

    public void setDefaultLang(String defaultLang) {
        this.defaultLang = defaultLang;
    }
}

META-INF 加载配置类

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.cloud.framework.datasource.hbase.HBaseConfiguration

spring-boot配置文件 国际化默认语言配置  前端不传取默认  登录后语言记录符存redis 每次从redis取   切换语言时  修改redis存值

#国际化配置  defaultLang 默认语言  zh_CN 中文  en_US英文
messages:
   basename: i18n/messages
   encoding: UTF-8
   cacheSeconds: 0
   isClientLang: false
   defaultLang: zh_CN

配置资源文件

资源文件就是 key-value 对每个资源文件中的 key 是不变的但是value 随着不同的国家语言而改变。
如下图所示提供了中文、英语俩种语言

英文

 

#public
PUBLIC_QUERY_SUCCESS=The query is successful
PUBLIC_QUERY_FAIL=The query fails

 中文

 

#public
PUBLIC_QUERY_SUCCESS=查询成功
PUBLIC_QUERY_FAIL=查询失败

 

测试

package com.cloud.user.controller;

import com.cloud.framework.bean.Result;
import com.cloud.framework.util.ResponseUtils;
import com.cloud.user.base.BaseResource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;


/**
 * i18 国际化  中英文 翻译
 */
@RestController
@RequestMapping("/i18")
public class I18TransController extends BaseResource {

    /**
     *默认翻译
     */
    @GetMapping("/defaultTran")
    public Result<Object> defaultTran() {
        return ResponseUtils.make(Result.OK, sysToLocale("PUBLIC_QUERY_SUCCESS"));
    }

    /**
     * 模拟登录 前端 传翻译类型  根据前端传值进行翻译  zh_CN 中文  en_US英文
     * @param lang
     * @return
     */
    @GetMapping("/login")
    public Result<Object> login(@RequestParam(name = "lang") String lang) {
        String errMsg="PUBLIC_QUERY_SUCCESS";
        errMsg = sysToLocale(lang, errMsg);
        return ResponseUtils.make(Result.OK, errMsg);
    }


    /**
     * 根据字典存值翻译  比如 下拉框类型翻译
     * @return
     */
    @GetMapping("/tranByDictSelect")
    public Result<Object> tranByDictSelect() {
        //strategyCategoryReserve模拟数据库字典表 存的需要翻译的值
        String name="strategyCategoryReserve";//下拉框数据 i18n_value字段对应存值
        String transName = languageSwitch(name);
        return ResponseUtils.make(Result.OK, transName);
    }

    /**
     * 根据字典存值翻译  菜单翻译
     * @return
     */
    @GetMapping("/tranByDictMenu")
    public Result<Object> tranByDictMenu() {
        //jurisdiction 模拟数据库字典表 存的需要翻译的值
        String name="jurisdiction";//菜单数据 i18n_value字段对应存值
        String typeKey="i18n_menu_name";//菜单数据 i18n_value字段对应存值
        String transName = languageSwitch(typeKey,name);
        return ResponseUtils.make(Result.OK, transName);
    }

}

 

启动项目时需把字典数据加入缓存  只贴关键性代码

package com.cloud.user;

import com.alibaba.fastjson.JSONObject;
import com.cloud.framework.cache.RedisUtils;
import com.cloud.framework.util.SpringContextUtils;
import com.cloud.user.entity.db1.XbDictionary;
import com.cloud.user.service.TestService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;

import java.util.Arrays;
import java.util.List;

@SpringBootApplication
@Slf4j
public class CloudUserApplication implements CommandLineRunner {

    private final ApplicationContext appContext;

    private final TestService testService;

    private final RedisUtils redisUtils;

    public CloudUserApplication(ApplicationContext appContext, TestService testService, RedisUtils redisUtils) {
        this.appContext = appContext;
        this.testService = testService;
        this.redisUtils = redisUtils;
    }


    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(CloudUserApplication.class, args);
        SpringContextUtils.setApplicationContext(context);
    }

    @Override
    public void run(String... args) throws Exception {
        String[] beans = appContext.getBeanDefinitionNames();
        Arrays.sort(beans);
        for (String bean : beans) {
            System.out.println(bean);
        }
        // 初始化字典表数据到redis 翻译时候从redis取
        redisDicCache();

    }

    /**
     * 存储结构  字典数据存储类型 key:value
     * 一级  root:TypeKey
     * 二级  父级TypeKey:二级TypeKey
     * 三级  二级TypeKey:三级TypeKey
     * 翻译数据 存储类型为list
     * language:二级TypeKey   下拉框数据 language:i18n_value   菜单数据language:i18n_menu_name
     */
    public void redisDicCache() {
        List<XbDictionary> dicList = testService.findAll();
        List<XbDictionary> list = testService.findParentIdisNull();
        //redisUtils.removePattern("language:*");
        for (XbDictionary item : list) {
            //若字典为一级记为root:TypeKey
            String pTypeKey = item.getTypeKey();
            //redisUtils.set("root" + ":" + pTypeKey, item);
            log.info("一级pTypeKey:{},item:{}", pTypeKey, item);
            for (XbDictionary dic : dicList) {
                if (item.getId().equals(dic.getParentId())) {
                    String typeKeyTwo = dic.getTypeKey();
                    log.info("一级{}二级{}typeKeyTwo:{},dic:{}", pTypeKey, typeKeyTwo, dic);
                    //redisUtils.set(pTypeKey + ":" + typeKeyTwo, dic);
                    for (XbDictionary dictionary : dicList) {
                        String typeKeyThree = dictionary.getTypeKey();
                        if (!typeKeyTwo.equals(typeKeyThree) &&
                                typeKeyThree.contains(typeKeyTwo)) {
                            // redisUtils.set(typeKeyTwo + ":" + typeKeyThree, dictionary);
                            log.info("二级{}三级{}typeKeyThree:{},dictionary:{}", typeKeyTwo, typeKeyThree, dictionary);
                        }
                        if (typeKeyTwo.contains("i18n_") && dic.getId().equals(dictionary.getParentId())) {
                            JSONObject jsonObject = new JSONObject();
                            jsonObject.put("id", dictionary.getId());
                            jsonObject.put("name", dictionary.getName());
                            jsonObject.put("parentId", dictionary.getParentId());
                            jsonObject.put("typeKey", dictionary.getTypeKey());
                            jsonObject.put("value", dictionary.getI18nValue());
                            //  redisUtils.lPush("language:" + dic.getTypeKey(), jsonObject);
                            log.info("翻译数据typeKey{},数据:{}", "language:" + dic.getTypeKey(), jsonObject);
                        }
                    }
                }
            }
        }
    }


}

postman访问   默认值配置的英文en_US

 配置的改为中文  zh_CN

根据前端传值 进行翻译

http://localhost:9000/i18/login?lang=zh_CN

 根据数据库字典表存值翻译  对应前端下拉框

 

  根据数据库字典表存值翻译  对应前端菜单

 

 

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: Spring

“spring-boot国际化i18n中英文实现” 的相关文章