From 7dd7ce73bcd9c10f339f08d6dc71b234f5690b2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=A5=E6=B5=A9?= Date: Wed, 29 Oct 2025 13:09:17 +0800 Subject: [PATCH] =?UTF-8?q?refactor(i18n):=20=E9=87=8D=E6=9E=84=E5=9B=BD?= =?UTF-8?q?=E9=99=85=E5=8C=96=E6=A8=A1=E5=9D=97=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- auto-imports.d.ts | 6 ++-- package.json | 2 +- src/composables/useMetaLayoutsMenuOptions.tsx | 2 +- src/locales-utils/i18n-auto-imports.ts | 28 ++++++++++++++++++ .../route-messages}/README.md | 8 ++--- .../route-messages}/en-US.ts | 0 .../route-messages-auto-imports.ts} | 4 +-- .../route-messages}/zh-CN.ts | 0 src/pages/demos/i18n-demo.page.vue | 10 ++----- src/plugins/00.vueI18n-plugin.ts | 29 +------------------ 10 files changed, 44 insertions(+), 45 deletions(-) create mode 100644 src/locales-utils/i18n-auto-imports.ts rename src/{locales-4-route => locales-utils/route-messages}/README.md (95%) rename src/{locales-4-route => locales-utils/route-messages}/en-US.ts (100%) rename src/{locales-4-route/_messages-auto-imports.ts => locales-utils/route-messages/route-messages-auto-imports.ts} (65%) rename src/{locales-4-route => locales-utils/route-messages}/zh-CN.ts (100%) diff --git a/auto-imports.d.ts b/auto-imports.d.ts index 02b19bb..f6f63aa 100644 --- a/auto-imports.d.ts +++ b/auto-imports.d.ts @@ -53,6 +53,8 @@ declare global { const getCurrentScope: typeof import('vue')['getCurrentScope'] const getCurrentWatcher: typeof import('vue')['getCurrentWatcher'] const h: typeof import('vue')['h'] + const i18nInstance: typeof import('./src/locales-utils/i18n-auto-imports')['i18nInstance'] + const i18nRouteMessages: typeof import('./src/locales-utils/route-messages/route-messages-auto-imports')['i18nRouteMessages'] const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch'] const inject: typeof import('vue')['inject'] const injectLocal: typeof import('@vueuse/core')['injectLocal'] @@ -62,7 +64,6 @@ declare global { const isReadonly: typeof import('vue')['isReadonly'] const isRef: typeof import('vue')['isRef'] const isShallow: typeof import('vue')['isShallow'] - const locales4RouteMessages: typeof import('./src/locales-4-route/_messages-auto-imports')['locales4RouteMessages'] const makeDestructurable: typeof import('@vueuse/core')['makeDestructurable'] const mapActions: typeof import('pinia')['mapActions'] const mapGetters: typeof import('pinia')['mapGetters'] @@ -395,6 +396,8 @@ declare module 'vue' { readonly getCurrentScope: UnwrapRef readonly getCurrentWatcher: UnwrapRef readonly h: UnwrapRef + readonly i18nInstance: UnwrapRef + readonly i18nRouteMessages: UnwrapRef readonly ignorableWatch: UnwrapRef readonly inject: UnwrapRef readonly injectLocal: UnwrapRef @@ -404,7 +407,6 @@ declare module 'vue' { readonly isReadonly: UnwrapRef readonly isRef: UnwrapRef readonly isShallow: UnwrapRef - readonly locales4RouteMessages: UnwrapRef readonly makeDestructurable: UnwrapRef readonly mapActions: UnwrapRef readonly mapGetters: UnwrapRef diff --git a/package.json b/package.json index 4cc0dde..0acf68e 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "{src,packages}/**/*.{css,less,scss,vue}": [ "stylelint --fix" ], - "{src/locales-4-route,src/locales}/**/*": "node scripts/type-check-for-lint-staged.mjs" + "{src/locales-utils,src/locales}/**/*": "node scripts/type-check-for-lint-staged.mjs" }, "pnpm": { "overrides": { diff --git a/src/composables/useMetaLayoutsMenuOptions.tsx b/src/composables/useMetaLayoutsMenuOptions.tsx index 8722f9a..e87a62a 100644 --- a/src/composables/useMetaLayoutsMenuOptions.tsx +++ b/src/composables/useMetaLayoutsMenuOptions.tsx @@ -16,7 +16,7 @@ export function useMetaLayoutsNMenuOptions({ menuInstRef }: { menuInstRef: Ref('app-locale', navigator.language); + +// https://vue-i18n.intlify.dev/guide/essentials/started.html#registering-the-i18n-plugin +export const i18nInstance = createI18n({ + legacy: false, // you must set `false`, to use Composition API + locale: locale.value, + fallbackRoot: false, + // flatJson: true, + missing: (locale, key /* , instance, type */) => { + consola.warn(`缺少国际化内容: locale='${locale}', key='${key}'`); + return `[${key}]`; + }, + missingWarn: !true, + fallbackWarn: !true, + messages, +}); + +watchEffect(() => { + locale.value = i18nInstance.global.locale.value; +}); diff --git a/src/locales-4-route/README.md b/src/locales-utils/route-messages/README.md similarity index 95% rename from src/locales-4-route/README.md rename to src/locales-utils/route-messages/README.md index a4d28dc..082c4f4 100644 --- a/src/locales-4-route/README.md +++ b/src/locales-utils/route-messages/README.md @@ -1,4 +1,4 @@ -# `locales-4-route` +# route-messages 此目录存放专门用于**路由名称**的国际化(i18n)消息。这些消息通过一套自定义的编译时安全机制,为应用的导航菜单提供标题。 @@ -27,7 +27,7 @@ 3. **编译时检查**:此目录下的每个语言环境文件(如 `en-US.ts`)都必须使用 `satisfies PageTitleLocalizations` 来进行类型断言。 ```typescript - // src/locales-4-route/en-US.ts + // ./en-US.ts export default { ... } satisfies PageTitleLocalizations; ``` @@ -52,13 +52,13 @@ 使用上一步中自动生成的 `name` 作为键,在此目录的每个语言文件中添加翻译。 ```ts - // src/locales-4-route/zh-CN.ts + // ./zh-CN.ts export default { // ... 其他翻译 DemosApiDemo: 'API 演示', } satisfies PageTitleLocalizations; - // src/locales-4-route/en-US.ts + // ./en-US.ts export default { // ... 其他翻译 DemosApiDemo: 'API Demo', diff --git a/src/locales-4-route/en-US.ts b/src/locales-utils/route-messages/en-US.ts similarity index 100% rename from src/locales-4-route/en-US.ts rename to src/locales-utils/route-messages/en-US.ts diff --git a/src/locales-4-route/_messages-auto-imports.ts b/src/locales-utils/route-messages/route-messages-auto-imports.ts similarity index 65% rename from src/locales-4-route/_messages-auto-imports.ts rename to src/locales-utils/route-messages/route-messages-auto-imports.ts index bdd2024..ef0e782 100644 --- a/src/locales-4-route/_messages-auto-imports.ts +++ b/src/locales-utils/route-messages/route-messages-auto-imports.ts @@ -1,13 +1,13 @@ import type { I18nOptions } from 'vue-i18n'; -const modules = import.meta.glob(['./*.ts', '!./_messages-auto-imports.ts'], { +const modules = import.meta.glob(['./*.ts', '!./route-messages-auto-imports'], { eager: true, import: 'default', }); type MessageType = Record; -export const locales4RouteMessages: I18nOptions['messages'] = Object.entries(modules).reduce( +export const i18nRouteMessages: I18nOptions['messages'] = Object.entries(modules).reduce( (messages, [path, mod]) => { const locale = path.replace(/(\.\/|\.ts)/g, ''); messages[locale] = mod as MessageType; diff --git a/src/locales-4-route/zh-CN.ts b/src/locales-utils/route-messages/zh-CN.ts similarity index 100% rename from src/locales-4-route/zh-CN.ts rename to src/locales-utils/route-messages/zh-CN.ts diff --git a/src/pages/demos/i18n-demo.page.vue b/src/pages/demos/i18n-demo.page.vue index f19b577..628e5c7 100644 --- a/src/pages/demos/i18n-demo.page.vue +++ b/src/pages/demos/i18n-demo.page.vue @@ -1,13 +1,9 @@ diff --git a/src/plugins/00.vueI18n-plugin.ts b/src/plugins/00.vueI18n-plugin.ts index d3f5967..417e91d 100644 --- a/src/plugins/00.vueI18n-plugin.ts +++ b/src/plugins/00.vueI18n-plugin.ts @@ -1,30 +1,3 @@ -/* https://github.com/intlify/bundle-tools/tree/main/packages/unplugin-vue-i18n#static-bundle-importing - * All i18n resources specified in the plugin `include` option can be loaded - * at once using the import syntax - */ -import messages from '@intlify/unplugin-vue-i18n/messages'; - -import { createI18n } from 'vue-i18n'; - export function install({ app }: { app: import('vue').App }) { - const locale = useLocalStorage('app-locale', navigator.language); - - // https://vue-i18n.intlify.dev/guide/essentials/started.html#registering-the-i18n-plugin - const i18n = createI18n({ - legacy: false, // you must set `false`, to use Composition API - locale: locale.value, - fallbackRoot: false, - // flatJson: true, - missing: (locale, key /* , instance, type */) => { - consola.warn(`缺少国际化内容: locale='${locale}', key='${key}'`); - return `[${key}]`; - }, - missingWarn: !true, - fallbackWarn: !true, - messages, - }); - watchEffect(() => { - locale.value = i18n.global.locale.value; - }); - app.use(i18n); + app.use(i18nInstance); }