feat: i18n

This commit is contained in:
wangdan-fit2cloud 2025-01-20 18:00:53 +08:00
parent 7ea082427b
commit c4de677c86
17 changed files with 136 additions and 92 deletions

View File

@ -25,6 +25,7 @@ interface User {
is_edit_password?: boolean
IS_XPACK?: boolean
XPACK_LICENSE_IS_VALID?: boolean
language: string
}
interface LoginRequest {

View File

@ -184,10 +184,10 @@ import { useRoute, useRouter } from 'vue-router'
import { getImgUrl } from '@/utils/utils'
import bus from '@/bus'
import 'recorder-core/src/engine/mp3'
import 'recorder-core/src/engine/mp3-engine'
import { MsgWarning } from '@/utils/message'
import useStore from '@/stores'
import { t } from '@/locales'
const router = useRouter()
const route = useRoute()
const { application } = useStore()

View File

@ -16,7 +16,7 @@ import bus from '@/bus'
import { ref, nextTick, onMounted } from 'vue'
import { t } from '@/locales'
const isOpen = ref<boolean>(false)
const eventVal = ref({})
const eventVal = ref()
function getSelection() {
const selection = window.getSelection()
if (selection && selection.anchorNode == null) {

View File

@ -45,6 +45,7 @@
<script setup lang="ts">
import { ref, nextTick, watch, computed, onMounted } from 'vue'
import { MsgError } from '@/utils/message'
import { t } from '@/locales'
defineOptions({ name: 'AppTable' })
import useStore from '@/stores'
@ -102,7 +103,7 @@ function submitHandle() {
loading.value = false
}, 200)
} else {
MsgError(`${props.quickCreateName}不能为空!`)
MsgError(`${props.quickCreateName}${t('components.dynamicsForm.tip.requiredMessage')}`)
}
}

View File

@ -2,7 +2,7 @@
<el-form-item>
<template #label>
<div class="flex-between">
选项值
{{ $t('components.dynamicsForm.Select.label') }}
<el-button link type="primary" @click.stop="addOption()">
<el-icon class="mr-4">
<Plus />
@ -12,13 +12,13 @@
</div>
</template>
<el-row style="width: 100%" :gutter="10">
<el-col :span="10"
><div class="grid-content ep-bg-purple" />
标签</el-col
>
<el-col :span="10">
<div class="grid-content ep-bg-purple" />
{{ $t('components.dynamicsForm.tag.label') }}
</el-col>
<el-col :span="12"
><div class="grid-content ep-bg-purple" />
选项值</el-col
{{ $t('components.dynamicsForm.Select.label') }}</el-col
>
</el-row>
<el-row
@ -30,11 +30,13 @@
>
<el-col :span="10"
><div class="grid-content ep-bg-purple" />
<el-input v-model="formValue.option_list[$index].label" placeholder="请输入选项标签"
<el-input v-model="formValue.option_list[$index].label" :placeholder="$t('components.dynamicsForm.tag.placeholder')"
/></el-col>
<el-col :span="12"
><div class="grid-content ep-bg-purple" />
<el-input v-model="formValue.option_list[$index].value" placeholder="请输入选项值"
<el-input
v-model="formValue.option_list[$index].value"
:placeholder="$t('components.dynamicsForm.Select.label')"
/></el-col>
<el-col :span="1"
><div class="grid-content ep-bg-purple" />
@ -50,7 +52,11 @@
:label="$t('components.dynamicsForm.default.label')"
:required="formValue.required"
prop="default_value"
:rules="formValue.required ? [{ required: true, message: $t('components.dynamicsForm.default.requiredMessage') }] : []"
:rules="
formValue.required
? [{ required: true, message: $t('components.dynamicsForm.default.requiredMessage') }]
: []
"
>
<div class="defaultValueCheckbox">
<el-checkbox

View File

