Browse Source

feat(i18n): 菜单动态支持i18n (#109)

* feat(i18n): 菜单动态支持i18n
hb0730 3 years ago
parent
commit
aa8005a982

+ 6 - 0
mock/asyncRoutes.ts

@@ -9,6 +9,7 @@ const systemRouter = {
   meta: {
     icon: "Setting",
     title: "message.hssysManagement",
+    i18n: true,
     showLink: true,
     rank: 6
   },
@@ -18,6 +19,7 @@ const systemRouter = {
       name: "user",
       meta: {
         title: "message.hsBaseinfo",
+        i18n: true,
         showLink: true
       }
     },
@@ -26,6 +28,7 @@ const systemRouter = {
       name: "dict",
       meta: {
         title: "message.hsDict",
+        i18n: true,
         showLink: true
       }
     }
@@ -39,6 +42,7 @@ const permissionRouter = {
   meta: {
     title: "message.permission",
     icon: "Lollipop",
+    i18n: true,
     showLink: true,
     rank: 3
   },
@@ -48,6 +52,7 @@ const permissionRouter = {
       name: "permissionPage",
       meta: {
         title: "message.permissionPage",
+        i18n: true,
         showLink: true
       }
     },
@@ -56,6 +61,7 @@ const permissionRouter = {
       name: "permissionButton",
       meta: {
         title: "message.permissionButton",
+        i18n: true,
         showLink: true,
         authority: []
       }

+ 7 - 2
src/layout/components/navbar.vue

@@ -10,6 +10,7 @@ import { unref, watch, getCurrentInstance } from "vue";
 import { deviceDetection } from "/@/utils/deviceDetection";
 import screenfull from "../components/screenfull/index.vue";
 import globalization from "/@/assets/svg/globalization.svg";
+import { getMessage } from "/@/utils/i18n";
 
 const instance =
   getCurrentInstance().appContext.config.globalProperties.$storage;
@@ -17,13 +18,17 @@ const pureApp = useAppStoreHook();
 const router = useRouter();
 const route = useRoute();
 let usename = storageSession.getItem("info")?.username;
-const { locale, t } = useI18n();
+const { locale } = useI18n();
 
 watch(
   () => locale.value,
   () => {
     //@ts-ignore
-    document.title = t(unref(route.meta.title)); // 动态title
+    document.title = getMessage(
+      //@ts-ignore
+      unref(route.meta.title),
+      unref(route.meta.i18n)
+    ); // 动态title
   }
 );
 

+ 7 - 3
src/layout/components/sidebar/breadCrumb.vue

@@ -1,6 +1,7 @@
 <script setup lang="ts">
 import { ref, watch } from "vue";
 import { useRoute, useRouter, RouteLocationMatched } from "vue-router";
+import { getMessage } from "/@/utils/i18n";
 
 const levelList = ref([]);
 const route = useRoute();
@@ -22,7 +23,7 @@ const getBreadcrumb = (): void => {
       {
         path: "/welcome",
         parentPath: "/",
-        meta: { title: "message.hshome" }
+        meta: { title: "message.hshome", i18n: true }
       } as unknown as RouteLocationMatched
     ].concat(matched);
   }
@@ -37,6 +38,9 @@ watch(
   () => route.path,
   () => getBreadcrumb()
 );
+const getI18nMessage = meta => {
+  return getMessage(meta.title, meta.i18n);
+};
 
 const handleLink = (item: RouteLocationMatched): any => {
   const { redirect, path } = item;
@@ -55,10 +59,10 @@ const handleLink = (item: RouteLocationMatched): any => {
         <span
           v-if="item.redirect === 'noRedirect' || index == levelList.length - 1"
           class="no-redirect"
-          >{{ $t(item.meta.title) }}</span
+          >{{ getI18nMessage(item.meta) }}</span
         >
         <a v-else @click.prevent="handleLink(item)">
-          {{ $t(item.meta.title) }}
+          {{ getI18nMessage(item.meta) }}
         </a>
       </el-breadcrumb-item>
     </transition-group>

+ 15 - 6
src/layout/components/sidebar/sidebarItem.vue

@@ -4,6 +4,7 @@ import { PropType, ref, nextTick, getCurrentInstance } from "vue";
 import { childrenType } from "../../types";
 import { useAppStoreHook } from "/@/store/modules/app";
 import Icon from "/@/components/ReIcon/src/Icon.vue";
+import { getMessage } from "/@/utils/i18n";
 import { findIconReg } from "/@/components/ReIcon";
 const instance = getCurrentInstance().appContext.app.config.globalProperties;
 const menuMode = instance.$storage.layout?.layout === "vertical";
@@ -109,14 +110,18 @@ function resolvePath(routePath) {
             overflow: 'hidden'
           }"
         >
-          <span v-if="!menuMode">{{ $t(onlyOneChild.meta.title) }}</span>
+          <span v-if="!menuMode">{{
+            getMessage(onlyOneChild.meta.title, onlyOneChild.meta.i18n)
+          }}</span>
           <el-tooltip
             v-else
             placement="top"
             :offset="-10"
             :disabled="!onlyOneChild.showTooltip"
           >
-            <template #content> {{ $t(onlyOneChild.meta.title) }} </template>
+            <template #content>
+              {{ getMessage(onlyOneChild.meta.title, onlyOneChild.meta.i18n) }}
+            </template>
             <span
               ref="menuTextRef"
               :style="{
@@ -126,7 +131,7 @@ function resolvePath(routePath) {
               }"
               @mouseover="hoverMenu(onlyOneChild)"
             >
-              {{ $t(onlyOneChild.meta.title) }}
+              {{ getMessage(onlyOneChild.meta.title, onlyOneChild.meta.i18n) }}
             </span>
           </el-tooltip>
           <Icon
@@ -151,14 +156,18 @@ function resolvePath(routePath) {
           :is="findIconReg(props.item.meta && props.item.meta.icon)"
         ></component>
       </el-icon>
-      <span v-if="!menuMode">{{ $t(props.item.meta.title) }}</span>
+      <span v-if="!menuMode">{{
+        getMessage(props.item.meta.title, props.item.meta.i18n)
+      }}</span>
       <el-tooltip
         v-else
         placement="top"
         :offset="-10"
         :disabled="!pureApp.sidebar.opened || !props.item.showTooltip"
       >
-        <template #content> {{ $t(props.item.meta.title) }} </template>
+        <template #content>
+          {{ getMessage(props.item.meta.title, props.item.meta.i18n) }}
+        </template>
         <div
           ref="menuTextRef"
           :style="{
@@ -170,7 +179,7 @@ function resolvePath(routePath) {
           @mouseover="hoverMenu(props.item)"
         >
           <span style="overflow: hidden; text-overflow: ellipsis">
-            {{ $t(props.item.meta.title) }}
+            {{ getMessage(props.item.meta.title, props.item.meta.i18n) }}
           </span>
         </div>
       </el-tooltip>

+ 1 - 0
src/layout/types.ts

@@ -58,6 +58,7 @@ export type childrenType = {
   meta?: {
     icon?: string;
     title?: string;
+    i18n?: boolean;
     extraIcon?: {
       svg?: boolean;
       name?: string;

+ 7 - 3
src/router/index.ts

@@ -7,7 +7,6 @@ import {
 } from "vue-router";
 import { RouteConfigs } from "/@/layout/types";
 import { split, uniqBy } from "lodash-es";
-import { i18n } from "/@/plugins/i18n";
 import { openLink } from "/@/utils/link";
 import NProgress from "/@/utils/progress";
 import { useTimeoutFn } from "@vueuse/core";
@@ -26,6 +25,7 @@ import flowChartRouter from "./modules/flowchart";
 import componentsRouter from "./modules/components";
 // 动态路由
 import { getAsyncRoutes } from "/@/api/routes";
+import { getMessage } from "../utils/i18n";
 
 // https://cn.vitejs.dev/guide/features.html#glob-import
 const modulesRoutes = import.meta.glob("/src/views/*/*/*.vue");
@@ -209,9 +209,13 @@ router.beforeEach((to, _from, next) => {
   NProgress.start();
   const externalLink = to?.redirectedFrom?.fullPath;
   // @ts-ignore
-  const { t } = i18n.global;
+  // const { t } = i18n.global;
   // @ts-ignore
-  if (!externalLink) to.meta.title ? (document.title = t(to.meta.title)) : "";
+  if (!externalLink)
+    to.meta.title
+      ? // @ts-ignore
+        (document.title = getMessage(to.meta.title, to.meta.i18n))
+      : "";
   if (name) {
     if (_from?.name) {
       // 如果路由包含http 则是超链接 反之是普通路由

+ 12 - 1
src/router/modules/components.ts

@@ -8,6 +8,7 @@ const componentsRouter = {
   meta: {
     icon: "Menu",
     title: "message.hscomponents",
+    i18n: true,
     showLink: true,
     rank: 4
   },
@@ -18,7 +19,8 @@ const componentsRouter = {
       component: () => import("/@/views/components/video/index.vue"),
       meta: {
         title: "message.hsvideo",
-        showLink: true
+        showLink: true,
+        i18n: true
       }
     },
     {
@@ -29,6 +31,7 @@ const componentsRouter = {
         title: "message.hsmap",
         showLink: true,
         keepAlive: true,
+        i18n: true,
         transition: {
           name: "fade"
         }
@@ -41,6 +44,7 @@ const componentsRouter = {
       meta: {
         title: "message.hsdraggable",
         showLink: true,
+        i18n: true,
         transition: {
           enterTransition: "animate__zoomIn",
           leaveTransition: "animate__zoomOut"
@@ -55,6 +59,7 @@ const componentsRouter = {
       meta: {
         title: "message.hssplitPane",
         showLink: true,
+        i18n: true,
         extraIcon: {
           svg: true,
           name: "team-iconxinpinrenqiwang"
@@ -67,6 +72,7 @@ const componentsRouter = {
       component: () => import("/@/views/components/button/index.vue"),
       meta: {
         title: "message.hsbutton",
+        i18n: true,
         showLink: true
       }
     },
@@ -76,6 +82,7 @@ const componentsRouter = {
       component: () => import("/@/views/components/cropping/index.vue"),
       meta: {
         title: "message.hscropping",
+        i18n: true,
         showLink: true
       }
     },
@@ -85,6 +92,7 @@ const componentsRouter = {
       component: () => import("/@/views/components/count-to/index.vue"),
       meta: {
         title: "message.hscountTo",
+        i18n: true,
         showLink: true
       }
     },
@@ -94,6 +102,7 @@ const componentsRouter = {
       component: () => import("/@/views/components/selector/index.vue"),
       meta: {
         title: "message.hsselector",
+        i18n: true,
         showLink: true
       }
     },
@@ -103,6 +112,7 @@ const componentsRouter = {
       component: () => import("/@/views/components/seamless-scroll/index.vue"),
       meta: {
         title: "message.hsseamless",
+        i18n: true,
         showLink: true
       }
     },
@@ -112,6 +122,7 @@ const componentsRouter = {
       component: () => import("/@/views/components/contextmenu/index.vue"),
       meta: {
         title: "message.hscontextmenu",
+        i18n: true,
         showLink: true
       }
     }

+ 2 - 0
src/router/modules/editor.ts

@@ -8,6 +8,7 @@ const editorRouter = {
   meta: {
     icon: "Edit",
     title: "message.hseditor",
+    i18n: true,
     showLink: true,
     rank: 2
   },
@@ -19,6 +20,7 @@ const editorRouter = {
       meta: {
         title: "message.hseditor",
         showLink: true,
+        i18n: true,
         keepAlive: true,
         extraIcon: {
           svg: true,

+ 3 - 0
src/router/modules/error.ts

@@ -9,6 +9,7 @@ const errorRouter = {
     icon: "Position",
     title: "message.hserror",
     showLink: true,
+    i18n: true,
     rank: 7
   },
   children: [
@@ -18,6 +19,7 @@ const errorRouter = {
       component: () => import("/@/views/error/401.vue"),
       meta: {
         title: "message.hsfourZeroOne",
+        i18n: true,
         showLink: true
       }
     },
@@ -27,6 +29,7 @@ const errorRouter = {
       component: () => import("/@/views/error/404.vue"),
       meta: {
         title: "message.hsfourZeroFour",
+        i18n: true,
         showLink: true
       }
     }

+ 2 - 0
src/router/modules/externalLink.ts

@@ -8,6 +8,7 @@ const externalLink = {
     icon: "Link",
     title: "message.externalLink",
     showLink: true,
+    i18n: true,
     rank: 190
   },
   children: [
@@ -16,6 +17,7 @@ const externalLink = {
       meta: {
         title: "message.externalLink",
         showLink: true,
+        i18n: true,
         rank: 191
       }
     }

+ 2 - 0
src/router/modules/flowchart.ts

@@ -9,6 +9,7 @@ const flowChartRouter = {
     icon: "SetUp",
     title: "message.hsflowChart",
     showLink: true,
+    i18n: true,
     rank: 1
   },
   children: [
@@ -18,6 +19,7 @@ const flowChartRouter = {
       component: () => import("/@/views/flow-chart/index.vue"),
       meta: {
         title: "message.hsflowChart",
+        i18n: true,
         showLink: true
       }
     }

+ 2 - 0
src/router/modules/home.ts

@@ -8,6 +8,7 @@ const homeRouter = {
   meta: {
     icon: "HomeFilled",
     showLink: true,
+    i18n: true,
     rank: 0
   },
   children: [
@@ -17,6 +18,7 @@ const homeRouter = {
       component: () => import("/@/views/welcome.vue"),
       meta: {
         title: "message.hshome",
+        i18n: true,
         showLink: true
       }
     }

+ 8 - 0
src/router/modules/nested.ts

@@ -9,6 +9,7 @@ const nestedRouter = {
     title: "message.hsmenus",
     icon: "Histogram",
     showLink: true,
+    i18n: true,
     rank: 5
   },
   children: [
@@ -19,6 +20,7 @@ const nestedRouter = {
       meta: {
         title: "message.hsmenu1",
         showLink: true,
+        i18n: true,
         keepAlive: true
       },
       redirect: "/nested/menu1/menu1-1",
@@ -30,6 +32,7 @@ const nestedRouter = {
           meta: {
             title: "message.hsmenu1-1",
             showLink: true,
+            i18n: true,
             keepAlive: true
           }
         },
@@ -41,6 +44,7 @@ const nestedRouter = {
           meta: {
             title: "message.hsmenu1-2",
             showLink: true,
+            i18n: true,
             keepAlive: true
           },
           children: [
@@ -52,6 +56,7 @@ const nestedRouter = {
               meta: {
                 title: "message.hsmenu1-2-1",
                 showLink: true,
+                i18n: true,
                 keepAlive: true
               }
             },
@@ -64,6 +69,7 @@ const nestedRouter = {
                 title: "message.hsmenu1-2-2",
                 showLink: true,
                 keepAlive: true,
+                i18n: true,
                 extraIcon: {
                   svg: true,
                   name: "team-iconxinpinrenqiwang"
@@ -79,6 +85,7 @@ const nestedRouter = {
           meta: {
             title: "message.hsmenu1-3",
             showLink: true,
+            i18n: true,
             keepAlive: true
           }
         }
@@ -91,6 +98,7 @@ const nestedRouter = {
       meta: {
         title: "message.hsmenu2",
         showLink: true,
+        i18n: true,
         keepAlive: true
       }
     }

+ 2 - 0
src/router/modules/remaining.ts

@@ -8,6 +8,7 @@ const remainingRouter = [
     meta: {
       title: "message.hslogin",
       showLink: false,
+      i18n: true,
       rank: 101
     }
   },
@@ -18,6 +19,7 @@ const remainingRouter = [
     meta: {
       icon: "HomeFilled",
       title: "message.hshome",
+      i18n: true,
       showLink: false,
       rank: 104
     },

+ 18 - 0
src/utils/i18n.ts

@@ -0,0 +1,18 @@
+import { i18n } from "../plugins/i18n";
+/**
+ * 获取对应的消息
+ * @param message message
+ * @param isI18n  如果true,获取对应的消息,否则返回this
+ * @returns message
+ */
+export function getMessage(message = "", isI18n: Boolean = false) {
+  if (!message) {
+    return "";
+  }
+  if (isI18n) {
+    //@ts-ignore
+    return i18n.global.tc.call(i18n.global, message);
+  } else {
+    return message;
+  }
+}