From a50e356f4202618ecd4377baf484ca8563871659 Mon Sep 17 00:00:00 2001 From: tongque <2863528786@qq.com> Date: Sat, 27 Apr 2024 17:24:53 +0800 Subject: [PATCH 1/4] feat(i18n): initialize vue-i18n for internationalization support - Added vue-i18n as a dependency. - Configured vue-i18n in the main application file. - Created initial locale files with translations. --- ui/env.d.ts | 1 + ui/src/components/icons/index.ts | 19 ++++++ ui/src/layout/components/top-bar/index.vue | 48 ++++++++------ ui/src/locales/index.ts | 66 +++++++++++++++++++ ui/src/locales/lang/en_US/components/index.ts | 4 ++ ui/src/locales/lang/en_US/index.ts | 12 ++++ ui/src/locales/lang/en_US/layout.ts | 7 ++ ui/src/locales/lang/en_US/pages/index.ts | 4 ++ ui/src/locales/lang/zh_CN/components/index.ts | 4 ++ ui/src/locales/lang/zh_CN/index.ts | 12 ++++ ui/src/locales/lang/zh_CN/layout.ts | 7 ++ ui/src/locales/lang/zh_CN/pages/index.ts | 4 ++ ui/src/locales/useLocale.ts | 28 ++++++++ ui/src/main.ts | 3 +- 14 files changed, 197 insertions(+), 22 deletions(-) create mode 100644 ui/src/locales/index.ts create mode 100644 ui/src/locales/lang/en_US/components/index.ts create mode 100644 ui/src/locales/lang/en_US/index.ts create mode 100644 ui/src/locales/lang/en_US/layout.ts create mode 100644 ui/src/locales/lang/en_US/pages/index.ts create mode 100644 ui/src/locales/lang/zh_CN/components/index.ts create mode 100644 ui/src/locales/lang/zh_CN/index.ts create mode 100644 ui/src/locales/lang/zh_CN/layout.ts create mode 100644 ui/src/locales/lang/zh_CN/pages/index.ts create mode 100644 ui/src/locales/useLocale.ts diff --git a/ui/env.d.ts b/ui/env.d.ts index ba311a842..52f545270 100644 --- a/ui/env.d.ts +++ b/ui/env.d.ts @@ -11,3 +11,4 @@ declare module 'katex' interface ImportMeta { readonly env: ImportMetaEnv } +declare type Recordable = Record; diff --git a/ui/src/components/icons/index.ts b/ui/src/components/icons/index.ts index 983ac7de2..ffac3bcdd 100644 --- a/ui/src/components/icons/index.ts +++ b/ui/src/components/icons/index.ts @@ -641,6 +641,25 @@ export const iconMap: any = { ]) } }, + 'app-translate': { + iconReader: () => { + return h('svg', { + xmlns: "http://www.w3.org/2000/svg", + viewBox: "0 0 20 20", + fill: "currentColor", + class: "w-5 h-5" + }, [ + h('path', { + d: "M7.75 2.75a.75.75 0 0 0-1.5 0v1.258a32.987 32.987 0 0 0-3.599.278.75.75 0 1 0 .198 1.487A31.545 31.545 0 0 1 8.7 5.545 19.381 19.381 0 0 1 7 9.56a19.418 19.418 0 0 1-1.002-2.05.75.75 0 0 0-1.384.577 20.935 20.935 0 0 0 1.492 2.91 19.613 19.613 0 0 1-3.828 4.154.75.75 0 1 0 .945 1.164A21.116 21.116 0 0 0 7 12.331c.095.132.192.262.29.391a.75.75 0 0 0 1.194-.91c-.204-.266-.4-.538-.59-.815a20.888 20.888 0 0 0 2.333-5.332c.31.031.618.068.924.108a.75.75 0 0 0 .198-1.487 32.832 32.832 0 0 0-3.599-.278V2.75Z" + }), + h('path', { + "fill-rule": "evenodd", + d: "M13 8a.75.75 0 0 1 .671.415l4.25 8.5a.75.75 0 1 1-1.342.67L15.787 16h-5.573l-.793 1.585a.75.75 0 1 1-1.342-.67l4.25-8.5A.75.75 0 0 1 13 8Zm2.037 6.5L13 10.427 10.964 14.5h4.073Z", + "clip-rule": "evenodd" + }) + ]); + } + }, 'app-user': { iconReader: () => { return h('i', [ diff --git a/ui/src/layout/components/top-bar/index.vue b/ui/src/layout/components/top-bar/index.vue index eff56f8f1..a4fa0fba7 100644 --- a/ui/src/layout/components/top-bar/index.vue +++ b/ui/src/layout/components/top-bar/index.vue @@ -11,30 +11,28 @@
- - + + - - + + - - + + + + + + +
@@ -43,9 +41,15 @@ import TopMenu from './top-menu/index.vue' import Avatar from './avatar/index.vue' import { useRouter } from 'vue-router' +import { langList } from '@/locales/index'; +import { useLocale } from '@/locales/useLocale'; const router = useRouter() const defaultTitle = import.meta.env.VITE_APP_TITLE +const { changeLocale } = useLocale(); +const changeLang = (lang: string) => { + changeLocale(lang); +}; function toUrl(url: string) { window.open(url, '_blank') } @@ -58,6 +62,7 @@ function toUrl(url: string) { .app-title-container { margin-right: 45px; + .app-title-icon { background-image: url('@/assets/logo.png'); background-size: 100% 100%; @@ -69,6 +74,7 @@ function toUrl(url: string) { font-size: 24px; } } + .line { height: 2em; } diff --git a/ui/src/locales/index.ts b/ui/src/locales/index.ts new file mode 100644 index 000000000..51f94c11c --- /dev/null +++ b/ui/src/locales/index.ts @@ -0,0 +1,66 @@ +import { useLocalStorage, usePreferredLanguages } from '@vueuse/core'; +import { computed } from 'vue'; +import { createI18n } from 'vue-i18n'; + +// 导入语言文件 +const langModules = import.meta.glob('./lang/*/index.ts', { eager: true }) as Record Promise<{ default: Object }>>; + +const langModuleMap = new Map(); + +export const langCode: Array = []; + +export const localeConfigKey = 'MaxKB-locale'; + +// 获取浏览器默认语言环境 +const languages = usePreferredLanguages(); + +// 生成语言模块列表 +const generateLangModuleMap = () => { + const fullPaths = Object.keys(langModules); + fullPaths.forEach((fullPath) => { + const k = fullPath.replace('./lang', ''); + const startIndex = 1; + const lastIndex = k.lastIndexOf('/'); + const code = k.substring(startIndex, lastIndex); + langCode.push(code); + langModuleMap.set(code, langModules[fullPath]); + }); +}; + +// 导出 Message +const importMessages = computed(() => { + generateLangModuleMap(); + + const message: Recordable = {}; + langModuleMap.forEach((value: any, key) => { + message[key] = value.default; + }); + return message; +}); + +export const i18n = createI18n({ + legacy: false, + locale: useLocalStorage(localeConfigKey, 'zh_CN').value || languages.value[0] || 'zh_CN', + fallbackLocale: 'zh_CN', + messages: importMessages.value, + globalInjection: true, +}); + +export const langList = computed(() => { + if (langModuleMap.size === 0) generateLangModuleMap(); + + const list:any=[] + langModuleMap.forEach((value: any, key) => { + list.push({ + label: value.default.lang, + value: key, + }); + }); + + return list; +}); + +// @ts-ignore +export const { t } = i18n.global; + +export default i18n; diff --git a/ui/src/locales/lang/en_US/components/index.ts b/ui/src/locales/lang/en_US/components/index.ts new file mode 100644 index 000000000..bd77588db --- /dev/null +++ b/ui/src/locales/lang/en_US/components/index.ts @@ -0,0 +1,4 @@ + +export default { + +}; diff --git a/ui/src/locales/lang/en_US/index.ts b/ui/src/locales/lang/en_US/index.ts new file mode 100644 index 000000000..16bd5f6bb --- /dev/null +++ b/ui/src/locales/lang/en_US/index.ts @@ -0,0 +1,12 @@ +import en from 'element-plus/es/locale/lang/en'; +import components from './components'; +import layout from './layout'; +import pages from './pages'; + +export default { + lang: 'English', + layout, + pages, + components, + en, +}; diff --git a/ui/src/locales/lang/en_US/layout.ts b/ui/src/locales/lang/en_US/layout.ts new file mode 100644 index 000000000..7e1e7f9de --- /dev/null +++ b/ui/src/locales/lang/en_US/layout.ts @@ -0,0 +1,7 @@ +export default { + topbar: { + github:"Github", + handbook:"Handbook", + forum:"Forum" + }, +}; diff --git a/ui/src/locales/lang/en_US/pages/index.ts b/ui/src/locales/lang/en_US/pages/index.ts new file mode 100644 index 000000000..bd77588db --- /dev/null +++ b/ui/src/locales/lang/en_US/pages/index.ts @@ -0,0 +1,4 @@ + +export default { + +}; diff --git a/ui/src/locales/lang/zh_CN/components/index.ts b/ui/src/locales/lang/zh_CN/components/index.ts new file mode 100644 index 000000000..bd77588db --- /dev/null +++ b/ui/src/locales/lang/zh_CN/components/index.ts @@ -0,0 +1,4 @@ + +export default { + +}; diff --git a/ui/src/locales/lang/zh_CN/index.ts b/ui/src/locales/lang/zh_CN/index.ts new file mode 100644 index 000000000..db4da9942 --- /dev/null +++ b/ui/src/locales/lang/zh_CN/index.ts @@ -0,0 +1,12 @@ +import zhCn from 'element-plus/es/locale/lang/zh-cn'; +import components from './components'; +import layout from './layout'; +import pages from './pages'; + +export default { + lang: '简体中文', + layout, + pages, + components, + zhCn, +}; diff --git a/ui/src/locales/lang/zh_CN/layout.ts b/ui/src/locales/lang/zh_CN/layout.ts new file mode 100644 index 000000000..f31efa826 --- /dev/null +++ b/ui/src/locales/lang/zh_CN/layout.ts @@ -0,0 +1,7 @@ +export default { + topbar: { + github:"项目地址", + handbook:"用户手册", + forum:"论坛求助" + }, +}; diff --git a/ui/src/locales/lang/zh_CN/pages/index.ts b/ui/src/locales/lang/zh_CN/pages/index.ts new file mode 100644 index 000000000..bd77588db --- /dev/null +++ b/ui/src/locales/lang/zh_CN/pages/index.ts @@ -0,0 +1,4 @@ + +export default { + +}; diff --git a/ui/src/locales/useLocale.ts b/ui/src/locales/useLocale.ts new file mode 100644 index 000000000..c8021627c --- /dev/null +++ b/ui/src/locales/useLocale.ts @@ -0,0 +1,28 @@ +import { useLocalStorage } from '@vueuse/core'; +import { computed } from 'vue'; +import { useI18n } from 'vue-i18n'; + +import { i18n, langCode, localeConfigKey } from '@/locales/index'; + +export function useLocale() { + const { locale } = useI18n({ useScope: 'global' }); + function changeLocale(lang: string) { + // 如果切换的语言不在对应语言文件里则默认为简体中文 + if (!langCode.includes(lang)) { + lang = 'zh_CN'; + } + + locale.value = lang; + useLocalStorage(localeConfigKey, 'zh_CN').value = lang; + } + + const getComponentsLocale = computed(() => { + return i18n.global.getLocaleMessage(locale.value).componentsLocale; + }); + + return { + changeLocale, + getComponentsLocale, + locale, + }; +} diff --git a/ui/src/main.ts b/ui/src/main.ts index 96affdbd5..a978a7efa 100644 --- a/ui/src/main.ts +++ b/ui/src/main.ts @@ -9,7 +9,7 @@ import directives from '@/directives' import App from './App.vue' import router from '@/router' import Components from '@/components' - +import i18n from './locales'; const app = createApp(App) app.use(store) app.use(directives) @@ -24,5 +24,6 @@ app.use(ElementPlus, { app.use(theme) app.use(router) +app.use(i18n); app.use(Components) app.mount('#app') From 601af09d03be41b1b05a0b5844b39c0f0eac0575 Mon Sep 17 00:00:00 2001 From: tongque <2863528786@qq.com> Date: Sat, 27 Apr 2024 17:31:15 +0800 Subject: [PATCH 2/4] feat(i18n): initialize vue-i18n for internationalization support - Added vue-i18n as a dependency. - Configured vue-i18n in the main application file. - Created initial locale files with translations. --- ui/package.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui/package.json b/ui/package.json index c9c61d73c..74b34f093 100644 --- a/ui/package.json +++ b/ui/package.json @@ -14,6 +14,7 @@ }, "dependencies": { "@ctrl/tinycolor": "^4.1.0", + "@vueuse/core": "^10.9.0", "axios": "^0.28.0", "cropperjs": "^1.6.2", "echarts": "^5.5.0", @@ -42,6 +43,7 @@ "screenfull": "^6.0.2", "vue": "^3.3.4", "vue-clipboard3": "^2.0.0", + "vue-i18n": "^9.13.1", "vue-router": "^4.2.4" }, "devDependencies": { From 63caa3631af3170d06c8d98da038ab6ef3089b02 Mon Sep 17 00:00:00 2001 From: tongque <2863528786@qq.com> Date: Sun, 28 Apr 2024 15:23:41 +0800 Subject: [PATCH 3/4] =?UTF-8?q?feat:layout=E9=83=A8=E5=88=86=E5=9B=BD?= =?UTF-8?q?=E9=99=85=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ui/src/layout/components/top-bar/index.vue | 2 +- .../components/top-bar/top-menu/MenuItem.vue | 19 +++++++++++++------ ui/src/locales/lang/en_US/layout.ts | 7 ++++++- ui/src/locales/lang/zh_CN/layout.ts | 8 +++++++- 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/ui/src/layout/components/top-bar/index.vue b/ui/src/layout/components/top-bar/index.vue index cc240035e..ac8ba27b8 100644 --- a/ui/src/layout/components/top-bar/index.vue +++ b/ui/src/layout/components/top-bar/index.vue @@ -35,7 +35,7 @@ @click="toUrl('https://bbs.fit2cloud.com/c/mk/11')" > - + diff --git a/ui/src/layout/components/top-bar/avatar/index.vue b/ui/src/layout/components/top-bar/avatar/index.vue index d6a889cf3..8042bd2a7 100644 --- a/ui/src/layout/components/top-bar/avatar/index.vue +++ b/ui/src/layout/components/top-bar/avatar/index.vue @@ -21,10 +21,10 @@

- 修改密码 + {{ $t("layout.topbar.avatar.resetPassword") }} - 关于 - 退出 + {{ $t("layout.topbar.avatar.about") }} + {{ $t("layout.topbar.avatar.logout") }}
diff --git a/ui/src/layout/components/top-bar/index.vue b/ui/src/layout/components/top-bar/index.vue index ac8ba27b8..8d1cb6d9a 100644 --- a/ui/src/layout/components/top-bar/index.vue +++ b/ui/src/layout/components/top-bar/index.vue @@ -19,7 +19,7 @@ @click="toUrl('https://github.com/1Panel-dev/MaxKB')" > - + - +