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 @@