feat(i18n): 引入 routeI18nInstance 以支持路由菜单标题的多语言处理
This commit is contained in:
2
auto-imports.d.ts
vendored
2
auto-imports.d.ts
vendored
@@ -111,6 +111,7 @@ declare global {
|
|||||||
const resolveComponent: typeof import('vue')['resolveComponent']
|
const resolveComponent: typeof import('vue')['resolveComponent']
|
||||||
const resolveRef: typeof import('@vueuse/core')['resolveRef']
|
const resolveRef: typeof import('@vueuse/core')['resolveRef']
|
||||||
const resolveUnref: typeof import('@vueuse/core')['resolveUnref']
|
const resolveUnref: typeof import('@vueuse/core')['resolveUnref']
|
||||||
|
const routeI18nInstance: typeof import('./src/locales-utils/i18n-auto-imports')['routeI18nInstance']
|
||||||
const setActivePinia: typeof import('pinia')['setActivePinia']
|
const setActivePinia: typeof import('pinia')['setActivePinia']
|
||||||
const setMapStoreSuffix: typeof import('pinia')['setMapStoreSuffix']
|
const setMapStoreSuffix: typeof import('pinia')['setMapStoreSuffix']
|
||||||
const setViewportCSSVars: typeof import('utils4u/browser')['setViewportCSSVars']
|
const setViewportCSSVars: typeof import('utils4u/browser')['setViewportCSSVars']
|
||||||
@@ -455,6 +456,7 @@ declare module 'vue' {
|
|||||||
readonly resolveComponent: UnwrapRef<typeof import('vue')['resolveComponent']>
|
readonly resolveComponent: UnwrapRef<typeof import('vue')['resolveComponent']>
|
||||||
readonly resolveRef: UnwrapRef<typeof import('@vueuse/core')['resolveRef']>
|
readonly resolveRef: UnwrapRef<typeof import('@vueuse/core')['resolveRef']>
|
||||||
readonly resolveUnref: UnwrapRef<typeof import('@vueuse/core')['resolveUnref']>
|
readonly resolveUnref: UnwrapRef<typeof import('@vueuse/core')['resolveUnref']>
|
||||||
|
readonly routeI18nInstance: UnwrapRef<typeof import('./src/locales-utils/i18n-auto-imports')['routeI18nInstance']>
|
||||||
readonly setActivePinia: UnwrapRef<typeof import('pinia')['setActivePinia']>
|
readonly setActivePinia: UnwrapRef<typeof import('pinia')['setActivePinia']>
|
||||||
readonly setMapStoreSuffix: UnwrapRef<typeof import('pinia')['setMapStoreSuffix']>
|
readonly setMapStoreSuffix: UnwrapRef<typeof import('pinia')['setMapStoreSuffix']>
|
||||||
readonly setViewportCSSVars: UnwrapRef<typeof import('utils4u/browser')['setViewportCSSVars']>
|
readonly setViewportCSSVars: UnwrapRef<typeof import('utils4u/browser')['setViewportCSSVars']>
|
||||||
|
|||||||
@@ -8,27 +8,7 @@ import IconMenuRounded from '~icons/material-symbols/menu-rounded';
|
|||||||
export function useMetaLayoutsNMenuOptions({ menuInstRef }: { menuInstRef: Ref<MenuInst | null> }) {
|
export function useMetaLayoutsNMenuOptions({ menuInstRef }: { menuInstRef: Ref<MenuInst | null> }) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const { t, te, locale } = useI18n({
|
const { t, te } = routeI18nInstance.global;
|
||||||
inheritLocale: true,
|
|
||||||
useScope: 'local',
|
|
||||||
missing: (locale, key) => {
|
|
||||||
consola.warn(`菜单翻译缺失: locale=${locale}, key=${key}`);
|
|
||||||
return key;
|
|
||||||
},
|
|
||||||
fallbackRoot: true,
|
|
||||||
messages: i18nRouteMessages,
|
|
||||||
});
|
|
||||||
|
|
||||||
// FIXME: 这个逻辑放在这里不太合适。
|
|
||||||
watch(
|
|
||||||
() => [router.currentRoute.value, locale.value] as const,
|
|
||||||
([currentRoute]) => {
|
|
||||||
const routeName = currentRoute.name;
|
|
||||||
const text = te(routeName) ? t(routeName) : routeName;
|
|
||||||
currentRoute.meta!.title = text;
|
|
||||||
},
|
|
||||||
{ immediate: true },
|
|
||||||
);
|
|
||||||
|
|
||||||
// 获取路由表但是不包含布局路由
|
// 获取路由表但是不包含布局路由
|
||||||
const routes = createGetRoutes(router)();
|
const routes = createGetRoutes(router)();
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
* All i18n resources specified in the plugin `include` option can be loaded
|
* All i18n resources specified in the plugin `include` option can be loaded
|
||||||
* at once using the import syntax
|
* at once using the import syntax
|
||||||
*/
|
*/
|
||||||
|
import { router } from '@/plugins/00.router-plugin';
|
||||||
import messages from '@intlify/unplugin-vue-i18n/messages';
|
import messages from '@intlify/unplugin-vue-i18n/messages';
|
||||||
|
import { createGetRoutes } from 'virtual:meta-layouts';
|
||||||
|
|
||||||
import { createI18n } from 'vue-i18n';
|
import { createI18n } from 'vue-i18n';
|
||||||
|
|
||||||
@@ -26,6 +28,44 @@ export const i18nInstance = createI18n({
|
|||||||
messages,
|
messages,
|
||||||
});
|
});
|
||||||
|
|
||||||
watchEffect(() => {
|
export const routeI18nInstance = createI18n({
|
||||||
locale.value = i18nInstance.global.locale.value;
|
legacy: false, // you must set `false`, to use Composition API
|
||||||
|
locale: locale.value,
|
||||||
|
inheritLocale: true,
|
||||||
|
useScope: 'local',
|
||||||
|
missing: (locale, key) => {
|
||||||
|
consola.warn(`菜单翻译缺失: locale=${locale}, key=${key}`);
|
||||||
|
return key;
|
||||||
|
},
|
||||||
|
fallbackRoot: true,
|
||||||
|
messages: i18nRouteMessages,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
watchEffect(
|
||||||
|
() => {
|
||||||
|
locale.value = i18nInstance.global.locale.value;
|
||||||
|
},
|
||||||
|
{ flush: 'sync' },
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => i18nInstance.global.locale.value,
|
||||||
|
() => {
|
||||||
|
routeI18nInstance.global.locale.value = i18nInstance.global.locale.value;
|
||||||
|
|
||||||
|
const routes = createGetRoutes(router)(); // 获取路由表但是不包含布局路由
|
||||||
|
|
||||||
|
routes.forEach((route) => {
|
||||||
|
const { t, te } = routeI18nInstance.global;
|
||||||
|
|
||||||
|
if (router.currentRoute.value.name) {
|
||||||
|
router.currentRoute.value.meta.title = t(router.currentRoute.value.name as string);
|
||||||
|
}
|
||||||
|
|
||||||
|
route.meta = route.meta || {};
|
||||||
|
const routeName = route.name as string;
|
||||||
|
route.meta.title = te(routeName) ? t(routeName) : routeName;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
{ immediate: true, flush: 'sync' },
|
||||||
|
);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { I18nOptions } from 'vue-i18n';
|
import type { I18nOptions } from 'vue-i18n';
|
||||||
|
|
||||||
const modules = import.meta.glob(['./*.ts', '!./route-messages-auto-imports'], {
|
const modules = import.meta.glob(['./*.ts', '!./route-messages-auto-imports'], {
|
||||||
eager: true,
|
eager: true /* true 为同步,false 为异步 */,
|
||||||
import: 'default',
|
import: 'default',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ function setLocale(newLocale: 'en-US' | 'zh-CN') {
|
|||||||
{{ t('page.i18n-demo.hello', { name: 'Kilo' }) }}
|
{{ t('page.i18n-demo.hello', { name: 'Kilo' }) }}
|
||||||
</n-p>
|
</n-p>
|
||||||
|
|
||||||
|
<n-p> $route.meta: {{ $route.meta }} </n-p>
|
||||||
|
|
||||||
<n-space>
|
<n-space>
|
||||||
<n-button type="primary" @click="setLocale('en-US')"> English </n-button>
|
<n-button type="primary" @click="setLocale('en-US')"> English </n-button>
|
||||||
<n-button type="success" @click="setLocale('zh-CN')"> 简体中文 </n-button>
|
<n-button type="success" @click="setLocale('zh-CN')"> 简体中文 </n-button>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ declare module 'vue-router' {
|
|||||||
hideInMenu?: boolean;
|
hideInMenu?: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 菜单标题 //!⚠️通过多语言标题方案(搜`PageTitleLocalizations`)维护标题
|
* @description 菜单标题 // !⚠️通过多语言标题方案(搜`PageTitleLocalizations`)维护标题
|
||||||
*/
|
*/
|
||||||
title?: string;
|
title?: string;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user