feat: 多语言国际化支持

This commit is contained in:
IGCrystal
2025-06-15 22:42:43 +08:00
parent c5f9b5861f
commit b2c382fa01
11 changed files with 334 additions and 20 deletions
+1
View File
@@ -28,6 +28,7 @@
"marked": "^15.0.7",
"pinia": "2.1.6",
"remixicon": "3.5.0",
"vue-i18n": "^9.8.0",
"vee-validate": "4.11.3",
"vite-plugin-vuetify": "1.0.2",
"vue": "3.3.4",
@@ -0,0 +1,69 @@
<template>
<v-menu>
<template v-slot:activator="{ props }">
<v-btn
v-bind="props"
variant="text"
icon
size="small"
class="language-switcher"
>
<v-icon>mdi-translate</v-icon>
<v-tooltip activator="parent" location="bottom">
{{ $t('common.language') }}
</v-tooltip>
</v-btn>
</template>
<v-list density="compact" min-width="140">
<v-list-item
v-for="lang in languages"
:key="lang.code"
:value="lang.code"
@click="changeLanguage(lang.code)"
:class="{ 'v-list-item--active': currentLocale === lang.code }"
>
<template v-slot:prepend>
<span class="language-flag">{{ lang.flag }}</span>
</template>
<v-list-item-title>{{ lang.name }}</v-list-item-title>
<template v-slot:append v-if="currentLocale === lang.code">
<v-icon color="primary" size="small">mdi-check</v-icon>
</template>
</v-list-item>
</v-list>
</v-menu>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'
const { locale } = useI18n()
const languages = [
{ code: 'zh-CN', name: '简体中文', flag: '🇨🇳' },
{ code: 'en-US', name: 'English', flag: '🇺🇸' }
]
const currentLocale = computed(() => locale.value)
const changeLanguage = (langCode: string) => {
locale.value = langCode
localStorage.setItem('locale', langCode)
// 可选:刷新页面以确保所有文本都更新
// window.location.reload()
}
</script>
<style scoped>
.language-flag {
font-size: 16px;
margin-right: 8px;
}
.language-switcher {
margin: 0 4px;
}
</style>
+20
View File
@@ -0,0 +1,20 @@
import { createI18n } from 'vue-i18n'
import zhCN from './locales/zh-CN.json'
import enUS from './locales/en-US.json'
// 从localStorage获取用户选择的语言,默认为中文
const savedLocale = localStorage.getItem('locale') || 'zh-CN'
// 创建i18n实例
const i18n = createI18n({
legacy: false, // 使用Composition API模式
locale: savedLocale, // 设置地区
fallbackLocale: 'zh-CN', // 设置备用语言
messages: {
'zh-CN': zhCN,
'en-US': enUS
},
globalInjection: true // 全局注入
})
export default i18n
+108
View File
@@ -0,0 +1,108 @@
{
"sidebar": {
"dashboard": "Dashboard",
"platforms": "Platforms",
"providers": "Providers",
"toolUse": "MCP",
"config": "Config",
"extension": "Extensions",
"extensionMarketplace": "Extension Market",
"chat": "Chat",
"conversation": "Conversations",
"console": "Console",
"alkaid": "Alkaid",
"about": "About",
"settings": "Settings",
"documentation": "Documentation",
"github": "GitHub",
"drag": "Drag"
},
"common": {
"save": "Save",
"cancel": "Cancel",
"close": "Close",
"delete": "Delete",
"edit": "Edit",
"add": "Add",
"confirm": "Confirm",
"loading": "Loading...",
"success": "Success",
"error": "Error",
"warning": "Warning",
"info": "Info",
"name": "Name",
"description": "Description",
"author": "Author",
"status": "Status",
"actions": "Actions",
"enable": "Enable",
"disable": "Disable",
"enabled": "Enabled",
"disabled": "Disabled",
"reload": "Reload",
"configure": "Configure",
"install": "Install",
"uninstall": "Uninstall",
"update": "Update",
"language": "Language"
},
"extension": {
"title": "Installed Extensions",
"subtitle": "Manage all installed extensions",
"showSystemPlugins": "Show System Plugins",
"hideSystemPlugins": "Hide System Plugins",
"platformCommandConfig": "Platform Command Config",
"noPlugins": "No plugins available",
"tryInstallOrShowSystem": "Try installing plugins or show system plugins",
"configDialog": {
"title": "Extension Configuration",
"noConfig": "This extension has no configuration"
},
"platformConfig": {
"title": "Platform Command Availability Configuration",
"description": "Set the availability of each plugin on different platforms, check to enable",
"noPlatforms": "No platform adapters found",
"addPlatformFirst": "Please add and configure platform adapters in Platform Management first, then set plugin platform availability",
"goToPlatformManagement": "Go to Platform Management"
}
},
"extensionMarketplace": {
"title": "Extension Market",
"installPlugin": "Install Extension",
"fromGitHub": "Download from GitHub",
"fromLocal": "Upload .zip file from local",
"repoUrl": "Repository URL",
"selectFile": "Select File",
"pluginDevelopmentDoc": "Plugin Development Documentation",
"submitPluginRepo": "Submit Plugin Repository"
},
"platform": {
"title": "Platform Adapter Management",
"subtitle": "Manage robot platform adapters to connect to different chat platforms",
"adapters": "Platform Adapters",
"addAdapter": "Add Adapter"
},
"provider": {
"title": "Service Providers",
"tabTypes": {
"chat_completion": "Chat Completion",
"speech_to_text": "Speech to Text",
"text_to_speech": "Text to Speech",
"embedding": "Embedding"
},
"openaiDescription": "{type} service provider. Also supports all OpenAI API compatible model providers.",
"defaultDescription": "{type} service provider"
},
"auth": {
"login": "Login",
"username": "Username",
"password": "Password"
},
"chart": {
"messageCount": "Message Count",
"time": "Time"
},
"alkaid": {
"comingSoon": "The world ahead, let's explore it later!"
}
}
+108
View File
@@ -0,0 +1,108 @@
{
"sidebar": {
"dashboard": "统计",
"platforms": "消息平台",
"providers": "服务提供商",
"toolUse": "MCP",
"config": "配置文件",
"extension": "插件管理",
"extensionMarketplace": "插件市场",
"chat": "聊天",
"conversation": "对话数据库",
"console": "控制台",
"alkaid": "Alkaid",
"about": "关于",
"settings": "设置",
"documentation": "官方文档",
"github": "GitHub",
"drag": "拖拽"
},
"common": {
"save": "保存",
"cancel": "取消",
"close": "关闭",
"delete": "删除",
"edit": "编辑",
"add": "添加",
"confirm": "确认",
"loading": "加载中...",
"success": "成功",
"error": "错误",
"warning": "警告",
"info": "信息",
"name": "名称",
"description": "描述",
"author": "作者",
"status": "状态",
"actions": "操作",
"enable": "启用",
"disable": "禁用",
"enabled": "已启用",
"disabled": "已禁用",
"reload": "重载",
"configure": "配置",
"install": "安装",
"uninstall": "卸载",
"update": "更新",
"language": "语言"
},
"extension": {
"title": "已安装的插件",
"subtitle": "管理已经安装的所有插件",
"showSystemPlugins": "显示系统插件",
"hideSystemPlugins": "隐藏系统插件",
"platformCommandConfig": "平台命令配置",
"noPlugins": "暂无插件",
"tryInstallOrShowSystem": "尝试安装插件或者显示系统插件",
"configDialog": {
"title": "插件配置",
"noConfig": "这个插件没有配置"
},
"platformConfig": {
"title": "平台命令可用性配置",
"description": "设置每个插件在不同平台上的可用性,勾选表示启用",
"noPlatforms": "未找到平台适配器",
"addPlatformFirst": "请先在 平台管理 中添加并配置平台适配器,然后再设置插件的平台可用性",
"goToPlatformManagement": "前往平台管理"
}
},
"extensionMarketplace": {
"title": "插件市场",
"installPlugin": "安装插件",
"fromGitHub": "从 GitHub 上在线下载",
"fromLocal": "从本机上传 .zip 压缩包",
"repoUrl": "仓库链接",
"selectFile": "选择文件",
"pluginDevelopmentDoc": "插件开发文档",
"submitPluginRepo": "提交插件仓库"
},
"platform": {
"title": "平台适配器管理",
"subtitle": "管理机器人的平台适配器,连接到不同的聊天平台",
"adapters": "平台适配器",
"addAdapter": "新增适配器"
},
"provider": {
"title": "服务提供商",
"tabTypes": {
"chat_completion": "基本对话",
"speech_to_text": "语音转文本",
"text_to_speech": "文本转语音",
"embedding": "Embedding"
},
"openaiDescription": "{type} 服务提供商。同时也支持所有兼容 OpenAI API 的模型提供商。",
"defaultDescription": "{type} 服务提供商"
},
"auth": {
"login": "登录",
"username": "用户名",
"password": "密码"
},
"chart": {
"messageCount": "消息条数",
"time": "时间"
},
"alkaid": {
"comingSoon": "前面的世界,以后再来探索吧!"
}
}
@@ -3,6 +3,7 @@ import {ref, computed} from 'vue';
import {useCustomizerStore} from '@/stores/customizer';
import axios from 'axios';
import Logo from '@/components/shared/Logo.vue';
import LanguageSwitcher from '@/components/shared/LanguageSwitcher.vue';
import {md5} from 'js-md5';
import {useAuthStore} from '@/stores/auth';
import {useCommonStore} from '@/stores/common';
@@ -146,7 +147,7 @@ function checkUpdate() {
dashboardHasNewVersion.value = res.data.data.dashboard_has_new_version;
})
.catch((err) => {
if (err.response.status == 401) {
if (err.response && err.response.status == 401) {
console.log("401");
const authStore = useAuthStore();
authStore.logout();
@@ -280,6 +281,9 @@ commonStore.getStartTime();
</small>
</div>
<!-- 语言切换器 -->
<LanguageSwitcher />
<!-- 主题切换按钮 -->
<v-btn size="small" @click="toggleDarkMode();" class="action-btn"
color="var(--v-theme-surface)" variant="flat" rounded="sm">
@@ -16,7 +16,7 @@ const props = defineProps({ item: Object, level: Number });
<template v-slot:prepend>
<v-icon v-if="item.icon" :size="item.iconSize" class="hide-menu" :icon="item.icon"></v-icon>
</template>
<v-list-item-title style="font-size: 14px;">{{ item.title }}</v-list-item-title>
<v-list-item-title style="font-size: 14px;">{{ $t(item.title) }}</v-list-item-title>
<v-list-item-subtitle v-if="item.subCaption" class="text-caption mt-n1 hide-menu">
{{ item.subCaption }}
</v-list-item-subtitle>
@@ -167,14 +167,14 @@ function endDrag() {
</template>
</v-list>
<div class="sidebar-footer" v-if="!customizer.mini_sidebar">
<v-btn style="margin-bottom: 8px;" size="small" variant="primary" to="/settings">
🔧 设置
<v-btn style="margin-bottom: 8px;" size="small" variant="tonal" color="primary" to="/settings">
🔧 {{ $t('sidebar.settings') }}
</v-btn>
<v-btn style="margin-bottom: 8px;" size="small" variant="plain" @click="toggleIframe">
官方文档
{{ $t('sidebar.documentation') }}
</v-btn>
<v-btn style="margin-bottom: 8px;" size="small" variant="plain" @click="openIframeLink('https://github.com/AstrBotDevs/AstrBot')">
GitHub
{{ $t('sidebar.github') }}
</v-btn>
</div>
</div>
@@ -189,7 +189,7 @@ function endDrag() {
<div :style="dragHeaderStyle" @mousedown="onMouseDown" @touchstart="onTouchStart">
<div style="display: flex; align-items: center;">
<v-icon icon="mdi-cursor-move" />
<span style="margin-left: 8px;">拖拽</span>
<span style="margin-left: 8px;">{{ $t('sidebar.drag') }}</span>
</div>
<div style="display: flex; gap: 8px;">
<!-- 跳转按钮 -->
@@ -14,64 +14,66 @@ export interface menu {
subCaption?: string;
}
// 注意:这个文件现在包含i18n键值而不是直接的文本
// 在组件中使用时需要通过$t()函数进行翻译
const sidebarItem: menu[] = [
{
title: '统计',
title: 'sidebar.dashboard',
icon: 'mdi-view-dashboard',
to: '/dashboard/default'
},
{
title: '消息平台',
title: 'sidebar.platforms',
icon: 'mdi-message-processing',
to: '/platforms',
},
{
title: '服务提供商',
title: 'sidebar.providers',
icon: 'mdi-creation',
to: '/providers',
},
{
title: 'MCP',
title: 'sidebar.toolUse',
icon: 'mdi-function-variant',
to: '/tool-use'
},
{
title: '配置文件',
title: 'sidebar.config',
icon: 'mdi-cog',
to: '/config',
},
{
title: '插件管理',
title: 'sidebar.extension',
icon: 'mdi-puzzle',
to: '/extension'
},
{
title: '插件市场',
title: 'sidebar.extensionMarketplace',
icon: 'mdi-storefront',
to: '/extension-marketplace'
},
{
title: '聊天',
title: 'sidebar.chat',
icon: 'mdi-chat',
to: '/chat'
},
{
title: '对话数据库',
title: 'sidebar.conversation',
icon: 'mdi-database',
to: '/conversation'
},
{
title: '控制台',
title: 'sidebar.console',
icon: 'mdi-console',
to: '/console'
},
{
title: 'Alkaid',
title: 'sidebar.alkaid',
icon: 'mdi-test-tube',
to: '/alkaid'
},
{
title: '关于',
title: 'sidebar.about',
icon: 'mdi-information',
to: '/about'
},
+2
View File
@@ -4,6 +4,7 @@ import App from './App.vue';
import { router } from './router';
import vuetify from './plugins/vuetify';
import confirmPlugin from './plugins/confirmPlugin';
import i18n from './i18n';
import '@/scss/style.scss';
import VueApexCharts from 'vue3-apexcharts';
@@ -14,6 +15,7 @@ import axios from 'axios';
const app = createApp(App);
app.use(router);
app.use(createPinia());
app.use(i18n);
app.use(print);
app.use(VueApexCharts);
app.use(vuetify);
+1 -1
View File
@@ -3,7 +3,7 @@
<div class="d-flex align-center justify-center"
style="flex-grow: 1; width: 100%; border: 1px solid #eee; border-radius: 8px;">
<span size="64">🌍</span>
<p class="text-h6 text-grey ml-4">前面的世界以后再来探索吧</p>
<p class="text-h6 text-grey ml-4">{{ $t('alkaid.comingSoon') }}</p>
</div>
</div>
</template>