✨ feat: 多语言国际化支持
This commit is contained in:
@@ -28,6 +28,7 @@
|
||||
"marked": "^15.0.7",
|
||||
"pinia": "2.1.6",
|
||||
"remixicon": "3.5.0",
|
||||
"vue-i18n": "^9.8.0",
|
||||
"vee-validate": "4.11.3",
|
||||
"vite-plugin-vuetify": "1.0.2",
|
||||
"vue": "3.3.4",
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
<template>
|
||||
<v-menu>
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn
|
||||
v-bind="props"
|
||||
variant="text"
|
||||
icon
|
||||
size="small"
|
||||
class="language-switcher"
|
||||
>
|
||||
<v-icon>mdi-translate</v-icon>
|
||||
<v-tooltip activator="parent" location="bottom">
|
||||
{{ $t('common.language') }}
|
||||
</v-tooltip>
|
||||
</v-btn>
|
||||
</template>
|
||||
|
||||
<v-list density="compact" min-width="140">
|
||||
<v-list-item
|
||||
v-for="lang in languages"
|
||||
:key="lang.code"
|
||||
:value="lang.code"
|
||||
@click="changeLanguage(lang.code)"
|
||||
:class="{ 'v-list-item--active': currentLocale === lang.code }"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
<span class="language-flag">{{ lang.flag }}</span>
|
||||
</template>
|
||||
<v-list-item-title>{{ lang.name }}</v-list-item-title>
|
||||
<template v-slot:append v-if="currentLocale === lang.code">
|
||||
<v-icon color="primary" size="small">mdi-check</v-icon>
|
||||
</template>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const { locale } = useI18n()
|
||||
|
||||
const languages = [
|
||||
{ code: 'zh-CN', name: '简体中文', flag: '🇨🇳' },
|
||||
{ code: 'en-US', name: 'English', flag: '🇺🇸' }
|
||||
]
|
||||
|
||||
const currentLocale = computed(() => locale.value)
|
||||
|
||||
const changeLanguage = (langCode: string) => {
|
||||
locale.value = langCode
|
||||
localStorage.setItem('locale', langCode)
|
||||
|
||||
// 可选:刷新页面以确保所有文本都更新
|
||||
// window.location.reload()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.language-flag {
|
||||
font-size: 16px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.language-switcher {
|
||||
margin: 0 4px;
|
||||
}
|
||||
</style>
|
||||
@@ -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
|
||||
@@ -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!"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
{
|
||||
"sidebar": {
|
||||
"dashboard": "统计",
|
||||
"platforms": "消息平台",
|
||||
"providers": "服务提供商",
|
||||
"toolUse": "MCP",
|
||||
"config": "配置文件",
|
||||
"extension": "插件管理",
|
||||
"extensionMarketplace": "插件市场",
|
||||
"chat": "聊天",
|
||||
"conversation": "对话数据库",
|
||||
"console": "控制台",
|
||||
"alkaid": "Alkaid",
|
||||
"about": "关于",
|
||||
"settings": "设置",
|
||||
"documentation": "官方文档",
|
||||
"github": "GitHub",
|
||||
"drag": "拖拽"
|
||||
},
|
||||
"common": {
|
||||
"save": "保存",
|
||||
"cancel": "取消",
|
||||
"close": "关闭",
|
||||
"delete": "删除",
|
||||
"edit": "编辑",
|
||||
"add": "添加",
|
||||
"confirm": "确认",
|
||||
"loading": "加载中...",
|
||||
"success": "成功",
|
||||
"error": "错误",
|
||||
"warning": "警告",
|
||||
"info": "信息",
|
||||
"name": "名称",
|
||||
"description": "描述",
|
||||
"author": "作者",
|
||||
"status": "状态",
|
||||
"actions": "操作",
|
||||
"enable": "启用",
|
||||
"disable": "禁用",
|
||||
"enabled": "已启用",
|
||||
"disabled": "已禁用",
|
||||
"reload": "重载",
|
||||
"configure": "配置",
|
||||
"install": "安装",
|
||||
"uninstall": "卸载",
|
||||
"update": "更新",
|
||||
"language": "语言"
|
||||
},
|
||||
"extension": {
|
||||
"title": "已安装的插件",
|
||||
"subtitle": "管理已经安装的所有插件",
|
||||
"showSystemPlugins": "显示系统插件",
|
||||
"hideSystemPlugins": "隐藏系统插件",
|
||||
"platformCommandConfig": "平台命令配置",
|
||||
"noPlugins": "暂无插件",
|
||||
"tryInstallOrShowSystem": "尝试安装插件或者显示系统插件",
|
||||
"configDialog": {
|
||||
"title": "插件配置",
|
||||
"noConfig": "这个插件没有配置"
|
||||
},
|
||||
"platformConfig": {
|
||||
"title": "平台命令可用性配置",
|
||||
"description": "设置每个插件在不同平台上的可用性,勾选表示启用",
|
||||
"noPlatforms": "未找到平台适配器",
|
||||
"addPlatformFirst": "请先在 平台管理 中添加并配置平台适配器,然后再设置插件的平台可用性",
|
||||
"goToPlatformManagement": "前往平台管理"
|
||||
}
|
||||
},
|
||||
"extensionMarketplace": {
|
||||
"title": "插件市场",
|
||||
"installPlugin": "安装插件",
|
||||
"fromGitHub": "从 GitHub 上在线下载",
|
||||
"fromLocal": "从本机上传 .zip 压缩包",
|
||||
"repoUrl": "仓库链接",
|
||||
"selectFile": "选择文件",
|
||||
"pluginDevelopmentDoc": "插件开发文档",
|
||||
"submitPluginRepo": "提交插件仓库"
|
||||
},
|
||||
"platform": {
|
||||
"title": "平台适配器管理",
|
||||
"subtitle": "管理机器人的平台适配器,连接到不同的聊天平台",
|
||||
"adapters": "平台适配器",
|
||||
"addAdapter": "新增适配器"
|
||||
},
|
||||
"provider": {
|
||||
"title": "服务提供商",
|
||||
"tabTypes": {
|
||||
"chat_completion": "基本对话",
|
||||
"speech_to_text": "语音转文本",
|
||||
"text_to_speech": "文本转语音",
|
||||
"embedding": "Embedding"
|
||||
},
|
||||
"openaiDescription": "{type} 服务提供商。同时也支持所有兼容 OpenAI API 的模型提供商。",
|
||||
"defaultDescription": "{type} 服务提供商"
|
||||
},
|
||||
"auth": {
|
||||
"login": "登录",
|
||||
"username": "用户名",
|
||||
"password": "密码"
|
||||
},
|
||||
"chart": {
|
||||
"messageCount": "消息条数",
|
||||
"time": "时间"
|
||||
},
|
||||
"alkaid": {
|
||||
"comingSoon": "前面的世界,以后再来探索吧!"
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import {ref, computed} from 'vue';
|
||||
import {useCustomizerStore} from '@/stores/customizer';
|
||||
import axios from 'axios';
|
||||
import Logo from '@/components/shared/Logo.vue';
|
||||
import LanguageSwitcher from '@/components/shared/LanguageSwitcher.vue';
|
||||
import {md5} from 'js-md5';
|
||||
import {useAuthStore} from '@/stores/auth';
|
||||
import {useCommonStore} from '@/stores/common';
|
||||
@@ -146,7 +147,7 @@ function checkUpdate() {
|
||||
dashboardHasNewVersion.value = res.data.data.dashboard_has_new_version;
|
||||
})
|
||||
.catch((err) => {
|
||||
if (err.response.status == 401) {
|
||||
if (err.response && err.response.status == 401) {
|
||||
console.log("401");
|
||||
const authStore = useAuthStore();
|
||||
authStore.logout();
|
||||
@@ -280,6 +281,9 @@ commonStore.getStartTime();
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<!-- 语言切换器 -->
|
||||
<LanguageSwitcher />
|
||||
|
||||
<!-- 主题切换按钮 -->
|
||||
<v-btn size="small" @click="toggleDarkMode();" class="action-btn"
|
||||
color="var(--v-theme-surface)" variant="flat" rounded="sm">
|
||||
|
||||
@@ -16,7 +16,7 @@ const props = defineProps({ item: Object, level: Number });
|
||||
<template v-slot:prepend>
|
||||
<v-icon v-if="item.icon" :size="item.iconSize" class="hide-menu" :icon="item.icon"></v-icon>
|
||||
</template>
|
||||
<v-list-item-title style="font-size: 14px;">{{ item.title }}</v-list-item-title>
|
||||
<v-list-item-title style="font-size: 14px;">{{ $t(item.title) }}</v-list-item-title>
|
||||
<v-list-item-subtitle v-if="item.subCaption" class="text-caption mt-n1 hide-menu">
|
||||
{{ item.subCaption }}
|
||||
</v-list-item-subtitle>
|
||||
|
||||
@@ -167,14 +167,14 @@ function endDrag() {
|
||||
</template>
|
||||
</v-list>
|
||||
<div class="sidebar-footer" v-if="!customizer.mini_sidebar">
|
||||
<v-btn style="margin-bottom: 8px;" size="small" variant="primary" to="/settings">
|
||||
🔧 设置
|
||||
<v-btn style="margin-bottom: 8px;" size="small" variant="tonal" color="primary" to="/settings">
|
||||
🔧 {{ $t('sidebar.settings') }}
|
||||
</v-btn>
|
||||
<v-btn style="margin-bottom: 8px;" size="small" variant="plain" @click="toggleIframe">
|
||||
官方文档
|
||||
{{ $t('sidebar.documentation') }}
|
||||
</v-btn>
|
||||
<v-btn style="margin-bottom: 8px;" size="small" variant="plain" @click="openIframeLink('https://github.com/AstrBotDevs/AstrBot')">
|
||||
GitHub
|
||||
{{ $t('sidebar.github') }}
|
||||
</v-btn>
|
||||
</div>
|
||||
</div>
|
||||
@@ -189,7 +189,7 @@ function endDrag() {
|
||||
<div :style="dragHeaderStyle" @mousedown="onMouseDown" @touchstart="onTouchStart">
|
||||
<div style="display: flex; align-items: center;">
|
||||
<v-icon icon="mdi-cursor-move" />
|
||||
<span style="margin-left: 8px;">拖拽</span>
|
||||
<span style="margin-left: 8px;">{{ $t('sidebar.drag') }}</span>
|
||||
</div>
|
||||
<div style="display: flex; gap: 8px;">
|
||||
<!-- 跳转按钮 -->
|
||||
|
||||
@@ -14,64 +14,66 @@ export interface menu {
|
||||
subCaption?: string;
|
||||
}
|
||||
|
||||
// 注意:这个文件现在包含i18n键值而不是直接的文本
|
||||
// 在组件中使用时需要通过$t()函数进行翻译
|
||||
const sidebarItem: menu[] = [
|
||||
{
|
||||
title: '统计',
|
||||
title: 'sidebar.dashboard',
|
||||
icon: 'mdi-view-dashboard',
|
||||
to: '/dashboard/default'
|
||||
},
|
||||
{
|
||||
title: '消息平台',
|
||||
title: 'sidebar.platforms',
|
||||
icon: 'mdi-message-processing',
|
||||
to: '/platforms',
|
||||
},
|
||||
{
|
||||
title: '服务提供商',
|
||||
title: 'sidebar.providers',
|
||||
icon: 'mdi-creation',
|
||||
to: '/providers',
|
||||
},
|
||||
{
|
||||
title: 'MCP',
|
||||
title: 'sidebar.toolUse',
|
||||
icon: 'mdi-function-variant',
|
||||
to: '/tool-use'
|
||||
},
|
||||
{
|
||||
title: '配置文件',
|
||||
title: 'sidebar.config',
|
||||
icon: 'mdi-cog',
|
||||
to: '/config',
|
||||
},
|
||||
{
|
||||
title: '插件管理',
|
||||
title: 'sidebar.extension',
|
||||
icon: 'mdi-puzzle',
|
||||
to: '/extension'
|
||||
},
|
||||
{
|
||||
title: '插件市场',
|
||||
title: 'sidebar.extensionMarketplace',
|
||||
icon: 'mdi-storefront',
|
||||
to: '/extension-marketplace'
|
||||
},
|
||||
{
|
||||
title: '聊天',
|
||||
title: 'sidebar.chat',
|
||||
icon: 'mdi-chat',
|
||||
to: '/chat'
|
||||
},
|
||||
{
|
||||
title: '对话数据库',
|
||||
title: 'sidebar.conversation',
|
||||
icon: 'mdi-database',
|
||||
to: '/conversation'
|
||||
},
|
||||
{
|
||||
title: '控制台',
|
||||
title: 'sidebar.console',
|
||||
icon: 'mdi-console',
|
||||
to: '/console'
|
||||
},
|
||||
{
|
||||
title: 'Alkaid',
|
||||
title: 'sidebar.alkaid',
|
||||
icon: 'mdi-test-tube',
|
||||
to: '/alkaid'
|
||||
},
|
||||
{
|
||||
title: '关于',
|
||||
title: 'sidebar.about',
|
||||
icon: 'mdi-information',
|
||||
to: '/about'
|
||||
},
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<div class="d-flex align-center justify-center"
|
||||
style="flex-grow: 1; width: 100%; border: 1px solid #eee; border-radius: 8px;">
|
||||
<span size="64">🌍</span>
|
||||
<p class="text-h6 text-grey ml-4">前面的世界,以后再来探索吧!</p>
|
||||
<p class="text-h6 text-grey ml-4">{{ $t('alkaid.comingSoon') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user