From cb1b7bc0e3b50f28c3ace09ebd67b3a53d9e61cb Mon Sep 17 00:00:00 2001 From: Wangnov Date: Mon, 8 Sep 2025 15:40:48 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0i18n=E6=A0=B8?= =?UTF-8?q?=E5=BF=83=E9=85=8D=E7=BD=AE=E5=92=8C=E8=AF=AD=E8=A8=80=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 创建i18n配置系统,支持简体中文/繁体中文/英文三种语言 - 实现浏览器语言自动检测和localStorage持久化 - 添加基础翻译文件,包含common、language、header、apiStats模块 - 创建locale store使用Pinia管理语言状态 - 配置语言标识符为纯文字:简/繁/EN,去除国旗emoji --- web/admin-spa/src/i18n/index.js | 68 +++++++++++++++++++++++++ web/admin-spa/src/i18n/locales/en.js | 38 ++++++++++++++ web/admin-spa/src/i18n/locales/zh-cn.js | 38 ++++++++++++++ web/admin-spa/src/i18n/locales/zh-tw.js | 38 ++++++++++++++ web/admin-spa/src/stores/locale.js | 42 +++++++++++++++ 5 files changed, 224 insertions(+) create mode 100644 web/admin-spa/src/i18n/index.js create mode 100644 web/admin-spa/src/i18n/locales/en.js create mode 100644 web/admin-spa/src/i18n/locales/zh-cn.js create mode 100644 web/admin-spa/src/i18n/locales/zh-tw.js create mode 100644 web/admin-spa/src/stores/locale.js diff --git a/web/admin-spa/src/i18n/index.js b/web/admin-spa/src/i18n/index.js new file mode 100644 index 00000000..4bd2028f --- /dev/null +++ b/web/admin-spa/src/i18n/index.js @@ -0,0 +1,68 @@ +import { createI18n } from 'vue-i18n' +import zhCn from './locales/zh-cn.js' +import zhTw from './locales/zh-tw.js' +import en from './locales/en.js' + +// 获取浏览器语言设置 +function getBrowserLocale() { + const navigatorLocale = navigator.languages ? navigator.languages[0] : navigator.language + + if (!navigatorLocale) { + return 'zh-cn' + } + + const trimmedLocale = navigatorLocale.trim().split(';')[0].toLowerCase() + + if (trimmedLocale.includes('zh')) { + if ( + trimmedLocale.includes('tw') || + trimmedLocale.includes('hk') || + trimmedLocale.includes('mo') + ) { + return 'zh-tw' + } + return 'zh-cn' + } + + if (trimmedLocale.includes('en')) { + return 'en' + } + + return 'zh-cn' // 默认简体中文 +} + +// 获取保存的语言设置或浏览器语言 +const savedLocale = localStorage.getItem('app-locale') +const defaultLocale = savedLocale || getBrowserLocale() + +export const SUPPORTED_LOCALES = { + 'zh-cn': { + name: '简体中文', + flag: '简', + shortName: '简' + }, + 'zh-tw': { + name: '繁體中文', + flag: '繁', + shortName: '繁' + }, + en: { + name: 'English', + flag: 'EN', + shortName: 'EN' + } +} + +export const i18n = createI18n({ + legacy: false, // 使用 Composition API 模式 + locale: defaultLocale, + fallbackLocale: 'zh-cn', + messages: { + 'zh-cn': zhCn, + 'zh-tw': zhTw, + en: en + }, + globalInjection: true // 全局注入 $t 函数 +}) + +export default i18n diff --git a/web/admin-spa/src/i18n/locales/en.js b/web/admin-spa/src/i18n/locales/en.js new file mode 100644 index 00000000..671af8ec --- /dev/null +++ b/web/admin-spa/src/i18n/locales/en.js @@ -0,0 +1,38 @@ +export default { + common: { + save: 'Save', + cancel: 'Cancel', + confirm: 'Confirm', + loading: 'Loading...', + edit: 'Edit', + delete: 'Delete', + create: 'Create', + update: 'Update', + search: 'Search', + reset: 'Reset' + }, + language: { + zh: '简体中文', + 'zh-tw': '繁體中文', + en: 'English', + current: 'Current Language', + switch: 'Switch Language' + }, + header: { + adminPanel: 'Admin Panel', + userMenu: 'User Menu', + logout: 'Logout', + settings: 'Settings' + }, + apiStats: { + title: 'API Key Usage Statistics', + tutorialTitle: 'Tutorial', + userLogin: 'User Login', + adminPanel: 'Admin Panel', + statsQuery: 'Statistics Query', + tutorial: 'Tutorial', + timeRange: 'Statistics Time Range', + today: 'Today', + thisMonth: 'This Month' + } +} diff --git a/web/admin-spa/src/i18n/locales/zh-cn.js b/web/admin-spa/src/i18n/locales/zh-cn.js new file mode 100644 index 00000000..38b3d997 --- /dev/null +++ b/web/admin-spa/src/i18n/locales/zh-cn.js @@ -0,0 +1,38 @@ +export default { + common: { + save: '保存', + cancel: '取消', + confirm: '确认', + loading: '加载中...', + edit: '编辑', + delete: '删除', + create: '创建', + update: '更新', + search: '搜索', + reset: '重置' + }, + language: { + zh: '简体中文', + 'zh-tw': '繁體中文', + en: 'English', + current: '当前语言', + switch: '切换语言' + }, + header: { + adminPanel: '管理后台', + userMenu: '用户菜单', + logout: '退出登录', + settings: '系统设置' + }, + apiStats: { + title: 'API Key 使用统计', + tutorialTitle: '使用教程', + userLogin: '用户登录', + adminPanel: '管理后台', + statsQuery: '统计查询', + tutorial: '使用教程', + timeRange: '统计时间范围', + today: '今日', + thisMonth: '本月' + } +} diff --git a/web/admin-spa/src/i18n/locales/zh-tw.js b/web/admin-spa/src/i18n/locales/zh-tw.js new file mode 100644 index 00000000..4290241d --- /dev/null +++ b/web/admin-spa/src/i18n/locales/zh-tw.js @@ -0,0 +1,38 @@ +export default { + common: { + save: '保存', + cancel: '取消', + confirm: '確認', + loading: '載入中...', + edit: '編輯', + delete: '刪除', + create: '建立', + update: '更新', + search: '搜尋', + reset: '重置' + }, + language: { + zh: '簡體中文', + 'zh-tw': '繁體中文', + en: 'English', + current: '當前語言', + switch: '切換語言' + }, + header: { + adminPanel: '管理後台', + userMenu: '用戶選單', + logout: '退出登錄', + settings: '系統設置' + }, + apiStats: { + title: 'API Key 使用統計', + tutorialTitle: '使用教學', + userLogin: '用戶登錄', + adminPanel: '管理後台', + statsQuery: '統計查詢', + tutorial: '使用教學', + timeRange: '統計時間範圍', + today: '今日', + thisMonth: '本月' + } +} diff --git a/web/admin-spa/src/stores/locale.js b/web/admin-spa/src/stores/locale.js new file mode 100644 index 00000000..7b6ad24d --- /dev/null +++ b/web/admin-spa/src/stores/locale.js @@ -0,0 +1,42 @@ +import { defineStore } from 'pinia' +import { ref } from 'vue' +import { i18n, SUPPORTED_LOCALES } from '@/i18n' + +export const useLocaleStore = defineStore('locale', () => { + const currentLocale = ref(i18n.global.locale.value) + + // 切换语言 + const setLocale = (locale) => { + if (!SUPPORTED_LOCALES[locale]) { + console.warn(`Unsupported locale: ${locale}`) + return + } + + currentLocale.value = locale + i18n.global.locale.value = locale + localStorage.setItem('app-locale', locale) + + // 更新HTML lang属性 + document.documentElement.setAttribute('lang', locale) + } + + // 获取当前语言信息 + const getCurrentLocaleInfo = () => { + return SUPPORTED_LOCALES[currentLocale.value] || SUPPORTED_LOCALES['zh-cn'] + } + + // 获取所有支持的语言 + const getSupportedLocales = () => { + return Object.entries(SUPPORTED_LOCALES).map(([key, value]) => ({ + code: key, + ...value + })) + } + + return { + currentLocale, + setLocale, + getCurrentLocaleInfo, + getSupportedLocales + } +})