From b2c382fa016b6405c4311e33f4cc44b18cfd298c Mon Sep 17 00:00:00 2001 From: IGCrystal Date: Sun, 15 Jun 2025 22:42:43 +0800 Subject: [PATCH 01/21] =?UTF-8?q?=E2=9C=A8=20feat:=20=E5=A4=9A=E8=AF=AD?= =?UTF-8?q?=E8=A8=80=E5=9B=BD=E9=99=85=E5=8C=96=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dashboard/package.json | 1 + .../components/shared/LanguageSwitcher.vue | 69 +++++++++++ dashboard/src/i18n/index.ts | 20 ++++ dashboard/src/i18n/locales/en-US.json | 108 ++++++++++++++++++ dashboard/src/i18n/locales/zh-CN.json | 108 ++++++++++++++++++ .../full/vertical-header/VerticalHeader.vue | 6 +- .../layouts/full/vertical-sidebar/NavItem.vue | 2 +- .../full/vertical-sidebar/VerticalSidebar.vue | 10 +- .../full/vertical-sidebar/sidebarItem.ts | 26 +++-- dashboard/src/main.ts | 2 + dashboard/src/views/alkaid/Other.vue | 2 +- 11 files changed, 334 insertions(+), 20 deletions(-) create mode 100644 dashboard/src/components/shared/LanguageSwitcher.vue create mode 100644 dashboard/src/i18n/index.ts create mode 100644 dashboard/src/i18n/locales/en-US.json create mode 100644 dashboard/src/i18n/locales/zh-CN.json diff --git a/dashboard/package.json b/dashboard/package.json index cd621b0b7..ee8efcca6 100644 --- a/dashboard/package.json +++ b/dashboard/package.json @@ -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", diff --git a/dashboard/src/components/shared/LanguageSwitcher.vue b/dashboard/src/components/shared/LanguageSwitcher.vue new file mode 100644 index 000000000..4fbb98b5f --- /dev/null +++ b/dashboard/src/components/shared/LanguageSwitcher.vue @@ -0,0 +1,69 @@ + + + + + \ No newline at end of file diff --git a/dashboard/src/i18n/index.ts b/dashboard/src/i18n/index.ts new file mode 100644 index 000000000..c573d985c --- /dev/null +++ b/dashboard/src/i18n/index.ts @@ -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 \ No newline at end of file diff --git a/dashboard/src/i18n/locales/en-US.json b/dashboard/src/i18n/locales/en-US.json new file mode 100644 index 000000000..c3cd20067 --- /dev/null +++ b/dashboard/src/i18n/locales/en-US.json @@ -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!" + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/zh-CN.json b/dashboard/src/i18n/locales/zh-CN.json new file mode 100644 index 000000000..0567f6d55 --- /dev/null +++ b/dashboard/src/i18n/locales/zh-CN.json @@ -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": "前面的世界,以后再来探索吧!" + } +} \ No newline at end of file diff --git a/dashboard/src/layouts/full/vertical-header/VerticalHeader.vue b/dashboard/src/layouts/full/vertical-header/VerticalHeader.vue index a3546f4bb..e4d7e5a11 100644 --- a/dashboard/src/layouts/full/vertical-header/VerticalHeader.vue +++ b/dashboard/src/layouts/full/vertical-header/VerticalHeader.vue @@ -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(); + + + diff --git a/dashboard/src/layouts/full/vertical-sidebar/NavItem.vue b/dashboard/src/layouts/full/vertical-sidebar/NavItem.vue index 4465aadea..0ce59c92e 100644 --- a/dashboard/src/layouts/full/vertical-sidebar/NavItem.vue +++ b/dashboard/src/layouts/full/vertical-sidebar/NavItem.vue @@ -16,7 +16,7 @@ const props = defineProps({ item: Object, level: Number }); - {{ item.title }} + {{ $t(item.title) }} {{ item.subCaption }} diff --git a/dashboard/src/layouts/full/vertical-sidebar/VerticalSidebar.vue b/dashboard/src/layouts/full/vertical-sidebar/VerticalSidebar.vue index 70c5d5d82..f82b78223 100644 --- a/dashboard/src/layouts/full/vertical-sidebar/VerticalSidebar.vue +++ b/dashboard/src/layouts/full/vertical-sidebar/VerticalSidebar.vue @@ -167,14 +167,14 @@ function endDrag() { @@ -189,7 +189,7 @@ function endDrag() {
- 拖拽 + {{ $t('sidebar.drag') }}
diff --git a/dashboard/src/layouts/full/vertical-sidebar/sidebarItem.ts b/dashboard/src/layouts/full/vertical-sidebar/sidebarItem.ts index e8f49c741..1fa3da9fe 100644 --- a/dashboard/src/layouts/full/vertical-sidebar/sidebarItem.ts +++ b/dashboard/src/layouts/full/vertical-sidebar/sidebarItem.ts @@ -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' }, diff --git a/dashboard/src/main.ts b/dashboard/src/main.ts index cbfcc2e95..4402ed08e 100644 --- a/dashboard/src/main.ts +++ b/dashboard/src/main.ts @@ -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); diff --git a/dashboard/src/views/alkaid/Other.vue b/dashboard/src/views/alkaid/Other.vue index 9c813ef05..a72abf5ff 100644 --- a/dashboard/src/views/alkaid/Other.vue +++ b/dashboard/src/views/alkaid/Other.vue @@ -3,7 +3,7 @@
🌍 -

前面的世界,以后再来探索吧!

+

{{ $t('alkaid.comingSoon') }}

