From 3d48aa8bbef37844876853f3a8fd3705aa22ff8c Mon Sep 17 00:00:00 2001 From: cc Date: Sat, 13 May 2023 12:58:35 +0800 Subject: [PATCH] =?UTF-8?q?feat(projects):=20=E5=A2=9E=E5=8A=A0i18n?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E7=BF=BB=E8=AF=91=E8=8F=9C=E5=8D=95,tab,titl?= =?UTF-8?q?e?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.vue | 12 +++++++ .../components/global-breadcrumb.vue | 7 ++-- .../global-header/components/header-menu.vue | 3 +- .../common/global-header/components/index.ts | 4 ++- .../global-header/components/toggle-lang.vue | 33 +++++++++++++++++++ src/layouts/common/global-header/index.vue | 4 ++- src/layouts/common/global-logo/index.vue | 14 ++------ .../components/vertical-mix-sider/index.vue | 8 +++-- .../components/vertical-menu.vue | 4 +-- .../components/tab-detail/index.vue | 3 +- src/locales/i18n.ts | 8 +++-- src/router/guard/index.ts | 3 +- src/router/modules/dashboard.ts | 9 +++-- src/store/modules/tab/helpers.ts | 1 - src/typings/route.d.ts | 2 ++ src/typings/storage.d.ts | 2 ++ src/typings/system.d.ts | 3 ++ src/utils/router/breadcrumb.ts | 3 +- src/utils/router/menu.ts | 26 ++++++++++++++- 19 files changed, 116 insertions(+), 33 deletions(-) create mode 100644 src/layouts/common/global-header/components/toggle-lang.vue diff --git a/src/App.vue b/src/App.vue index a801c855..38294b4c 100644 --- a/src/App.vue +++ b/src/App.vue @@ -13,14 +13,26 @@ diff --git a/src/layouts/common/global-header/components/global-breadcrumb.vue b/src/layouts/common/global-header/components/global-breadcrumb.vue index e24ab689..be2e257a 100644 --- a/src/layouts/common/global-header/components/global-breadcrumb.vue +++ b/src/layouts/common/global-header/components/global-breadcrumb.vue @@ -9,7 +9,7 @@ v-if="theme.header.crumb.showIcon" class="inline-block align-text-bottom mr-4px text-16px" /> - {{ breadcrumb.label }} + {{ breadcrumb.i18nTitle ? t(breadcrumb.i18nTitle) : breadcrumb.label }} @@ -33,6 +35,7 @@ import { routePath } from '@/router'; import { useRouteStore, useThemeStore } from '@/store'; import { useRouterPush } from '@/composables'; import { getBreadcrumbByRouteKey } from '@/utils'; +import { t } from '@/locales'; defineOptions({ name: 'GlobalBreadcrumb' }); diff --git a/src/layouts/common/global-header/components/header-menu.vue b/src/layouts/common/global-header/components/header-menu.vue index e19cd64c..e67550c1 100644 --- a/src/layouts/common/global-header/components/header-menu.vue +++ b/src/layouts/common/global-header/components/header-menu.vue @@ -20,6 +20,7 @@ import { useRoute } from 'vue-router'; import type { MenuOption } from 'naive-ui'; import { useRouteStore, useThemeStore } from '@/store'; import { useRouterPush } from '@/composables'; +import { translateMenuLabel } from '@/utils'; defineOptions({ name: 'HeaderMenu' }); @@ -28,7 +29,7 @@ const routeStore = useRouteStore(); const theme = useThemeStore(); const { routerPush } = useRouterPush(); -const menus = computed(() => routeStore.menus as App.GlobalMenuOption[]); +const menus = computed(() => translateMenuLabel(routeStore.menus as App.GlobalMenuOption[])); const activeKey = computed(() => (route.meta?.activeMenu ? route.meta.activeMenu : route.name) as string); function handleUpdateMenu(_key: string, item: MenuOption) { diff --git a/src/layouts/common/global-header/components/index.ts b/src/layouts/common/global-header/components/index.ts index f358911a..3443505e 100644 --- a/src/layouts/common/global-header/components/index.ts +++ b/src/layouts/common/global-header/components/index.ts @@ -7,6 +7,7 @@ import ThemeMode from './theme-mode.vue'; import UserAvatar from './user-avatar.vue'; import SystemMessage from './system-message.vue'; import SettingButton from './setting-button.vue'; +import ToggleLang from './toggle-lang.vue'; export { MenuCollapse, @@ -17,5 +18,6 @@ export { ThemeMode, UserAvatar, SystemMessage, - SettingButton + SettingButton, + ToggleLang }; diff --git a/src/layouts/common/global-header/components/toggle-lang.vue b/src/layouts/common/global-header/components/toggle-lang.vue new file mode 100644 index 00000000..d5e8e2f9 --- /dev/null +++ b/src/layouts/common/global-header/components/toggle-lang.vue @@ -0,0 +1,33 @@ + + + + diff --git a/src/layouts/common/global-header/index.vue b/src/layouts/common/global-header/index.vue index c25dd1c6..4c66c4c0 100644 --- a/src/layouts/common/global-header/index.vue +++ b/src/layouts/common/global-header/index.vue @@ -11,6 +11,7 @@ + @@ -32,7 +33,8 @@ import { SettingButton, SystemMessage, ThemeMode, - UserAvatar + UserAvatar, + ToggleLang } from './components'; defineOptions({ name: 'GlobalHeader' }); diff --git a/src/layouts/common/global-logo/index.vue b/src/layouts/common/global-logo/index.vue index a5a25b29..d4c592c2 100644 --- a/src/layouts/common/global-logo/index.vue +++ b/src/layouts/common/global-logo/index.vue @@ -1,11 +1,7 @@ - {{ item.meta.title }} + {{ item.meta.i18nTitle ? t(item.meta.i18nTitle) : item.meta.title }} { // 设置document title - useTitle(to.meta.title); + useTitle(to.meta.i18nTitle ? t(to.meta.i18nTitle) : to.meta.title); // 结束 loadingBar window.$loadingBar?.finish(); }); diff --git a/src/router/modules/dashboard.ts b/src/router/modules/dashboard.ts index 3243b743..82a863c0 100644 --- a/src/router/modules/dashboard.ts +++ b/src/router/modules/dashboard.ts @@ -10,7 +10,8 @@ const dashboard: AuthRoute.Route = { meta: { title: '分析页', requiresAuth: true, - icon: 'icon-park-outline:analysis' + icon: 'icon-park-outline:analysis', + i18nTitle: 'message.routes.dashboard.analysis' } }, { @@ -20,14 +21,16 @@ const dashboard: AuthRoute.Route = { meta: { title: '工作台', requiresAuth: true, - icon: 'icon-park-outline:workbench' + icon: 'icon-park-outline:workbench', + i18nTitle: 'message.routes.dashboard.workbench' } } ], meta: { title: '仪表盘', icon: 'mdi:monitor-dashboard', - order: 1 + order: 1, + i18nTitle: 'message.routes.dashboard.dashboard' } }; diff --git a/src/store/modules/tab/helpers.ts b/src/store/modules/tab/helpers.ts index d5833625..87ed2158 100644 --- a/src/store/modules/tab/helpers.ts +++ b/src/store/modules/tab/helpers.ts @@ -7,7 +7,6 @@ import { localStg } from '@/utils'; */ export function getTabRouteByVueRoute(route: RouteRecordNormalized | RouteLocationNormalizedLoaded) { const fullPath = hasFullPath(route) ? route.fullPath : route.path; - const tabRoute: App.GlobalTabRoute = { name: route.name, fullPath, diff --git a/src/typings/route.d.ts b/src/typings/route.d.ts index 0235dbe4..a40004f7 100644 --- a/src/typings/route.d.ts +++ b/src/typings/route.d.ts @@ -31,6 +31,8 @@ declare namespace AuthRoute { interface RouteMeta { /** 路由标题(可用来作document.title或者菜单的名称) */ title: string; + /** 用来支持多国语言 如果i18nTitle和title同时存在优先使用i18nTitle */ + i18nTitle?: string; /** 路由的动态路径(需要动态路径的页面需要将path添加进范型参数) */ dynamicPath?: AuthRouteUtils.GetDynamicPath; /** 作为单级路由的父级路由布局组件 */ diff --git a/src/typings/storage.d.ts b/src/typings/storage.d.ts index 892a7167..7d343a52 100644 --- a/src/typings/storage.d.ts +++ b/src/typings/storage.d.ts @@ -18,5 +18,7 @@ declare namespace StorageInterface { themeSettings: Theme.Setting; /** 多页签路由信息 */ multiTabRoutes: App.GlobalTabRoute[]; + /** 本地语言缓存 */ + lang: I18nType.langType; } } diff --git a/src/typings/system.d.ts b/src/typings/system.d.ts index cb88b031..f9b1936e 100644 --- a/src/typings/system.d.ts +++ b/src/typings/system.d.ts @@ -242,6 +242,7 @@ declare namespace App { routePath: string; icon?: () => import('vue').VNodeChild; children?: GlobalMenuOption[]; + i18nTitle?: string; }; /** 面包屑 */ @@ -252,6 +253,7 @@ declare namespace App { routeName: string; hasChildren: boolean; icon?: import('vue').Component; + i18nTitle?: string; options?: import('naive-ui/es/dropdown/src/interface').DropdownMixedOption[]; }; @@ -300,6 +302,7 @@ declare namespace App { } declare namespace I18nType { + type langType = 'en' | 'zh-CN'; interface Schema { system: { title: string; diff --git a/src/utils/router/breadcrumb.ts b/src/utils/router/breadcrumb.ts index 2955f5d4..19640264 100644 --- a/src/utils/router/breadcrumb.ts +++ b/src/utils/router/breadcrumb.ts @@ -59,7 +59,8 @@ function transformBreadcrumbMenuToBreadcrumb(menu: App.GlobalMenuOption, rootPat label: menu.label as string, routeName: menu.routeName, disabled: menu.routePath === rootPath, - hasChildren + hasChildren, + i18nTitle: menu.i18nTitle }; if (menu.icon) { breadcrumb.icon = menu.icon; diff --git a/src/utils/router/menu.ts b/src/utils/router/menu.ts index b3eb5dc7..abed1766 100644 --- a/src/utils/router/menu.ts +++ b/src/utils/router/menu.ts @@ -1,4 +1,5 @@ import { useIconRender } from '@/composables'; +import { t } from '@/locales'; /** * 将权限路由转换成菜单 @@ -18,7 +19,8 @@ export function transformAuthRouteToMenu(routes: AuthRoute.Route[]): App.GlobalM key: routeName, label: meta.title, routeName, - routePath: path + routePath: path, + i18nTitle: meta.i18nTitle }, icon: meta.icon, localIcon: meta.localIcon, @@ -33,6 +35,28 @@ export function transformAuthRouteToMenu(routes: AuthRoute.Route[]): App.GlobalM return globalMenu; } +/** + * 翻译菜单 + * @param menus + * @returns + */ +export function translateMenuLabel(menus: App.GlobalMenuOption[]): App.GlobalMenuOption[] { + const globalMenu: App.GlobalMenuOption[] = []; + menus.forEach(menu => { + let menuChildren: App.GlobalMenuOption[] | undefined; + if (menu.children && menu.children.length > 0) { + menuChildren = translateMenuLabel(menu.children); + } + const menuItem: App.GlobalMenuOption = { + ...menu, + children: menuChildren, + label: menu.i18nTitle ? t(menu.i18nTitle) : menu.label + }; + globalMenu.push(menuItem); + }); + return globalMenu; +} + /** * 获取当前路由所在菜单数据的paths * @param activeKey - 当前路由的key