server i18n
This commit is contained in:
parent
a1ba010375
commit
4423a44c55
|
@ -86,6 +86,16 @@
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-lang3</artifactId>
|
<artifactId>commons-lang3</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-collections4</artifactId>
|
||||||
|
<version>4.1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-text</artifactId>
|
||||||
|
<version>1.8</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>commons-codec</groupId>
|
<groupId>commons-codec</groupId>
|
||||||
<artifactId>commons-codec</artifactId>
|
<artifactId>commons-codec</artifactId>
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
package io.metersphere.commons.constants;
|
||||||
|
|
||||||
|
public class I18nConstants {
|
||||||
|
|
||||||
|
public static final String LANG_COOKIE_NAME = "MS_USER_LANG";
|
||||||
|
|
||||||
|
public static final String LOCAL = "local";
|
||||||
|
public static final String CLUSTER = "cluster";
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,190 @@
|
||||||
|
package io.metersphere.commons.constants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Author: chunxing
|
||||||
|
* Date: 2018/6/26 下午3:44
|
||||||
|
* Description:
|
||||||
|
*/
|
||||||
|
public interface ParamConstants {
|
||||||
|
|
||||||
|
String getValue();
|
||||||
|
|
||||||
|
enum KeyCloak implements ParamConstants {
|
||||||
|
|
||||||
|
USERNAME("keycloak.username"),
|
||||||
|
PASSWORD("keycloak.password"),
|
||||||
|
REALM("keycloak.realm"),
|
||||||
|
AUTH_SERVER_URL("keycloak.auth-server-url"),
|
||||||
|
ADDRESS("keycloak-server-address");
|
||||||
|
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
KeyCloak(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Type implements ParamConstants {
|
||||||
|
|
||||||
|
PASSWORD("password"),
|
||||||
|
TEXT("text"),
|
||||||
|
JSON("json");
|
||||||
|
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
Type(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Classify implements ParamConstants {
|
||||||
|
|
||||||
|
KEYCLOAK("keycloak"),
|
||||||
|
MAIL("smtp"),
|
||||||
|
UI("ui"),
|
||||||
|
REGISTRY("registry");
|
||||||
|
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
Classify(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum UI implements ParamConstants {
|
||||||
|
|
||||||
|
LOGO("ui.logo"),
|
||||||
|
SYSTEM_NAME("ui.system.name"),
|
||||||
|
THEME_PRIMARY("ui.theme.primary"),
|
||||||
|
THEME_ACCENT("ui.theme.accent"),
|
||||||
|
FAVICON("ui.favicon"),
|
||||||
|
LOGIN_TITLE("ui.login.title"),
|
||||||
|
LOGIN_IMG("ui.login.img"),
|
||||||
|
SUPPORT_NAME("ui.support.name"),
|
||||||
|
SUPPORT_URL("ui.support.url"),
|
||||||
|
TITLE("ui.title");
|
||||||
|
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
UI(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum MAIL {
|
||||||
|
SERVER("smtp.server", 1),
|
||||||
|
PORT("smtp.port", 2),
|
||||||
|
ACCOUNT("smtp.account", 3),
|
||||||
|
PASSWORD("smtp.password", 4),
|
||||||
|
SSL("smtp.ssl", 5),
|
||||||
|
TLS("smtp.tls", 6);
|
||||||
|
|
||||||
|
private String key;
|
||||||
|
private Integer value;
|
||||||
|
|
||||||
|
MAIL(String key, Integer value) {
|
||||||
|
this.key = key;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Log implements ParamConstants {
|
||||||
|
KEEP_MONTHS("log.keep.months");
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
Log(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Registry implements ParamConstants {
|
||||||
|
URL("registry.url"),
|
||||||
|
REPO("registry.repo"),
|
||||||
|
USERNAME("registry.username"),
|
||||||
|
PASSWORD("registry.password");
|
||||||
|
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
Registry(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum I18n implements ParamConstants {
|
||||||
|
|
||||||
|
LANGUAGE("i18n.language");
|
||||||
|
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
I18n(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package io.metersphere.config;
|
||||||
|
|
||||||
|
import io.metersphere.i18n.I18nManager;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class I18nConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
public I18nManager i18nManager() {
|
||||||
|
List<String> dirs = new ArrayList<>();
|
||||||
|
dirs.add("i18n/");
|
||||||
|
return new I18nManager(dirs);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
package io.metersphere.controller;
|
||||||
|
|
||||||
|
|
||||||
|
import io.metersphere.commons.constants.I18nConstants;
|
||||||
|
import io.metersphere.commons.exception.MSException;
|
||||||
|
import io.metersphere.commons.utils.LogUtil;
|
||||||
|
import io.metersphere.i18n.Lang;
|
||||||
|
import io.metersphere.service.UserService;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.servlet.http.Cookie;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by liqiang on 2019/4/1.
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
public class I18nController {
|
||||||
|
|
||||||
|
private static final int FOR_EVER = 3600 * 24 * 30 * 12 * 10; //10 years in second
|
||||||
|
|
||||||
|
@Value("${run.mode:release}")
|
||||||
|
private String runMode;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private UserService userService;
|
||||||
|
|
||||||
|
@GetMapping("lang/change/{lang}")
|
||||||
|
public void changeLang(@PathVariable String lang, HttpServletResponse response) {
|
||||||
|
Lang targetLang = Lang.getLangWithoutDefault(lang);
|
||||||
|
if (targetLang == null) {
|
||||||
|
response.setStatus(HttpServletResponse.SC_NOT_ACCEPTABLE);
|
||||||
|
LogUtil.error("Invalid parameter: " + lang);
|
||||||
|
MSException.throwException("ERROR_LANG_INVALID");
|
||||||
|
}
|
||||||
|
userService.setLanguage(targetLang.getDesc());
|
||||||
|
Cookie cookie = new Cookie(I18nConstants.LANG_COOKIE_NAME, targetLang.getDesc());
|
||||||
|
cookie.setPath("/");
|
||||||
|
cookie.setMaxAge(FOR_EVER);
|
||||||
|
response.addCookie(cookie);
|
||||||
|
//重新登录
|
||||||
|
if ("release".equals(runMode)) {
|
||||||
|
Cookie f2cCookie = new Cookie("MS_COOKIE_ID", "deleteMe");
|
||||||
|
f2cCookie.setPath("/");
|
||||||
|
f2cCookie.setMaxAge(0);
|
||||||
|
response.addCookie(f2cCookie);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,6 +21,8 @@ public class UserDTO {
|
||||||
|
|
||||||
private Long updateTime;
|
private Long updateTime;
|
||||||
|
|
||||||
|
private String language;
|
||||||
|
|
||||||
private String lastWorkspaceId;
|
private String lastWorkspaceId;
|
||||||
|
|
||||||
private String lastOrganizationId;
|
private String lastOrganizationId;
|
||||||
|
@ -103,6 +105,14 @@ public class UserDTO {
|
||||||
this.userRoles = userRoles;
|
this.userRoles = userRoles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getLanguage() {
|
||||||
|
return language;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLanguage(String language) {
|
||||||
|
this.language = language;
|
||||||
|
}
|
||||||
|
|
||||||
public String getLastWorkspaceId() {
|
public String getLastWorkspaceId() {
|
||||||
return lastWorkspaceId;
|
return lastWorkspaceId;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
package io.metersphere.i18n;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.alibaba.fastjson.TypeReference;
|
||||||
|
import io.metersphere.commons.utils.IOUtils;
|
||||||
|
import io.metersphere.commons.utils.LogUtil;
|
||||||
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.boot.ApplicationArguments;
|
||||||
|
import org.springframework.boot.ApplicationRunner;
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
|
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||||
|
import org.springframework.util.ResourceUtils;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class I18nManager implements ApplicationRunner {
|
||||||
|
|
||||||
|
private static Map<String, Map<String, String>> i18nMap = new HashMap<>();
|
||||||
|
|
||||||
|
private List<String> dirs;
|
||||||
|
|
||||||
|
public I18nManager(List<String> dirs) {
|
||||||
|
this.dirs = dirs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<String, Map<String, String>> getI18nMap() {
|
||||||
|
return i18nMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Resource[] getResources(String dir, String suffix) throws IOException {
|
||||||
|
Resource[] result = new Resource[0];
|
||||||
|
PathMatchingResourcePatternResolver patternResolver = new PathMatchingResourcePatternResolver();
|
||||||
|
if (!patternResolver.getResource(ResourceUtils.CLASSPATH_URL_PREFIX + dir).exists()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
Resource[] resources = patternResolver.getResources(ResourceUtils.CLASSPATH_URL_PREFIX + dir + "*");
|
||||||
|
for (Resource resource : resources) {
|
||||||
|
if (StringUtils.endsWithIgnoreCase(resource.getFilename(), suffix)) {
|
||||||
|
result = ArrayUtils.add(result, resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init() {
|
||||||
|
try {
|
||||||
|
for (Lang lang : Lang.values()) {
|
||||||
|
Resource[] resources = new Resource[0];
|
||||||
|
String i18nKey = lang.getDesc().toLowerCase();
|
||||||
|
for (String dir : dirs) {
|
||||||
|
resources = ArrayUtils.addAll(resources, getResources(dir, i18nKey + ".json"));
|
||||||
|
}
|
||||||
|
for (Resource resource : resources) {
|
||||||
|
if (resource.exists()) {
|
||||||
|
try (InputStream inputStream = resource.getInputStream()) {
|
||||||
|
String fileContent = IOUtils.toString(inputStream, Charset.defaultCharset());
|
||||||
|
Map<String, String> langMap = JSON.parseObject(fileContent, new TypeReference<HashMap<String, String>>() {
|
||||||
|
});
|
||||||
|
i18nMap.computeIfAbsent(i18nKey, k -> new HashMap<>());
|
||||||
|
i18nMap.get(i18nKey).putAll(langMap);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
LogUtil.error("failed to load resource: " + resource.getURI());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtil.error("failed to load i18n.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 国际化配置初始化
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void run(ApplicationArguments args) {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package io.metersphere.i18n;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
public enum Lang {
|
||||||
|
|
||||||
|
zh_CN("zh-CN"), zh_TW("zh-TW"), en_US("en-US");
|
||||||
|
|
||||||
|
private String desc;
|
||||||
|
|
||||||
|
Lang(String desc) {
|
||||||
|
this.desc = desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDesc() {
|
||||||
|
return this.desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Lang getLang(String lang) {
|
||||||
|
Lang result = getLangWithoutDefault(lang);
|
||||||
|
if (result == null) {
|
||||||
|
result = zh_CN;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Lang getLangWithoutDefault(String lang) {
|
||||||
|
if (StringUtils.isBlank(lang)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (Lang lang1 : values()) {
|
||||||
|
if (StringUtils.equalsIgnoreCase(lang1.getDesc(), lang)) {
|
||||||
|
return lang1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (StringUtils.startsWithIgnoreCase(lang, "zh-CN")) {
|
||||||
|
return zh_CN;
|
||||||
|
}
|
||||||
|
if (StringUtils.startsWithIgnoreCase(lang, "zh-HK") || StringUtils.startsWithIgnoreCase(lang, "zh-TW")) {
|
||||||
|
return zh_TW;
|
||||||
|
}
|
||||||
|
if (StringUtils.startsWithIgnoreCase(lang, "en")) {
|
||||||
|
return en_US;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,274 @@
|
||||||
|
package io.metersphere.i18n;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.alibaba.fastjson.serializer.JavaBeanSerializer;
|
||||||
|
import com.alibaba.fastjson.serializer.ObjectSerializer;
|
||||||
|
import com.alibaba.fastjson.serializer.SerializeConfig;
|
||||||
|
import io.metersphere.commons.constants.I18nConstants;
|
||||||
|
import io.metersphere.commons.exception.MSException;
|
||||||
|
import io.metersphere.commons.utils.BeanUtils;
|
||||||
|
import io.metersphere.service.CommonBeanFactory;
|
||||||
|
import io.metersphere.commons.utils.LogUtil;
|
||||||
|
import io.metersphere.service.SystemParameterService;
|
||||||
|
import io.metersphere.user.SessionUtils;
|
||||||
|
import org.apache.commons.collections4.MapUtils;
|
||||||
|
import org.apache.commons.collections4.map.PassiveExpiringMap;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||||
|
import org.apache.commons.text.StringSubstitutor;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||||
|
|
||||||
|
import java.lang.reflect.Array;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import javax.servlet.http.Cookie;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
public class Translator {
|
||||||
|
|
||||||
|
public static final String PREFIX = "$[{";
|
||||||
|
public static final String SUFFIX = "}]";
|
||||||
|
private static final String JSON_SYMBOL = "\":";
|
||||||
|
|
||||||
|
private static final HashSet<String> IGNORE_KEYS = new HashSet<>(Arrays.asList("id", "password", "passwd"));
|
||||||
|
|
||||||
|
private static Map<String, String> langCache4Thread = Collections.synchronizedMap(new PassiveExpiringMap(1, TimeUnit.MINUTES));
|
||||||
|
|
||||||
|
public static String getLangDes() {
|
||||||
|
return getLang().getDesc();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Lang getLang() {
|
||||||
|
HttpServletRequest request = getRequest();
|
||||||
|
return getLang(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Object gets(Object keys) {
|
||||||
|
return gets(getLang(), keys);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Object gets(Lang lang, Object keys) {
|
||||||
|
Map<String, String> context = I18nManager.getI18nMap().get(lang.getDesc().toLowerCase());
|
||||||
|
return translateObject(keys, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 单Key翻译
|
||||||
|
public static String get(String key) {
|
||||||
|
return get(getLang(), key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String get(Lang lang, String key) {
|
||||||
|
if (StringUtils.isBlank(key)) {
|
||||||
|
return StringUtils.EMPTY;
|
||||||
|
}
|
||||||
|
return translateKey(key, I18nManager.getI18nMap().get(lang.getDesc().toLowerCase()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String toI18nKey(String key) {
|
||||||
|
return String.format("%s%s%s", PREFIX, key, SUFFIX);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HttpServletRequest getRequest() {
|
||||||
|
try {
|
||||||
|
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
|
||||||
|
} catch (NullPointerException npe) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Lang getLang(HttpServletRequest request) {
|
||||||
|
String preferLang = Lang.zh_CN.getDesc();
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
if (request != null) {
|
||||||
|
Object sessionLang = request.getSession(true).getAttribute(I18nConstants.LANG_COOKIE_NAME);
|
||||||
|
if (sessionLang != null && StringUtils.isNotBlank(sessionLang.toString())) {
|
||||||
|
return Lang.getLang(sessionLang.toString());
|
||||||
|
}
|
||||||
|
preferLang = getSystemParameterLanguage(preferLang);
|
||||||
|
if (StringUtils.isNotBlank(request.getHeader(HttpHeaders.ACCEPT_LANGUAGE))) {
|
||||||
|
String preferLangWithComma = StringUtils.substringBefore(request.getHeader(HttpHeaders.ACCEPT_LANGUAGE), ";");
|
||||||
|
String acceptLanguage = StringUtils.replace(StringUtils.substringBefore(preferLangWithComma, ","), "-", "_");
|
||||||
|
if (Lang.getLangWithoutDefault(acceptLanguage) != null) {
|
||||||
|
preferLang = acceptLanguage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (request.getCookies() != null && request.getCookies().length > 0) {
|
||||||
|
for (Cookie cookie : request.getCookies()) {
|
||||||
|
if (StringUtils.equalsIgnoreCase(cookie.getName(), I18nConstants.LANG_COOKIE_NAME)) {
|
||||||
|
preferLang = cookie.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (SessionUtils.getUser() != null && StringUtils.isNotBlank(SessionUtils.getUser().getLanguage())) {
|
||||||
|
preferLang = SessionUtils.getUser().getLanguage();
|
||||||
|
}
|
||||||
|
request.getSession(true).setAttribute(I18nConstants.LANG_COOKIE_NAME, preferLang);
|
||||||
|
} else {
|
||||||
|
preferLang = getSystemParameterLanguage(preferLang);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtil.error("Fail to getLang.", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Lang.getLang(preferLang);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getSystemParameterLanguage(String defaultLang) {
|
||||||
|
String result = defaultLang;
|
||||||
|
try {
|
||||||
|
String cachedLang = langCache4Thread.get(I18nConstants.LANG_COOKIE_NAME);
|
||||||
|
if (StringUtils.isNotBlank(cachedLang)) {
|
||||||
|
return cachedLang;
|
||||||
|
}
|
||||||
|
String systemLanguage = Objects.requireNonNull(CommonBeanFactory.getBean(SystemParameterService.class)).getSystemLanguage();
|
||||||
|
if (StringUtils.isNotBlank(systemLanguage)) {
|
||||||
|
result = systemLanguage;
|
||||||
|
}
|
||||||
|
langCache4Thread.put(I18nConstants.LANG_COOKIE_NAME, result);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtil.error(e);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Object translateObject(Object javaObject, final Map<String, String> context) {
|
||||||
|
if (MapUtils.isEmpty(context)) {
|
||||||
|
return javaObject;
|
||||||
|
}
|
||||||
|
if (javaObject == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (javaObject instanceof String) {
|
||||||
|
String rawString = javaObject.toString();
|
||||||
|
if (StringUtils.contains(rawString, JSON_SYMBOL)) {
|
||||||
|
try {
|
||||||
|
Object jsonObject = JSON.parse(rawString);
|
||||||
|
Object a = translateObject(jsonObject, context);
|
||||||
|
return JSON.toJSONString(a);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtil.warn("Failed to translate object " + rawString + ". Error: " + ExceptionUtils.getStackTrace(e));
|
||||||
|
return translateRawString(null, rawString, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return translateRawString(null, rawString, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (javaObject instanceof Map) {
|
||||||
|
Map<Object, Object> map = (Map<Object, Object>) javaObject;
|
||||||
|
|
||||||
|
for (Map.Entry<Object, Object> entry : map.entrySet()) {
|
||||||
|
if (entry.getValue() != null) {
|
||||||
|
if (entry.getValue() instanceof String) {
|
||||||
|
if (StringUtils.contains(entry.getValue().toString(), JSON_SYMBOL)) {
|
||||||
|
map.put(entry.getKey(), translateObject(entry.getValue(), context));
|
||||||
|
} else {
|
||||||
|
map.put(entry.getKey(), translateRawString(entry.getKey().toString(), entry.getValue().toString(), context));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
translateObject(entry.getValue(), context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (javaObject instanceof Collection) {
|
||||||
|
Collection<Object> collection = (Collection<Object>) javaObject;
|
||||||
|
for (Object item : collection) {
|
||||||
|
translateObject(item, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (javaObject.getClass().isArray()) {
|
||||||
|
for (int i = 0; i < Array.getLength(javaObject); ++i) {
|
||||||
|
Object item = Array.get(javaObject, i);
|
||||||
|
Array.set(javaObject, i, translateObject(item, context));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectSerializer serializer = SerializeConfig.globalInstance.getObjectWriter(javaObject.getClass());
|
||||||
|
if (serializer instanceof JavaBeanSerializer) {
|
||||||
|
JavaBeanSerializer javaBeanSerializer = (JavaBeanSerializer) serializer;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Map<String, Object> values = javaBeanSerializer.getFieldValuesMap(javaObject);
|
||||||
|
for (Map.Entry<String, Object> entry : values.entrySet()) {
|
||||||
|
if (entry.getValue() != null) {
|
||||||
|
if (entry.getValue() instanceof String) {
|
||||||
|
if (StringUtils.contains(entry.getValue().toString(), JSON_SYMBOL)) {
|
||||||
|
BeanUtils.setFieldValueByName(javaObject, entry.getKey(), translateObject(entry.getValue(), context), String.class);
|
||||||
|
} else {
|
||||||
|
BeanUtils.setFieldValueByName(javaObject, entry.getKey(), translateRawString(entry.getKey(), entry.getValue().toString(), context), String.class);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
translateObject(entry.getValue(), context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
MSException.throwException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return javaObject;
|
||||||
|
} catch (StackOverflowError stackOverflowError) {
|
||||||
|
try {
|
||||||
|
return JSON.parseObject(translateRawString(null, JSON.toJSONString(javaObject), context).toString(), javaObject.getClass());
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtil.error("Failed to translate object " + javaObject.toString(), e);
|
||||||
|
return javaObject;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Object translateRawString(String key, String rawString, Map<String, String> context) {
|
||||||
|
if (StringUtils.isBlank(rawString)) {
|
||||||
|
return rawString;
|
||||||
|
}
|
||||||
|
for (String ignoreKey : IGNORE_KEYS) {
|
||||||
|
if (StringUtils.containsIgnoreCase(key, ignoreKey)) {
|
||||||
|
return rawString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (StringUtils.contains(rawString, PREFIX)) {
|
||||||
|
rawString = new StringSubstitutor(context, PREFIX, SUFFIX).replace(rawString);
|
||||||
|
if (StringUtils.contains(rawString, PREFIX)) {
|
||||||
|
String[] unTrans = StringUtils.substringsBetween(rawString, PREFIX, SUFFIX);
|
||||||
|
if (unTrans != null) {
|
||||||
|
for (String unTran : unTrans) {
|
||||||
|
rawString = StringUtils.replace(rawString, PREFIX + unTran + SUFFIX, unTran);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (key != null) {
|
||||||
|
String desc = context.get(rawString);
|
||||||
|
if (StringUtils.isNotBlank(desc)) {
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rawString;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String translateKey(String key, Map<String, String> context) {
|
||||||
|
if (MapUtils.isEmpty(context)) {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
String desc = context.get(StringUtils.replace(StringUtils.replace(key, PREFIX, StringUtils.EMPTY), SUFFIX, StringUtils.EMPTY));
|
||||||
|
if (StringUtils.isNotBlank(desc)) {
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package io.metersphere.service;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.ApplicationContextAware;
|
||||||
|
|
||||||
|
public class CommonBeanFactory implements ApplicationContextAware {
|
||||||
|
private static ApplicationContext context;
|
||||||
|
|
||||||
|
public CommonBeanFactory() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setApplicationContext(ApplicationContext ctx) throws BeansException {
|
||||||
|
context = ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Object getBean(String beanName) {
|
||||||
|
return context != null && !StringUtils.isBlank(beanName) ? context.getBean(beanName) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T getBean(Class<T> className) {
|
||||||
|
return context != null && className != null ? context.getBean(className) : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
package io.metersphere.service;
|
||||||
|
|
||||||
|
import io.metersphere.base.domain.SystemParameter;
|
||||||
|
import io.metersphere.base.domain.SystemParameterExample;
|
||||||
|
import io.metersphere.base.mapper.SystemParameterMapper;
|
||||||
|
import io.metersphere.commons.constants.ParamConstants;
|
||||||
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class SystemParameterService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SystemParameterMapper systemParameterMapper;
|
||||||
|
|
||||||
|
public String getSystemLanguage() {
|
||||||
|
String result = StringUtils.EMPTY;
|
||||||
|
SystemParameterExample example = new SystemParameterExample();
|
||||||
|
example.createCriteria().andParamKeyEqualTo(ParamConstants.I18n.LANGUAGE.getValue());
|
||||||
|
List<SystemParameter> list = systemParameterMapper.selectByExample(example);
|
||||||
|
if (CollectionUtils.isNotEmpty(list)) {
|
||||||
|
String value = list.get(0).getParamValue();
|
||||||
|
if (StringUtils.isNotBlank(value)) {
|
||||||
|
result = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -337,4 +337,14 @@ public class UserService {
|
||||||
public List<User> getBesideOrgMemberList(String orgId) {
|
public List<User> getBesideOrgMemberList(String orgId) {
|
||||||
return extUserRoleMapper.getBesideOrgMemberList(orgId);
|
return extUserRoleMapper.getBesideOrgMemberList(orgId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setLanguage(String lang) {
|
||||||
|
if (SessionUtils.getUser() != null) {
|
||||||
|
User user = new User();
|
||||||
|
user.setId(SessionUtils.getUser().getId());
|
||||||
|
user.setLanguage(lang);
|
||||||
|
updateUser(user);
|
||||||
|
SessionUtils.getUser().setLanguage(lang);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"i18n_test": "测试"
|
||||||
|
}
|
Loading…
Reference in New Issue