From 757444408a4caec25a4fd52315ca50797d291b39 Mon Sep 17 00:00:00 2001 From: ChenXj6 <2953076676@qq.com> Date: Tue, 26 Mar 2024 11:28:23 +0800 Subject: [PATCH] =?UTF-8?q?feat(vue-i18n):=20=E5=A2=9E=E5=8A=A0=E5=9B=BD?= =?UTF-8?q?=E9=99=85=E5=8C=96=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + pnpm-lock.yaml | 41 +++++++ src/components/locale-picker/index.ts | 1 + src/components/locale-picker/index.vue | 39 +++++++ src/components/title-i18n/index.ts | 1 + src/components/title-i18n/index.vue | 26 +++++ src/hooks/useI18n.ts | 70 ++++++++++++ src/layout/index.vue | 9 +- src/locales/config.ts | 21 ++++ src/locales/helper.ts | 37 ++++++ src/locales/index.ts | 41 +++++++ src/locales/package/en-US/common.ts | 40 +++++++ src/locales/package/en-US/component.ts | 28 +++++ src/locales/package/en-US/layout.ts | 21 ++++ src/locales/package/en-US/routes/account.ts | 4 + src/locales/package/en-US/routes/basic.ts | 11 ++ src/locales/package/en-US/routes/dashboard.ts | 6 + src/locales/package/en-US/routes/demo.ts | 20 ++++ src/locales/package/en-US/routes/my.ts | 34 ++++++ src/locales/package/en_US.ts | 13 +++ src/locales/package/zh-CN/common.ts | 41 +++++++ src/locales/package/zh-CN/component.ts | 32 ++++++ src/locales/package/zh-CN/layout.ts | 21 ++++ src/locales/package/zh-CN/routes/account.ts | 4 + src/locales/package/zh-CN/routes/basic.ts | 11 ++ src/locales/package/zh-CN/routes/dashboard.ts | 6 + src/locales/package/zh-CN/routes/demo.ts | 20 ++++ src/locales/package/zh-CN/routes/my.ts | 34 ++++++ src/locales/package/zh_CN.ts | 11 ++ src/locales/useLocale.ts | 72 ++++++++++++ src/main.ts | 2 + src/router/modules.ts | 23 ++-- src/store/modules/lang.ts | 42 +++++++ src/store/mutation-types.ts | 1 + src/views/dashboard/index.vue | 9 +- src/views/example/index.vue | 20 ++-- src/views/exception/403.vue | 45 ++++++++ src/views/exception/404.vue | 2 + src/views/exception/500.vue | 45 ++++++++ src/views/login/ForgetPasswordForm.vue | 13 ++- src/views/login/LoginForm.vue | 14 ++- src/views/login/RegisterForm.vue | 19 ++-- src/views/login/useLogin.ts | 1 + src/views/message/barChart.vue | 105 ------------------ src/views/message/index.vue | 4 - src/views/message/lineChart.vue | 4 +- src/views/message/pieChart.vue | 64 ----------- src/views/my/AccountSetting.vue | 7 +- src/views/my/ChangePassword.vue | 2 +- src/views/my/EditNickname.vue | 3 +- src/views/my/EditSign.vue | 5 +- src/views/my/EditUserInfo.vue | 36 ++++-- src/views/my/ThemeSetting.vue | 13 ++- src/views/my/components/NavBar.vue | 6 +- src/views/my/index.vue | 24 ++-- src/views/my/pickColumns.ts | 33 +++--- 56 files changed, 978 insertions(+), 280 deletions(-) create mode 100644 src/components/locale-picker/index.ts create mode 100644 src/components/locale-picker/index.vue create mode 100644 src/components/title-i18n/index.ts create mode 100644 src/components/title-i18n/index.vue create mode 100644 src/hooks/useI18n.ts create mode 100644 src/locales/config.ts create mode 100644 src/locales/helper.ts create mode 100644 src/locales/index.ts create mode 100644 src/locales/package/en-US/common.ts create mode 100644 src/locales/package/en-US/component.ts create mode 100644 src/locales/package/en-US/layout.ts create mode 100644 src/locales/package/en-US/routes/account.ts create mode 100644 src/locales/package/en-US/routes/basic.ts create mode 100644 src/locales/package/en-US/routes/dashboard.ts create mode 100644 src/locales/package/en-US/routes/demo.ts create mode 100644 src/locales/package/en-US/routes/my.ts create mode 100644 src/locales/package/en_US.ts create mode 100644 src/locales/package/zh-CN/common.ts create mode 100644 src/locales/package/zh-CN/component.ts create mode 100644 src/locales/package/zh-CN/layout.ts create mode 100644 src/locales/package/zh-CN/routes/account.ts create mode 100644 src/locales/package/zh-CN/routes/basic.ts create mode 100644 src/locales/package/zh-CN/routes/dashboard.ts create mode 100644 src/locales/package/zh-CN/routes/demo.ts create mode 100644 src/locales/package/zh-CN/routes/my.ts create mode 100644 src/locales/package/zh_CN.ts create mode 100644 src/locales/useLocale.ts create mode 100644 src/store/modules/lang.ts create mode 100644 src/views/exception/403.vue create mode 100644 src/views/exception/500.vue delete mode 100644 src/views/message/barChart.vue delete mode 100644 src/views/message/pieChart.vue diff --git a/package.json b/package.json index 4645da0..41586dd 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "qs": "^6.11.2", "vant": "^4.8.1", "vue": "^3.3.13", + "vue-i18n": "^9.10.1", "vue-router": "4.2.5" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fd2741a..1ba3d34 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -47,6 +47,9 @@ dependencies: vue: specifier: ^3.3.13 version: 3.3.13(typescript@5.3.3) + vue-i18n: + specifier: ^9.10.1 + version: 9.10.2(vue@3.3.13) vue-router: specifier: 4.2.5 version: 4.2.5(vue@3.3.13) @@ -1316,6 +1319,27 @@ packages: - supports-color dev: true + /@intlify/core-base@9.10.2: + resolution: {integrity: sha512-HGStVnKobsJL0DoYIyRCGXBH63DMQqEZxDUGrkNI05FuTcruYUtOAxyL3zoAZu/uDGO6mcUvm3VXBaHG2GdZCg==} + engines: {node: '>= 16'} + dependencies: + '@intlify/message-compiler': 9.10.2 + '@intlify/shared': 9.10.2 + dev: false + + /@intlify/message-compiler@9.10.2: + resolution: {integrity: sha512-ntY/kfBwQRtX5Zh6wL8cSATujPzWW2ZQd1QwKyWwAy5fMqJyyixHMeovN4fmEyCqSu+hFfYOE63nU94evsy4YA==} + engines: {node: '>= 16'} + dependencies: + '@intlify/shared': 9.10.2 + source-map-js: 1.0.2 + dev: false + + /@intlify/shared@9.10.2: + resolution: {integrity: sha512-ttHCAJkRy7R5W2S9RVnN9KYQYPIpV2+GiS79T4EE37nrPyH6/1SrOh3bmdCRC1T3ocL8qCDx7x2lBJ0xaITU7Q==} + engines: {node: '>= 16'} + dev: false + /@jridgewell/gen-mapping@0.3.3: resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} engines: {node: '>=6.0.0'} @@ -1449,6 +1473,7 @@ packages: resolution: {integrity: sha512-u3XkZVvxcvlAOlQJ3UsD1rFvLWqu4Ef/Ggl40WAVCuogf4S1nJPHh5RTgqYFpCOvuGJ7H5yGHabjFKEZGExk5Q==} cpu: [arm64] os: [linux] + libc: [glibc] requiresBuild: true dev: true optional: true @@ -1457,6 +1482,7 @@ packages: resolution: {integrity: sha512-0XSYN/rfWShW+i+qjZ0phc6vZ7UWI8XWNz4E/l+6edFt+FxoEghrJHjX1EY/kcUGCnZzYYRCl31SNdfOi450Aw==} cpu: [arm64] os: [linux] + libc: [musl] requiresBuild: true dev: true optional: true @@ -1465,6 +1491,7 @@ packages: resolution: {integrity: sha512-LmYIO65oZVfFt9t6cpYkbC4d5lKHLYv5B4CSHRpnANq0VZUQXGcCPXHzbCXCz4RQnx7jvlYB1ISVNCE/omz5cw==} cpu: [riscv64] os: [linux] + libc: [glibc] requiresBuild: true dev: true optional: true @@ -1473,6 +1500,7 @@ packages: resolution: {integrity: sha512-kr8rEPQ6ns/Lmr/hiw8sEVj9aa07gh1/tQF2Y5HrNCCEPiCBGnBUt9tVusrcBBiJfIt1yNaXN6r1CCmpbFEDpg==} cpu: [x64] os: [linux] + libc: [glibc] requiresBuild: true dev: true optional: true @@ -1481,6 +1509,7 @@ packages: resolution: {integrity: sha512-t4QSR7gN+OEZLG0MiCgPqMWZGwmeHhsM4AkegJ0Kiy6TnJ9vZ8dEIwHw1LcZKhbHxTY32hp9eVCMdR3/I8MGRw==} cpu: [x64] os: [linux] + libc: [musl] requiresBuild: true dev: true optional: true @@ -7268,6 +7297,18 @@ packages: - supports-color dev: true + /vue-i18n@9.10.2(vue@3.3.13): + resolution: {integrity: sha512-ECJ8RIFd+3c1d3m1pctQ6ywG5Yj8Efy1oYoAKQ9neRdkLbuKLVeW4gaY5HPkD/9ssf1pOnUrmIFjx2/gkGxmEw==} + engines: {node: '>= 16'} + peerDependencies: + vue: ^3.0.0 + dependencies: + '@intlify/core-base': 9.10.2 + '@intlify/shared': 9.10.2 + '@vue/devtools-api': 6.5.1 + vue: 3.3.13(typescript@5.3.3) + dev: false + /vue-router@4.2.5(vue@3.3.13): resolution: {integrity: sha512-DIUpKcyg4+PTQKfFPX88UWhlagBEBEfJ5A8XDXRJLUnZOvcpMF8o/dnL90vpVkGaPbjvXazV/rC1qBKrZlFugw==} peerDependencies: diff --git a/src/components/locale-picker/index.ts b/src/components/locale-picker/index.ts new file mode 100644 index 0000000..94ad5d4 --- /dev/null +++ b/src/components/locale-picker/index.ts @@ -0,0 +1 @@ +export { default as LocalePicker } from './index.vue' diff --git a/src/components/locale-picker/index.vue b/src/components/locale-picker/index.vue new file mode 100644 index 0000000..dbc21ea --- /dev/null +++ b/src/components/locale-picker/index.vue @@ -0,0 +1,39 @@ + + + diff --git a/src/components/title-i18n/index.ts b/src/components/title-i18n/index.ts new file mode 100644 index 0000000..d16d012 --- /dev/null +++ b/src/components/title-i18n/index.ts @@ -0,0 +1 @@ +export { default as TitleI18n } from './index.vue' diff --git a/src/components/title-i18n/index.vue b/src/components/title-i18n/index.vue new file mode 100644 index 0000000..80628a8 --- /dev/null +++ b/src/components/title-i18n/index.vue @@ -0,0 +1,26 @@ + + + diff --git a/src/hooks/useI18n.ts b/src/hooks/useI18n.ts new file mode 100644 index 0000000..4124cf1 --- /dev/null +++ b/src/hooks/useI18n.ts @@ -0,0 +1,70 @@ +import type { Composer } from 'vue-i18n' +import * as locales from '@/locales' + +type I18nGlobalTranslation = Composer['t'] +type I18nTranslationRestParameters = [string, any] + +function getKey(namespace: string | undefined, key: string) { + if (!namespace) { + return key + } + if (key.startsWith(namespace)) { + return key + } + return `${namespace}.${key}` +} + +export function useI18n(namespace?: string): { + t: I18nGlobalTranslation +} { + const i18n = locales.i18n + const normalFn = { + t: (key: string) => { + return getKey(namespace, key) + }, + } + + if (!i18n) { + return normalFn + } + + const { t } = i18n.global + + const tFn: I18nGlobalTranslation = (key: string, ...arg: any[]) => { + if (!key) { + return '' + } + if (!key.includes('.') && !namespace) { + return key + } + return t(getKey(namespace, key), ...(arg as I18nTranslationRestParameters)) + } + console.log(i18n.global) + return Object.assign(i18n.global, { t: tFn }) +} + +/** + * 国际化转换工具函数,主要用于处理动态路由的title + * @param {string | Title18n} message message + * @param isI18n 默认为true,获取对应的翻译文本,否则返回本身 + * @returns message + */ +export function transformI18n(message: string | Title18n = '', isI18n = true) { + if (!message) { + return '' + } + const i18n = locales.i18n + + // 处理动态路由的title, 格式 {zh_CN:"",en_US:""} + if (typeof message === 'object') { + return message[i18n.global?.locale] + } + + if (isI18n && typeof message === 'string') { + return i18n.global.t(message) + } + return message +} + +// 主要用于配合vscode i18nn ally插件的提示。此功能仅用于路由和菜单。请在其他地方使用 vue-i18n 的 useI18n +export const t = (key: string) => key diff --git a/src/layout/index.vue b/src/layout/index.vue index ad9f027..36bdac3 100644 --- a/src/layout/index.vue +++ b/src/layout/index.vue @@ -1,7 +1,11 @@