feat: 支持用户设置默认语言

Signed-off-by: fit2-zhao <yong.zhao@fit2cloud.com>
This commit is contained in:
fit2-zhao 2024-08-09 17:44:05 +08:00 committed by Craftsman
parent 6d80ded7ff
commit 7cbe5f5f30
11 changed files with 274 additions and 165 deletions

View File

@ -1,8 +1,11 @@
import Vue from 'vue'; import Vue from 'vue';
import VueI18n from 'vue-i18n'; import VueI18n from 'vue-i18n';
import axios from 'axios';
Vue.use(VueI18n); Vue.use(VueI18n);
// 直接加载翻译的语言文件 // 直接加载翻译的语言文件
const LOADED_LANGUAGES = ['zh-CN', 'zh-TW', 'en-US']; const LOADED_LANGUAGES = ['zh-CN', 'zh-TW', 'en-US'];
const LANG_FILES = require.context('./lang', true, /\.js$/); const LANG_FILES = require.context('./lang', true, /\.js$/);
// 自动加载lang目录下语言文件默认只加载LOADED_LANGUAGES中规定的语言文件其他的语言动态加载 // 自动加载lang目录下语言文件默认只加载LOADED_LANGUAGES中规定的语言文件其他的语言动态加载
const messages = LANG_FILES.keys().reduce((messages, path) => { const messages = LANG_FILES.keys().reduce((messages, path) => {
@ -17,9 +20,17 @@ const messages = LANG_FILES.keys().reduce((messages, path) => {
export const getLanguage = () => { export const getLanguage = () => {
let language = localStorage.getItem('language'); let language = localStorage.getItem('language');
if (!language) { if (!language) {
// 远程接口获取用户语言
language = navigator.language || navigator.browserLanguage; language = navigator.language || navigator.browserLanguage;
axios.get('/system/default-locale').then((response) => {
if (response.data && response.data.data) {
language = response.data.data.replace('_', '-');
}
return language;
});
} else {
return language;
} }
return language;
}; };
const i18n = new VueI18n({ const i18n = new VueI18n({

View File

@ -1,51 +1,60 @@
import Vue from 'vue'; import Vue from 'vue';
import VueI18n from "vue-i18n"; import VueI18n from 'vue-i18n';
import axios from 'axios';
Vue.use(VueI18n); Vue.use(VueI18n);
// 直接加载翻译的语言文件 // 直接加载翻译的语言文件
const LOADED_LANGUAGES = ['zh-CN', 'zh-TW', 'en-US']; const LOADED_LANGUAGES = ['zh-CN', 'zh-TW', 'en-US'];
const LANG_FILES = require.context('./lang', true, /\.js$/) const LANG_FILES = require.context('./lang', true, /\.js$/);
// 自动加载lang目录下语言文件默认只加载LOADED_LANGUAGES中规定的语言文件其他的语言动态加载 // 自动加载lang目录下语言文件默认只加载LOADED_LANGUAGES中规定的语言文件其他的语言动态加载
const messages = LANG_FILES.keys().reduce((messages, path) => { const messages = LANG_FILES.keys().reduce((messages, path) => {
const value = LANG_FILES(path) const value = LANG_FILES(path);
const lang = path.replace(/^\.\/(.*)\.\w+$/, '$1'); const lang = path.replace(/^\.\/(.*)\.\w+$/, '$1');
if (LOADED_LANGUAGES.includes(lang)) { if (LOADED_LANGUAGES.includes(lang)) {
messages[lang] = value.default messages[lang] = value.default;
} }
return messages; return messages;
}, {}) }, {});
export const getLanguage = () => { export const getLanguage = () => {
let language = localStorage.getItem('language') let language = localStorage.getItem('language');
if (!language) { if (!language) {
language = navigator.language || navigator.browserLanguage // 远程接口获取用户语言
language = navigator.language || navigator.browserLanguage;
axios.get('/system/default-locale').then((response) => {
if (response.data && response.data.data) {
language = response.data.data.replace('_', '-');
}
return language;
});
} else {
return language;
} }
return language; };
}
const i18n = new VueI18n({ const i18n = new VueI18n({
locale: getLanguage(), locale: getLanguage(),
messages, messages,
}); });
const importLanguage = lang => { const importLanguage = (lang) => {
if (!LOADED_LANGUAGES.includes(lang)) { if (!LOADED_LANGUAGES.includes(lang)) {
return import(`./lang/${lang}`).then(response => { return import(`./lang/${lang}`).then((response) => {
i18n.mergeLocaleMessage(lang, response.default); i18n.mergeLocaleMessage(lang, response.default);
LOADED_LANGUAGES.push(lang); LOADED_LANGUAGES.push(lang);
return Promise.resolve(lang) return Promise.resolve(lang);
}) });
} }
return Promise.resolve(lang) return Promise.resolve(lang);
} };
const setLang = lang => { const setLang = (lang) => {
localStorage.setItem('language', lang) localStorage.setItem('language', lang);
i18n.locale = lang; i18n.locale = lang;
} };
export const setLanguage = lang => { export const setLanguage = (lang) => {
if (!lang) { if (!lang) {
return; return;
} }
@ -55,24 +64,24 @@ export const setLanguage = lang => {
} else { } else {
setLang(lang); setLang(lang);
} }
} };
// 组合翻译例如key为'请输入{0}'keys为login.username则自动将keys翻译并替换到{0} {1}... // 组合翻译例如key为'请输入{0}'keys为login.username则自动将keys翻译并替换到{0} {1}...
Vue.prototype.$tm = function (key, ...keys) { Vue.prototype.$tm = function (key, ...keys) {
let values = []; let values = [];
for (const k of keys) { for (const k of keys) {
values.push(i18n.t(k)) values.push(i18n.t(k));
} }
return i18n.t(key, values); return i18n.t(key, values);
}; };
// 忽略警告不存在Key直接返回Key // 忽略警告不存在Key直接返回Key
Vue.prototype.$tk = function (key) { Vue.prototype.$tk = function (key) {
const hasKey = i18n.te(key) const hasKey = i18n.te(key);
if (hasKey) { if (hasKey) {
return i18n.t(key) return i18n.t(key);
} }
return key return key;
}; };
// 设置当前语言LOADED_LANGUAGES以外的翻译文件会自动从lang目录获取(如果有的话), 如果不需要动态加载语言文件直接用setLang // 设置当前语言LOADED_LANGUAGES以外的翻译文件会自动从lang目录获取(如果有的话), 如果不需要动态加载语言文件直接用setLang

View File

@ -82,6 +82,8 @@ public class FilterChainUtils {
filterChainDefinitionMap.put("/performance/update/cache", "anon"); filterChainDefinitionMap.put("/performance/update/cache", "anon");
// websocket // websocket
filterChainDefinitionMap.put("/websocket/**", "csrf"); filterChainDefinitionMap.put("/websocket/**", "csrf");
// 默认语言
filterChainDefinitionMap.put("/system/default-locale", "anon");
return filterChainDefinitionMap; return filterChainDefinitionMap;
} }

View File

@ -0,0 +1,28 @@
package io.metersphere.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
import java.nio.charset.StandardCharsets;
import java.util.Locale;
@Configuration
public class BundleConfig {
@Value("${spring.messages.default-locale}")
private String defaultLocale;
@Value("${spring.messages.basename}")
private String[] basements;
@Bean
public ResourceBundleMessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
Locale defaultLocale = Locale.forLanguageTag(this.defaultLocale);
// 设置消息资源文件的基名
messageSource.setBasenames(basements);
messageSource.setDefaultEncoding(StandardCharsets.UTF_8.name()); // 设置编码
messageSource.setDefaultLocale(defaultLocale); // 设置默认语言
return messageSource;
}
}

View File

@ -16,6 +16,7 @@ import io.metersphere.service.BaseUserService;
import io.metersphere.service.SystemParameterService; import io.metersphere.service.SystemParameterService;
import org.apache.shiro.authz.annotation.Logical; import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions; import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -34,6 +35,9 @@ public class SystemParameterController {
@Resource @Resource
private BaseUserService baseUserService; private BaseUserService baseUserService;
@Value("${spring.messages.default-locale}")
private String defaultLocale;
@PostMapping("/edit/email") @PostMapping("/edit/email")
@RequiresPermissions(PermissionConstants.SYSTEM_SETTING_READ_EDIT) @RequiresPermissions(PermissionConstants.SYSTEM_SETTING_READ_EDIT)
@ -139,5 +143,10 @@ public class SystemParameterController {
return systemParameter; return systemParameter;
} }
@GetMapping(value = "/default-locale")
public String defaultLocale() {
return defaultLocale;
}
} }

View File

@ -108,3 +108,4 @@ eureka.client.registry-fetch-interval-seconds=10
# redisson # redisson
spring.redis.redisson.file=file:/opt/metersphere/conf/redisson.yml spring.redis.redisson.file=file:/opt/metersphere/conf/redisson.yml
spring.session.redis.repository-type=indexed spring.session.redis.repository-type=indexed
spring.messages.default-locale=zh_CN

View File

@ -1,75 +1,84 @@
import Vue from 'vue'; import Vue from "vue";
import VueI18n from "vue-i18n"; import VueI18n from "vue-i18n";
import axios from "axios";
Vue.use(VueI18n); Vue.use(VueI18n);
// 直接加载翻译的语言文件 // 直接加载翻译的语言文件
const LOADED_LANGUAGES = ['zh-CN', 'zh-TW', 'en-US']; const LOADED_LANGUAGES = ["zh-CN", "zh-TW", "en-US"];
const LANG_FILES = require.context('./lang', true, /\.js$/) const LANG_FILES = require.context("./lang", true, /\.js$/);
// 自动加载lang目录下语言文件默认只加载LOADED_LANGUAGES中规定的语言文件其他的语言动态加载 // 自动加载lang目录下语言文件默认只加载LOADED_LANGUAGES中规定的语言文件其他的语言动态加载
const messages = LANG_FILES.keys().reduce((messages, path) => { const messages = LANG_FILES.keys().reduce((messages, path) => {
const value = LANG_FILES(path) const value = LANG_FILES(path);
const lang = path.replace(/^\.\/(.*)\.\w+$/, '$1'); const lang = path.replace(/^\.\/(.*)\.\w+$/, "$1");
if (LOADED_LANGUAGES.includes(lang)) { if (LOADED_LANGUAGES.includes(lang)) {
messages[lang] = value.default messages[lang] = value.default;
} }
return messages; return messages;
}, {}) }, {});
export const getLanguage = () => { export const getLanguage = () => {
let language = localStorage.getItem('language') let language = localStorage.getItem("language");
if (!language) { if (!language) {
language = navigator.language || navigator.browserLanguage // 远程接口获取用户语言
language = navigator.language || navigator.browserLanguage;
axios.get("/system/default-locale").then((response) => {
if (response.data && response.data.data) {
language = response.data.data.replace("_", "-");
}
return language;
});
} else {
return language;
} }
return language; };
}
const i18n = new VueI18n({ const i18n = new VueI18n({
locale: getLanguage(), locale: getLanguage(),
messages, messages,
}); });
const importLanguage = lang => { const importLanguage = (lang) => {
if (!LOADED_LANGUAGES.includes(lang)) { if (!LOADED_LANGUAGES.includes(lang)) {
return import(`./lang/${lang}`).then(response => { return import(`./lang/${lang}`).then((response) => {
i18n.mergeLocaleMessage(lang, response.default); i18n.mergeLocaleMessage(lang, response.default);
LOADED_LANGUAGES.push(lang); LOADED_LANGUAGES.push(lang);
return Promise.resolve(lang) return Promise.resolve(lang);
}) });
} }
return Promise.resolve(lang) return Promise.resolve(lang);
} };
const setLang = lang => { const setLang = (lang) => {
localStorage.setItem('language', lang) localStorage.setItem("language", lang);
i18n.locale = lang; i18n.locale = lang;
} };
export const setLanguage = lang => { export const setLanguage = (lang) => {
if (lang) { if (lang) {
lang = lang.replace('_', '-'); lang = lang.replace("_", "-");
} }
if (i18n.locale !== lang) { if (i18n.locale !== lang) {
importLanguage(lang).then(setLang); importLanguage(lang).then(setLang);
} }
} };
// 组合翻译例如key为'请输入{0}'keys为login.username则自动将keys翻译并替换到{0} {1}... // 组合翻译例如key为'请输入{0}'keys为login.username则自动将keys翻译并替换到{0} {1}...
Vue.prototype.$tm = function (key, ...keys) { Vue.prototype.$tm = function (key, ...keys) {
let values = []; let values = [];
for (const k of keys) { for (const k of keys) {
values.push(i18n.t(k)) values.push(i18n.t(k));
} }
return i18n.t(key, values); return i18n.t(key, values);
}; };
// 忽略警告不存在Key直接返回Key // 忽略警告不存在Key直接返回Key
Vue.prototype.$tk = function (key) { Vue.prototype.$tk = function (key) {
const hasKey = i18n.te(key) const hasKey = i18n.te(key);
if (hasKey) { if (hasKey) {
return i18n.t(key) return i18n.t(key);
} }
return key return key;
}; };
// 设置当前语言LOADED_LANGUAGES以外的翻译文件会自动从lang目录获取(如果有的话), 如果不需要动态加载语言文件直接用setLang // 设置当前语言LOADED_LANGUAGES以外的翻译文件会自动从lang目录获取(如果有的话), 如果不需要动态加载语言文件直接用setLang

View File

@ -1,76 +1,85 @@
import Vue from 'vue'; import Vue from "vue";
import VueI18n from "vue-i18n"; import VueI18n from "vue-i18n";
import axios from "axios";
Vue.use(VueI18n); Vue.use(VueI18n);
// 直接加载翻译的语言文件 // 直接加载翻译的语言文件
const LOADED_LANGUAGES = ['zh-CN', 'zh-TW', 'en-US']; const LOADED_LANGUAGES = ["zh-CN", "zh-TW", "en-US"];
const LANG_FILES = require.context('./lang', true, /\.js$/) const LANG_FILES = require.context("./lang", true, /\.js$/);
// 自动加载lang目录下语言文件默认只加载LOADED_LANGUAGES中规定的语言文件其他的语言动态加载 // 自动加载lang目录下语言文件默认只加载LOADED_LANGUAGES中规定的语言文件其他的语言动态加载
const messages = LANG_FILES.keys().reduce((messages, path) => { const messages = LANG_FILES.keys().reduce((messages, path) => {
const value = LANG_FILES(path) const value = LANG_FILES(path);
const lang = path.replace(/^\.\/(.*)\.\w+$/, '$1'); const lang = path.replace(/^\.\/(.*)\.\w+$/, "$1");
if (LOADED_LANGUAGES.includes(lang)) { if (LOADED_LANGUAGES.includes(lang)) {
messages[lang] = value.default messages[lang] = value.default;
} }
return messages; return messages;
}, {}) }, {});
export const getLanguage = () => { export const getLanguage = () => {
let language = localStorage.getItem('language') let language = localStorage.getItem("language");
if (!language) { if (!language) {
language = navigator.language || navigator.browserLanguage // 远程接口获取用户语言
language = navigator.language || navigator.browserLanguage;
axios.get("/system/default-locale").then((response) => {
if (response.data && response.data.data) {
language = response.data.data.replace("_", "-");
}
return language;
});
} else {
return language;
} }
return language; };
}
const i18n = new VueI18n({ const i18n = new VueI18n({
locale: getLanguage(), locale: getLanguage(),
messages, messages,
silentTranslationWarn: true // todo 暂时隐藏控制台警告 silentTranslationWarn: true, // todo 暂时隐藏控制台警告
}); });
const importLanguage = lang => { const importLanguage = (lang) => {
if (!LOADED_LANGUAGES.includes(lang)) { if (!LOADED_LANGUAGES.includes(lang)) {
return import(`./lang/${lang}`).then(response => { return import(`./lang/${lang}`).then((response) => {
i18n.mergeLocaleMessage(lang, response.default); i18n.mergeLocaleMessage(lang, response.default);
LOADED_LANGUAGES.push(lang); LOADED_LANGUAGES.push(lang);
return Promise.resolve(lang) return Promise.resolve(lang);
}) });
} }
return Promise.resolve(lang) return Promise.resolve(lang);
} };
const setLang = lang => { const setLang = (lang) => {
localStorage.setItem('language', lang) localStorage.setItem("language", lang);
i18n.locale = lang; i18n.locale = lang;
} };
export const setLanguage = lang => { export const setLanguage = (lang) => {
if (lang) { if (lang) {
lang = lang.replace('_', '-'); lang = lang.replace("_", "-");
} }
if (i18n.locale !== lang) { if (i18n.locale !== lang) {
importLanguage(lang).then(setLang); importLanguage(lang).then(setLang);
} }
} };
// 组合翻译例如key为'请输入{0}'keys为login.username则自动将keys翻译并替换到{0} {1}... // 组合翻译例如key为'请输入{0}'keys为login.username则自动将keys翻译并替换到{0} {1}...
Vue.prototype.$tm = function (key, ...keys) { Vue.prototype.$tm = function (key, ...keys) {
let values = []; let values = [];
for (const k of keys) { for (const k of keys) {
values.push(i18n.t(k)) values.push(i18n.t(k));
} }
return i18n.t(key, values); return i18n.t(key, values);
}; };
// 忽略警告不存在Key直接返回Key // 忽略警告不存在Key直接返回Key
Vue.prototype.$tk = function (key) { Vue.prototype.$tk = function (key) {
const hasKey = i18n.te(key) const hasKey = i18n.te(key);
if (hasKey) { if (hasKey) {
return i18n.t(key) return i18n.t(key);
} }
return key return key;
}; };
// 设置当前语言LOADED_LANGUAGES以外的翻译文件会自动从lang目录获取(如果有的话), 如果不需要动态加载语言文件直接用setLang // 设置当前语言LOADED_LANGUAGES以外的翻译文件会自动从lang目录获取(如果有的话), 如果不需要动态加载语言文件直接用setLang

View File

@ -1,76 +1,85 @@
import Vue from 'vue'; import Vue from "vue";
import VueI18n from "vue-i18n"; import VueI18n from "vue-i18n";
import axios from "axios";
Vue.use(VueI18n); Vue.use(VueI18n);
// 直接加载翻译的语言文件 // 直接加载翻译的语言文件
const LOADED_LANGUAGES = ['zh-CN', 'zh-TW', 'en-US']; const LOADED_LANGUAGES = ["zh-CN", "zh-TW", "en-US"];
const LANG_FILES = require.context('./lang', true, /\.js$/) const LANG_FILES = require.context("./lang", true, /\.js$/);
// 自动加载lang目录下语言文件默认只加载LOADED_LANGUAGES中规定的语言文件其他的语言动态加载 // 自动加载lang目录下语言文件默认只加载LOADED_LANGUAGES中规定的语言文件其他的语言动态加载
const messages = LANG_FILES.keys().reduce((messages, path) => { const messages = LANG_FILES.keys().reduce((messages, path) => {
const value = LANG_FILES(path) const value = LANG_FILES(path);
const lang = path.replace(/^\.\/(.*)\.\w+$/, '$1'); const lang = path.replace(/^\.\/(.*)\.\w+$/, "$1");
if (LOADED_LANGUAGES.includes(lang)) { if (LOADED_LANGUAGES.includes(lang)) {
messages[lang] = value.default messages[lang] = value.default;
} }
return messages; return messages;
}, {}) }, {});
export const getLanguage = () => { export const getLanguage = () => {
let language = localStorage.getItem('language') let language = localStorage.getItem("language");
if (!language) { if (!language) {
language = navigator.language || navigator.browserLanguage // 远程接口获取用户语言
language = navigator.language || navigator.browserLanguage;
axios.get("/system/default-locale").then((response) => {
if (response.data && response.data.data) {
language = response.data.data.replace("_", "-");
}
return language;
});
} else {
return language;
} }
return language; };
}
const i18n = new VueI18n({ const i18n = new VueI18n({
locale: getLanguage(), locale: getLanguage(),
messages, messages,
silentTranslationWarn: true // todo 暂时隐藏控制台警告 silentTranslationWarn: true, // todo 暂时隐藏控制台警告
}); });
const importLanguage = lang => { const importLanguage = (lang) => {
if (!LOADED_LANGUAGES.includes(lang)) { if (!LOADED_LANGUAGES.includes(lang)) {
return import(`./lang/${lang}`).then(response => { return import(`./lang/${lang}`).then((response) => {
i18n.mergeLocaleMessage(lang, response.default); i18n.mergeLocaleMessage(lang, response.default);
LOADED_LANGUAGES.push(lang); LOADED_LANGUAGES.push(lang);
return Promise.resolve(lang) return Promise.resolve(lang);
}) });
} }
return Promise.resolve(lang) return Promise.resolve(lang);
} };
const setLang = lang => { const setLang = (lang) => {
localStorage.setItem('language', lang) localStorage.setItem("language", lang);
i18n.locale = lang; i18n.locale = lang;
} };
export const setLanguage = lang => { export const setLanguage = (lang) => {
if (lang) { if (lang) {
lang = lang.replace('_', '-'); lang = lang.replace("_", "-");
} }
if (i18n.locale !== lang) { if (i18n.locale !== lang) {
importLanguage(lang).then(setLang); importLanguage(lang).then(setLang);
} }
} };
// 组合翻译例如key为'请输入{0}'keys为login.username则自动将keys翻译并替换到{0} {1}... // 组合翻译例如key为'请输入{0}'keys为login.username则自动将keys翻译并替换到{0} {1}...
Vue.prototype.$tm = function (key, ...keys) { Vue.prototype.$tm = function (key, ...keys) {
let values = []; let values = [];
for (const k of keys) { for (const k of keys) {
values.push(i18n.t(k)) values.push(i18n.t(k));
} }
return i18n.t(key, values); return i18n.t(key, values);
}; };
// 忽略警告不存在Key直接返回Key // 忽略警告不存在Key直接返回Key
Vue.prototype.$tk = function (key) { Vue.prototype.$tk = function (key) {
const hasKey = i18n.te(key) const hasKey = i18n.te(key);
if (hasKey) { if (hasKey) {
return i18n.t(key) return i18n.t(key);
} }
return key return key;
}; };
// 设置当前语言LOADED_LANGUAGES以外的翻译文件会自动从lang目录获取(如果有的话), 如果不需要动态加载语言文件直接用setLang // 设置当前语言LOADED_LANGUAGES以外的翻译文件会自动从lang目录获取(如果有的话), 如果不需要动态加载语言文件直接用setLang

View File

@ -1,87 +1,100 @@
import Vue from 'vue'; import Vue from "vue";
import VueI18n from "vue-i18n"; import VueI18n from "vue-i18n";
import axios from "axios";
Vue.use(VueI18n); Vue.use(VueI18n);
// 直接加载翻译的语言文件 // 直接加载翻译的语言文件
const LOADED_LANGUAGES = ['zh-CN', 'zh-TW', 'en-US']; const LOADED_LANGUAGES = ["zh-CN", "zh-TW", "en-US"];
const LANG_FILES = require.context('./lang', true, /\.js$/) const LANG_FILES = require.context("./lang", true, /\.js$/);
// 自动加载lang目录下语言文件默认只加载LOADED_LANGUAGES中规定的语言文件其他的语言动态加载 // 自动加载lang目录下语言文件默认只加载LOADED_LANGUAGES中规定的语言文件其他的语言动态加载
const messages = LANG_FILES.keys().reduce((messages, path) => { const messages = LANG_FILES.keys().reduce((messages, path) => {
const lang = path.replace(/^\.\/(.*)\.\w+$/, '$1'); const lang = path.replace(/^\.\/(.*)\.\w+$/, "$1");
if (LOADED_LANGUAGES.includes(lang)) { if (LOADED_LANGUAGES.includes(lang)) {
const value = LANG_FILES(path) const value = LANG_FILES(path);
messages[lang] = value.default messages[lang] = value.default;
} }
return messages; return messages;
}, {}); }, {});
// 添加脑图国际化文件 // 添加脑图国际化文件
const MINDER_LANG_FILES = require.context('vue-minder-editor-plus/src/locale/lang', true, /\.js$/); const MINDER_LANG_FILES = require.context(
MINDER_LANG_FILES.keys().forEach(path => { "vue-minder-editor-plus/src/locale/lang",
const lang = path.replace(/^\.\/(.*)\.\w+$/, '$1'); true,
/\.js$/
);
MINDER_LANG_FILES.keys().forEach((path) => {
const lang = path.replace(/^\.\/(.*)\.\w+$/, "$1");
if (LOADED_LANGUAGES.includes(lang)) { if (LOADED_LANGUAGES.includes(lang)) {
const value = MINDER_LANG_FILES(path); const value = MINDER_LANG_FILES(path);
Object.keys(value.default).forEach(key => { Object.keys(value.default).forEach((key) => {
messages[lang][key] = value.default[key]; messages[lang][key] = value.default[key];
}); });
} }
}); });
export const getLanguage = () => { export const getLanguage = () => {
let language = localStorage.getItem('language') let language = localStorage.getItem("language");
if (!language) { if (!language) {
language = navigator.language || navigator.browserLanguage // 远程接口获取用户语言
language = navigator.language || navigator.browserLanguage;
axios.get("/system/default-locale").then((response) => {
if (response.data && response.data.data) {
language = response.data.data.replace("_", "-");
}
return language;
});
} else {
return language;
} }
return language; };
}
const i18n = new VueI18n({ const i18n = new VueI18n({
locale: getLanguage(), locale: getLanguage(),
messages, messages,
}); });
const importLanguage = lang => { const importLanguage = (lang) => {
if (!LOADED_LANGUAGES.includes(lang)) { if (!LOADED_LANGUAGES.includes(lang)) {
return import(`./lang/${lang}`).then(response => { return import(`./lang/${lang}`).then((response) => {
i18n.mergeLocaleMessage(lang, response.default); i18n.mergeLocaleMessage(lang, response.default);
LOADED_LANGUAGES.push(lang); LOADED_LANGUAGES.push(lang);
return Promise.resolve(lang) return Promise.resolve(lang);
}) });
} }
return Promise.resolve(lang) return Promise.resolve(lang);
} };
const setLang = lang => { const setLang = (lang) => {
localStorage.setItem('language', lang) localStorage.setItem("language", lang);
i18n.locale = lang; i18n.locale = lang;
} };
export const setLanguage = lang => { export const setLanguage = (lang) => {
if (lang) { if (lang) {
lang = lang.replace('_', '-'); lang = lang.replace("_", "-");
} }
if (i18n.locale !== lang) { if (i18n.locale !== lang) {
importLanguage(lang).then(setLang); importLanguage(lang).then(setLang);
} }
} };
// 组合翻译例如key为'请输入{0}'keys为login.username则自动将keys翻译并替换到{0} {1}... // 组合翻译例如key为'请输入{0}'keys为login.username则自动将keys翻译并替换到{0} {1}...
Vue.prototype.$tm = function (key, ...keys) { Vue.prototype.$tm = function (key, ...keys) {
let values = []; let values = [];
for (const k of keys) { for (const k of keys) {
values.push(i18n.t(k)) values.push(i18n.t(k));
} }
return i18n.t(key, values); return i18n.t(key, values);
}; };
// 忽略警告不存在Key直接返回Key // 忽略警告不存在Key直接返回Key
Vue.prototype.$tk = function (key) { Vue.prototype.$tk = function (key) {
const hasKey = i18n.te(key) const hasKey = i18n.te(key);
if (hasKey) { if (hasKey) {
return i18n.t(key) return i18n.t(key);
} }
return key return key;
}; };
// 设置当前语言LOADED_LANGUAGES以外的翻译文件会自动从lang目录获取(如果有的话), 如果不需要动态加载语言文件直接用setLang // 设置当前语言LOADED_LANGUAGES以外的翻译文件会自动从lang目录获取(如果有的话), 如果不需要动态加载语言文件直接用setLang

View File

@ -1,75 +1,84 @@
import Vue from 'vue'; import Vue from "vue";
import VueI18n from "vue-i18n"; import VueI18n from "vue-i18n";
import axios from "axios";
Vue.use(VueI18n); Vue.use(VueI18n);
// 直接加载翻译的语言文件 // 直接加载翻译的语言文件
const LOADED_LANGUAGES = ['zh-CN', 'zh-TW', 'en-US']; const LOADED_LANGUAGES = ["zh-CN", "zh-TW", "en-US"];
const LANG_FILES = require.context('./lang', true, /\.js$/) const LANG_FILES = require.context("./lang", true, /\.js$/);
// 自动加载lang目录下语言文件默认只加载LOADED_LANGUAGES中规定的语言文件其他的语言动态加载 // 自动加载lang目录下语言文件默认只加载LOADED_LANGUAGES中规定的语言文件其他的语言动态加载
const messages = LANG_FILES.keys().reduce((messages, path) => { const messages = LANG_FILES.keys().reduce((messages, path) => {
const value = LANG_FILES(path) const value = LANG_FILES(path);
const lang = path.replace(/^\.\/(.*)\.\w+$/, '$1'); const lang = path.replace(/^\.\/(.*)\.\w+$/, "$1");
if (LOADED_LANGUAGES.includes(lang)) { if (LOADED_LANGUAGES.includes(lang)) {
messages[lang] = value.default messages[lang] = value.default;
} }
return messages; return messages;
}, {}) }, {});
export const getLanguage = () => { export const getLanguage = () => {
let language = localStorage.getItem('language') let language = localStorage.getItem("language");
if (!language) { if (!language) {
language = navigator.language || navigator.browserLanguage // 远程接口获取用户语言
language = navigator.language || navigator.browserLanguage;
axios.get("/system/default-locale").then((response) => {
if (response.data && response.data.data) {
language = response.data.data.replace("_", "-");
}
return language;
});
} else {
return language;
} }
return language; };
}
const i18n = new VueI18n({ const i18n = new VueI18n({
locale: getLanguage(), locale: getLanguage(),
messages, messages,
}); });
const importLanguage = lang => { const importLanguage = (lang) => {
if (!LOADED_LANGUAGES.includes(lang)) { if (!LOADED_LANGUAGES.includes(lang)) {
return import(`./lang/${lang}`).then(response => { return import(`./lang/${lang}`).then((response) => {
i18n.mergeLocaleMessage(lang, response.default); i18n.mergeLocaleMessage(lang, response.default);
LOADED_LANGUAGES.push(lang); LOADED_LANGUAGES.push(lang);
return Promise.resolve(lang) return Promise.resolve(lang);
}) });
} }
return Promise.resolve(lang) return Promise.resolve(lang);
} };
const setLang = lang => { const setLang = (lang) => {
localStorage.setItem('language', lang) localStorage.setItem("language", lang);
i18n.locale = lang; i18n.locale = lang;
} };
export const setLanguage = lang => { export const setLanguage = (lang) => {
if (lang) { if (lang) {
lang = lang.replace('_', '-'); lang = lang.replace("_", "-");
} }
if (i18n.locale !== lang) { if (i18n.locale !== lang) {
importLanguage(lang).then(setLang); importLanguage(lang).then(setLang);
} }
} };
// 组合翻译例如key为'请输入{0}'keys为login.username则自动将keys翻译并替换到{0} {1}... // 组合翻译例如key为'请输入{0}'keys为login.username则自动将keys翻译并替换到{0} {1}...
Vue.prototype.$tm = function (key, ...keys) { Vue.prototype.$tm = function (key, ...keys) {
let values = []; let values = [];
for (const k of keys) { for (const k of keys) {
values.push(i18n.t(k)) values.push(i18n.t(k));
} }
return i18n.t(key, values); return i18n.t(key, values);
}; };
// 忽略警告不存在Key直接返回Key // 忽略警告不存在Key直接返回Key
Vue.prototype.$tk = function (key) { Vue.prototype.$tk = function (key) {
const hasKey = i18n.te(key) const hasKey = i18n.te(key);
if (hasKey) { if (hasKey) {
return i18n.t(key) return i18n.t(key);
} }
return key return key;
}; };
// 设置当前语言LOADED_LANGUAGES以外的翻译文件会自动从lang目录获取(如果有的话), 如果不需要动态加载语言文件直接用setLang // 设置当前语言LOADED_LANGUAGES以外的翻译文件会自动从lang目录获取(如果有的话), 如果不需要动态加载语言文件直接用setLang