如果你还在为国际化的问题苦恼的话, 不妨往下看看 ↓↓↓
本文采取数据库去存储国际化字典,再对响应内容做全局处理
1.数据库设计
CREATE TABLE `i18n_dictionary` ( `key` varchar(255) DEFAULT NULL COMMENT '中文内容', `system` varchar(255) DEFAULT NULL COMMENT '自定义程序标识,用来区分程序', `lang_en` varchar(255) DEFAULT NULL COMMENT '英语', `lang_thai` varchar(255) DEFAULT NULL COMMENT '泰文', `type` varchar(255) DEFAULT NULL COMMENT '类型 content表示json内容 key表示json的key' ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
讯享网
2.依赖
讯享网<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.83</version> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.4</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.2</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency>
3.目录展示

4.查询sql

/ * 获取表头 * @return */ @Select("SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE table_name = 'i18n_dictionary'") List<String> getI18nDictionary(); / * 根据类型获取国际化数据 * @param type * @return */ @Select("select * from i18n_dictionary where type=#{type}") List<Map<String,String>> getI18nListMap(@Param("type")String type);
5.初始化缓存加载和全局处理
缓存类
初始加载字典缓存, 以及对字典定时刷新
讯享网import com.zsx.i18ndemo.mapper.I18nMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @Component @Slf4j public class I18nDictionaryCache {
// 语言, 中文 对应content内容 private static Map<String, Map<String, String>> i18nContentDictionary = new HashMap<>(); // 语言, 中文, 对应json返回map的key private static Map<String, Map<String, String>> i18nKeyDictionary = new HashMap<>(); //其他, 支持自定义呗 private static Map<String, Map<String, String>> i18nHeaderDictionary = new HashMap<>(); // 外国语言转成中文用于批量导入 private static Map<String, Map<String, String>> i18nTransChineseDict = new HashMap<>(); @Autowired private I18nMapper i18nMapper; / * 初始化加载字典 */ @PostConstruct public void init() {
long time = System.currentTimeMillis(); initDictionary("content", i18nContentDictionary, TranTypeEnum.CN_TO_OTHER); initDictionary("key", i18nKeyDictionary, TranTypeEnum.CN_TO_OTHER); initDictionary("header", i18nHeaderDictionary, TranTypeEnum.CN_TO_OTHER); initDictionary("title", i18nTransChineseDict, TranTypeEnum.OTHER_TO_CN); log.info("初始化国际化字典信息完成,耗时:" + (System.currentTimeMillis() - time)); } / * 初始化加载字典 */ @Scheduled(fixedRate = 30000) public void refreshDictionary() {
long time = System.currentTimeMillis(); initDictionary("content", i18nContentDictionary, TranTypeEnum.CN_TO_OTHER); initDictionary("key", i18nKeyDictionary, TranTypeEnum.CN_TO_OTHER); initDictionary("header", i18nHeaderDictionary, TranTypeEnum.CN_TO_OTHER); initDictionary("title", i18nTransChineseDict, TranTypeEnum.OTHER_TO_CN); log.info("刷新化国际化字典信息完成,耗时:" + (System.currentTimeMillis() - time)); } / * 添加字典 */ public static void addDictionary(String locale, String key, String value, Map<String, Map<String, String>> i18nContentDictionary) {
Map<String, String> stringStringMap = i18nContentDictionary.computeIfAbsent(locale, k -> new LinkedHashMap<>()); stringStringMap.put(key, value); } / * 将国际化字典添加到map,(批量导入的,其他语言转成中文) * * @param type * @param i18nDictionaryType */ public void initDictionary(String type, Map<String, Map<String, String>> i18nDictionaryType, TranTypeEnum tranType) {
List<String> columns = i18nMapper.getI18nDictionary(); List<Map<String, String>> i18nListMap = i18nMapper.getI18nListMap(type); //这里进行一下排序,防止转换不全: 例如 添加成功 先匹配成功 ,就成了 添加success List<Map<String, String>> i18nListMapSorted = i18nListMap.stream().sorted((i, j) -> j.get("key").length() - i.get("key").length()).collect(Collectors.toList()); if (i18nListMapSorted.size() > 0 && i18nDictionaryType.size() > 0) {
i18nDictionaryType.clear(); } for (Map<String, String> map : i18nListMapSorted) {
for (String column : columns) {
if (column.contains("lang")) {
if (tranType.getValue() == 0) {
//其他语言做key addDictionary(column, map.get("key"), map.get(column), i18nDictionaryType); } else {
//中**key addDictionary(column, map.get(column), map.get("key"), i18nDictionaryType); } } } } } public static Map<String, String> getContentDictionary(String locale) {
return i18nContentDictionary.get(locale);} public static Map<String, String> getKeyDictionary(String locale) {
return i18nKeyDictionary.get(locale);} public static Map<String, String> getHeaderDictionary(String locale) {
return i18nHeaderDictionary.get(locale);} public static Map<String,String> getTransChineseDict(String locale){
return i18nTransChineseDict.get(locale);}
转换类型枚举
public enum TranTypeEnum {
CN_TO_OTHER(0,"中文作key"), OTHER_TO_CN(1,"英**key") ; private Integer value; private String remark; TranTypeEnum(int value, String remark) {
this.value=value; this.remark=remark; } public Integer getValue() {
return value; } public String getRemark() {
return remark; } }
通用返回实体
讯享网@Data public class RetObj<T> {
int code; / * 结果描述信息 */ String msg; / * 结果对象 */ T obj; / * 扩展数据 */ Map<String, Object> extend; public RetObj(){
code = 200; } public RetObj(int code, String msg, T obj, Map<String, Object> extend) {
super(); this.code = code; this.msg = msg; this.obj = obj; this.extend = extend; } /* * 设置为错误 * @param msg */ public void fail(String msg){
code = 500; this.msg = msg; } }
测试用户实体
@Data @NoArgsConstructor @AllArgsConstructor public class User {
private String name; private Integer age; private String address; private String sex; }
全局处理
讯享网import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.zsx.i18ndemo.cache.I18nDictionaryCache; import com.zsx.i18ndemo.util.ResponseI18nUtil; import org.springframework.core.MethodParameter; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; import java.util.Map; @ControllerAdvice(basePackages = "com.zsx.i18ndemo.controller") public class ResponseBodyI18nAdvice implements ResponseBodyAdvice<Object> {
@Override public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
return true; } @Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
//响应国际化内容 HttpHeaders headers = request.getHeaders(); //需要响应的语言 String locale = headers.getFirst("locale"); if(locale!=null && body!=null){
Map<String, String> contentDictionary = I18nDictionaryCache.getContentDictionary(locale); if(contentDictionary!=null){
JSONObject jsonObject = (JSONObject) JSON.toJSON(body); ResponseI18nUtil.jsonObjectI18n(jsonObject,contentDictionary); Map<String, String> keyDictionary = I18nDictionaryCache.getKeyDictionary(locale); //转换中文key if(keyDictionary!=null){
return ResponseI18nUtil.changeJsonObj(jsonObject,keyDictionary); } return jsonObject; } } return body; } }
6.响应帮助类
import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.zsx.i18ndemo.cache.I18nDictionaryCache; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; import java.lang.reflect.Field; import java.util.*; public class ResponseI18nUtil {
/ * jsonObject国际化 * * @param jsonObject * @param keyMap */ public static void jsonObjectI18n(JSONObject jsonObject, Map<String, String> keyMap) {
Set<String> keySet = jsonObject.keySet(); for (String key : keySet) {
Object obj = jsonObject.get(key); if (obj instanceof String) {
replaceValue(jsonObject, key, keyMap); } else {
if (obj instanceof JSONObject) {
jsonObjectI18n(jsonObject.getJSONObject(key), keyMap); } if (obj instanceof JSONArray) {
jsonArrayI18n(jsonObject.getJSONArray(key), keyMap); } } } } / * jsonArray国际化 * * @param jsonArray * @param keyMap */ public static void jsonArrayI18n(JSONArray jsonArray, Map<String, String> keyMap) {
for (int i = 0; i < jsonArray.size(); i++) {
Object obj = jsonArray.get(i); if (obj instanceof JSONObject) {
jsonObjectI18n(jsonArray.getJSONObject(i), keyMap); } if (obj instanceof JSONArray) {
jsonArrayI18n(jsonArray.getJSONArray(i), keyMap); } } } / * 替换value值 * * @param jsonObject * @param key * @param keyMap */ public static void replaceValue(JSONObject jsonObject, String key, Map<String, String> keyMap) {
String value = jsonObject.getString(key); for (Map.Entry<String, String> entry : keyMap.entrySet()) {
if (StrUtil.isNotBlank(key)) {
if (value.contains(entry.getKey())&&entry.getValue()!=null) {
value = value.replace(entry.getKey(), entry.getValue()); } } } jsonObject.put(key, value); } / * 国际化集合中对象的String字段 * * @param data * @throws Exception */ private static <T> void changeStringField(List<T> data, Map<String, String> keyMap) throws Exception {
for (T obj : data) {
Field[] fields = obj.getClass().getDeclaredFields(); for (Field field : fields) {
if (field.getType() == String.class) {
field.setAccessible(true); String oldValue = (String) field.get(obj); for (Map.Entry<String, String> entry : keyMap.entrySet()) {
if (StrUtil.isNotBlank(oldValue)) {
if (oldValue.contains(entry.getKey())&&entry.getValue()!=null) {
oldValue = oldValue.replace(entry.getKey(), entry.getValue()); } } } field.set(obj, oldValue); } } } } / * 国际化对象集合中的String字段 * * @param data * @throws Exception */ public static <T> void i18nFormatExportData(List<T> data) throws Exception {
HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest(); String locale = request.getHeader("locale"); if (StrUtil.isNotBlank(locale)) {
Map<String, String> keyMap = I18nDictionaryCache.getContentDictionary(locale); if(keyMap==null){
return; } changeStringField(data, keyMap); } } / * 国际化对象集合中的String字段 * * @param titleHeaders * @throws Exception */ private static void i18nFormatExportHeader(Map<String, String> titleHeaders) {
HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest(); String locale = request.getHeader("locale"); if (StrUtil.isNotBlank(locale)) {
Map<String, String> keyMap = I18nDictionaryCache.getHeaderDictionary(locale); if(keyMap==null){
return; } for (Map.Entry<String, String> entry : titleHeaders.entrySet()) {
String oldValue = entry.getValue(); for (Map.Entry<String, String> dictEntry : keyMap.entrySet()) {
if (oldValue.contains(dictEntry.getKey())&&dictEntry.getValue()!=null) {
oldValue = oldValue.replace(dictEntry.getKey(), dictEntry.getValue()); } } titleHeaders.put(entry.getKey(),oldValue); } } } public static String[] i18nFormatExportHeader(String[] titleHeaders) {
HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest(); String locale = request.getHeader("locale"); if (StrUtil.isNotBlank(locale)) {
List<String> titleHeaderList = new ArrayList<>(); Map<String, String> keyMap = I18nDictionaryCache.getHeaderDictionary(locale); for (String oldValue : titleHeaders) {
for (Map.Entry<String, String> dictEntry : keyMap.entrySet()) {
if (oldValue.contains(dictEntry.getKey())&&dictEntry.getValue()!=null) {
oldValue = oldValue.replace(dictEntry.getKey(), dictEntry.getValue()); } } titleHeaderList.add(oldValue); } return titleHeaderList.toArray(new String[titleHeaderList.size()]); } return titleHeaders; } public static String[] i18nFormatExportHeader(String[] titleHeaders,String locale) {
if (StrUtil.isNotBlank(locale)) {
List<String> titleHeaderList = new ArrayList<>(); Map<String, String> keyMap = I18nDictionaryCache.getHeaderDictionary(locale); for (String oldValue : titleHeaders) {
for (Map.Entry<String, String> dictEntry : keyMap.entrySet()) {
if (oldValue.contains(dictEntry.getKey())&&dictEntry.getValue()!=null) {
oldValue = oldValue.replace(dictEntry.getKey(), dictEntry.getValue()); } } titleHeaderList.add(oldValue); } return titleHeaderList.toArray(new String[titleHeaderList.size()]); } return titleHeaders; } public static String i18nFormatExportFileName(String fileName){
HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest(); String locale = request.getHeader("locale"); if (StrUtil.isNotBlank(locale) && null != fileName) {
Map<String, String> keyMap = I18nDictionaryCache.getHeaderDictionary(locale); for (Map.Entry<String, String> dictEntry : keyMap.entrySet()) {
if (null != dictEntry.getKey() && dictEntry.getKey().equals(fileName)) {
return dictEntry.getValue().replaceAll(" ", ""); } } } return fileName; } / * key的国际化 * * @param jsonObj * @param keyMap * @return */ public static JSONObject changeJsonObj(JSONObject jsonObj, Map<String, String> keyMap) {
JSONObject resJson = new JSONObject(); Set<String> keySet = jsonObj.keySet(); for (String key : keySet) {
String resKey = keyMap.get(key) == null ? key : keyMap.get(key); try {
Object obj= jsonObj.get(key); if(obj instanceof String){
resJson.put(resKey, jsonObj.get(key)); } else {
JSONObject jsonobj1 = jsonObj.getJSONObject(key); resJson.put(resKey, changeJsonObj(jsonobj1, keyMap)); } } catch (Exception e) {
try {
JSONArray jsonArr = jsonObj.getJSONArray(key); resJson.put(resKey, changeJsonArr(jsonArr, keyMap)); } catch (Exception x) {
resJson.put(resKey, jsonObj.get(key)); } } } return resJson; } / * key的国际化 * * @param jsonArr * @param keyMap * @return */ public static JSONArray changeJsonArr(JSONArray jsonArr, Map<String, String> keyMap) {
JSONArray resJson = new JSONArray(); for (int i = 0; i < jsonArr.size(); i++) {
JSONObject jsonObj = jsonArr.getJSONObject(i); resJson.add(changeJsonObj(jsonObj, keyMap)); } return resJson; } public static void i18nFormatContentData(List<Map<String, Object>> list) {
HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest(); String locale = request.getHeader("locale"); if (StrUtil.isNotBlank(locale)) {
Map<String, String> keyMap = I18nDictionaryCache.getContentDictionary(locale); if (keyMap != null) {
list.forEach(x -> {
for (Map.Entry<String, Object> valueEntry : x.entrySet()) {
if (null != valueEntry.getValue()) {
for (Map.Entry<String, String> dictEntry : keyMap.entrySet()) {
String value = valueEntry.getValue().toString(); if (value.contains(dictEntry.getKey()) && dictEntry.getValue() != null) {
value = value.replace(dictEntry.getKey(), dictEntry.getValue()); x.put(valueEntry.getKey(), value); } } } } }); } } } public static String i18nFormatStringValue(String value) {
HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest(); String locale = request.getHeader("locale"); if (StrUtil.isNotBlank(locale)) {
Map<String, String> keyMap = I18nDictionaryCache.getContentDictionary(locale); for (Map.Entry<String, String> dictEntry : keyMap.entrySet()) {
if (value.contains(dictEntry.getKey())&&dictEntry.getValue()!=null) {
value = value.replaceAll(dictEntry.getKey(), dictEntry.getValue()); } } } return value; } / * 其他语言 转换中文 * @return */ public static String i18nTransChinese(String value){
HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest(); String locale = request.getHeader("locale"); if (StrUtil.isNotBlank(locale)) {
Map<String, String> keyMap = I18nDictionaryCache.getTransChineseDict(locale); for (Map.Entry<String, String> dictEntry : keyMap.entrySet()) {
if (value.equals(dictEntry.getKey())&&dictEntry.getValue()!=null) {
value = dictEntry.getValue(); } } } return value; }
7.测试代码
讯享网@RestController @RequestMapping("/user") public class I18nController {
@RequestMapping("/getInfo") public RetObj<User> getUserInfo(){
RetObj<User> ret=new RetObj<>(); User user = new User("汤姆", 23, "中国", "男"); ret.setMsg("成功"); ret.setObj(user); return ret; } }
未设置国际化标识

设置国际化标识之后


版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/33953.html