@ -2,7 +2,7 @@
<el-form-item>
<template #label>
<div class="flex-between">
选项值
{{ $t('components.dynamicsForm.Select.label') }}
<el-button link type="primary" @click.stop="addOption()">
<el-icon class="mr-4">
<Plus />
@ -13,13 +13,13 @@
</template>
<el-row style="width: 100%" :gutter="10">
<el-col :span="10"
><div class="grid-content ep-bg-purple" />
标签</el-col
>
<el-col :span="10">
<div class="grid-content ep-bg-purple" />
{{ $t('components.dynamicsForm.tag.label') }}
</el-col>
<el-col :span="12"
><div class="grid-content ep-bg-purple" />
选项值</el-col
{{ $t('components.dynamicsForm.Select.label') }}</el-col
>
</el-row>
<el-row
@ -31,11 +31,13 @@
>
<el-col :span="10"
><div class="grid-content ep-bg-purple" />
<el-input v-model="formValue.option_list[$index].label" placeholder="请输入选项标签"
<el-input v-model="formValue.option_list[$index].label" :placeholder="$t('components.dynamicsForm.tag.placeholder')"
/></el-col>
<el-col :span="12"
><div class="grid-content ep-bg-purple" />
<el-input v-model="formValue.option_list[$index].value" placeholder="请输入选项值"
<el-input
v-model="formValue.option_list[$index].value"
:placeholder="$t('components.dynamicsForm.Select.label')"
/></el-col>
<el-col :span="1"
><div class="grid-content ep-bg-purple" />

View File

@ -2,7 +2,7 @@
<el-form-item>
<template #label>
<div class="flex-between">
选项值
{{ $t('components.dynamicsForm.Select.label') }}
<el-button link type="primary" @click.stop="addOption()">
<el-icon class="mr-4">
<Plus />
@ -13,14 +13,14 @@
</template>
<el-row style="width: 100%" :gutter="10">
<el-col :span="10"
><div class="grid-content ep-bg-purple" />
标签</el-col
>
<el-col :span="12"
><div class="grid-content ep-bg-purple" />
选项值</el-col
>
<el-col :span="10">
<div class="grid-content ep-bg-purple" />
{{ $t('components.dynamicsForm.tag.label') }}
</el-col>
<el-col :span="12">
<div class="grid-content ep-bg-purple" />
{{ $t('components.dynamicsForm.Select.label') }}
</el-col>
</el-row>
<el-row
style="width: 100%"
@ -31,11 +31,15 @@
>
<el-col :span="10"
><div class="grid-content ep-bg-purple" />
<el-input v-model="formValue.option_list[$index].label" placeholder="请输入选项标签"
<el-input
v-model="formValue.option_list[$index].label"
:placeholder="$t('components.dynamicsForm.tag.placeholder')"
/></el-col>
<el-col :span="12"
><div class="grid-content ep-bg-purple" />
<el-input v-model="formValue.option_list[$index].value" placeholder="请输入选项值"
<el-input
v-model="formValue.option_list[$index].value"
:placeholder="$t('components.dynamicsForm.Select.label')"
/></el-col>
<el-col :span="1"
><div class="grid-content ep-bg-purple" />

View File

@ -2,7 +2,7 @@
<el-form-item>
<template #label>
<div class="flex-between">
选项值
{{ $t('components.dynamicsForm.Select.label') }}
<el-button link type="primary" @click.stop="addOption()">
<el-icon class="mr-4">
<Plus />
@ -15,12 +15,12 @@
<el-row style="width: 100%" :gutter="10">
<el-col :span="10"
><div class="grid-content ep-bg-purple" />
标签</el-col
>
<el-col :span="12"
><div class="grid-content ep-bg-purple" />
选项值</el-col
{{ $t('components.dynamicsForm.tag.label') }}</el-col
>
<el-col :span="12">
<div class="grid-content ep-bg-purple" />
{{ $t('components.dynamicsForm.Select.label') }}
</el-col>
</el-row>
<el-row
style="width: 100%"
@ -31,11 +31,13 @@
>
<el-col :span="10"
><div class="grid-content ep-bg-purple" />
<el-input v-model="formValue.option_list[$index].label" placeholder="请输入选项标签"
<el-input v-model="formValue.option_list[$index].label" :placeholder="$t('components.dynamicsForm.tag.placeholder')"
/></el-col>
<el-col :span="12"
><div class="grid-content ep-bg-purple" />
<el-input v-model="formValue.option_list[$index].value" placeholder="请输入选项值"
<el-input
v-model="formValue.option_list[$index].value"
:placeholder="$t('components.dynamicsForm.Select.label')"
/></el-col>
<el-col :span="1"
><div class="grid-content ep-bg-purple" />

