mirror of
https://github.com/dataease/dataease.git
synced 2026-05-14 21:12:33 +08:00
feat: 自定义外部国际化文件
This commit is contained in:
@@ -37,6 +37,10 @@ public class DeMvcConfig implements WebMvcConfigurer {
|
||||
String geoUrlPattern = ensureBoth(GEO_URL, AuthConstant.DE_API_PREFIX, URL_SEPARATOR) + "**";
|
||||
registry.addResourceHandler(geoUrlPattern).addResourceLocations(geoDir);
|
||||
|
||||
String i18nDir = FILE_PROTOCOL + ensureSuffix(I18N_DIR, FILE_SEPARATOR);
|
||||
String i18nUrlPattern = ensureBoth(I18N_URL, AuthConstant.DE_API_PREFIX, URL_SEPARATOR) + "**";
|
||||
registry.addResourceHandler(i18nUrlPattern).addResourceLocations(i18nDir);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -4,14 +4,17 @@ import io.dataease.api.system.SysParameterApi;
|
||||
import io.dataease.api.system.request.OnlineMapEditor;
|
||||
import io.dataease.api.system.vo.SettingItemVO;
|
||||
import io.dataease.api.system.vo.ShareBaseVO;
|
||||
import io.dataease.constant.StaticResourceConstants;
|
||||
import io.dataease.constant.XpackSettingConstants;
|
||||
import io.dataease.system.dao.auto.entity.CoreSysSetting;
|
||||
import io.dataease.system.manage.SysParameterManage;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -52,10 +55,9 @@ public class SysParameterServer implements SysParameterApi {
|
||||
|
||||
@Override
|
||||
public Integer RequestTimeOut() {
|
||||
Integer frontTimeOut = 60;
|
||||
int frontTimeOut = 60;
|
||||
List<SettingItemVO> settingItemVOS = queryBasicSetting();
|
||||
for (int i = 0; i < settingItemVOS.size(); i++) {
|
||||
SettingItemVO settingItemVO = settingItemVOS.get(i);
|
||||
for (SettingItemVO settingItemVO : settingItemVOS) {
|
||||
if (StringUtils.isNotBlank(settingItemVO.getPkey()) && settingItemVO.getPkey().equalsIgnoreCase(XpackSettingConstants.Front_Time_Out) && StringUtils.isNotBlank(settingItemVO.getPval())) {
|
||||
frontTimeOut = Integer.parseInt(settingItemVO.getPval());
|
||||
}
|
||||
@@ -69,8 +71,7 @@ public class SysParameterServer implements SysParameterApi {
|
||||
map.put(XpackSettingConstants.DEFAULT_SORT, "1");
|
||||
|
||||
List<SettingItemVO> settingItemVOS = queryBasicSetting();
|
||||
for (int i = 0; i < settingItemVOS.size(); i++) {
|
||||
SettingItemVO settingItemVO = settingItemVOS.get(i);
|
||||
for (SettingItemVO settingItemVO : settingItemVOS) {
|
||||
if (StringUtils.isNotBlank(settingItemVO.getPkey()) && settingItemVO.getPkey().equalsIgnoreCase(XpackSettingConstants.DEFAULT_SORT) && StringUtils.isNotBlank(settingItemVO.getPval())) {
|
||||
map.put(XpackSettingConstants.DEFAULT_SORT, settingItemVO.getPval());
|
||||
}
|
||||
@@ -95,4 +96,24 @@ public class SysParameterServer implements SysParameterApi {
|
||||
public ShareBaseVO shareBase() {
|
||||
return sysParameterManage.shareBase();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> i18nOptions() {
|
||||
File dir = new File(StaticResourceConstants.I18N_DIR);
|
||||
File[] files = null;
|
||||
if (!dir.exists() || ObjectUtils.isEmpty(files = dir.listFiles())) {
|
||||
return null;
|
||||
}
|
||||
Map<String, String> result = new HashMap<>();
|
||||
for (File file : files) {
|
||||
String name = file.getName();
|
||||
int start = name.indexOf("custom_") + 7;
|
||||
int end = name.indexOf("front");
|
||||
String i18nName = name.substring(start, end - 1).replace("_", "-");
|
||||
String languageName = name.substring(end + 6, name.lastIndexOf("."));
|
||||
result.put(i18nName, languageName);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -171,7 +171,10 @@ service.interceptors.response.use(
|
||||
} else if (response.config.url.match(/^\/map|geo\/\d{3}\/\d+\.json$/)) {
|
||||
// TODO 处理静态文件
|
||||
return response
|
||||
} else if (response.config.url.includes('DEXPack.umd.js')) {
|
||||
} else if (
|
||||
response.config.url.includes('DEXPack.umd.js') ||
|
||||
response.config.url.includes('/i18n/custom_')
|
||||
) {
|
||||
return response
|
||||
} else if (response.config.url.startsWith('/xpackComponent/pluginStaticInfo/extensions-')) {
|
||||
return response
|
||||
|
||||
@@ -279,7 +279,7 @@ if (uid.value === '1') {
|
||||
padding-bottom: 0 !important;
|
||||
}
|
||||
.language-popover {
|
||||
max-height: 112px;
|
||||
// max-height: 112px;
|
||||
.ed-popper__arrow {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
<script lang="ts" setup>
|
||||
import icon_done_outlined from '@/assets/svg/icon_done_outlined.svg'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { ref, onMounted, reactive } from 'vue'
|
||||
import { Icon } from '@/components/icon-custom'
|
||||
import { useUserStoreWithOut } from '@/store/modules/user'
|
||||
import { usePermissionStoreWithOut } from '@/store/modules/permission'
|
||||
import { useLocaleStoreWithOut } from '@/store/modules/locale'
|
||||
import { switchLangApi } from '@/api/user'
|
||||
const permissionStore = usePermissionStoreWithOut()
|
||||
const userStore = useUserStoreWithOut()
|
||||
const localeStore = useLocaleStoreWithOut()
|
||||
|
||||
const language = ref(null)
|
||||
const handleSetLanguage = lang => {
|
||||
const param = { lang }
|
||||
@@ -19,13 +22,16 @@ const handleSetLanguage = lang => {
|
||||
}
|
||||
})
|
||||
}
|
||||
const options = [
|
||||
{ value: 'zh-CN', name: '简体中文' },
|
||||
{ value: 'tw', name: '繁體中文' },
|
||||
{ value: 'en', name: 'English' }
|
||||
]
|
||||
onMounted(() => {
|
||||
|
||||
const options = reactive([])
|
||||
|
||||
onMounted(async () => {
|
||||
language.value = userStore.getLanguage
|
||||
const localeMap = await localeStore.getLocaleMap
|
||||
localeMap.forEach(item => {
|
||||
const option = { value: item['lang'], name: item['name'] }
|
||||
options.push(option)
|
||||
})
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
|
||||
@@ -3,21 +3,34 @@ import { createI18n } from 'vue-i18n'
|
||||
import { useLocaleStoreWithOut } from '@/store/modules/locale'
|
||||
import type { I18n, I18nOptions } from 'vue-i18n'
|
||||
import { setHtmlPageLang } from './helper'
|
||||
|
||||
export let i18n: ReturnType<typeof createI18n>
|
||||
|
||||
import { PATH_URL } from '@/config/axios/service'
|
||||
const createI18nOptions = async (): Promise<I18nOptions> => {
|
||||
const localeStore = useLocaleStoreWithOut()
|
||||
const locale = localeStore.getCurrentLocale
|
||||
const localeMap = localeStore.getLocaleMap
|
||||
const defaultLocal = await import(`../../locales/${locale.lang}.ts`)
|
||||
let locale = localeStore.getCurrentLocale
|
||||
const localeMap = await localeStore.getLocaleMap
|
||||
const cMap: any = localeMap.find(item => {
|
||||
return item.lang === locale.lang
|
||||
})
|
||||
let defaultLocal = null
|
||||
if (cMap) {
|
||||
if (cMap['custom']) {
|
||||
defaultLocal = await loadRemoteI18n(cMap)
|
||||
} else {
|
||||
defaultLocal = await import(`../../locales/${locale.lang}.ts`)
|
||||
}
|
||||
} else {
|
||||
const item = localeMap[0]
|
||||
localeStore.setLang(item.lang)
|
||||
locale = localeStore.getCurrentLocale
|
||||
defaultLocal = await import(`../../locales/${locale.lang}.ts`)
|
||||
}
|
||||
const message = defaultLocal.default ?? {}
|
||||
|
||||
setHtmlPageLang(locale.lang)
|
||||
|
||||
localeStore.setCurrentLocale({
|
||||
lang: locale.lang
|
||||
// elLocale: elLocal
|
||||
})
|
||||
|
||||
return {
|
||||
@@ -35,6 +48,13 @@ const createI18nOptions = async (): Promise<I18nOptions> => {
|
||||
}
|
||||
}
|
||||
|
||||
const loadRemoteI18n = async (option: any) => {
|
||||
const name = option.lang.replace('-', '_')
|
||||
// const basePath = import.meta.env.VITE_API_BASEPATH
|
||||
const url = `${PATH_URL}/i18n/custom_${name}_front_${option.name}.js`
|
||||
return await import(url)
|
||||
}
|
||||
|
||||
export const setupI18n = async (app: App<Element>) => {
|
||||
const options = await createI18nOptions()
|
||||
i18n = createI18n(options) as I18n
|
||||
|
||||
@@ -5,13 +5,14 @@ import zhCn from 'element-plus-secondary/es/locale/lang/zh-cn'
|
||||
import en from 'element-plus-secondary/es/locale/lang/en'
|
||||
import tw from 'element-plus-secondary/es/locale/lang/zh-tw'
|
||||
import { getLocale } from '@/utils/utils'
|
||||
|
||||
import request from '@/config/axios'
|
||||
const elLocaleMap = {
|
||||
'zh-CN': zhCn,
|
||||
en: en,
|
||||
tw: tw
|
||||
}
|
||||
interface LocaleState {
|
||||
customLoaded: boolean
|
||||
currentLocale: LocaleDropdownType
|
||||
localeMap: LocaleDropdownType[]
|
||||
}
|
||||
@@ -19,6 +20,7 @@ interface LocaleState {
|
||||
export const useLocaleStore = defineStore('locales', {
|
||||
state: (): LocaleState => {
|
||||
return {
|
||||
customLoaded: false,
|
||||
currentLocale: {
|
||||
lang: getLocale(),
|
||||
elLocale: elLocaleMap[getLocale()]
|
||||
@@ -44,8 +46,27 @@ export const useLocaleStore = defineStore('locales', {
|
||||
getCurrentLocale(): LocaleDropdownType {
|
||||
return this.currentLocale
|
||||
},
|
||||
getLocaleMap(): LocaleDropdownType[] {
|
||||
return this.localeMap
|
||||
async getLocaleMap(): Promise<LocaleDropdownType[]> {
|
||||
if (this.customLoaded) {
|
||||
return this.localeMap
|
||||
}
|
||||
try {
|
||||
const res = await request.get({ url: '/sysParameter/i18nOptions' })
|
||||
this.customLoaded = true
|
||||
const customMap = res.data
|
||||
for (const key in customMap) {
|
||||
const item = {
|
||||
lang: key,
|
||||
name: customMap[key],
|
||||
custom: true
|
||||
}
|
||||
this.localeMap.push(item)
|
||||
}
|
||||
return this.localeMap
|
||||
} catch (error) {
|
||||
this.customLoaded = true
|
||||
return this.localeMap
|
||||
}
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { store } from '../index'
|
||||
import { useCache } from '@/hooks/web/useCache'
|
||||
import { useLocaleStoreWithOut } from './locale'
|
||||
const { wsCache } = useCache()
|
||||
const locale = useLocaleStoreWithOut()
|
||||
|
||||
interface UserState {
|
||||
token: string
|
||||
uid: string
|
||||
@@ -91,6 +91,7 @@ export const userStore = defineStore('user', {
|
||||
this.oid = oid
|
||||
},
|
||||
setLanguage(language: string) {
|
||||
const locale = useLocaleStoreWithOut()
|
||||
if (!language || language === 'zh_CN') {
|
||||
language = 'zh-CN'
|
||||
}
|
||||
|
||||
@@ -62,4 +62,7 @@ public interface SysParameterApi {
|
||||
@Operation(summary = "查询分享设置")
|
||||
ShareBaseVO shareBase();
|
||||
|
||||
@GetMapping("/i18nOptions")
|
||||
@Operation(summary = "查询自定义国际化选项")
|
||||
Map<String, String> i18nOptions();
|
||||
}
|
||||
|
||||
@@ -20,9 +20,11 @@ public class StaticResourceConstants {
|
||||
public static String APPEARANCE_DIR = ensureSuffix(USER_HOME, FILE_SEPARATOR) + "appearance";
|
||||
public static String REPORT_DIR = ensureSuffix(USER_HOME, FILE_SEPARATOR) + "report";
|
||||
public static String PLUGIN_DIR = ensureSuffix(USER_HOME, FILE_SEPARATOR) + "plugin";
|
||||
public static String I18N_DIR = ensureSuffix(USER_HOME, FILE_SEPARATOR) + "i18n/front";
|
||||
|
||||
public static String MAP_URL = "/map";
|
||||
public static String GEO_URL = "/geo";
|
||||
public static String I18N_URL = "/i18n";
|
||||
|
||||
/**
|
||||
* Upload prefix.
|
||||
|
||||
@@ -46,6 +46,7 @@ public class WhitelistUtils {
|
||||
"/sysParameter/ui",
|
||||
"/sysParameter/defaultLogin",
|
||||
"/embedded/initIframe",
|
||||
"/sysParameter/i18nOptions",
|
||||
"/");
|
||||
|
||||
public static boolean match(String requestURI) {
|
||||
@@ -84,6 +85,7 @@ public class WhitelistUtils {
|
||||
|| StringUtils.startsWithAny(requestURI, "/typeface/defaultFont")
|
||||
|| StringUtils.startsWithAny(requestURI, "/typeface/listFont")
|
||||
|| StringUtils.startsWithAny(requestURI, "/exportCenter/download")
|
||||
|| StringUtils.startsWithAny(requestURI, "/i18n/")
|
||||
|| StringUtils.startsWithAny(requestURI, "/communicate/image/")
|
||||
|| StringUtils.startsWithAny(requestURI, "/communicate/down/");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user