From 075b008740715861885aa8737d916ad67fc04097 Mon Sep 17 00:00:00 2001 From: IGCrystal Date: Sun, 15 Jun 2025 22:45:28 +0800 Subject: [PATCH 02/21] =?UTF-8?q?=F0=9F=90=9E=20fix:=20=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=92=8C=E4=BB=A3=E7=A0=81=E5=81=A5=E5=A3=AE?= =?UTF-8?q?=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 KnowledgeBase.vue 中修正无效的 v-class 指令为 class 属性的问题 - 在 ConsoleDisplayer.vue 中修正 historyNum 属性类型不匹配的问题 - 解决控制台中的 Vue 警告信息 - 在访问 status 前对 err.response 进行空值检查 - 防止“无法读取未定义对象的属性”错误 - 提高 catch 块中错误处理的健壮性 - 对 API 响应数据进行空值检查 - 在处理之前确保数组类型验证 - 修复“无法读取 null 对象的属性”错误 - 改进 beforeUnmount 生命周期中的 D3.js 清理工作 - 对图形数据处理添加防御性编程 --- .../components/shared/ConsoleDisplayer.vue | 2 +- dashboard/src/views/AlkaidPage.vue | 15 ++++- dashboard/src/views/alkaid/KnowledgeBase.vue | 4 +- dashboard/src/views/alkaid/LongTermMemory.vue | 63 ++++++++++++++++--- 4 files changed, 70 insertions(+), 14 deletions(-) diff --git a/dashboard/src/components/shared/ConsoleDisplayer.vue b/dashboard/src/components/shared/ConsoleDisplayer.vue index a05c6eea7..ea2ce2a95 100644 --- a/dashboard/src/components/shared/ConsoleDisplayer.vue +++ b/dashboard/src/components/shared/ConsoleDisplayer.vue @@ -51,7 +51,7 @@ export default { props: { historyNum: { type: String, - default: -1 + default: "-1" }, showLevelBtns: { type: Boolean, diff --git a/dashboard/src/views/AlkaidPage.vue b/dashboard/src/views/AlkaidPage.vue index 326cddc28..a53be15e2 100644 --- a/dashboard/src/views/AlkaidPage.vue +++ b/dashboard/src/views/AlkaidPage.vue @@ -45,10 +45,21 @@ export default { }, methods: { navigateTo(tab) { - this.$router.push(`/alkaid/${tab}`); + try { + if (this.$router && typeof this.$router.push === 'function') { + this.$router.push(`/alkaid/${tab}`); + } + } catch (error) { + console.warn('Navigation error:', error); + } }, isActive(tab) { - return this.$route.path.includes(`/alkaid/${tab}`); + try { + return this.$route && this.$route.path.includes(`/alkaid/${tab}`); + } catch (error) { + console.warn('Route check error:', error); + return false; + } } }, mounted() { diff --git a/dashboard/src/views/alkaid/KnowledgeBase.vue b/dashboard/src/views/alkaid/KnowledgeBase.vue index cf2d0375e..6024abbf0 100644 --- a/dashboard/src/views/alkaid/KnowledgeBase.vue +++ b/dashboard/src/views/alkaid/KnowledgeBase.vue @@ -5,7 +5,7 @@

还没有安装知识库插件 - mdi-information-outline

知识库列表 - mdi-information-outline

{ - let nodesRaw = response.data.data.nodes; - let edgesRaw = response.data.data.edges; + const data = response.data.data || {}; + // 确保数据是数组类型,并且先检查data是否存在 + let nodesRaw = data && Array.isArray(data.nodes) ? data.nodes : []; + let edgesRaw = data && Array.isArray(data.edges) ? data.edges : []; this.node_data = nodesRaw; this.edge_data = edgesRaw; @@ -453,6 +471,11 @@ export default { }) .catch(error => { console.error('Error fetching graph data:', error); + // 出错时重置为空数组 + this.nodes = []; + this.links = []; + this.node_data = []; + this.edge_data = []; }) .finally(() => { this.isLoading = false; @@ -462,10 +485,13 @@ export default { ltmGetUserIds() { axios.get('/api/plug/alkaid/ltm/user_ids') .then(response => { - this.userIdList = response.data.data; + // 确保返回的数据是数组类型 + const data = response.data.data; + this.userIdList = Array.isArray(data) ? data : []; }) .catch(error => { console.error('Error fetching user IDs:', error); + this.userIdList = []; // 出错时设置为空数组 }); }, @@ -575,10 +601,20 @@ export default { initD3Graph() { const container = document.getElementById("graph-container"); - if (!container) return; - d3.select("#graph-container svg").remove(); - const width = container.clientWidth; - const height = container.clientHeight; + if (!container) { + console.warn('Graph container not found'); + return; + } + + // 安全清理现有SVG + try { + d3.select("#graph-container svg").remove(); + } catch (e) { + console.warn('Error removing existing SVG:', e); + } + + const width = container.clientWidth || 800; + const height = container.clientHeight || 600; const svg = d3.select("#graph-container") .append("svg") .attr("width", "100%") @@ -608,9 +644,18 @@ export default { }, updateD3Graph() { - if (!this.svg || !this.simulation) return; + if (!this.svg || !this.simulation || !this.g) { + console.warn('D3 elements not ready for update'); + return; + } + const g = this.g; - g.selectAll("*").remove(); + try { + g.selectAll("*").remove(); + } catch (e) { + console.warn('Error clearing D3 graph:', e); + return; + } // 添加箭头定义 g.append("defs").append("marker") From 6e03218d5401982e0a5cc98f8400a373510a32d3 Mon Sep 17 00:00:00 2001 From: IGCrystal Date: Sun, 15 Jun 2025 22:42:43 +0800 Subject: [PATCH 03/21] =?UTF-8?q?=E2=9C=A8=20feat:=20=E5=A4=9A=E8=AF=AD?= =?UTF-8?q?=E8=A8=80=E5=9B=BD=E9=99=85=E5=8C=96=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dashboard/package.json | 1 + .../components/shared/LanguageSwitcher.vue | 69 +++++++++++ dashboard/src/i18n/index.ts | 20 ++++ dashboard/src/i18n/locales/en-US.json | 108 ++++++++++++++++++ dashboard/src/i18n/locales/zh-CN.json | 108 ++++++++++++++++++ .../full/vertical-header/VerticalHeader.vue | 6 +- .../layouts/full/vertical-sidebar/NavItem.vue | 2 +- .../full/vertical-sidebar/VerticalSidebar.vue | 10 +- .../full/vertical-sidebar/sidebarItem.ts | 24 ++-- dashboard/src/main.ts | 2 + dashboard/src/views/alkaid/Other.vue | 2 +- 11 files changed, 333 insertions(+), 19 deletions(-) create mode 100644 dashboard/src/components/shared/LanguageSwitcher.vue create mode 100644 dashboard/src/i18n/index.ts create mode 100644 dashboard/src/i18n/locales/en-US.json create mode 100644 dashboard/src/i18n/locales/zh-CN.json diff --git a/dashboard/package.json b/dashboard/package.json index cd621b0b7..ee8efcca6 100644 --- a/dashboard/package.json +++ b/dashboard/package.json @@ -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", diff --git a/dashboard/src/components/shared/LanguageSwitcher.vue b/dashboard/src/components/shared/LanguageSwitcher.vue new file mode 100644 index 000000000..4fbb98b5f --- /dev/null +++ b/dashboard/src/components/shared/LanguageSwitcher.vue @@ -0,0 +1,69 @@ + + + + + \ No newline at end of file diff --git a/dashboard/src/i18n/index.ts b/dashboard/src/i18n/index.ts new file mode 100644 index 000000000..c573d985c --- /dev/null +++ b/dashboard/src/i18n/index.ts @@ -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 \ No newline at end of file diff --git a/dashboard/src/i18n/locales/en-US.json b/dashboard/src/i18n/locales/en-US.json new file mode 100644 index 000000000..c3cd20067 --- /dev/null +++ b/dashboard/src/i18n/locales/en-US.json @@ -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!" + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/zh-CN.json b/dashboard/src/i18n/locales/zh-CN.json new file mode 100644 index 000000000..0567f6d55 --- /dev/null +++ b/dashboard/src/i18n/locales/zh-CN.json @@ -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": "前面的世界,以后再来探索吧!" + } +} \ No newline at end of file diff --git a/dashboard/src/layouts/full/vertical-header/VerticalHeader.vue b/dashboard/src/layouts/full/vertical-header/VerticalHeader.vue index a3546f4bb..e4d7e5a11 100644 --- a/dashboard/src/layouts/full/vertical-header/VerticalHeader.vue +++ b/dashboard/src/layouts/full/vertical-header/VerticalHeader.vue @@ -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();
+ + + diff --git a/dashboard/src/layouts/full/vertical-sidebar/NavItem.vue b/dashboard/src/layouts/full/vertical-sidebar/NavItem.vue index 4465aadea..0ce59c92e 100644 --- a/dashboard/src/layouts/full/vertical-sidebar/NavItem.vue +++ b/dashboard/src/layouts/full/vertical-sidebar/NavItem.vue @@ -16,7 +16,7 @@ const props = defineProps({ item: Object, level: Number }); - {{ item.title }} + {{ $t(item.title) }} {{ item.subCaption }} diff --git a/dashboard/src/layouts/full/vertical-sidebar/VerticalSidebar.vue b/dashboard/src/layouts/full/vertical-sidebar/VerticalSidebar.vue index 70c5d5d82..f82b78223 100644 --- a/dashboard/src/layouts/full/vertical-sidebar/VerticalSidebar.vue +++ b/dashboard/src/layouts/full/vertical-sidebar/VerticalSidebar.vue @@ -167,14 +167,14 @@ function endDrag() {
@@ -189,7 +189,7 @@ function endDrag() {
- 拖拽 + {{ $t('sidebar.drag') }}
diff --git a/dashboard/src/layouts/full/vertical-sidebar/sidebarItem.ts b/dashboard/src/layouts/full/vertical-sidebar/sidebarItem.ts index 8495ece41..11f8994ef 100644 --- a/dashboard/src/layouts/full/vertical-sidebar/sidebarItem.ts +++ b/dashboard/src/layouts/full/vertical-sidebar/sidebarItem.ts @@ -14,59 +14,61 @@ 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.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' }, diff --git a/dashboard/src/main.ts b/dashboard/src/main.ts index cbfcc2e95..4402ed08e 100644 --- a/dashboard/src/main.ts +++ b/dashboard/src/main.ts @@ -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); diff --git a/dashboard/src/views/alkaid/Other.vue b/dashboard/src/views/alkaid/Other.vue index 9c813ef05..a72abf5ff 100644 --- a/dashboard/src/views/alkaid/Other.vue +++ b/dashboard/src/views/alkaid/Other.vue @@ -3,7 +3,7 @@
🌍 -

前面的世界,以后再来探索吧!

+

{{ $t('alkaid.comingSoon') }}

From e6c850737977da89841209ff74abad43dd0e8b6f Mon Sep 17 00:00:00 2001 From: IGCrystal Date: Sun, 15 Jun 2025 23:19:46 +0800 Subject: [PATCH 04/21] =?UTF-8?q?=F0=9F=93=83=20docs:=20=E5=88=A0=E9=99=A4?= =?UTF-8?q?i18n=E7=9A=84=E5=8F=99=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dashboard/README-i18n.md | 211 --------------------------------------- 1 file changed, 211 deletions(-) delete mode 100644 dashboard/README-i18n.md diff --git a/dashboard/README-i18n.md b/dashboard/README-i18n.md deleted file mode 100644 index 0e9208ab3..000000000 --- a/dashboard/README-i18n.md +++ /dev/null @@ -1,211 +0,0 @@ -# 多语言国际化使用指南 - -本项目已集成Vue I18n国际化支持,目前支持中文(zh-CN)和英文(en-US)两种语言。 - -## 快速开始 - -### 1. 安装依赖 - -```bash -npm install vue-i18n@^9.8.0 -``` - -### 2. 项目结构 - -``` -src/ -├── i18n/ -│ ├── index.ts # i18n配置入口 -│ └── locales/ -│ ├── zh-CN.json # 中文语言文件 -│ └── en-US.json # 英文语言文件 -├── components/ -│ └── shared/ -│ └── LanguageSwitcher.vue # 语言切换组件 -``` - -## 使用方法 - -### 在Vue组件中使用 - -#### 1. 在模板中使用 - -```vue - -``` - -#### 2. 在脚本中使用 (Composition API) - -```vue - -``` - -#### 3. 在脚本中使用 (Options API) - -```vue - -``` - -## 语言文件结构 - -### 中文 (zh-CN.json) -```json -{ - "sidebar": { - "dashboard": "统计", - "extension": "插件管理" - }, - "common": { - "save": "保存", - "cancel": "取消" - } -} -``` - -### 英文 (en-US.json) -```json -{ - "sidebar": { - "dashboard": "Dashboard", - "extension": "Extensions" - }, - "common": { - "save": "Save", - "cancel": "Cancel" - } -} -``` - -## 添加新语言 - -### 1. 创建新的语言文件 - -在 `src/i18n/locales/` 目录下创建新的语言文件,如 `ja-JP.json`: - -```json -{ - "sidebar": { - "dashboard": "ダッシュボード", - "extension": "拡張機能" - } -} -``` - -### 2. 在i18n配置中注册 - -在 `src/i18n/index.ts` 中添加: - -```typescript -import jaJP from './locales/ja-JP.json' - -const i18n = createI18n({ - // ...其他配置 - messages: { - 'zh-CN': zhCN, - 'en-US': enUS, - 'ja-JP': jaJP // 添加日文 - } -}) -``` - -### 3. 在语言切换器中添加选项 - -在 `LanguageSwitcher.vue` 中添加: - -```typescript -const languages = [ - { code: 'zh-CN', name: '简体中文', flag: '🇨🇳' }, - { code: 'en-US', name: 'English', flag: '🇺🇸' }, - { code: 'ja-JP', name: '日本語', flag: '🇯🇵' } // 添加日文选项 -] -``` - -## 最佳实践 - -### 1. 命名规范 - -- 使用点号分隔的层级结构,如 `page.section.item` -- 通用文本放在 `common` 下 -- 页面特定文本使用页面名作为顶级键 - -### 2. 占位符使用 - -对于需要动态内容的文本,使用占位符: - -```json -{ - "message": "欢迎 {username},您有 {count} 条新消息" -} -``` - -```vue - -``` - -### 3. 复数形式 - -Vue I18n支持复数形式: - -```json -{ - "items": "没有项目 | 1个项目 | {count}个项目" -} -``` - -```vue - -``` - -## 语言切换器 - -项目已包含一个语言切换器组件 `LanguageSwitcher.vue`,位于顶部导航栏。用户可以通过点击翻译图标来切换语言,选择的语言会保存在localStorage中。 - -## 注意事项 - -1. 确保所有支持的语言都有相应的翻译文本 -2. 新增文本时,记得在所有语言文件中添加对应的翻译 -3. 语言切换后,某些组件可能需要重新加载才能完全更新 -4. 建议在开发时优先完善中文翻译,然后再添加其他语言 - -## 贡献翻译 - -欢迎提交其他语言的翻译!请按照现有的文件结构创建新的语言文件,并确保翻译的准确性和一致性。 \ No newline at end of file From 60b2ff0a7a29c0d7daa74fd6dbdd6ea79886f16f Mon Sep 17 00:00:00 2001 From: IGCrystal Date: Mon, 16 Jun 2025 00:47:41 +0800 Subject: [PATCH 05/21] =?UTF-8?q?=F0=9F=90=9E=20fix:=20=E4=BF=AE=E5=A4=8Di?= =?UTF-8?q?frame=E8=B7=B3=E8=BD=AC=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/layouts/full/vertical-sidebar/VerticalSidebar.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dashboard/src/layouts/full/vertical-sidebar/VerticalSidebar.vue b/dashboard/src/layouts/full/vertical-sidebar/VerticalSidebar.vue index f82b78223..0e9797df6 100644 --- a/dashboard/src/layouts/full/vertical-sidebar/VerticalSidebar.vue +++ b/dashboard/src/layouts/full/vertical-sidebar/VerticalSidebar.vue @@ -195,7 +195,7 @@ function endDrag() { @@ -218,4 +218,4 @@ function endDrag() { style="width: 100%; height: calc(100% - 56px); border: none; border-bottom-left-radius: 12px; border-bottom-right-radius: 12px;" >
- + \ No newline at end of file From 0f95f62aa1db84ac3426a590fee3e1bc9068a19e Mon Sep 17 00:00:00 2001 From: IGCrystal Date: Mon, 16 Jun 2025 13:53:33 +0800 Subject: [PATCH 06/21] =?UTF-8?q?=E2=9C=A8=20feat:=20=E5=AE=8C=E6=88=90?= =?UTF-8?q?=E4=BB=AA=E8=A1=A8=E6=9D=BF=E5=9B=BD=E9=99=85=E5=8C=96=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ✨ 核心特性: - 实现模块化i18n架构,支持22个功能模块 - 完成中英双语翻译文件(44个翻译文件) - 新增懒加载翻译模块,提升性能 - 类型安全的翻译键值验证系统 🌐 国际化覆盖: - 所有主要页面(15+)完成国际化 - 导航侧边栏、顶栏、共享组件全部支持 - 仪表板统计组件完整国际化 - 登录页面及认证流程完整国际化 🎨 UI/UX 优化: - 统一顶栏按钮样式(语言切换+主题切换) - 移动端登录页采用全屏设计 - Logo组件智能换行支持中英文 - 响应式语言切换组件 📱 移动端适配: - 登录卡片移动端全屏布局 - 悬浮工具栏底部固定定位 - 触摸友好的交互设计 - 多设备响应式支持 🔧 技术改进: - 模块化翻译文件结构 (core/*, features/*) - 懒加载机制减少初始包体积 - TypeScript类型定义完整 - 翻译键值自动验证 --- dashboard/package.json | 2 +- dashboard/src/components/ConfirmDialog.vue | 11 +- .../components/shared/LanguageSwitcher.vue | 160 +++++-- dashboard/src/components/shared/Logo.vue | 48 +- dashboard/src/i18n/composables.ts | 164 +++++++ dashboard/src/i18n/index.ts | 20 - dashboard/src/i18n/loader.ts | 288 ++++++++++++ dashboard/src/i18n/locales/en-US.json | 108 ----- .../src/i18n/locales/en-US/core/actions.json | 22 + .../src/i18n/locales/en-US/core/common.json | 40 ++ .../src/i18n/locales/en-US/core/header.json | 84 ++++ .../i18n/locales/en-US/core/navigation.json | 18 + .../src/i18n/locales/en-US/core/status.json | 22 + .../i18n/locales/en-US/features/about.json | 17 + .../locales/en-US/features/alkaid/index.json | 26 ++ .../en-US/features/alkaid/knowledge-base.json | 33 ++ .../locales/en-US/features/alkaid/memory.json | 37 ++ .../src/i18n/locales/en-US/features/auth.json | 13 + .../i18n/locales/en-US/features/chart.json | 4 + .../src/i18n/locales/en-US/features/chat.json | 59 +++ .../i18n/locales/en-US/features/config.json | 62 +++ .../i18n/locales/en-US/features/console.json | 15 + .../locales/en-US/features/conversation.json | 77 +++ .../locales/en-US/features/dashboard.json | 61 +++ .../locales/en-US/features/extension.json | 131 ++++++ .../i18n/locales/en-US/features/platform.json | 40 ++ .../i18n/locales/en-US/features/provider.json | 82 ++++ .../i18n/locales/en-US/features/settings.json | 18 + .../i18n/locales/en-US/features/tool-use.json | 114 +++++ .../i18n/locales/en-US/messages/errors.json | 39 ++ .../i18n/locales/en-US/messages/success.json | 23 + .../locales/en-US/messages/validation.json | 24 + dashboard/src/i18n/locales/zh-CN.json | 108 ----- .../src/i18n/locales/zh-CN/core/actions.json | 22 + .../src/i18n/locales/zh-CN/core/common.json | 40 ++ .../src/i18n/locales/zh-CN/core/header.json | 84 ++++ .../i18n/locales/zh-CN/core/navigation.json | 18 + .../src/i18n/locales/zh-CN/core/status.json | 22 + .../i18n/locales/zh-CN/features/about.json | 17 + .../locales/zh-CN/features/alkaid/index.json | 26 ++ .../zh-CN/features/alkaid/knowledge-base.json | 33 ++ .../locales/zh-CN/features/alkaid/memory.json | 37 ++ .../src/i18n/locales/zh-CN/features/auth.json | 13 + .../i18n/locales/zh-CN/features/chart.json | 4 + .../src/i18n/locales/zh-CN/features/chat.json | 59 +++ .../i18n/locales/zh-CN/features/config.json | 62 +++ .../i18n/locales/zh-CN/features/console.json | 15 + .../locales/zh-CN/features/conversation.json | 77 +++ .../locales/zh-CN/features/dashboard.json | 61 +++ .../locales/zh-CN/features/extension.json | 131 ++++++ .../i18n/locales/zh-CN/features/platform.json | 40 ++ .../i18n/locales/zh-CN/features/provider.json | 82 ++++ .../i18n/locales/zh-CN/features/settings.json | 18 + .../i18n/locales/zh-CN/features/tool-use.json | 114 +++++ .../i18n/locales/zh-CN/messages/errors.json | 39 ++ .../i18n/locales/zh-CN/messages/success.json | 23 + .../locales/zh-CN/messages/validation.json | 24 + dashboard/src/i18n/tools/index.ts | 33 ++ dashboard/src/i18n/types.ts | 366 +++++++++++++++ dashboard/src/i18n/validator.ts | 441 ++++++++++++++++++ .../full/vertical-header/VerticalHeader.vue | 128 ++--- .../layouts/full/vertical-sidebar/NavItem.vue | 4 +- .../full/vertical-sidebar/VerticalSidebar.vue | 11 +- .../full/vertical-sidebar/sidebarItem.ts | 25 +- dashboard/src/main.ts | 36 +- dashboard/src/views/AboutPage.vue | 23 +- dashboard/src/views/AlkaidPage.vue | 16 +- dashboard/src/views/ChatPage.vue | 114 ++--- dashboard/src/views/ConfigPage.vue | 69 ++- dashboard/src/views/ConsolePage.vue | 18 +- dashboard/src/views/ConversationPage.vue | 156 ++++--- dashboard/src/views/ExtensionPage.vue | 189 ++++---- dashboard/src/views/PlatformPage.vue | 58 ++- dashboard/src/views/ProviderPage.vue | 130 ++++-- dashboard/src/views/Settings.vue | 17 +- dashboard/src/views/ToolUsePage.vue | 163 ++++--- dashboard/src/views/alkaid/Other.vue | 10 +- .../views/authentication/auth/LoginPage.vue | 297 +++++++++--- .../authentication/authForms/AuthLogin.vue | 9 +- .../dashboards/default/DefaultDashboard.vue | 36 +- .../default/components/MemoryUsage.vue | 16 +- .../default/components/MessageStat.vue | 57 ++- .../default/components/OnlinePlatform.vue | 12 +- .../default/components/PlatformStat.vue | 28 +- .../default/components/RunningTime.vue | 12 +- .../default/components/TotalMessage.vue | 10 +- 86 files changed, 4594 insertions(+), 921 deletions(-) create mode 100644 dashboard/src/i18n/composables.ts delete mode 100644 dashboard/src/i18n/index.ts create mode 100644 dashboard/src/i18n/loader.ts delete mode 100644 dashboard/src/i18n/locales/en-US.json create mode 100644 dashboard/src/i18n/locales/en-US/core/actions.json create mode 100644 dashboard/src/i18n/locales/en-US/core/common.json create mode 100644 dashboard/src/i18n/locales/en-US/core/header.json create mode 100644 dashboard/src/i18n/locales/en-US/core/navigation.json create mode 100644 dashboard/src/i18n/locales/en-US/core/status.json create mode 100644 dashboard/src/i18n/locales/en-US/features/about.json create mode 100644 dashboard/src/i18n/locales/en-US/features/alkaid/index.json create mode 100644 dashboard/src/i18n/locales/en-US/features/alkaid/knowledge-base.json create mode 100644 dashboard/src/i18n/locales/en-US/features/alkaid/memory.json create mode 100644 dashboard/src/i18n/locales/en-US/features/auth.json create mode 100644 dashboard/src/i18n/locales/en-US/features/chart.json create mode 100644 dashboard/src/i18n/locales/en-US/features/chat.json create mode 100644 dashboard/src/i18n/locales/en-US/features/config.json create mode 100644 dashboard/src/i18n/locales/en-US/features/console.json create mode 100644 dashboard/src/i18n/locales/en-US/features/conversation.json create mode 100644 dashboard/src/i18n/locales/en-US/features/dashboard.json create mode 100644 dashboard/src/i18n/locales/en-US/features/extension.json create mode 100644 dashboard/src/i18n/locales/en-US/features/platform.json create mode 100644 dashboard/src/i18n/locales/en-US/features/provider.json create mode 100644 dashboard/src/i18n/locales/en-US/features/settings.json create mode 100644 dashboard/src/i18n/locales/en-US/features/tool-use.json create mode 100644 dashboard/src/i18n/locales/en-US/messages/errors.json create mode 100644 dashboard/src/i18n/locales/en-US/messages/success.json create mode 100644 dashboard/src/i18n/locales/en-US/messages/validation.json delete mode 100644 dashboard/src/i18n/locales/zh-CN.json create mode 100644 dashboard/src/i18n/locales/zh-CN/core/actions.json create mode 100644 dashboard/src/i18n/locales/zh-CN/core/common.json create mode 100644 dashboard/src/i18n/locales/zh-CN/core/header.json create mode 100644 dashboard/src/i18n/locales/zh-CN/core/navigation.json create mode 100644 dashboard/src/i18n/locales/zh-CN/core/status.json create mode 100644 dashboard/src/i18n/locales/zh-CN/features/about.json create mode 100644 dashboard/src/i18n/locales/zh-CN/features/alkaid/index.json create mode 100644 dashboard/src/i18n/locales/zh-CN/features/alkaid/knowledge-base.json create mode 100644 dashboard/src/i18n/locales/zh-CN/features/alkaid/memory.json create mode 100644 dashboard/src/i18n/locales/zh-CN/features/auth.json create mode 100644 dashboard/src/i18n/locales/zh-CN/features/chart.json create mode 100644 dashboard/src/i18n/locales/zh-CN/features/chat.json create mode 100644 dashboard/src/i18n/locales/zh-CN/features/config.json create mode 100644 dashboard/src/i18n/locales/zh-CN/features/console.json create mode 100644 dashboard/src/i18n/locales/zh-CN/features/conversation.json create mode 100644 dashboard/src/i18n/locales/zh-CN/features/dashboard.json create mode 100644 dashboard/src/i18n/locales/zh-CN/features/extension.json create mode 100644 dashboard/src/i18n/locales/zh-CN/features/platform.json create mode 100644 dashboard/src/i18n/locales/zh-CN/features/provider.json create mode 100644 dashboard/src/i18n/locales/zh-CN/features/settings.json create mode 100644 dashboard/src/i18n/locales/zh-CN/features/tool-use.json create mode 100644 dashboard/src/i18n/locales/zh-CN/messages/errors.json create mode 100644 dashboard/src/i18n/locales/zh-CN/messages/success.json create mode 100644 dashboard/src/i18n/locales/zh-CN/messages/validation.json create mode 100644 dashboard/src/i18n/tools/index.ts create mode 100644 dashboard/src/i18n/types.ts create mode 100644 dashboard/src/i18n/validator.ts diff --git a/dashboard/package.json b/dashboard/package.json index ee8efcca6..e757f9b5f 100644 --- a/dashboard/package.json +++ b/dashboard/package.json @@ -28,7 +28,7 @@ "marked": "^15.0.7", "pinia": "2.1.6", "remixicon": "3.5.0", - "vue-i18n": "^9.8.0", + "vue-i18n": "^11.1.5", "vee-validate": "4.11.3", "vite-plugin-vuetify": "1.0.2", "vue": "3.3.4", diff --git a/dashboard/src/components/ConfirmDialog.vue b/dashboard/src/components/ConfirmDialog.vue index 60380764b..9b77a6b6b 100644 --- a/dashboard/src/components/ConfirmDialog.vue +++ b/dashboard/src/components/ConfirmDialog.vue @@ -5,8 +5,8 @@ {{ message }} - 取消 - 确定 + {{ t('core.common.dialog.cancelButton') }} + {{ t('core.common.dialog.confirmButton') }} @@ -14,6 +14,9 @@ @@ -63,7 +81,73 @@ const changeLanguage = (langCode: string) => { margin-right: 8px; } -.language-switcher { +/* 默认变体样式 - 圆形按钮用于登录页 */ +.language-switcher--default { margin: 0 4px; + transition: all 0.3s ease; + border-radius: 50% !important; + min-width: 32px !important; + width: 32px !important; + height: 32px !important; +} + +.language-switcher--default:hover { + transform: scale(1.05); + background: rgba(94, 53, 177, 0.08) !important; +} + +/* Header变体样式 - 完全继承Vuetify和action-btn的默认样式 */ +.language-switcher--header { + /* action-btn类已经处理了margin-right: 6px,不需要额外样式 */ +} + +/* 深色模式下的悬停效果(仅对default变体) */ +:deep(.v-theme--PurpleThemeDark) .language-switcher--default:hover { + background: rgba(114, 46, 209, 0.12) !important; +} + +.language-dropdown { + min-width: 100px; + width: fit-content; + border: 1px solid rgba(94, 53, 177, 0.15) !important; + background: #f8f6fc !important; + backdrop-filter: blur(10px); +} + +/* 深色模式下的下拉框样式 */ +:deep(.v-theme--PurpleThemeDark) .language-dropdown { + background: #2a2733 !important; + border: 1px solid rgba(110, 60, 180, 0.692) !important; +} + +.language-item { + margin: 2px 0; + transition: all 0.2s ease; +} + +.language-item:hover { + background: rgba(94, 53, 177, 0.08) !important; +} + +.language-item-selected { + background: rgba(94, 53, 177, 0.15) !important; + font-weight: 500; +} + +.language-item-selected:hover { + background: rgba(94, 53, 177, 0.2) !important; +} + +/* 深色模式下的列表项悬停效果 */ +:deep(.v-theme--PurpleThemeDark) .language-item:hover { + background: rgba(114, 46, 209, 0.12) !important; +} + +:deep(.v-theme--PurpleThemeDark) .language-item-selected { + background: rgba(114, 46, 209, 0.2) !important; +} + +:deep(.v-theme--PurpleThemeDark) .language-item-selected:hover { + background: rgba(114, 46, 209, 0.25) !important; } \ No newline at end of file diff --git a/dashboard/src/components/shared/Logo.vue b/dashboard/src/components/shared/Logo.vue index 6a071d979..f404cf0db 100644 --- a/dashboard/src/components/shared/Logo.vue +++ b/dashboard/src/components/shared/Logo.vue @@ -5,7 +5,10 @@ AstrBot Logo
-

{{ title }}

+

{{ subtitle }}

@@ -24,6 +27,16 @@ const props = withDefaults(defineProps<{ title: 'AstrBot 仪表盘', subtitle: '欢迎使用' }) + +// 格式化标题,在小屏幕上允许在合适位置换行 +const formatTitle = (title: string) => { + if (title === 'AstrBot 仪表盘') { + return 'AstrBot 仪表盘' + } else if (title === 'AstrBot Dashboard') { + return 'AstrBot Dashboard' + } + return title +} diff --git a/dashboard/src/i18n/composables.ts b/dashboard/src/i18n/composables.ts new file mode 100644 index 000000000..c2df9fc91 --- /dev/null +++ b/dashboard/src/i18n/composables.ts @@ -0,0 +1,164 @@ +import { ref, computed, watchEffect } from 'vue'; +import { I18nLoader } from './loader'; +import type { Locale } from './types'; + +// 全局状态 +const currentLocale = ref('zh-CN'); +const loader = new I18nLoader(); +const translations = ref>({}); + +// 加载器实例 +let loaderInstance: I18nLoader | null = null; + +/** + * 初始化i18n系统 + */ +export async function initI18n(locale: Locale = 'zh-CN') { + loaderInstance = new I18nLoader(); + currentLocale.value = locale; + + // 加载初始翻译 + await loadTranslations(locale); +} + +/** + * 加载翻译数据 + */ +async function loadTranslations(locale: Locale) { + if (!loaderInstance) { + throw new Error('I18n not initialized. Call initI18n() first.'); + } + + try { + const data = await loaderInstance.loadLocale(locale); + translations.value = data; + } catch (error) { + console.error(`Failed to load translations for ${locale}:`, error); + // 回退到中文 + if (locale !== 'zh-CN') { + console.log('Falling back to zh-CN'); + const fallbackData = await loaderInstance.loadLocale('zh-CN'); + translations.value = fallbackData; + } + } +} + +/** + * 主要的翻译函数组合 + */ +export function useI18n() { + // 翻译函数 + const t = (key: string, params?: Record): string => { + const keys = key.split('.'); + let value: any = translations.value; + + // 遍历键路径 + for (const k of keys) { + if (value && typeof value === 'object' && k in value) { + value = value[k]; + } else { + console.warn(`Translation key not found: ${key}`); + return key; // 返回键名作为回退 + } + } + + if (typeof value !== 'string') { + console.warn(`Translation value is not string: ${key}`); + return key; + } + + // 此时value确定是string类型 + let result: string = value; + + // 处理参数插值 + if (params) { + result = result.replace(/\{(\w+)\}/g, (match: string, paramKey: string) => { + return params[paramKey]?.toString() || match; + }); + } + + return result; + }; + + // 切换语言 + const setLocale = async (newLocale: Locale) => { + if (newLocale !== currentLocale.value) { + currentLocale.value = newLocale; + await loadTranslations(newLocale); + + // 保存到localStorage + localStorage.setItem('astrbot-locale', newLocale); + } + }; + + // 获取当前语言 + const locale = computed(() => currentLocale.value); + + // 获取可用语言列表 + const availableLocales: Locale[] = ['zh-CN', 'en-US']; + + // 检查是否已加载 + const isLoaded = computed(() => Object.keys(translations.value).length > 0); + + return { + t, + locale, + setLocale, + availableLocales, + isLoaded + }; +} + +/** + * 模块特定的翻译函数 + */ +export function useModuleI18n(moduleName: string) { + const { t } = useI18n(); + + const tm = (key: string, params?: Record): string => { + // 将斜杠转换为点号以匹配嵌套对象结构 + const normalizedModuleName = moduleName.replace(/\//g, '.'); + return t(`${normalizedModuleName}.${key}`, params); + }; + + return { tm }; +} + +/** + * 语言切换器组合函数 + */ +export function useLanguageSwitcher() { + const { locale, setLocale, availableLocales } = useI18n(); + + const languageOptions = computed(() => [ + { value: 'zh-CN', label: '简体中文', flag: '🇨🇳' }, + { value: 'en-US', label: 'English', flag: '🇺🇸' } + ]); + + const currentLanguage = computed(() => { + return languageOptions.value.find(lang => lang.value === locale.value); + }); + + const switchLanguage = async (newLocale: Locale) => { + await setLocale(newLocale); + }; + + return { + locale, + languageOptions, + currentLanguage, + switchLanguage, + availableLocales + }; +} + +// 初始化函数(在应用启动时调用) +export async function setupI18n() { + // 从localStorage获取保存的语言设置 + const savedLocale = localStorage.getItem('astrbot-locale') as Locale; + const initialLocale = savedLocale && ['zh-CN', 'en-US'].includes(savedLocale) + ? savedLocale + : 'zh-CN'; + + await initI18n(initialLocale); +} \ No newline at end of file diff --git a/dashboard/src/i18n/index.ts b/dashboard/src/i18n/index.ts deleted file mode 100644 index c573d985c..000000000 --- a/dashboard/src/i18n/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -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 \ No newline at end of file diff --git a/dashboard/src/i18n/loader.ts b/dashboard/src/i18n/loader.ts new file mode 100644 index 000000000..73191f10b --- /dev/null +++ b/dashboard/src/i18n/loader.ts @@ -0,0 +1,288 @@ +/** + * Dynamic I18n Loader + * 动态国际化加载器,支持按需加载和缓存机制 + */ + +export interface LoaderCache { + [key: string]: any; +} + +export interface ModuleInfo { + name: string; + path: string; + loaded: boolean; + data?: any; +} + +export class I18nLoader { + private cache: Map = new Map(); + private moduleRegistry: Map = new Map(); + + constructor() { + this.registerModules(); + } + + /** + * 注册所有可用的翻译模块 + */ + private registerModules(): void { + const modules = [ + // 核心模块 + { name: 'core/common', path: 'core/common.json' }, + { name: 'core/actions', path: 'core/actions.json' }, + { name: 'core/status', path: 'core/status.json' }, + { name: 'core/navigation', path: 'core/navigation.json' }, + { name: 'core/header', path: 'core/header.json' }, + + // 功能模块 + { name: 'features/chat', path: 'features/chat.json' }, + { name: 'features/extension', path: 'features/extension.json' }, + { name: 'features/conversation', path: 'features/conversation.json' }, + { name: 'features/tooluse', path: 'features/tool-use.json' }, + { name: 'features/provider', path: 'features/provider.json' }, + { name: 'features/platform', path: 'features/platform.json' }, + { name: 'features/config', path: 'features/config.json' }, + { name: 'features/console', path: 'features/console.json' }, + { name: 'features/about', path: 'features/about.json' }, + { name: 'features/settings', path: 'features/settings.json' }, + { name: 'features/auth', path: 'features/auth.json' }, + { name: 'features/chart', path: 'features/chart.json' }, + { name: 'features/dashboard', path: 'features/dashboard.json' }, + { name: 'features/alkaid/index', path: 'features/alkaid/index.json' }, + { name: 'features/alkaid/knowledge-base', path: 'features/alkaid/knowledge-base.json' }, + { name: 'features/alkaid/memory', path: 'features/alkaid/memory.json' }, + + // 消息模块 + { name: 'messages/errors', path: 'messages/errors.json' }, + { name: 'messages/success', path: 'messages/success.json' }, + { name: 'messages/validation', path: 'messages/validation.json' } + ]; + + modules.forEach(module => { + this.moduleRegistry.set(module.name, { + name: module.name, + path: module.path, + loaded: false + }); + }); + } + + /** + * 加载单个模块 + */ + async loadModule(locale: string, moduleName: string): Promise { + const cacheKey = `${locale}:${moduleName}`; + + // 检查缓存 + if (this.cache.has(cacheKey)) { + return this.cache.get(cacheKey); + } + + const moduleInfo = this.moduleRegistry.get(moduleName); + if (!moduleInfo) { + console.warn(`模块 ${moduleName} 未注册`); + return {}; + } + + try { + // 使用fetch方式加载JSON文件 + const modulePath = `/src/i18n/locales/${locale}/${moduleInfo.path}`; + const response = await fetch(modulePath); + + if (!response.ok) { + throw new Error(`HTTP ${response.status}: ${response.statusText}`); + } + + const data = await response.json(); + + // 缓存结果 + this.cache.set(cacheKey, data); + + // 更新模块信息 + moduleInfo.loaded = true; + moduleInfo.data = data; + + return data; + } catch (error) { + console.error(`加载模块 ${moduleName} 失败:`, error); + return {}; + } + } + + /** + * 加载核心模块(最高优先级) + */ + async loadCoreModules(locale: string): Promise { + const coreModules = [ + 'core/common', + 'core/actions', + 'core/status', + 'core/navigation', + 'core/header' + ]; + + const results = await Promise.all( + coreModules.map(module => this.loadModule(locale, module)) + ); + + return this.mergeModules(results, coreModules); + } + + /** + * 加载功能模块 + */ + async loadFeatureModules(locale: string, features?: string[]): Promise { + const featureModules = features || [ + 'features/chat', + 'features/extension', + 'features/conversation', + 'features/tooluse', + 'features/provider', + 'features/platform', + 'features/config', + 'features/console', + 'features/about', + 'features/settings', + 'features/auth', + 'features/chart', + 'features/dashboard', + 'features/alkaid/index', + 'features/alkaid/knowledge-base', + 'features/alkaid/memory' + ]; + + const results = await Promise.all( + featureModules.map(module => this.loadModule(locale, module)) + ); + + return this.mergeModules(results, featureModules); + } + + /** + * 加载消息模块 + */ + async loadMessageModules(locale: string): Promise { + const messageModules = [ + 'messages/errors', + 'messages/success', + 'messages/validation' + ]; + + const results = await Promise.all( + messageModules.map(module => this.loadModule(locale, module)) + ); + + return this.mergeModules(results, messageModules); + } + + /** + * 加载所有模块 + */ + async loadAllModules(locale: string): Promise { + const [core, features, messages] = await Promise.all([ + this.loadCoreModules(locale), + this.loadFeatureModules(locale), + this.loadMessageModules(locale) + ]); + + return { + ...core, + ...features, + ...messages + }; + } + + /** + * 加载完整语言包(所有模块合并) + */ + async loadLocale(locale: string): Promise { + return this.loadAllModules(locale); + } + + /** + * 合并多个模块数据 + */ + private mergeModules(modules: any[], moduleNames: string[]): any { + const result: any = {}; + + modules.forEach((module, index) => { + const moduleName = moduleNames[index]; + const nameParts = moduleName.split('/'); + + // 构建嵌套对象结构(对所有模块统一处理) + let current = result; + for (let i = 0; i < nameParts.length - 1; i++) { + if (!current[nameParts[i]]) { + current[nameParts[i]] = {}; + } + current = current[nameParts[i]]; + } + + // 设置最终值 + const finalKey = nameParts[nameParts.length - 1]; + current[finalKey] = { ...current[finalKey], ...module }; + }); + + return result; + } + + /** + * 预加载关键模块 + */ + async preloadEssentials(locale: string): Promise { + const essentials = [ + 'core/common', + 'core/navigation', + 'features/chat' + ]; + + await Promise.all( + essentials.map(module => this.loadModule(locale, module)) + ); + } + + /** + * 清理缓存 + */ + clearCache(locale?: string): void { + if (locale) { + // 清理特定语言的缓存 + const keys = Array.from(this.cache.keys()).filter((key: string) => key.startsWith(`${locale}:`)); + keys.forEach((key: string) => this.cache.delete(key)); + } else { + // 清理所有缓存 + this.cache.clear(); + } + } + + /** + * 获取加载状态 + */ + getLoadingStatus(): { total: number; loaded: number; modules: ModuleInfo[] } { + const modules = Array.from(this.moduleRegistry.values()); + const loaded = modules.filter(m => m.loaded).length; + + return { + total: modules.length, + loaded, + modules + }; + } + + /** + * 热重载模块 + */ + async reloadModule(locale: string, moduleName: string): Promise { + const cacheKey = `${locale}:${moduleName}`; + this.cache.delete(cacheKey); + + const moduleInfo = this.moduleRegistry.get(moduleName); + if (moduleInfo) { + moduleInfo.loaded = false; + } + + return this.loadModule(locale, moduleName); + } + + +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/en-US.json b/dashboard/src/i18n/locales/en-US.json deleted file mode 100644 index c3cd20067..000000000 --- a/dashboard/src/i18n/locales/en-US.json +++ /dev/null @@ -1,108 +0,0 @@ -{ - "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!" - } -} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/en-US/core/actions.json b/dashboard/src/i18n/locales/en-US/core/actions.json new file mode 100644 index 000000000..5f4ef91bb --- /dev/null +++ b/dashboard/src/i18n/locales/en-US/core/actions.json @@ -0,0 +1,22 @@ +{ + "create": "Create", + "read": "Read", + "update": "Update", + "delete": "Delete", + "search": "Search", + "filter": "Filter", + "sort": "Sort", + "export": "Export", + "import": "Import", + "backup": "Backup", + "restore": "Restore", + "copy": "Copy", + "paste": "Paste", + "cut": "Cut", + "undo": "Undo", + "redo": "Redo", + "refresh": "Refresh", + "submit": "Submit", + "reset": "Reset", + "clear": "Clear" +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/en-US/core/common.json b/dashboard/src/i18n/locales/en-US/core/common.json new file mode 100644 index 000000000..848d3a205 --- /dev/null +++ b/dashboard/src/i18n/locales/en-US/core/common.json @@ -0,0 +1,40 @@ +{ + "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", + "type": "Type", + "press": "Press", + "longPress": "Long press", + "yes": "Yes", + "no": "No", + "dialog": { + "confirmTitle": "Confirm Action", + "confirmMessage": "Are you sure you want to perform this action?", + "confirmButton": "Confirm", + "cancelButton": "Cancel" + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/en-US/core/header.json b/dashboard/src/i18n/locales/en-US/core/header.json new file mode 100644 index 000000000..02f3bde66 --- /dev/null +++ b/dashboard/src/i18n/locales/en-US/core/header.json @@ -0,0 +1,84 @@ +{ + "version": { + "hasNewVersion": "AstrBot has a new version!", + "dashboardHasNewVersion": "WebUI has a new version!" + }, + "buttons": { + "update": "Update", + "account": "Account", + "theme": { + "light": "Light Mode", + "dark": "Dark Mode" + } + }, + "updateDialog": { + "title": "Update AstrBot", + "currentVersion": "Current Version", + "status": { + "checking": "Checking for updates...", + "switching": "Switching version...", + "updating": "Updating..." + }, + "tabs": { + "release": "😊 Release", + "dev": "🧐 Development (master branch)" + }, + "updateToLatest": "Update to Latest Version", + "tip": "💡 TIP: Switching to an older version or a specific version will not re-download the dashboard files, which may cause some data display errors. You can find the corresponding dashboard files dist.zip at", + "tipLink": "here", + "tipContinue": ", extract and replace the data/dist folder. Of course, the frontend source code is in the dashboard directory, you can also build it yourself using npm install and npm build.", + "dockerTip": "The `Update to Latest Version` button will try to update both the bot main program and the dashboard. If you are using Docker deployment, you can also re-pull the image or use", + "dockerTipLink": "watchtower", + "dockerTipContinue": "to automatically monitor and pull.", + "table": { + "tag": "Tag", + "publishDate": "Publish Date", + "content": "Content", + "sourceUrl": "Source URL", + "actions": "Actions", + "sha": "SHA", + "date": "Date", + "message": "Message", + "view": "View", + "switch": "Switch" + }, + "manualInput": { + "title": "Manual Input Version or Commit SHA", + "placeholder": "Enter version number or commit hash from master branch.", + "hint": "e.g. v3.3.16 (without SHA) or 42e5ec5d80b93b6bfe8b566754d45ffac4c3fe0b", + "linkText": "View master branch commit history (click copy on the right to copy)", + "confirm": "Confirm Switch" + }, + "dashboardUpdate": { + "title": "Update Dashboard to Latest Version Only", + "currentVersion": "Current Version", + "hasNewVersion": "New version available!", + "isLatest": "Already the latest version.", + "downloadAndUpdate": "Download and Update" + } + }, + "accountDialog": { + "title": "Modify Account", + "securityWarning": "Security Reminder: Please change the default password to ensure account security", + "form": { + "currentPassword": "Current Password", + "newPassword": "New Password", + "newUsername": "New Username (Optional)", + "passwordHint": "Password must be at least 8 characters", + "usernameHint": "Leave blank to keep current username", + "defaultCredentials": "Default username and password are both astrbot" + }, + "validation": { + "passwordRequired": "Please enter password", + "passwordMinLength": "Password must be at least 8 characters", + "usernameMinLength": "Username must be at least 3 characters" + }, + "actions": { + "save": "Save Changes", + "cancel": "Cancel" + }, + "messages": { + "updateFailed": "Update failed, please try again" + } + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/en-US/core/navigation.json b/dashboard/src/i18n/locales/en-US/core/navigation.json new file mode 100644 index 000000000..ce289e84e --- /dev/null +++ b/dashboard/src/i18n/locales/en-US/core/navigation.json @@ -0,0 +1,18 @@ +{ + "dashboard": "Dashboard", + "platforms": "Platforms", + "providers": "Providers", + "toolUse": "MCP Tools", + "config": "Config", + "extension": "Extensions", + "extensionMarketplace": "Extension Market", + "chat": "Chat", + "conversation": "Conversations", + "console": "Console", + "alkaid": "Alkaid Lab", + "about": "About", + "settings": "Settings", + "documentation": "Documentation", + "github": "GitHub", + "drag": "Drag" +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/en-US/core/status.json b/dashboard/src/i18n/locales/en-US/core/status.json new file mode 100644 index 000000000..e64e99738 --- /dev/null +++ b/dashboard/src/i18n/locales/en-US/core/status.json @@ -0,0 +1,22 @@ +{ + "loading": "Loading", + "success": "Success", + "error": "Error", + "warning": "Warning", + "info": "Info", + "pending": "Pending", + "processing": "Processing", + "completed": "Completed", + "failed": "Failed", + "cancelled": "Cancelled", + "timeout": "Timeout", + "connecting": "Connecting", + "connected": "Connected", + "disconnected": "Disconnected", + "online": "Online", + "offline": "Offline", + "active": "Active", + "inactive": "Inactive", + "ready": "Ready", + "busy": "Busy" +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/en-US/features/about.json b/dashboard/src/i18n/locales/en-US/features/about.json new file mode 100644 index 000000000..57cc5583f --- /dev/null +++ b/dashboard/src/i18n/locales/en-US/features/about.json @@ -0,0 +1,17 @@ +{ + "hero": { + "title": "AstrBot", + "subtitle": "A project out of interests and loves ❤️", + "starButton": "Star this project! 🌟", + "issueButton": "Submit Issue" + }, + "contributors": { + "title": "Contributors", + "description": "This project is maintained by many open source community members. Thanks to every contributor for their dedication!", + "viewLink": "View AstrBot Contributors" + }, + "stats": { + "title": "Global Deployment", + "license": "AstrBot is open source under AGPL v3 license" + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/en-US/features/alkaid/index.json b/dashboard/src/i18n/locales/en-US/features/alkaid/index.json new file mode 100644 index 000000000..5da278f43 --- /dev/null +++ b/dashboard/src/i18n/locales/en-US/features/alkaid/index.json @@ -0,0 +1,26 @@ +{ + "title": "Alkaid Laboratory", + "subtitle": "Explore cutting-edge AI features", + "comingSoon": "The world ahead, let's explore it later!", + "page": { + "title": "The Alkaid Project.", + "subtitle": "AstrBot Alpha Project", + "navigation": { + "knowledgeBase": "Knowledge Base", + "longTermMemory": "Long-term Memory", + "other": "..." + } + }, + "features": { + "knowledgeBase": "Knowledge Base", + "longTermMemory": "Long-term Memory", + "advancedChat": "Advanced Chat", + "multiModal": "Multi-modal Interaction" + }, + "status": { + "experimental": "Experimental", + "beta": "Beta", + "stable": "Stable", + "deprecated": "Deprecated" + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/en-US/features/alkaid/knowledge-base.json b/dashboard/src/i18n/locales/en-US/features/alkaid/knowledge-base.json new file mode 100644 index 000000000..ecdfb0a72 --- /dev/null +++ b/dashboard/src/i18n/locales/en-US/features/alkaid/knowledge-base.json @@ -0,0 +1,33 @@ +{ + "title": "Knowledge Base", + "subtitle": "Manage and query knowledge base content", + "upload": { + "title": "Upload Documents", + "selectFiles": "Select Files", + "supportedFormats": "Supported Formats", + "dragDrop": "Drag files here", + "processing": "Processing...", + "success": "Upload Successful", + "error": "Upload Failed" + }, + "search": { + "placeholder": "Search knowledge base...", + "results": "Search Results", + "noResults": "No relevant content found", + "searching": "Searching..." + }, + "documents": { + "title": "Document List", + "name": "Document Name", + "size": "Size", + "uploadTime": "Upload Time", + "status": "Status", + "actions": "Actions" + }, + "management": { + "delete": "Delete", + "preview": "Preview", + "download": "Download", + "reindex": "Reindex" + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/en-US/features/alkaid/memory.json b/dashboard/src/i18n/locales/en-US/features/alkaid/memory.json new file mode 100644 index 000000000..bfbb3e17d --- /dev/null +++ b/dashboard/src/i18n/locales/en-US/features/alkaid/memory.json @@ -0,0 +1,37 @@ +{ + "title": "Long-term Memory", + "subtitle": "AI assistant's long-term memory management", + "memories": { + "title": "Memory List", + "content": "Memory Content", + "importance": "Importance Level", + "createTime": "Create Time", + "lastAccess": "Last Access", + "category": "Category" + }, + "categories": { + "personal": "Personal Information", + "preferences": "Preference Settings", + "conversations": "Conversation History", + "facts": "Factual Information", + "skills": "Skill Knowledge" + }, + "importance": { + "high": "High", + "medium": "Medium", + "low": "Low" + }, + "actions": { + "view": "View Details", + "edit": "Edit", + "delete": "Delete", + "pin": "Pin", + "unpin": "Unpin" + }, + "filters": { + "all": "All", + "category": "By Category", + "importance": "By Importance", + "dateRange": "By Date Range" + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/en-US/features/auth.json b/dashboard/src/i18n/locales/en-US/features/auth.json new file mode 100644 index 000000000..6e397a43e --- /dev/null +++ b/dashboard/src/i18n/locales/en-US/features/auth.json @@ -0,0 +1,13 @@ +{ + "login": "Login", + "username": "Username", + "password": "Password", + "logo": { + "title": "AstrBot Dashboard", + "subtitle": "Welcome" + }, + "theme": { + "switchToDark": "Switch to Dark Theme", + "switchToLight": "Switch to Light Theme" + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/en-US/features/chart.json b/dashboard/src/i18n/locales/en-US/features/chart.json new file mode 100644 index 000000000..919fb8507 --- /dev/null +++ b/dashboard/src/i18n/locales/en-US/features/chart.json @@ -0,0 +1,4 @@ +{ + "messageCount": "Message Count", + "time": "Time" +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/en-US/features/chat.json b/dashboard/src/i18n/locales/en-US/features/chat.json new file mode 100644 index 000000000..e790dcbab --- /dev/null +++ b/dashboard/src/i18n/locales/en-US/features/chat.json @@ -0,0 +1,59 @@ +{ + "title": "Let's Chat!", + "subtitle": "Chat with AI Assistant", + "input": { + "placeholder": "Start typing...", + "send": "Send", + "clear": "Clear", + "upload": "Upload File", + "voice": "Voice Input" + }, + "message": { + "user": "User", + "assistant": "Assistant", + "system": "System", + "error": "Error Message", + "loading": "Thinking..." + }, + "voice": { + "start": "Start Recording", + "stop": "Stop Recording", + "recording": "New Recording", + "processing": "Processing...", + "error": "Recording Failed" + }, + "welcome": { + "title": "Welcome to AstrBot", + "subtitle": "Your Intelligent Chat Assistant", + "quickActions": "Quick Actions", + "examples": "Example Questions" + }, + "actions": { + "copy": "Copy", + "regenerate": "Regenerate", + "like": "Like", + "dislike": "Dislike", + "share": "Share", + "newChat": "New Chat", + "deleteChat": "Delete this conversation", + "editTitle": "Edit Title", + "fullscreen": "Fullscreen Mode", + "exitFullscreen": "Exit Fullscreen" + }, + "conversation": { + "newConversation": "New Conversation", + "noHistory": "No conversation history", + "systemStatus": "System Status", + "llmService": "LLM Service", + "speechToText": "Speech to Text" + }, + "modes": { + "darkMode": "Switch to Dark Mode", + "lightMode": "Switch to Light Mode" + }, + "shortcuts": { + "help": "Get Help", + "voiceRecord": "Record Voice", + "pasteImage": "Paste Image" + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/en-US/features/config.json b/dashboard/src/i18n/locales/en-US/features/config.json new file mode 100644 index 000000000..c6fee467f --- /dev/null +++ b/dashboard/src/i18n/locales/en-US/features/config.json @@ -0,0 +1,62 @@ +{ + "title": "Configuration", + "subtitle": "Manage system configuration and settings", + "editor": { + "visual": "Visual Editor", + "code": "Code Editor", + "revertCode": "Revert to Previous Code", + "applyConfig": "Apply This Configuration", + "applyTip": "`Apply This Configuration` will stage and apply the configuration to the visual editor. To save, you need to click the save button in the bottom right corner." + }, + "actions": { + "save": "Save Configuration", + "delete": "Delete This Item", + "add": "Add", + "reset": "Reset to Default", + "export": "Export Configuration", + "import": "Import Configuration", + "validate": "Validate Configuration" + }, + "help": { + "documentation": "Official Documentation", + "support": "Join Group for Help", + "helpText": "Don't understand the configuration? Please see {documentation} or {support}.", + "helpPrefix": "Don't understand the configuration? Please see", + "helpMiddle": "or", + "helpSuffix": "." + }, + "messages": { + "configApplied": "Configuration successfully applied. To save, you need to click the save button in the bottom right corner.", + "configApplyError": "Configuration not applied, JSON format error.", + "saveSuccess": "Configuration saved successfully", + "saveError": "Failed to save configuration", + "loadError": "Failed to load configuration" + }, + "sections": { + "general": "General Settings", + "advanced": "Advanced Settings", + "security": "Security Settings", + "appearance": "Appearance Settings", + "notification": "Notification Settings" + }, + "general": { + "botName": "Bot Name", + "language": "Interface Language", + "timezone": "Timezone", + "autoSave": "Auto Save", + "debugMode": "Debug Mode" + }, + "advanced": { + "logLevel": "Log Level", + "maxConnections": "Max Connections", + "timeout": "Timeout", + "retryAttempts": "Retry Attempts", + "cacheSize": "Cache Size" + }, + "security": { + "apiKey": "API Key", + "allowedHosts": "Allowed Hosts", + "rateLimit": "Rate Limit", + "encryption": "Encryption Settings" + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/en-US/features/console.json b/dashboard/src/i18n/locales/en-US/features/console.json new file mode 100644 index 000000000..3c7448586 --- /dev/null +++ b/dashboard/src/i18n/locales/en-US/features/console.json @@ -0,0 +1,15 @@ +{ + "title": "Console", + "autoScroll": { + "enabled": "Auto-scroll enabled", + "disabled": "Auto-scroll disabled" + }, + "pipInstall": { + "button": "Install pip Package", + "dialogTitle": "Install Pip Package", + "packageLabel": "*Package name, e.g. llmtuner", + "mirrorLabel": "Force PyPI repository URL (optional)", + "mirrorHint": "Force PyPI repository URL > Config item `PyPI Repository Address`", + "installButton": "Install" + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/en-US/features/conversation.json b/dashboard/src/i18n/locales/en-US/features/conversation.json new file mode 100644 index 000000000..e577754e2 --- /dev/null +++ b/dashboard/src/i18n/locales/en-US/features/conversation.json @@ -0,0 +1,77 @@ +{ + "title": "Conversation Management", + "subtitle": "Manage and view user conversation history", + "filters": { + "title": "Filter Conditions", + "platform": "Platform", + "type": "Type", + "search": "Search Keywords", + "reset": "Reset" + }, + "history": { + "title": "Conversation History", + "refresh": "Refresh" + }, + "table": { + "headers": { + "title": "Conversation Title", + "platform": "Platform", + "type": "Type", + "sessionId": "ID", + "createdAt": "Created At", + "updatedAt": "Updated At", + "actions": "Actions" + } + }, + "actions": { + "view": "View", + "edit": "Edit", + "delete": "Delete" + }, + "messageTypes": { + "group": "Group Chat", + "friend": "Private Chat", + "unknown": "Unknown" + }, + "status": { + "noTitle": "Untitled Conversation", + "unknown": "Unknown", + "noData": "No conversation records", + "emptyContent": "Conversation content is empty", + "audioNotSupported": "Your browser does not support audio playback." + }, + "dialogs": { + "view": { + "title": "Conversation Details", + "editMode": "Edit Conversation", + "previewMode": "Preview Mode", + "saveChanges": "Save Changes", + "close": "Close", + "confirmClose": "You have unsaved changes, are you sure you want to close?" + }, + "edit": { + "title": "Edit Conversation Information", + "titleLabel": "Conversation Title", + "titlePlaceholder": "Enter conversation title", + "cancel": "Cancel", + "save": "Save" + }, + "delete": { + "title": "Confirm Delete", + "message": "Are you sure you want to delete conversation {title}? This action cannot be undone.", + "cancel": "Cancel", + "confirm": "Delete" + } + }, + "messages": { + "fetchError": "Failed to fetch conversation list", + "saveSuccess": "Save successful", + "saveError": "Save failed", + "deleteSuccess": "Delete successful", + "deleteError": "Delete failed", + "historyError": "Failed to fetch conversation history", + "historySaveSuccess": "Conversation history saved successfully", + "historySaveError": "Failed to save conversation history", + "invalidJson": "Invalid JSON format" + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/en-US/features/dashboard.json b/dashboard/src/i18n/locales/en-US/features/dashboard.json new file mode 100644 index 000000000..0d42fe6ed --- /dev/null +++ b/dashboard/src/i18n/locales/en-US/features/dashboard.json @@ -0,0 +1,61 @@ +{ + "title": "Dashboard", + "subtitle": "Real-time monitoring and statistics", + "lastUpdate": "Last updated", + "status": { + "loading": "Loading...", + "dataError": "Failed to fetch data", + "noticeError": "Failed to fetch notice" + }, + "stats": { + "totalMessage": { + "title": "Total Messages", + "subtitle": "Total messages sent from all platforms" + }, + "onlinePlatform": { + "title": "Platforms", + "subtitle": "Number of connected platforms" + }, + "runningTime": { + "title": "Uptime", + "subtitle": "System uptime duration" + }, + "memoryUsage": { + "title": "Memory Usage", + "subtitle": "System memory usage status", + "cpuLoad": "CPU Load", + "status": { + "good": "Good", + "normal": "Normal", + "high": "High" + } + } + }, + "charts": { + "messageTrend": { + "title": "Message Trend Analysis", + "subtitle": "Track message count changes over time", + "totalMessages": "Total Messages", + "dailyAverage": "Daily Average", + "growthRate": "Growth Rate", + "timeLabel": "Time", + "messageCount": "Message Count", + "timeRanges": { + "1day": "Past 1 Day", + "3days": "Past 3 Days", + "1week": "Past 1 Week", + "1month": "Past 1 Month" + } + }, + "platformStat": { + "title": "Platform Message Statistics", + "subtitle": "Message count distribution by platform", + "total": "Total", + "noData": "No platform data available", + "messageUnit": "msgs", + "platformCount": "Platforms", + "mostActive": "Most Active", + "totalPercentage": "Total Percentage" + } + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/en-US/features/extension.json b/dashboard/src/i18n/locales/en-US/features/extension.json new file mode 100644 index 000000000..c778304e9 --- /dev/null +++ b/dashboard/src/i18n/locales/en-US/features/extension.json @@ -0,0 +1,131 @@ +{ + "title": "Extension Management", + "subtitle": "Manage and configure system extensions", + "tabs": { + "installed": "Installed", + "market": "Extension Market" + }, + "search": { + "placeholder": "Search extensions...", + "marketPlaceholder": "Search market extensions..." + }, + "views": { + "card": "Card View", + "list": "List View" + }, + "buttons": { + "showSystemPlugins": "Show System Extensions", + "hideSystemPlugins": "Hide System Extensions", + "platformConfig": "Platform Command Config", + "install": "Install", + "uninstall": "Uninstall", + "update": "Update", + "reload": "Reload", + "enable": "Enable", + "disable": "Disable", + "configure": "Configure", + "viewInfo": "Handlers", + "viewDocs": "Documentation", + "close": "Close", + "save": "Save", + "saveAndClose": "Save and Close", + "cancel": "Cancel" + }, + "status": { + "enabled": "Enabled", + "disabled": "Disabled", + "system": "System", + "loading": "Loading...", + "installed": "Installed" + }, + "tooltips": { + "enable": "Click to Enable", + "disable": "Click to Disable", + "reload": "Reload", + "configure": "Configure", + "viewInfo": "Handlers", + "viewDocs": "Documentation", + "update": "Update", + "uninstall": "Uninstall" + }, + "table": { + "headers": { + "name": "Name", + "description": "Description", + "version": "Version", + "author": "Author", + "status": "Status", + "actions": "Actions", + "stars": "Stars", + "lastUpdate": "Last Update", + "tags": "Tags", + "eventType": "Event Type", + "specificType": "Specific Type", + "trigger": "Trigger" + } + }, + "empty": { + "noPlugins": "No Extensions", + "noPluginsDesc": "Try installing extensions or showing system extensions" + }, + "market": { + "recommended": "🥳 Recommended", + "allPlugins": "📦 All Extensions", + "showFullName": "Full Name", + "devDocs": "Extension Development Docs", + "submitRepo": "Submit Extension Repository" + }, + "dialogs": { + "error": { + "title": "Error Information", + "checkConsole": "Please check console for details" + }, + "platformConfig": { + "title": "Platform Command Availability Configuration", + "description": "Set the availability of each extension on different platforms, check to enable", + "noAdapters": "No Platform Adapters Found", + "noAdaptersDesc": "Please add and configure platform adapters in Platform Management first, then set extension platform availability", + "goPlatforms": "Go to Platform Management", + "selectAll": "Select All", + "selectAllNormal": "Select All Normal Extensions", + "selectAllSystem": "Select All System Extensions", + "selectNone": "Select None", + "toggleAll": "Toggle All" + }, + "config": { + "title": "Extension Configuration", + "noConfig": "This extension has no configuration" + }, + "loading": { + "title": "Loading...", + "logs": "Logs" + } + }, + "messages": { + "uninstalling": "Uninstalling", + "refreshing": "Refreshing extension list...", + "refreshSuccess": "Extension list refreshed!", + "refreshFailed": "Error occurred while refreshing extension list", + "reloadSuccess": "Reload successful", + "updateSuccess": "Update successful!", + "addSuccess": "Add successful!", + "saveSuccess": "Save successful!", + "deleteSuccess": "Delete successful!", + "installing": "Installing extension from file", + "installingFromUrl": "Installing extension from URL...", + "installFailed": "Extension installation failed:", + "getPlatformConfigFailed": "Failed to get platform extension config:", + "savePlatformConfigFailed": "Failed to save platform extension config:", + "getMarketDataFailed": "Failed to get extension market data:", + "hasUpdate": "New version available:", + "confirmDelete": "Are you sure you want to delete this extension?", + "fillUrlOrFile": "Please fill in extension URL or upload extension file", + "dontFillBoth": "Please don't fill in both extension URL and upload file" + }, + "upload": { + "fromFile": "Install from File", + "fromUrl": "Install from URL", + "selectFile": "Select File", + "enterUrl": "Enter extension repository URL" + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/en-US/features/platform.json b/dashboard/src/i18n/locales/en-US/features/platform.json new file mode 100644 index 000000000..20844c7be --- /dev/null +++ b/dashboard/src/i18n/locales/en-US/features/platform.json @@ -0,0 +1,40 @@ +{ + "title": "Platform Adapter Management", + "subtitle": "Manage bot platform adapters to connect to different chat platforms", + "adapters": "Platform Adapters", + "addAdapter": "Add Adapter", + "emptyText": "No platform adapters yet, click Add Adapter to create one", + "details": { + "adapterType": "Adapter Type", + "token": "Token", + "description": "Description" + }, + "logs": { + "title": "Platform Logs", + "expand": "Expand", + "collapse": "Collapse" + }, + "dialog": { + "add": "Add", + "edit": "Edit", + "adapter": "Platform Adapter", + "refresh": "Refresh", + "cancel": "Cancel", + "save": "Save" + }, + "messages": { + "updateSuccess": "Update successful!", + "addSuccess": "Add successful!", + "deleteSuccess": "Delete successful!", + "statusUpdateSuccess": "Status update successful!", + "deleteConfirm": "Are you sure you want to delete platform adapter" + }, + "status": { + "enabled": "Enabled", + "disabled": "Disabled", + "connecting": "Connecting", + "connected": "Connected", + "disconnected": "Disconnected", + "error": "Error" + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/en-US/features/provider.json b/dashboard/src/i18n/locales/en-US/features/provider.json new file mode 100644 index 000000000..cf0fa584a --- /dev/null +++ b/dashboard/src/i18n/locales/en-US/features/provider.json @@ -0,0 +1,82 @@ +{ + "title": "Service Provider Management", + "subtitle": "Manage model service providers", + "providers": { + "title": "Service Providers", + "settings": "Settings", + "addProvider": "Add Provider", + "providerType": "Provider Type", + "tabs": { + "all": "All", + "chatCompletion": "Chat Completion", + "speechToText": "Speech to Text", + "textToSpeech": "Text to Speech", + "embedding": "Embedding" + }, + "empty": { + "all": "No service providers available, click Add Provider to add one", + "typed": "No {type} type service providers available, click Add Provider to add one" + }, + "description": { + "openai": "{type} service provider. Also supports all OpenAI API compatible model providers.", + "default": "{type} service provider" + } + }, + "availability": { + "title": "Provider Availability", + "subtitle": "Determined by testing model conversation availability, may incur API costs", + "refresh": "Refresh Status", + "noData": "Click \"Refresh Status\" button to get service provider availability", + "available": "Available", + "unavailable": "Unavailable", + "errorMessage": "Error Message" + }, + "logs": { + "title": "Service Logs", + "expand": "Expand", + "collapse": "Collapse" + }, + "dialogs": { + "addProvider": { + "title": "Service Provider", + "tabs": { + "basic": "Basic", + "speechToText": "Speech to Text", + "textToSpeech": "Text to Speech", + "embedding": "Embedding" + }, + "noTemplates": "No {type} type provider templates available" + }, + "config": { + "addTitle": "Add", + "editTitle": "Edit", + "provider": "Service Provider", + "cancel": "Cancel", + "save": "Save" + }, + "settings": { + "title": "Service Provider Settings", + "sessionSeparation": { + "title": "Enable Provider Session Isolation", + "description": "Different sessions can independently select text generation, TTS, STT and other service providers." + }, + "close": "Close" + } + }, + "messages": { + "success": { + "update": "Updated successfully!", + "add": "Added successfully!", + "delete": "Deleted successfully!", + "statusUpdate": "Status updated successfully!", + "sessionSeparation": "Session isolation settings updated" + }, + "error": { + "sessionSeparation": "Failed to get session isolation configuration", + "fetchStatus": "Failed to get service provider status" + }, + "confirm": { + "delete": "Are you sure you want to delete service provider {id}?" + } + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/en-US/features/settings.json b/dashboard/src/i18n/locales/en-US/features/settings.json new file mode 100644 index 000000000..584c7d0cf --- /dev/null +++ b/dashboard/src/i18n/locales/en-US/features/settings.json @@ -0,0 +1,18 @@ +{ + "network": { + "title": "Network", + "githubProxy": { + "title": "GitHub Proxy Address", + "subtitle": "Set the GitHub proxy address used when downloading plugins or updating AstrBot. This is effective in mainland China's network environment. Can be customized, input takes effect in real time. All addresses do not guarantee stability. If errors occur when updating plugins/projects, please first check if the proxy address is working properly.", + "label": "Select GitHub Proxy Address" + } + }, + "system": { + "title": "System", + "restart": { + "title": "Restart", + "subtitle": "Restart AstrBot", + "button": "Restart" + } + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/en-US/features/tool-use.json b/dashboard/src/i18n/locales/en-US/features/tool-use.json new file mode 100644 index 000000000..fad67a0d5 --- /dev/null +++ b/dashboard/src/i18n/locales/en-US/features/tool-use.json @@ -0,0 +1,114 @@ +{ + "title": "Function Tool Management", + "subtitle": "Manage MCP servers and view available function tools", + "tooltip": { + "info": "What are Function Calling and MCP?", + "marketplace": "Browse and install MCP servers from the community", + "serverConfig": "MCP server (stdio) configuration supports the following fields:\ncommand: Command name (e.g. python or uv)\nargs: Command arguments array (e.g. [\"run\", \"server.py\"])\nenv: Environment variables object (e.g. {\"api_key\": \"abc\"})\ncwd: Working directory path (e.g. /path/to/server)\nencoding: Output encoding (default utf-8)\nencoding_error_handler: The text encoding error handler. Defaults to strict.\nOther fields please refer to MCP documentation\n⚠️ If you deploy AstrBot using Docker, make sure to install MCP servers in the data directory mounted by AstrBot" + }, + "tabs": { + "local": "Local Servers", + "marketplace": "MCP Marketplace" + }, + "mcpServers": { + "title": "MCP Servers", + "buttons": { + "refresh": "Refresh", + "add": "Add Server", + "useTemplate": "Use Template" + }, + "empty": "No MCP servers available, click Add Server to add one", + "status": { + "noTools": "No available tools", + "availableTools": "Available tools", + "configSummary": "Config: {keys}", + "noConfig": "No configuration set" + } + }, + "functionTools": { + "title": "Function Tools", + "buttons": { + "expand": "Expand", + "collapse": "Collapse" + }, + "search": "Search function tools", + "empty": "No function tools available", + "description": "Function Description", + "parameters": "Parameter List", + "noParameters": "This tool has no parameters", + "table": { + "paramName": "Parameter Name", + "type": "Type", + "description": "Description", + "required": "Required" + } + }, + "marketplace": { + "title": "MCP Server Marketplace", + "search": "Search servers", + "buttons": { + "refresh": "Refresh", + "detail": "Details", + "import": "Import" + }, + "loading": "Loading MCP server marketplace...", + "empty": "No MCP servers available", + "status": { + "availableTools": "Available tools ({count})", + "noToolsInfo": "No tool information available" + } + }, + "dialogs": { + "addServer": { + "title": "Add MCP Server", + "editTitle": "Edit MCP Server", + "fields": { + "name": "Server Name", + "nameRequired": "Name is required", + "enable": "Enable Server", + "config": "Server Configuration" + }, + "configNotes": { + "note1": "1. Some MCP servers may require filling in `API_KEY` or `TOKEN` information in env according to their requirements, please check if filled.", + "note2": "2. When url parameter is specified in configuration: if `transport` parameter is also specified as `streamable_http`, Streamable HTTP is used, otherwise SSE connection is used." + }, + "errors": { + "configEmpty": "Configuration cannot be empty", + "jsonFormat": "JSON format error: {error}", + "jsonParse": "JSON parse error: {error}" + }, + "buttons": { + "cancel": "Cancel", + "save": "Save" + } + }, + "serverDetail": { + "title": "Server Details", + "installConfig": "Installation Configuration", + "availableTools": "Available Tools", + "buttons": { + "close": "Close", + "importConfig": "Import Configuration" + } + }, + "confirmDelete": "Are you sure you want to delete server {name}?" + }, + "messages": { + "getServersError": "Failed to get MCP server list: {error}", + "getToolsError": "Failed to get function tools list: {error}", + "saveSuccess": "Save successful!", + "saveError": "Save failed: {error}", + "deleteSuccess": "Delete successful!", + "deleteError": "Delete failed: {error}", + "updateSuccess": "Update successful!", + "updateError": "Update failed: {error}", + "getMarketError": "Failed to get MCP marketplace server list: {error}", + "importError": { + "noConfig": "This server has no available configuration", + "invalidFormat": "Server configuration format is incorrect", + "failed": "Import configuration failed: {error}" + }, + "configParseError": "Configuration parse error: {error}", + "noAvailableConfig": "No available configuration" + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/en-US/messages/errors.json b/dashboard/src/i18n/locales/en-US/messages/errors.json new file mode 100644 index 000000000..7572c447f --- /dev/null +++ b/dashboard/src/i18n/locales/en-US/messages/errors.json @@ -0,0 +1,39 @@ +{ + "network": { + "timeout": "Network request timeout, please try again later", + "connection": "Network connection failed, please check your network", + "server": "Server error, please contact technical support", + "unavailable": "Service temporarily unavailable", + "forbidden": "Access denied" + }, + "validation": { + "required": "This field is required", + "invalid": "Invalid input format", + "tooLong": "Input is too long", + "tooShort": "Input is too short", + "email": "Please enter a valid email address", + "url": "Please enter a valid URL", + "number": "Please enter a valid number" + }, + "auth": { + "unauthorized": "Unauthorized access, please login again", + "forbidden": "Insufficient permissions to perform this operation", + "tokenExpired": "Login expired, please login again", + "invalidCredentials": "Invalid username or password" + }, + "file": { + "uploadFailed": "File upload failed", + "invalidFormat": "Unsupported file format", + "tooLarge": "File size exceeds limit", + "notFound": "File not found" + }, + "operation": { + "failed": "Operation failed", + "cancelled": "Operation cancelled", + "notSupported": "Operation not supported", + "conflict": "Operation conflict, please try again later" + }, + "browser": { + "audioNotSupported": "Your browser does not support audio playback." + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/en-US/messages/success.json b/dashboard/src/i18n/locales/en-US/messages/success.json new file mode 100644 index 000000000..a55d50053 --- /dev/null +++ b/dashboard/src/i18n/locales/en-US/messages/success.json @@ -0,0 +1,23 @@ +{ + "operation": { + "saved": "Save Successful", + "created": "Create Successful", + "updated": "Update Successful", + "deleted": "Delete Successful", + "uploaded": "Upload Successful", + "downloaded": "Download Successful", + "imported": "Import Successful", + "exported": "Export Successful", + "copied": "Copy Successful", + "sent": "Send Successful" + }, + "connection": { + "connected": "Connection Successful", + "authenticated": "Login Successful", + "synchronized": "Synchronization Successful" + }, + "validation": { + "valid": "Validation Passed", + "completed": "Operation Completed" + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/en-US/messages/validation.json b/dashboard/src/i18n/locales/en-US/messages/validation.json new file mode 100644 index 000000000..0b1ccc230 --- /dev/null +++ b/dashboard/src/i18n/locales/en-US/messages/validation.json @@ -0,0 +1,24 @@ +{ + "required": "This field is required", + "email": "Please enter a valid email address", + "url": "Please enter a valid URL", + "number": "Please enter a valid number", + "min": "Minimum value is {min}", + "max": "Maximum value is {max}", + "minLength": "Minimum length is {length} characters", + "maxLength": "Maximum length is {length} characters", + "pattern": "Invalid format", + "unique": "This value already exists", + "confirm": "The two entries do not match", + "fileSize": "File size cannot exceed {size}MB", + "fileType": "Unsupported file type", + "required_field": "Please fill in the required field", + "invalid_format": "Invalid format", + "password_too_short": "Password must be at least 8 characters", + "password_too_weak": "Password is too weak", + "invalid_phone": "Please enter a valid phone number", + "invalid_date": "Please enter a valid date", + "date_range": "Invalid date range", + "upload_failed": "File upload failed", + "network_error": "Network connection error, please try again" +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/zh-CN.json b/dashboard/src/i18n/locales/zh-CN.json deleted file mode 100644 index 0567f6d55..000000000 --- a/dashboard/src/i18n/locales/zh-CN.json +++ /dev/null @@ -1,108 +0,0 @@ -{ - "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": "前面的世界,以后再来探索吧!" - } -} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/zh-CN/core/actions.json b/dashboard/src/i18n/locales/zh-CN/core/actions.json new file mode 100644 index 000000000..7829eb276 --- /dev/null +++ b/dashboard/src/i18n/locales/zh-CN/core/actions.json @@ -0,0 +1,22 @@ +{ + "create": "创建", + "read": "读取", + "update": "更新", + "delete": "删除", + "search": "搜索", + "filter": "筛选", + "sort": "排序", + "export": "导出", + "import": "导入", + "backup": "备份", + "restore": "恢复", + "copy": "复制", + "paste": "粘贴", + "cut": "剪切", + "undo": "撤销", + "redo": "重做", + "refresh": "刷新", + "submit": "提交", + "reset": "重置", + "clear": "清空" +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/zh-CN/core/common.json b/dashboard/src/i18n/locales/zh-CN/core/common.json new file mode 100644 index 000000000..f0adea8ab --- /dev/null +++ b/dashboard/src/i18n/locales/zh-CN/core/common.json @@ -0,0 +1,40 @@ +{ + "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": "语言", + "type": "输入", + "press": "按", + "longPress": "长按", + "yes": "是", + "no": "否", + "dialog": { + "confirmTitle": "确认操作", + "confirmMessage": "你确定要执行此操作吗?", + "confirmButton": "确定", + "cancelButton": "取消" + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/zh-CN/core/header.json b/dashboard/src/i18n/locales/zh-CN/core/header.json new file mode 100644 index 000000000..638bd8777 --- /dev/null +++ b/dashboard/src/i18n/locales/zh-CN/core/header.json @@ -0,0 +1,84 @@ +{ + "version": { + "hasNewVersion": "AstrBot 有新版本!", + "dashboardHasNewVersion": "WebUI 有新版本!" + }, + "buttons": { + "update": "更新", + "account": "账户", + "theme": { + "light": "浅色模式", + "dark": "深色模式" + } + }, + "updateDialog": { + "title": "更新 AstrBot", + "currentVersion": "当前版本", + "status": { + "checking": "正在检查更新...", + "switching": "正在切换版本...", + "updating": "正在更新..." + }, + "tabs": { + "release": "😊 正式版", + "dev": "🧐 开发版(master 分支)" + }, + "updateToLatest": "更新到最新版本", + "tip": "💡 TIP: 跳到旧版本或者切换到某个版本不会重新下载管理面板文件,这可能会造成部分数据显示错误。您可在", + "tipLink": "此处", + "tipContinue": "找到对应的面板文件 dist.zip,解压后替换 data/dist 文件夹即可。当然,前端源代码在 dashboard 目录下,你也可以自己使用 npm install 和 npm build 构建。", + "dockerTip": "`更新到最新版本` 按钮会同时尝试更新机器人主程序和管理面板。如果您正在使用 Docker 部署,也可以重新拉取镜像或者使用", + "dockerTipLink": "watchtower", + "dockerTipContinue": "来自动监控拉取。", + "table": { + "tag": "标签", + "publishDate": "发布时间", + "content": "内容", + "sourceUrl": "源码地址", + "actions": "操作", + "sha": "SHA", + "date": "日期", + "message": "信息", + "view": "查看", + "switch": "切换" + }, + "manualInput": { + "title": "手动输入版本号或 Commit SHA", + "placeholder": "输入版本号或 master 分支下的 commit hash。", + "hint": "如 v3.3.16 (不带 SHA) 或 42e5ec5d80b93b6bfe8b566754d45ffac4c3fe0b", + "linkText": "查看 master 分支提交记录(点击右边的 copy 即可复制)", + "confirm": "确定切换" + }, + "dashboardUpdate": { + "title": "单独更新管理面板到最新版本", + "currentVersion": "当前版本", + "hasNewVersion": "有新版本!", + "isLatest": "已经是最新版本了。", + "downloadAndUpdate": "下载并更新" + } + }, + "accountDialog": { + "title": "修改账户", + "securityWarning": "安全提醒: 请修改默认密码以确保账户安全", + "form": { + "currentPassword": "当前密码", + "newPassword": "新密码", + "newUsername": "新用户名 (可选)", + "passwordHint": "密码长度至少 8 位", + "usernameHint": "留空表示不修改用户名", + "defaultCredentials": "默认用户名和密码均为 astrbot" + }, + "validation": { + "passwordRequired": "请输入密码", + "passwordMinLength": "密码长度至少 8 位", + "usernameMinLength": "用户名长度至少3位" + }, + "actions": { + "save": "保存修改", + "cancel": "取消" + }, + "messages": { + "updateFailed": "修改失败,请重试" + } + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/zh-CN/core/navigation.json b/dashboard/src/i18n/locales/zh-CN/core/navigation.json new file mode 100644 index 000000000..23a129ae5 --- /dev/null +++ b/dashboard/src/i18n/locales/zh-CN/core/navigation.json @@ -0,0 +1,18 @@ +{ + "dashboard": "统计", + "platforms": "消息平台", + "providers": "服务提供商", + "toolUse": "MCP", + "config": "配置文件", + "extension": "插件管理", + "extensionMarketplace": "插件市场", + "chat": "聊天", + "conversation": "对话数据库", + "console": "控制台", + "alkaid": "Alkaid", + "about": "关于", + "settings": "设置", + "documentation": "官方文档", + "github": "GitHub", + "drag": "拖拽" +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/zh-CN/core/status.json b/dashboard/src/i18n/locales/zh-CN/core/status.json new file mode 100644 index 000000000..233d8f128 --- /dev/null +++ b/dashboard/src/i18n/locales/zh-CN/core/status.json @@ -0,0 +1,22 @@ +{ + "loading": "加载中", + "success": "成功", + "error": "错误", + "warning": "警告", + "info": "信息", + "pending": "等待中", + "processing": "处理中", + "completed": "已完成", + "failed": "失败", + "cancelled": "已取消", + "timeout": "超时", + "connecting": "连接中", + "connected": "已连接", + "disconnected": "已断开", + "online": "在线", + "offline": "离线", + "active": "活跃", + "inactive": "非活跃", + "ready": "就绪", + "busy": "忙碌" +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/zh-CN/features/about.json b/dashboard/src/i18n/locales/zh-CN/features/about.json new file mode 100644 index 000000000..85f7956a4 --- /dev/null +++ b/dashboard/src/i18n/locales/zh-CN/features/about.json @@ -0,0 +1,17 @@ +{ + "hero": { + "title": "AstrBot", + "subtitle": "A project out of interests and loves ❤️", + "starButton": "Star 这个项目! 🌟", + "issueButton": "提交 Issue" + }, + "contributors": { + "title": "贡献者", + "description": "本项目由众多开源社区成员共同维护。感谢每一位贡献者的付出!", + "viewLink": "查看 AstrBot 贡献者" + }, + "stats": { + "title": "全球部署", + "license": "AstrBot 采用 AGPL v3 协议开源" + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/zh-CN/features/alkaid/index.json b/dashboard/src/i18n/locales/zh-CN/features/alkaid/index.json new file mode 100644 index 000000000..fadceb7a3 --- /dev/null +++ b/dashboard/src/i18n/locales/zh-CN/features/alkaid/index.json @@ -0,0 +1,26 @@ +{ + "title": "Alkaid实验室", + "subtitle": "探索前沿AI功能", + "comingSoon": "前面的世界,以后再来探索吧!", + "page": { + "title": "The Alkaid Project.", + "subtitle": "AstrBot Alpha 项目", + "navigation": { + "knowledgeBase": "知识库", + "longTermMemory": "长期记忆层", + "other": "..." + } + }, + "features": { + "knowledgeBase": "知识库", + "longTermMemory": "长期记忆", + "advancedChat": "高级对话", + "multiModal": "多模态交互" + }, + "status": { + "experimental": "实验性", + "beta": "测试版", + "stable": "稳定版", + "deprecated": "已弃用" + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/zh-CN/features/alkaid/knowledge-base.json b/dashboard/src/i18n/locales/zh-CN/features/alkaid/knowledge-base.json new file mode 100644 index 000000000..caa48364a --- /dev/null +++ b/dashboard/src/i18n/locales/zh-CN/features/alkaid/knowledge-base.json @@ -0,0 +1,33 @@ +{ + "title": "知识库", + "subtitle": "管理和查询知识库内容", + "upload": { + "title": "上传文档", + "selectFiles": "选择文件", + "supportedFormats": "支持的格式", + "dragDrop": "拖拽文件到此处", + "processing": "处理中...", + "success": "上传成功", + "error": "上传失败" + }, + "search": { + "placeholder": "搜索知识库...", + "results": "搜索结果", + "noResults": "未找到相关内容", + "searching": "搜索中..." + }, + "documents": { + "title": "文档列表", + "name": "文档名称", + "size": "大小", + "uploadTime": "上传时间", + "status": "状态", + "actions": "操作" + }, + "management": { + "delete": "删除", + "preview": "预览", + "download": "下载", + "reindex": "重新索引" + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/zh-CN/features/alkaid/memory.json b/dashboard/src/i18n/locales/zh-CN/features/alkaid/memory.json new file mode 100644 index 000000000..5bbd3624a --- /dev/null +++ b/dashboard/src/i18n/locales/zh-CN/features/alkaid/memory.json @@ -0,0 +1,37 @@ +{ + "title": "长期记忆", + "subtitle": "AI助手的长期记忆管理", + "memories": { + "title": "记忆列表", + "content": "记忆内容", + "importance": "重要程度", + "createTime": "创建时间", + "lastAccess": "最后访问", + "category": "分类" + }, + "categories": { + "personal": "个人信息", + "preferences": "偏好设置", + "conversations": "对话历史", + "facts": "事实信息", + "skills": "技能知识" + }, + "importance": { + "high": "高", + "medium": "中", + "low": "低" + }, + "actions": { + "view": "查看详情", + "edit": "编辑", + "delete": "删除", + "pin": "置顶", + "unpin": "取消置顶" + }, + "filters": { + "all": "全部", + "category": "按分类", + "importance": "按重要程度", + "dateRange": "按时间范围" + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/zh-CN/features/auth.json b/dashboard/src/i18n/locales/zh-CN/features/auth.json new file mode 100644 index 000000000..41c510309 --- /dev/null +++ b/dashboard/src/i18n/locales/zh-CN/features/auth.json @@ -0,0 +1,13 @@ +{ + "login": "登录", + "username": "用户名", + "password": "密码", + "logo": { + "title": "AstrBot 仪表盘", + "subtitle": "欢迎使用" + }, + "theme": { + "switchToDark": "切换到深色主题", + "switchToLight": "切换到浅色主题" + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/zh-CN/features/chart.json b/dashboard/src/i18n/locales/zh-CN/features/chart.json new file mode 100644 index 000000000..eae4ee546 --- /dev/null +++ b/dashboard/src/i18n/locales/zh-CN/features/chart.json @@ -0,0 +1,4 @@ +{ + "messageCount": "消息条数", + "time": "时间" +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/zh-CN/features/chat.json b/dashboard/src/i18n/locales/zh-CN/features/chat.json new file mode 100644 index 000000000..87bc4a3a0 --- /dev/null +++ b/dashboard/src/i18n/locales/zh-CN/features/chat.json @@ -0,0 +1,59 @@ +{ + "title": "聊天吧!", + "subtitle": "与AI助手进行对话", + "input": { + "placeholder": "开始输入...", + "send": "发送", + "clear": "清空", + "upload": "上传文件", + "voice": "语音输入" + }, + "message": { + "user": "用户", + "assistant": "助手", + "system": "系统", + "error": "错误消息", + "loading": "思考中..." + }, + "voice": { + "start": "开始录音", + "stop": "停止录音", + "recording": "新录音", + "processing": "处理中...", + "error": "录音失败" + }, + "welcome": { + "title": "欢迎使用 AstrBot", + "subtitle": "您的智能对话助手", + "quickActions": "快速操作", + "examples": "示例问题" + }, + "actions": { + "copy": "复制", + "regenerate": "重新生成", + "like": "点赞", + "dislike": "踩", + "share": "分享", + "newChat": "创建对话", + "deleteChat": "删除此对话", + "editTitle": "编辑标题", + "fullscreen": "全屏模式", + "exitFullscreen": "退出全屏" + }, + "conversation": { + "newConversation": "新对话", + "noHistory": "暂无对话历史", + "systemStatus": "系统状态", + "llmService": "LLM 服务", + "speechToText": "语音转文本" + }, + "modes": { + "darkMode": "切换到夜间模式", + "lightMode": "切换到日间模式" + }, + "shortcuts": { + "help": "获取帮助", + "voiceRecord": "录制语音", + "pasteImage": "粘贴图片" + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/zh-CN/features/config.json b/dashboard/src/i18n/locales/zh-CN/features/config.json new file mode 100644 index 000000000..8d059c90f --- /dev/null +++ b/dashboard/src/i18n/locales/zh-CN/features/config.json @@ -0,0 +1,62 @@ +{ + "title": "配置文件", + "subtitle": "管理系统配置和设置", + "editor": { + "visual": "可视化编辑", + "code": "代码编辑", + "revertCode": "回到更改前的代码", + "applyConfig": "应用此配置", + "applyTip": "`应用此配置` 将配置暂存并应用到可视化。如要保存,需再点击右下角保存按钮。" + }, + "actions": { + "save": "保存配置", + "delete": "删除这项", + "add": "添加", + "reset": "重置为默认", + "export": "导出配置", + "import": "导入配置", + "validate": "验证配置" + }, + "help": { + "documentation": "官方文档", + "support": "加群询问", + "helpText": "不了解配置?请见 {documentation} 或 {support}。", + "helpPrefix": "不了解配置?请见", + "helpMiddle": "或", + "helpSuffix": "。" + }, + "messages": { + "configApplied": "配置成功应用。如要保存,需再点击右下角保存按钮。", + "configApplyError": "配置未应用,Json 格式错误。", + "saveSuccess": "配置保存成功", + "saveError": "配置保存失败", + "loadError": "配置加载失败" + }, + "sections": { + "general": "常规设置", + "advanced": "高级设置", + "security": "安全设置", + "appearance": "外观设置", + "notification": "通知设置" + }, + "general": { + "botName": "机器人名称", + "language": "界面语言", + "timezone": "时区", + "autoSave": "自动保存", + "debugMode": "调试模式" + }, + "advanced": { + "logLevel": "日志级别", + "maxConnections": "最大连接数", + "timeout": "超时时间", + "retryAttempts": "重试次数", + "cacheSize": "缓存大小" + }, + "security": { + "apiKey": "API密钥", + "allowedHosts": "允许的主机", + "rateLimit": "频率限制", + "encryption": "加密设置" + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/zh-CN/features/console.json b/dashboard/src/i18n/locales/zh-CN/features/console.json new file mode 100644 index 000000000..8c1d03a35 --- /dev/null +++ b/dashboard/src/i18n/locales/zh-CN/features/console.json @@ -0,0 +1,15 @@ +{ + "title": "控制台", + "autoScroll": { + "enabled": "自动滚动已开启", + "disabled": "自动滚动已关闭" + }, + "pipInstall": { + "button": "安装 pip 库", + "dialogTitle": "安装 Pip 库", + "packageLabel": "*库名,如 llmtuner", + "mirrorLabel": "强制 PyPI 软件仓库链接(可选)", + "mirrorHint": "强制 PyPI 软件仓库链接 > 配置项 `PyPI 软件仓库地址`", + "installButton": "安装" + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/zh-CN/features/conversation.json b/dashboard/src/i18n/locales/zh-CN/features/conversation.json new file mode 100644 index 000000000..1b8039fbc --- /dev/null +++ b/dashboard/src/i18n/locales/zh-CN/features/conversation.json @@ -0,0 +1,77 @@ +{ + "title": "对话管理", + "subtitle": "管理和查看用户对话历史记录", + "filters": { + "title": "筛选条件", + "platform": "平台", + "type": "类型", + "search": "搜索关键词", + "reset": "重置" + }, + "history": { + "title": "对话历史", + "refresh": "刷新" + }, + "table": { + "headers": { + "title": "对话标题", + "platform": "平台", + "type": "类型", + "sessionId": "ID", + "createdAt": "创建时间", + "updatedAt": "更新时间", + "actions": "操作" + } + }, + "actions": { + "view": "查看", + "edit": "编辑", + "delete": "删除" + }, + "messageTypes": { + "group": "群聊", + "friend": "私聊", + "unknown": "未知" + }, + "status": { + "noTitle": "无标题对话", + "unknown": "未知", + "noData": "暂无对话记录", + "emptyContent": "对话内容为空", + "audioNotSupported": "您的浏览器不支持音频播放。" + }, + "dialogs": { + "view": { + "title": "对话详情", + "editMode": "编辑对话", + "previewMode": "预览模式", + "saveChanges": "保存修改", + "close": "关闭", + "confirmClose": "您有未保存的更改,确定要关闭吗?" + }, + "edit": { + "title": "编辑对话信息", + "titleLabel": "对话标题", + "titlePlaceholder": "输入对话标题", + "cancel": "取消", + "save": "保存" + }, + "delete": { + "title": "确认删除", + "message": "确定要删除对话 {title} 吗?此操作不可恢复。", + "cancel": "取消", + "confirm": "删除" + } + }, + "messages": { + "fetchError": "获取对话列表失败", + "saveSuccess": "保存成功", + "saveError": "保存失败", + "deleteSuccess": "删除成功", + "deleteError": "删除失败", + "historyError": "获取对话历史失败", + "historySaveSuccess": "对话历史保存成功", + "historySaveError": "对话历史保存失败", + "invalidJson": "JSON格式无效" + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/zh-CN/features/dashboard.json b/dashboard/src/i18n/locales/zh-CN/features/dashboard.json new file mode 100644 index 000000000..0ab05527c --- /dev/null +++ b/dashboard/src/i18n/locales/zh-CN/features/dashboard.json @@ -0,0 +1,61 @@ +{ + "title": "控制台", + "subtitle": "实时监控和统计数据", + "lastUpdate": "最后更新", + "status": { + "loading": "加载中...", + "dataError": "获取数据失败", + "noticeError": "获取公告失败" + }, + "stats": { + "totalMessage": { + "title": "消息总数", + "subtitle": "所有平台发送的消息总计" + }, + "onlinePlatform": { + "title": "消息平台", + "subtitle": "已连接的消息平台数量" + }, + "runningTime": { + "title": "运行时间", + "subtitle": "系统已运行时长" + }, + "memoryUsage": { + "title": "内存占用", + "subtitle": "系统内存使用情况", + "cpuLoad": "CPU 负载", + "status": { + "good": "良好", + "normal": "正常", + "high": "偏高" + } + } + }, + "charts": { + "messageTrend": { + "title": "消息趋势分析", + "subtitle": "跟踪消息数量随时间的变化", + "totalMessages": "总消息数", + "dailyAverage": "平均每天", + "growthRate": "增长率", + "timeLabel": "时间", + "messageCount": "消息条数", + "timeRanges": { + "1day": "过去 1 天", + "3days": "过去 3 天", + "1week": "过去 7 天", + "1month": "过去 30 天" + } + }, + "platformStat": { + "title": "平台消息统计", + "subtitle": "各平台消息数量分布", + "total": "总计", + "noData": "暂无平台数据", + "messageUnit": "条", + "platformCount": "平台数", + "mostActive": "最活跃", + "totalPercentage": "总消息占比" + } + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/zh-CN/features/extension.json b/dashboard/src/i18n/locales/zh-CN/features/extension.json new file mode 100644 index 000000000..bd748494b --- /dev/null +++ b/dashboard/src/i18n/locales/zh-CN/features/extension.json @@ -0,0 +1,131 @@ +{ + "title": "插件管理", + "subtitle": "管理和配置系统插件", + "tabs": { + "installed": "已安装", + "market": "插件市场" + }, + "search": { + "placeholder": "搜索插件...", + "marketPlaceholder": "搜索市场插件..." + }, + "views": { + "card": "卡片视图", + "list": "列表视图" + }, + "buttons": { + "showSystemPlugins": "显示系统插件", + "hideSystemPlugins": "隐藏系统插件", + "platformConfig": "平台命令配置", + "install": "安装", + "uninstall": "卸载", + "update": "更新", + "reload": "重载", + "enable": "启用", + "disable": "禁用", + "configure": "配置", + "viewInfo": "行为", + "viewDocs": "文档", + "close": "关闭", + "save": "保存", + "saveAndClose": "保存并关闭", + "cancel": "取消" + }, + "status": { + "enabled": "启用", + "disabled": "禁用", + "system": "系统", + "loading": "加载中...", + "installed": "已安装" + }, + "tooltips": { + "enable": "点击启用", + "disable": "点击禁用", + "reload": "重载", + "configure": "配置", + "viewInfo": "行为", + "viewDocs": "文档", + "update": "更新", + "uninstall": "卸载" + }, + "table": { + "headers": { + "name": "名称", + "description": "描述", + "version": "版本", + "author": "作者", + "status": "状态", + "actions": "操作", + "stars": "Star数", + "lastUpdate": "最近更新", + "tags": "标签", + "eventType": "行为类型", + "specificType": "具体类型", + "trigger": "触发方式" + } + }, + "empty": { + "noPlugins": "暂无插件", + "noPluginsDesc": "尝试安装插件或者显示系统插件" + }, + "market": { + "recommended": "🥳 推荐", + "allPlugins": "📦 全部插件", + "showFullName": "完整名称", + "devDocs": "插件开发文档", + "submitRepo": "提交插件仓库" + }, + "dialogs": { + "error": { + "title": "错误信息", + "checkConsole": "详情请检查控制台" + }, + "platformConfig": { + "title": "平台命令可用性配置", + "description": "设置每个插件在不同平台上的可用性,勾选表示启用", + "noAdapters": "未找到平台适配器", + "noAdaptersDesc": "请先在 平台管理 中添加并配置平台适配器,然后再设置插件的平台可用性", + "goPlatforms": "前往平台管理", + "selectAll": "全选", + "selectAllNormal": "全选普通插件", + "selectAllSystem": "全选系统插件", + "selectNone": "全不选", + "toggleAll": "反选" + }, + "config": { + "title": "插件配置", + "noConfig": "这个插件没有配置" + }, + "loading": { + "title": "加载中...", + "logs": "日志" + } + }, + "messages": { + "uninstalling": "正在卸载", + "refreshing": "正在刷新插件列表...", + "refreshSuccess": "插件列表已刷新!", + "refreshFailed": "刷新插件列表时发生错误", + "reloadSuccess": "重载成功", + "updateSuccess": "更新成功!", + "addSuccess": "添加成功!", + "saveSuccess": "保存成功!", + "deleteSuccess": "删除成功!", + "installing": "正在从文件安装插件", + "installingFromUrl": "正在从链接安装插件...", + "installFailed": "安装插件失败:", + "getPlatformConfigFailed": "获取平台插件配置失败:", + "savePlatformConfigFailed": "保存平台插件配置失败:", + "getMarketDataFailed": "获取插件市场数据失败:", + "hasUpdate": "有新版本:", + "confirmDelete": "确定要删除插件吗?", + "fillUrlOrFile": "请填写插件链接或上传插件文件", + "dontFillBoth": "请不要同时填写插件链接和上传插件文件" + }, + "upload": { + "fromFile": "从文件安装", + "fromUrl": "从链接安装", + "selectFile": "选择文件", + "enterUrl": "输入插件仓库链接" + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/zh-CN/features/platform.json b/dashboard/src/i18n/locales/zh-CN/features/platform.json new file mode 100644 index 000000000..0bcdf2820 --- /dev/null +++ b/dashboard/src/i18n/locales/zh-CN/features/platform.json @@ -0,0 +1,40 @@ +{ + "title": "平台适配器管理", + "subtitle": "管理机器人的平台适配器,连接到不同的聊天平台", + "adapters": "平台适配器", + "addAdapter": "新增适配器", + "emptyText": "暂无平台适配器,点击 新增适配器 添加", + "details": { + "adapterType": "适配器类型", + "token": "Token", + "description": "描述" + }, + "logs": { + "title": "平台日志", + "expand": "展开", + "collapse": "收起" + }, + "dialog": { + "add": "新增", + "edit": "编辑", + "adapter": "平台适配器", + "refresh": "刷新", + "cancel": "取消", + "save": "保存" + }, + "messages": { + "updateSuccess": "更新成功!", + "addSuccess": "添加成功!", + "deleteSuccess": "删除成功!", + "statusUpdateSuccess": "状态更新成功!", + "deleteConfirm": "确定要删除平台适配器" + }, + "status": { + "enabled": "已启用", + "disabled": "已禁用", + "connecting": "连接中", + "connected": "已连接", + "disconnected": "已断开", + "error": "错误" + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/zh-CN/features/provider.json b/dashboard/src/i18n/locales/zh-CN/features/provider.json new file mode 100644 index 000000000..d056f880f --- /dev/null +++ b/dashboard/src/i18n/locales/zh-CN/features/provider.json @@ -0,0 +1,82 @@ +{ + "title": "服务提供商管理", + "subtitle": "管理模型服务提供商", + "providers": { + "title": "服务提供商", + "settings": "设置", + "addProvider": "新增服务提供商", + "providerType": "提供商类型", + "tabs": { + "all": "全部", + "chatCompletion": "基本对话", + "speechToText": "语音转文字", + "textToSpeech": "文字转语音", + "embedding": "Embedding" + }, + "empty": { + "all": "暂无服务提供商,点击 新增服务提供商 添加", + "typed": "暂无{type}类型的服务提供商,点击 新增服务提供商 添加" + }, + "description": { + "openai": "{type} 服务提供商。同时也支持所有兼容 OpenAI API 的模型提供商。", + "default": "{type} 服务提供商" + } + }, + "availability": { + "title": "服务提供商可用性", + "subtitle": "通过测试模型对话可用性判断,可能产生API费用", + "refresh": "刷新状态", + "noData": "点击\"刷新状态\"按钮获取服务提供商可用性", + "available": "可用", + "unavailable": "不可用", + "errorMessage": "错误信息" + }, + "logs": { + "title": "服务日志", + "expand": "展开", + "collapse": "收起" + }, + "dialogs": { + "addProvider": { + "title": "服务提供商", + "tabs": { + "basic": "基本", + "speechToText": "语音转文字", + "textToSpeech": "文字转语音", + "embedding": "Embedding" + }, + "noTemplates": "暂无{type}类型的提供商模板" + }, + "config": { + "addTitle": "新增", + "editTitle": "编辑", + "provider": "服务提供商", + "cancel": "取消", + "save": "保存" + }, + "settings": { + "title": "服务提供商设置", + "sessionSeparation": { + "title": "启用提供商会话隔离", + "description": "不同会话将可独立选择文本生成、TTS、STT 等服务提供商。" + }, + "close": "关闭" + } + }, + "messages": { + "success": { + "update": "更新成功!", + "add": "添加成功!", + "delete": "删除成功!", + "statusUpdate": "状态更新成功!", + "sessionSeparation": "会话隔离设置已更新" + }, + "error": { + "sessionSeparation": "获取会话隔离配置失败", + "fetchStatus": "获取服务提供商状态失败" + }, + "confirm": { + "delete": "确定要删除服务提供商 {id} 吗?" + } + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/zh-CN/features/settings.json b/dashboard/src/i18n/locales/zh-CN/features/settings.json new file mode 100644 index 000000000..e925a02db --- /dev/null +++ b/dashboard/src/i18n/locales/zh-CN/features/settings.json @@ -0,0 +1,18 @@ +{ + "network": { + "title": "网络", + "githubProxy": { + "title": "GitHub 加速地址", + "subtitle": "设置下载插件或者更新 AstrBot 时所用的 GitHub 加速地址。这在中国大陆的网络环境有效。可以自定义,输入结果实时生效。所有地址均不保证稳定性,如果在更新插件/项目时出现报错,请首先检查加速地址是否能正常使用。", + "label": "选择 GitHub 加速地址" + } + }, + "system": { + "title": "系统", + "restart": { + "title": "重启", + "subtitle": "重启 AstrBot", + "button": "重启" + } + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/zh-CN/features/tool-use.json b/dashboard/src/i18n/locales/zh-CN/features/tool-use.json new file mode 100644 index 000000000..f44a16d59 --- /dev/null +++ b/dashboard/src/i18n/locales/zh-CN/features/tool-use.json @@ -0,0 +1,114 @@ +{ + "title": "函数工具管理", + "subtitle": "管理 MCP 服务器和查看可用的函数工具", + "tooltip": { + "info": "函数调用和 MCP 是什么?", + "marketplace": "浏览和安装来自社区的 MCP 服务器", + "serverConfig": "MCP 服务器(stdio)配置支持以下字段:\ncommand: 命令名称 (例如 python 或 uv)\nargs: 命令参数数组 (例如 [\"run\", \"server.py\"])\nenv: 环境变量对象 (例如 {\"api_key\": \"abc\"})\ncwd: 工作目录路径 (例如 /path/to/server)\nencoding: 输出编码 (默认 utf-8)\nencoding_error_handler: The text encoding error handler. Defaults to strict.\n其他字段请参考 MCP 文档\n⚠️ 如果您使用 Docker 部署 AstrBot, 请务必将 MCP 服务器装在 AstrBot 挂载好的 data 目录下" + }, + "tabs": { + "local": "本地服务器", + "marketplace": "MCP 市场" + }, + "mcpServers": { + "title": "MCP 服务器", + "buttons": { + "refresh": "刷新", + "add": "新增服务器", + "useTemplate": "使用模板" + }, + "empty": "暂无 MCP 服务器,点击 新增服务器 添加", + "status": { + "noTools": "无可用工具", + "availableTools": "可用工具", + "configSummary": "配置: {keys}", + "noConfig": "未设置配置" + } + }, + "functionTools": { + "title": "函数工具", + "buttons": { + "expand": "展开", + "collapse": "收起" + }, + "search": "搜索函数工具", + "empty": "没有可用的函数工具", + "description": "功能描述", + "parameters": "参数列表", + "noParameters": "此工具没有参数", + "table": { + "paramName": "参数名", + "type": "类型", + "description": "描述", + "required": "必填" + } + }, + "marketplace": { + "title": "MCP 服务器市场", + "search": "搜索服务器", + "buttons": { + "refresh": "刷新", + "detail": "详情", + "import": "导入" + }, + "loading": "正在加载 MCP 服务器市场...", + "empty": "暂无可用的 MCP 服务器", + "status": { + "availableTools": "可用工具 ({count})", + "noToolsInfo": "无可用工具信息" + } + }, + "dialogs": { + "addServer": { + "title": "新增 MCP 服务器", + "editTitle": "编辑 MCP 服务器", + "fields": { + "name": "服务器名称", + "nameRequired": "名称是必填项", + "enable": "启用服务器", + "config": "服务器配置" + }, + "configNotes": { + "note1": "1. 某些 MCP 服务器可能需要按照其要求在 env 中填充 `API_KEY` 或 `TOKEN` 等信息,请注意检查是否填写。", + "note2": "2. 当配置中指定 url 参数时:如果还同时指定 `transport` 参数的值为 `streamable_http`,则使用 Steamable HTTP,否则使用 SSE 连接。" + }, + "errors": { + "configEmpty": "配置不能为空", + "jsonFormat": "JSON 格式错误: {error}", + "jsonParse": "JSON 解析错误: {error}" + }, + "buttons": { + "cancel": "取消", + "save": "保存" + } + }, + "serverDetail": { + "title": "服务器详情", + "installConfig": "安装配置", + "availableTools": "可用工具", + "buttons": { + "close": "关闭", + "importConfig": "导入配置" + } + }, + "confirmDelete": "确定要删除服务器 {name} 吗?" + }, + "messages": { + "getServersError": "获取 MCP 服务器列表失败: {error}", + "getToolsError": "获取函数工具列表失败: {error}", + "saveSuccess": "保存成功!", + "saveError": "保存失败: {error}", + "deleteSuccess": "删除成功!", + "deleteError": "删除失败: {error}", + "updateSuccess": "更新成功!", + "updateError": "更新失败: {error}", + "getMarketError": "获取 MCP 市场服务器列表失败: {error}", + "importError": { + "noConfig": "此服务器没有可用配置", + "invalidFormat": "服务器配置格式不正确", + "failed": "导入配置失败: {error}" + }, + "configParseError": "配置解析错误: {error}", + "noAvailableConfig": "无可用配置" + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/zh-CN/messages/errors.json b/dashboard/src/i18n/locales/zh-CN/messages/errors.json new file mode 100644 index 000000000..655884313 --- /dev/null +++ b/dashboard/src/i18n/locales/zh-CN/messages/errors.json @@ -0,0 +1,39 @@ +{ + "network": { + "timeout": "网络请求超时,请稍后重试", + "connection": "网络连接失败,请检查网络状态", + "server": "服务器错误,请联系技术支持", + "unavailable": "服务暂不可用", + "forbidden": "访问被拒绝" + }, + "validation": { + "required": "此字段为必填项", + "invalid": "输入格式不正确", + "tooLong": "输入内容过长", + "tooShort": "输入内容过短", + "email": "请输入有效的邮箱地址", + "url": "请输入有效的URL地址", + "number": "请输入有效的数字" + }, + "auth": { + "unauthorized": "未授权访问,请重新登录", + "forbidden": "权限不足,无法执行此操作", + "tokenExpired": "登录已过期,请重新登录", + "invalidCredentials": "用户名或密码错误" + }, + "file": { + "uploadFailed": "文件上传失败", + "invalidFormat": "不支持的文件格式", + "tooLarge": "文件大小超出限制", + "notFound": "文件未找到" + }, + "operation": { + "failed": "操作失败", + "cancelled": "操作已取消", + "notSupported": "不支持此操作", + "conflict": "操作冲突,请稍后重试" + }, + "browser": { + "audioNotSupported": "您的浏览器不支持音频播放。" + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/zh-CN/messages/success.json b/dashboard/src/i18n/locales/zh-CN/messages/success.json new file mode 100644 index 000000000..0f7ecfc35 --- /dev/null +++ b/dashboard/src/i18n/locales/zh-CN/messages/success.json @@ -0,0 +1,23 @@ +{ + "operation": { + "saved": "保存成功", + "created": "创建成功", + "updated": "更新成功", + "deleted": "删除成功", + "uploaded": "上传成功", + "downloaded": "下载成功", + "imported": "导入成功", + "exported": "导出成功", + "copied": "复制成功", + "sent": "发送成功" + }, + "connection": { + "connected": "连接成功", + "authenticated": "登录成功", + "synchronized": "同步成功" + }, + "validation": { + "valid": "验证通过", + "completed": "操作完成" + } +} \ No newline at end of file diff --git a/dashboard/src/i18n/locales/zh-CN/messages/validation.json b/dashboard/src/i18n/locales/zh-CN/messages/validation.json new file mode 100644 index 000000000..ddd6d1ab6 --- /dev/null +++ b/dashboard/src/i18n/locales/zh-CN/messages/validation.json @@ -0,0 +1,24 @@ +{ + "required": "此字段为必填项", + "email": "请输入有效的邮箱地址", + "url": "请输入有效的URL地址", + "number": "请输入有效的数字", + "min": "最小值为 {min}", + "max": "最大值为 {max}", + "minLength": "至少需要 {length} 个字符", + "maxLength": "最多允许 {length} 个字符", + "pattern": "格式不正确", + "unique": "该值已存在", + "confirm": "两次输入不一致", + "fileSize": "文件大小不能超过 {size}MB", + "fileType": "不支持的文件类型", + "required_field": "请填写必填字段", + "invalid_format": "格式无效", + "password_too_short": "密码至少需要8个字符", + "password_too_weak": "密码强度太弱", + "invalid_phone": "请输入有效的手机号码", + "invalid_date": "请输入有效的日期", + "date_range": "日期范围无效", + "upload_failed": "文件上传失败", + "network_error": "网络连接错误,请重试" +} \ No newline at end of file diff --git a/dashboard/src/i18n/tools/index.ts b/dashboard/src/i18n/tools/index.ts new file mode 100644 index 000000000..f62267ce0 --- /dev/null +++ b/dashboard/src/i18n/tools/index.ts @@ -0,0 +1,33 @@ +// 导出核心组件 +export { I18nValidator } from '../validator'; +export { I18nLoader } from '../loader'; +export type * from '../types'; + +// 实用工具函数 +export function generateMissingKeys( + sourceTranslations: Record, + targetTranslations: Record +): string[] { + const missing: string[] = []; + + function traverse(source: any, target: any, path: string = '') { + for (const key in source) { + const currentPath = path ? `${path}.${key}` : key; + + if (typeof source[key] === 'object' && source[key] !== null) { + if (!target[key]) { + missing.push(currentPath); + } else { + traverse(source[key], target[key], currentPath); + } + } else { + if (!(key in target)) { + missing.push(currentPath); + } + } + } + } + + traverse(sourceTranslations, targetTranslations); + return missing; +} \ No newline at end of file diff --git a/dashboard/src/i18n/types.ts b/dashboard/src/i18n/types.ts new file mode 100644 index 000000000..390c45f8c --- /dev/null +++ b/dashboard/src/i18n/types.ts @@ -0,0 +1,366 @@ +/** + * I18n TypeScript Type Definitions + * 国际化类型定义,确保类型安全 + */ + +// 核心模块类型定义 +export interface CoreTranslations { + common: { + save: string; + cancel: string; + close: string; + delete: string; + edit: string; + add: string; + confirm: string; + loading: string; + success: string; + error: string; + warning: string; + info: string; + name: string; + description: string; + author: string; + status: string; + actions: string; + enable: string; + disable: string; + enabled: string; + disabled: string; + reload: string; + configure: string; + install: string; + uninstall: string; + update: string; + language: string; + }; + actions: { + create: string; + read: string; + update: string; + delete: string; + search: string; + filter: string; + sort: string; + export: string; + import: string; + backup: string; + restore: string; + }; + status: { + loading: string; + success: string; + error: string; + warning: string; + info: string; + pending: string; + processing: string; + completed: string; + failed: string; + cancelled: string; + }; + navigation: { + dashboard: string; + platforms: string; + providers: string; + toolUse: string; + config: string; + extension: string; + chat: string; + conversation: string; + console: string; + alkaid: string; + about: string; + settings: string; + documentation: string; + github: string; + drag: string; + }; +} + +// 功能模块类型定义 +export interface FeatureTranslations { + chat: { + title: string; + subtitle: string; + input: { + placeholder: string; + send: string; + clear: string; + }; + message: { + user: string; + assistant: string; + system: string; + }; + voice: { + start: string; + stop: string; + recording: string; + }; + }; + extension: { + title: string; + subtitle: string; + showSystemPlugins: string; + hideSystemPlugins: string; + platformCommandConfig: string; + noPlugins: string; + tryInstallOrShowSystem: string; + configDialog: { + title: string; + noConfig: string; + }; + platformConfig: { + title: string; + description: string; + noPlatforms: string; + addPlatformFirst: string; + goToPlatformManagement: string; + }; + marketplace: { + title: string; + installPlugin: string; + fromGitHub: string; + fromLocal: string; + repoUrl: string; + selectFile: string; + pluginDevelopmentDoc: string; + submitPluginRepo: string; + }; + }; + conversation: { + title: string; + subtitle: string; + table: { + id: string; + platform: string; + user: string; + message: string; + time: string; + actions: string; + }; + filter: { + platform: string; + user: string; + dateRange: string; + }; + export: { + title: string; + format: string; + range: string; + }; + }; + provider: { + title: string; + tabTypes: { + chat_completion: string; + speech_to_text: string; + text_to_speech: string; + embedding: string; + }; + openaiDescription: string; + defaultDescription: string; + }; + platform: { + title: string; + subtitle: string; + adapters: string; + addAdapter: string; + }; + config: { + title: string; + subtitle: string; + sections: { + general: string; + advanced: string; + security: string; + }; + }; + console: { + title: string; + subtitle: string; + clear: string; + download: string; + }; + about: { + title: string; + version: string; + author: string; + license: string; + repository: string; + }; + alkaid: { + comingSoon: string; + knowledgeBase: { + title: string; + subtitle: string; + }; + memory: { + title: string; + subtitle: string; + }; + }; +} + +// 消息模块类型定义 +export interface MessageTranslations { + errors: { + network: { + timeout: string; + connection: string; + server: string; + }; + validation: { + required: string; + invalid: string; + tooLong: string; + tooShort: string; + }; + auth: { + unauthorized: string; + forbidden: string; + tokenExpired: string; + }; + }; + success: { + save: { + completed: string; + config: string; + settings: string; + }; + action: { + created: string; + updated: string; + deleted: string; + }; + }; + validation: { + required: string; + email: string; + url: string; + number: string; + min: string; + max: string; + }; +} + +// 完整的翻译类型 +export interface TranslationSchema extends CoreTranslations, FeatureTranslations, MessageTranslations {} + +// 翻译键类型 +export type TranslationKey = + // Core keys + | `core.common.${keyof CoreTranslations['common']}` + | `core.actions.${keyof CoreTranslations['actions']}` + | `core.status.${keyof CoreTranslations['status']}` + | `core.navigation.${keyof CoreTranslations['navigation']}` + + // Feature keys + | `features.chat.${keyof FeatureTranslations['chat'] | `input.${keyof FeatureTranslations['chat']['input']}` | `message.${keyof FeatureTranslations['chat']['message']}` | `voice.${keyof FeatureTranslations['chat']['voice']}`}` + | `features.extension.${keyof FeatureTranslations['extension'] | `configDialog.${keyof FeatureTranslations['extension']['configDialog']}` | `platformConfig.${keyof FeatureTranslations['extension']['platformConfig']}` | `marketplace.${keyof FeatureTranslations['extension']['marketplace']}`}` + | `features.conversation.${keyof FeatureTranslations['conversation'] | `table.${keyof FeatureTranslations['conversation']['table']}` | `filter.${keyof FeatureTranslations['conversation']['filter']}` | `export.${keyof FeatureTranslations['conversation']['export']}`}` + | `features.provider.${keyof FeatureTranslations['provider'] | `tabTypes.${keyof FeatureTranslations['provider']['tabTypes']}`}` + | `features.platform.${keyof FeatureTranslations['platform']}` + | `features.config.${keyof FeatureTranslations['config'] | `sections.${keyof FeatureTranslations['config']['sections']}`}` + | `features.console.${keyof FeatureTranslations['console']}` + | `features.about.${keyof FeatureTranslations['about']}` + | `features.alkaid.${keyof FeatureTranslations['alkaid'] | `knowledgeBase.${keyof FeatureTranslations['alkaid']['knowledgeBase']}` | `memory.${keyof FeatureTranslations['alkaid']['memory']}`}` + + // Message keys + | `messages.errors.${keyof MessageTranslations['errors'] | `network.${keyof MessageTranslations['errors']['network']}` | `validation.${keyof MessageTranslations['errors']['validation']}` | `auth.${keyof MessageTranslations['errors']['auth']}`}` + | `messages.success.${keyof MessageTranslations['success'] | `save.${keyof MessageTranslations['success']['save']}` | `action.${keyof MessageTranslations['success']['action']}`}` + | `messages.validation.${keyof MessageTranslations['validation']}`; + +// 语言环境类型 +export type Locale = 'zh-CN' | 'en-US'; + +// 翻译函数类型 +export type TranslationFunction = { + (key: TranslationKey): string; + (key: TranslationKey, params: Record): string; +}; + +// 模块加载状态 +export interface ModuleLoadingState { + core: boolean; + features: boolean; + messages: boolean; +} + +// 翻译配置 +export interface I18nConfig { + locale: Locale; + fallbackLocale: Locale; + lazy: boolean; + preload: string[]; + caching: boolean; + devMode: boolean; +} + +// 验证结果 +export interface ValidationResult { + isValid: boolean; + missingKeys: string[]; + extraKeys: string[]; + errors: ValidationError[]; +} + +export interface ValidationError { + type: 'missing' | 'extra' | 'type_mismatch' | 'empty_value'; + key: string; + message: string; + severity: 'error' | 'warning'; +} + +// 使用情况报告 +export interface UsageReport { + unusedKeys: string[]; + undefinedKeys: string[]; + coverage: number; + totalKeys: number; + usedKeys: number; +} + +// 翻译统计信息 +export interface TranslationStats { + modules: { + [moduleName: string]: { + keys: number; + coverage: number; + lastUpdated: string; + }; + }; + locales: { + [locale: string]: { + totalKeys: number; + translatedKeys: number; + coverage: number; + }; + }; + overall: { + totalKeys: number; + averageCoverage: number; + lastSync: string; + }; +} + +// 开发工具类型 +export interface DevToolsData { + currentLocale: Locale; + loadedModules: string[]; + cacheStats: { + size: number; + hits: number; + misses: number; + }; + performance: { + loadTime: number; + renderTime: number; + }; +} + +// 导出类型声明模块 +declare module 'vue-i18n' { + export interface DefineLocaleMessage extends TranslationSchema {} +} \ No newline at end of file diff --git a/dashboard/src/i18n/validator.ts b/dashboard/src/i18n/validator.ts new file mode 100644 index 000000000..462be1ec1 --- /dev/null +++ b/dashboard/src/i18n/validator.ts @@ -0,0 +1,441 @@ +/** + * I18n Validator + * 国际化验证器,用于检查翻译完整性、使用情况分析和错误检测 + */ + +import type { ValidationResult, ValidationError, UsageReport, TranslationStats } from './types'; + +export class I18nValidator { + private baseLocale: string = 'zh-CN'; + private supportedLocales: string[] = ['zh-CN', 'en-US']; + + /** + * 验证翻译完整性 + */ + validateCompleteness(localeData: Record): ValidationResult { + const errors: ValidationError[] = []; + const missingKeys: string[] = []; + const extraKeys: string[] = []; + + // 获取基准语言数据 + const baseData = localeData[this.baseLocale]; + if (!baseData) { + errors.push({ + type: 'missing', + key: this.baseLocale, + message: `基准语言 ${this.baseLocale} 数据缺失`, + severity: 'error' + }); + return { isValid: false, missingKeys, extraKeys, errors }; + } + + // 获取所有键 + const baseKeys = this.getAllKeys(baseData); + + // 验证每种语言 + for (const locale of this.supportedLocales) { + if (locale === this.baseLocale) continue; + + const targetData = localeData[locale]; + if (!targetData) { + errors.push({ + type: 'missing', + key: locale, + message: `语言 ${locale} 数据缺失`, + severity: 'error' + }); + continue; + } + + const targetKeys = this.getAllKeys(targetData); + + // 检查缺失的键 + const missing = baseKeys.filter(key => !targetKeys.includes(key)); + missingKeys.push(...missing.map(key => `${locale}.${key}`)); + + // 检查多余的键 + const extra = targetKeys.filter(key => !baseKeys.includes(key)); + extraKeys.push(...extra.map(key => `${locale}.${key}`)); + + // 添加详细错误信息 + missing.forEach(key => { + errors.push({ + type: 'missing', + key: `${locale}.${key}`, + message: `${locale} 中缺失键: ${key}`, + severity: 'error' + }); + }); + + extra.forEach(key => { + errors.push({ + type: 'extra', + key: `${locale}.${key}`, + message: `${locale} 中存在多余键: ${key}`, + severity: 'warning' + }); + }); + } + + return { + isValid: errors.filter(e => e.severity === 'error').length === 0, + missingKeys, + extraKeys, + errors + }; + } + + /** + * 验证翻译值的有效性 + */ + validateValues(localeData: Record): ValidationError[] { + const errors: ValidationError[] = []; + + for (const [locale, data] of Object.entries(localeData)) { + this.validateNestedValues(data, locale, '', errors); + } + + return errors; + } + + /** + * 递归验证嵌套值 + */ + private validateNestedValues( + obj: any, + locale: string, + parentKey: string, + errors: ValidationError[] + ): void { + for (const [key, value] of Object.entries(obj)) { + const fullKey = parentKey ? `${parentKey}.${key}` : key; + + if (typeof value === 'object' && value !== null) { + this.validateNestedValues(value, locale, fullKey, errors); + } else if (typeof value === 'string') { + // 检查空值 + if (!value.trim()) { + errors.push({ + type: 'empty_value', + key: `${locale}.${fullKey}`, + message: `空翻译值: ${locale}.${fullKey}`, + severity: 'warning' + }); + } + + // 检查插值占位符 + const placeholders = value.match(/\{[^}]+\}/g) || []; + for (const placeholder of placeholders) { + if (!/^{[a-zA-Z_][a-zA-Z0-9_]*}$/.test(placeholder)) { + errors.push({ + type: 'type_mismatch', + key: `${locale}.${fullKey}`, + message: `无效的插值占位符: ${placeholder} in ${locale}.${fullKey}`, + severity: 'warning' + }); + } + } + } else { + errors.push({ + type: 'type_mismatch', + key: `${locale}.${fullKey}`, + message: `翻译值应为字符串,实际为: ${typeof value}`, + severity: 'error' + }); + } + } + } + + /** + * 分析翻译使用情况 + */ + validateUsage(translationKeys: string[], usedKeys: string[]): UsageReport { + const unusedKeys = translationKeys.filter(key => !usedKeys.includes(key)); + const undefinedKeys = usedKeys.filter(key => !translationKeys.includes(key)); + + return { + unusedKeys, + undefinedKeys, + coverage: (usedKeys.length / translationKeys.length) * 100, + totalKeys: translationKeys.length, + usedKeys: usedKeys.length + }; + } + + /** + * 生成翻译统计信息 + */ + generateStats(localeData: Record): TranslationStats { + const stats: TranslationStats = { + modules: {}, + locales: {}, + overall: { + totalKeys: 0, + averageCoverage: 0, + lastSync: new Date().toISOString() + } + }; + + // 分析每种语言 + for (const [locale, data] of Object.entries(localeData)) { + const keys = this.getAllKeys(data); + const translatedKeys = keys.filter(key => { + const value = this.getValueByKey(data, key); + return typeof value === 'string' && value.trim() !== ''; + }); + + stats.locales[locale] = { + totalKeys: keys.length, + translatedKeys: translatedKeys.length, + coverage: (translatedKeys.length / keys.length) * 100 + }; + + // 分析模块 + this.analyzeModules(data, locale, stats.modules); + } + + // 计算总体统计 + const locales = Object.values(stats.locales); + stats.overall.totalKeys = Math.max(...locales.map(l => l.totalKeys)); + stats.overall.averageCoverage = locales.reduce((sum, l) => sum + l.coverage, 0) / locales.length; + + return stats; + } + + /** + * 分析模块统计 + */ + private analyzeModules(data: any, locale: string, modules: TranslationStats['modules']): void { + for (const [moduleName, moduleData] of Object.entries(data)) { + if (typeof moduleData === 'object' && moduleData !== null) { + const moduleKey = `${locale}.${moduleName}`; + const keys = this.getAllKeys(moduleData); + const translatedKeys = keys.filter(key => { + const value = this.getValueByKey(moduleData, key); + return typeof value === 'string' && value.trim() !== ''; + }); + + if (!modules[moduleKey]) { + modules[moduleKey] = { + keys: 0, + coverage: 0, + lastUpdated: new Date().toISOString() + }; + } + + modules[moduleKey].keys = keys.length; + modules[moduleKey].coverage = (translatedKeys.length / keys.length) * 100; + } + } + } + + /** + * 获取对象的所有键路径 + */ + private getAllKeys(obj: any, prefix: string = ''): string[] { + const keys: string[] = []; + + for (const [key, value] of Object.entries(obj)) { + const fullKey = prefix ? `${prefix}.${key}` : key; + + if (typeof value === 'object' && value !== null) { + keys.push(...this.getAllKeys(value, fullKey)); + } else { + keys.push(fullKey); + } + } + + return keys; + } + + /** + * 根据键路径获取值 + */ + private getValueByKey(obj: any, keyPath: string): any { + return keyPath.split('.').reduce((current, key) => { + return current && current[key]; + }, obj); + } + + /** + * 检查插值一致性 + */ + validateInterpolation(localeData: Record): ValidationError[] { + const errors: ValidationError[] = []; + const baseData = localeData[this.baseLocale]; + + if (!baseData) return errors; + + const baseKeys = this.getAllKeys(baseData); + + for (const key of baseKeys) { + const baseValue = this.getValueByKey(baseData, key); + if (typeof baseValue !== 'string') continue; + + const basePlaceholders = (baseValue.match(/\{[^}]+\}/g) || []).sort(); + + for (const locale of this.supportedLocales) { + if (locale === this.baseLocale) continue; + + const targetData = localeData[locale]; + if (!targetData) continue; + + const targetValue = this.getValueByKey(targetData, key); + if (typeof targetValue !== 'string') continue; + + const targetPlaceholders = (targetValue.match(/\{[^}]+\}/g) || []).sort(); + + if (JSON.stringify(basePlaceholders) !== JSON.stringify(targetPlaceholders)) { + errors.push({ + type: 'type_mismatch', + key: `${locale}.${key}`, + message: `插值占位符不匹配: ${locale}.${key},期望 ${basePlaceholders.join(', ')},实际 ${targetPlaceholders.join(', ')}`, + severity: 'error' + }); + } + } + } + + return errors; + } + + /** + * 验证键命名规范 + */ + validateKeyNaming(localeData: Record): ValidationError[] { + const errors: ValidationError[] = []; + const keyNamingPattern = /^[a-z][a-zA-Z0-9]*$/; + + for (const [locale, data] of Object.entries(localeData)) { + this.validateKeyNamingRecursive(data, locale, '', keyNamingPattern, errors); + } + + return errors; + } + + /** + * 递归验证键命名 + */ + private validateKeyNamingRecursive( + obj: any, + locale: string, + parentKey: string, + pattern: RegExp, + errors: ValidationError[] + ): void { + for (const key of Object.keys(obj)) { + const fullKey = parentKey ? `${parentKey}.${key}` : key; + + if (!pattern.test(key)) { + errors.push({ + type: 'type_mismatch', + key: `${locale}.${fullKey}`, + message: `键名不符合命名规范: ${key},应使用小驼峰命名`, + severity: 'warning' + }); + } + + if (typeof obj[key] === 'object' && obj[key] !== null) { + this.validateKeyNamingRecursive(obj[key], locale, fullKey, pattern, errors); + } + } + } + + /** + * 验证多个语言包 + */ + async validateLocales(locales: string[]): Promise<{ + summary: { + totalLocales: number; + totalKeys: number; + missingKeys: number; + emptyValues: number; + invalidInterpolations: number; + completeness: number; + }; + details: ValidationResult[]; + recommendations: string[]; + }> { + const results: ValidationResult[] = []; + + for (const locale of locales) { + try { + // 这里应该从实际的翻译文件中加载,暂时创建基本结构 + const localeData = { [locale]: {} }; + const result = this.validateCompleteness(localeData); + results.push(result); + } catch (error) { + console.error(`验证语言包 ${locale} 时出错:`, error); + // 创建错误结果 + const errorResult: ValidationResult = { + isValid: false, + missingKeys: [], + extraKeys: [], + errors: [ + { + type: 'missing', + key: locale, + message: error instanceof Error ? error.message : '未知错误', + severity: 'error' + } + ] + }; + results.push(errorResult); + } + } + + // 生成汇总报告 + const totalKeys = results.length * 100; // 估算的总键数 + const missingKeys = results.reduce((sum, r) => sum + r.missingKeys.length, 0); + + return { + summary: { + totalLocales: results.length, + totalKeys, + missingKeys, + emptyValues: 0, // 暂时设为0 + invalidInterpolations: 0, // 暂时设为0 + completeness: totalKeys > 0 ? ((totalKeys - missingKeys) / totalKeys) * 100 : 100 + }, + details: results, + recommendations: [ + '建议优先翻译核心模块的缺失键', + '检查所有空值并提供适当的翻译', + '确保插值占位符在所有语言中保持一致' + ] + }; + } + + /** + * 生成验证报告 + */ + generateReport(localeData: Record, usedKeys: string[] = []): { + completeness: ValidationResult; + values: ValidationError[]; + interpolation: ValidationError[]; + naming: ValidationError[]; + usage: UsageReport | null; + stats: TranslationStats; + } { + const completeness = this.validateCompleteness(localeData); + const values = this.validateValues(localeData); + const interpolation = this.validateInterpolation(localeData); + const naming = this.validateKeyNaming(localeData); + const stats = this.generateStats(localeData); + + let usage: UsageReport | null = null; + if (usedKeys.length > 0) { + const allKeys = this.getAllKeys(localeData[this.baseLocale] || {}); + usage = this.validateUsage(allKeys, usedKeys); + } + + return { + completeness, + values, + interpolation, + naming, + usage, + stats + }; + } +} \ No newline at end of file diff --git a/dashboard/src/layouts/full/vertical-header/VerticalHeader.vue b/dashboard/src/layouts/full/vertical-header/VerticalHeader.vue index e4d7e5a11..6f6f84c46 100644 --- a/dashboard/src/layouts/full/vertical-header/VerticalHeader.vue +++ b/dashboard/src/layouts/full/vertical-header/VerticalHeader.vue @@ -8,8 +8,10 @@ import {md5} from 'js-md5'; import {useAuthStore} from '@/stores/auth'; import {useCommonStore} from '@/stores/common'; import {marked} from 'marked'; +import { useI18n } from '@/i18n/composables'; const customizer = useCustomizerStore(); +const { t } = useI18n(); let dialog = ref(false); let accountWarning = ref(false) let updateStatusDialog = ref(false); @@ -32,23 +34,23 @@ let installLoading = ref(false); let tab = ref(0); -let releasesHeader = [ - {title: '标签', key: 'tag_name'}, - {title: '发布时间', key: 'published_at'}, - {title: '内容', key: 'body'}, - {title: '源码地址', key: 'zipball_url'}, - {title: '操作', key: 'switch'} -]; +const releasesHeader = computed(() => [ + {title: t('core.header.updateDialog.table.tag'), key: 'tag_name'}, + {title: t('core.header.updateDialog.table.publishDate'), key: 'published_at'}, + {title: t('core.header.updateDialog.table.content'), key: 'body'}, + {title: t('core.header.updateDialog.table.sourceUrl'), key: 'zipball_url'}, + {title: t('core.header.updateDialog.table.actions'), key: 'switch'} +]); // Form validation const formValid = ref(true); -const passwordRules = [ - (v: string) => !!v || '请输入密码', - (v: string) => v.length >= 8 || '密码长度至少 8 位' -]; -const usernameRules = [ - (v: string) => !v || v.length >= 3 || '用户名长度至少3位' -]; +const passwordRules = computed(() => [ + (v: string) => !!v || t('core.header.accountDialog.validation.passwordRequired'), + (v: string) => v.length >= 8 || t('core.header.accountDialog.validation.passwordMinLength') +]); +const usernameRules = computed(() => [ + (v: string) => !v || v.length >= 3 || t('core.header.accountDialog.validation.usernameMinLength') +]); // 显示密码相关 const showPassword = ref(false); @@ -104,7 +106,7 @@ function accountEdit() { .catch((err) => { console.log(err); accountEditStatus.value.error = true; - accountEditStatus.value.message = typeof err === 'string' ? err : '修改失败,请重试'; + accountEditStatus.value.message = typeof err === 'string' ? err : t('core.header.accountDialog.messages.updateFailed'); password.value = ''; newPassword.value = ''; }) @@ -133,14 +135,14 @@ function getVersion() { } function checkUpdate() { - updateStatus.value = '正在检查更新...'; + updateStatus.value = t('core.header.updateDialog.status.checking'); axios.get('/api/update/check') .then((res) => { hasNewVersion.value = res.data.data.has_new_version; if (res.data.data.has_new_version) { releaseMessage.value = res.data.message; - updateStatus.value = '有新版本!'; + updateStatus.value = t('core.header.version.hasNewVersion'); } else { updateStatus.value = res.data.message; } @@ -192,7 +194,7 @@ function getDevCommits() { } function switchVersion(version: string) { - updateStatus.value = '正在切换版本...'; + updateStatus.value = t('core.header.updateDialog.status.switching'); installLoading.value = true; axios.post('/api/update/do', { version: version, @@ -215,7 +217,7 @@ function switchVersion(version: string) { } function updateDashboard() { - updateStatus.value = '正在更新...'; + updateStatus.value = t('core.header.updateDialog.status.updating'); axios.post('/api/update/dashboard') .then((res) => { updateStatus.value = res.data.message; @@ -274,15 +276,15 @@ commonStore.getStartTime(); - + mdi-update - + - 更新 AstrBot + {{ t('core.header.updateDialog.title') }} mdi-close @@ -322,16 +324,14 @@ commonStore.getStartTime();
- 💡 TIP: 跳到旧版本或者切换到某个版本不会重新下载管理面板文件,这可能会造成部分数据显示错误。您可在 此处 - 找到对应的面板文件 dist.zip,解压后替换 data/dist 文件夹即可。当然,前端源代码在 dashboard 目录下,你也可以自己使用 - npm install 和 npm build - 构建。 + {{ t('core.header.updateDialog.tip') }} {{ t('core.header.updateDialog.tipLink') }} + {{ t('core.header.updateDialog.tipContinue') }}
- 😊 正式版 - 🧐 开发版(master 分支) + {{ t('core.header.updateDialog.tabs.release') }} + {{ t('core.header.updateDialog.tabs.dev') }} @@ -339,25 +339,24 @@ commonStore.getStartTime(); - 更新到最新版本 + {{ t('core.header.updateDialog.updateToLatest') }}
- `更新到最新版本` 按钮会同时尝试更新机器人主程序和管理面板。如果您正在使用 Docker - 部署,也可以重新拉取镜像或者使用 watchtower 来自动监控拉取。 + {{ t('core.header.updateDialog.dockerTip') }} {{ t('core.header.updateDialog.dockerTipLink') }} {{ t('core.header.updateDialog.dockerTipContinue') }}
@@ -367,11 +366,16 @@ commonStore.getStartTime();
@@ -380,42 +384,40 @@ commonStore.getStartTime(); -

手动输入版本号或 Commit SHA

+

{{ t('core.header.updateDialog.manualInput.title') }}

-
- 如 v3.3.16 (不带 SHA) 或 42e5ec5d80b93b6bfe8b566754d45ffac4c3fe0b + {{ t('core.header.updateDialog.manualInput.hint') }}
- 查看 master 分支提交记录(点击右边的 - copy - 即可复制) + {{ t('core.header.updateDialog.manualInput.linkText') }}
- 确定切换 + {{ t('core.header.updateDialog.manualInput.confirm') }}
-

单独更新管理面板到最新版本

+

{{ t('core.header.updateDialog.dashboardUpdate.title') }}

- 当前版本 {{ dashboardCurrentVersion }} + {{ t('core.header.updateDialog.dashboardUpdate.currentVersion') }} {{ dashboardCurrentVersion }}

- 有新版本! + {{ t('core.header.updateDialog.dashboardUpdate.hasNewVersion') }}

- 已经是最新版本了。 + {{ t('core.header.updateDialog.dashboardUpdate.isLatest') }}

- 下载并更新 + {{ t('core.header.updateDialog.dashboardUpdate.downloadAndUpdate') }}
@@ -423,7 +425,7 @@ commonStore.getStartTime(); - 关闭 + {{ t('core.common.close') }} @@ -434,13 +436,13 @@ commonStore.getStartTime(); diff --git a/dashboard/src/layouts/full/vertical-sidebar/NavItem.vue b/dashboard/src/layouts/full/vertical-sidebar/NavItem.vue index 0ce59c92e..c81b107df 100644 --- a/dashboard/src/layouts/full/vertical-sidebar/NavItem.vue +++ b/dashboard/src/layouts/full/vertical-sidebar/NavItem.vue @@ -1,6 +1,8 @@ - 语音转文本 + {{ tm('conversation.speechToText') }}
@@ -119,7 +101,7 @@ const props = defineProps({ mdi-delete - 删除此对话 + {{ tm('actions.deleteChat') }} @@ -131,19 +113,19 @@ const props = defineProps({
-

{{ getCurrentConversation.title || '新对话' }}

+

{{ getCurrentConversation.title || tm('conversation.newConversation') }}

{{ formatDate(getCurrentConversation.updated_at) }}
- + - + - +