View File

@ -73,7 +73,7 @@
</template>
<script setup lang="ts">
import { computed, onBeforeMount, watch } from 'vue'
import { t } from '@/locales'
const props = defineProps<{
modelValue: any
}>()
@ -101,7 +101,7 @@ const getData = () => {
props_info: {
rules: [
{
message: formValue.value.label + '不能为空',
message: formValue.value.label + t('components.dynamicsForm.tip.requiredMessage'),
trigger: 'blur',
required: formValue.value.required
}

View File

@ -1,66 +1,71 @@
import { useLocalStorage, usePreferredLanguages } from '@vueuse/core';
import { computed } from 'vue';
import { createI18n } from 'vue-i18n';
import { useLocalStorage, usePreferredLanguages } from '@vueuse/core'
import { computed } from 'vue'
import { createI18n } from 'vue-i18n'
import useStore from '@/stores'
const { user } = useStore()
// 导入语言文件
const langModules = import.meta.glob('./lang/*/index.ts', { eager: true }) as Record<string, () => Promise<{ default: Object }>>;
const langModules = import.meta.glob('./lang/*/index.ts', { eager: true }) as Record<
string,
() => Promise<{ default: Object }>
>
const langModuleMap = new Map<string, Object>();
const langModuleMap = new Map<string, Object>()
export const langCode: Array<string> = [];
export const langCode: Array<string> = []
export const localeConfigKey = 'MaxKB-locale';
export const localeConfigKey = 'MaxKB-locale'
// 获取浏览器默认语言环境
const languages = usePreferredLanguages();
const languages = usePreferredLanguages()
// 生成语言模块列表
const generateLangModuleMap = () => {
const fullPaths = Object.keys(langModules);
fullPaths.forEach((fullPath) => {
const k = fullPath.replace('./lang', '');
const startIndex = 1;
const lastIndex = k.lastIndexOf('/');
const code = k.substring(startIndex, lastIndex);
langCode.push(code);
langModuleMap.set(code, langModules[fullPath]);
});
};
const fullPaths = Object.keys(langModules)
fullPaths.forEach((fullPath) => {
const k = fullPath.replace('./lang', '')
const startIndex = 1
const lastIndex = k.lastIndexOf('/')
const code = k.substring(startIndex, lastIndex)
langCode.push(code)
langModuleMap.set(code, langModules[fullPath])
})
}
// 导出 Message
const importMessages = computed(() => {
generateLangModuleMap();
generateLangModuleMap()
const message: Recordable = {};
langModuleMap.forEach((value: any, key) => {
message[key] = value.default;
});
return message;
});
const message: Recordable = {}
langModuleMap.forEach((value: any, key) => {
message[key] = value.default
})
return message
})
export const i18n = createI18n({
legacy: false,
locale: useLocalStorage(localeConfigKey, 'zh_CN').value || languages.value[0] || 'zh_CN',
fallbackLocale: 'zh_CN',
messages: importMessages.value,
globalInjection: true,
});
legacy: false,
locale: user.getLanguage() || languages.value[0] || 'zh_CN',
fallbackLocale: 'zh_CN',
messages: importMessages.value,
globalInjection: true
})
export const langList = computed(() => {
if (langModuleMap.size === 0) generateLangModuleMap();
if (langModuleMap.size === 0) generateLangModuleMap()
const list:any=[]
langModuleMap.forEach((value: any, key) => {
list.push({
label: value.default.lang,
value: key,
});
});
const list: any = []
langModuleMap.forEach((value: any, key) => {
list.push({
label: value.default.lang,
value: key
})
})
return list;
});
return list
})
// @ts-ignore
export const { t } = i18n.global;
export const { t } = i18n.global
export default i18n;
export default i18n

View File

@ -95,7 +95,7 @@ export default {
},
table: {
name: 'File Name',
char_length: 'Character Count',
char_length: 'Character',
paragraph: 'Segment',
all: 'All',
updateTime: 'Update Time'
@ -111,7 +111,7 @@ export default {
REVOKE: 'Cancelling'
},
enableStatus: {
label: 'Enable Status',
label: 'Status',
enable: 'Enabled',
close: 'Disabled'
},

View File

@ -63,5 +63,16 @@ export default {
label: '格式',
placeholder: '请选择格式'
}
},
Select: {
label: '选项值',
placeholder: '请输入选项值'
},
tag: {
label: '标签',
placeholder: '请输入选项标签'
},
Slider: {
showInput:''
}
}

View File

@ -203,10 +203,12 @@ export const postStream: (url: string, data?: unknown) => Promise<Result<any> |
) => {
const { user } = useStore()
const token = user.getToken()
const language = user.getLanguage()
const headers: HeadersInit = { 'Content-Type': 'application/json' }
if (token) {
headers['AUTHORIZATION'] = `${token}`
}
headers['Accept-Language'] = `${language}`
return fetch(url, {
method: 'POST',
body: data ? JSON.stringify(data) : undefined,

View File

@ -8,7 +8,8 @@ import useUserStore from './user'
const useApplicationStore = defineStore({
id: 'application',
state: () => ({
location: `${window.location.origin}/ui/chat/`
location: `${window.location.origin}/ui/chat/`,
userLanguage: ''
}),
actions: {
async asyncGetAllApplication() {
@ -77,10 +78,10 @@ const useApplicationStore = defineStore({
async asyncGetAppProfile(loading?: Ref<boolean>) {
return new Promise((resolve, reject) => {
const user = useUserStore()
applicationApi
.getAppProfile(loading)
.then((data) => {
this.userLanguage = data.data?.language
resolve(data)
})
.catch((error) => {

View File

@ -6,7 +6,7 @@ import UserApi from '@/api/user'
import ThemeApi from '@/api/theme'
import { useElementPlusTheme } from 'use-element-plus-theme'
import { defaultPlatformSetting } from '@/utils/theme'
import useApplicationStore from './application'
export interface userStateTypes {
userType: number // 1 系统操作者 2 对话用户
userInfo: User | null
@ -30,6 +30,12 @@ const useUserStore = defineStore({
themeInfo: null
}),
actions: {
getLanguage() {
const application = useApplicationStore()
return this.userType === 1
? this.userInfo?.language || localStorage.getItem('language')
: application?.userLanguage
},
showXpack() {
return this.isXPack
},
@ -118,6 +124,7 @@ const useUserStore = defineStore({
async profile() {
return UserApi.profile().then(async (ok) => {
this.userInfo = ok.data
localStorage.setItem('language', ok.data?.language)
return this.asyncGetProfile()
})
},

View File

@ -76,6 +76,7 @@
prop="char_length"
:label="$t('views.document.table.char_length')"
align="right"
min-width="90"
>
<template #default="{ row }">
{{ numberFormat(row.char_length) }}
@ -85,6 +86,7 @@
prop="paragraph_count"
:label="$t('views.document.table.paragraph')"
align="right"
min-width="90"
/>
<el-table-column prop="status" :label="$t('views.document.fileStatus.label')" width="130">
<template #header>
@ -216,7 +218,7 @@
<el-icon><Filter /></el-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu style="width: 100px">
<el-dropdown-menu style="width: 150px">
<el-dropdown-item
:class="filterMethod['hit_handling_method'] ? '' : 'is-active'"
:command="beforeCommand('hit_handling_method', '')"
@ -228,7 +230,7 @@
:class="filterMethod['hit_handling_method'] === key ? 'is-active' : ''"
class="justify-center"
:command="beforeCommand('hit_handling_method', key)"
>{{ value }}</el-dropdown-item
>{{ $t(value) }}</el-dropdown-item
>
</template>
</el-dropdown-menu>

View File

@ -79,7 +79,7 @@ import AddParamDrawer from './AddParamDrawer.vue'
import { MsgError, MsgSuccess } from '@/utils/message'
import ModelApi from '@/api/model'
import { input_type_list } from '@/components/dynamics-form/constructor/data'
import { t } from '@/locales'
const props = defineProps<{
model: Model
}>()