多语言路由切换时导航守卫的核心任务是识别语言状态、补全正确语言前缀并透传query/hash参数,本质为重定向+参数透传;需解析to.path语言前缀、对比i18n.locale、安全构造newPath并显式传递query与hash,排除白名单路径,配合动态路由配置与命名路由调用。

多语言路由切换时,导航守卫的核心任务不是“校验语言”,而是识别当前语言状态、确保目标路径携带正确语言前缀、并维持原有路由参数(query/hash)不丢失。它本质上是路由重定向 + 参数透传的组合逻辑,而非权限类校验。
识别当前语言与目标语言是否匹配
守卫需从两个来源判断语言一致性:
- 从
to.fullPath或to.path解析出当前 URL 中的语言前缀(如/zh/product/123中的zh) - 从应用状态获取期望语言(如
i18n.locale、store.state.lang或 localStorage 中的lang) - 若两者不一致(比如用户切换语言后点击链接跳转到
/product/123,但当前应为/en/product/123),就触发标准化重定向
构造带语言前缀的目标路径并保留 query 和 hash
不能简单用 next('/en' + to.path),否则会丢掉 ?ref=home 和 #specs。正确做法是:
递归分析 Vue 项目组件依赖,从入口文件生成组件层级图,支持 Vue 2/3,输出组件名、文件路径和属性。适用于分析组件结构、排查依赖或了解项目架构。
- 提取
to.path的纯路径部分(去掉已有语言前缀,如把/zh/product/123→/product/123) - 拼接新语言前缀:
const newPath = `/${targetLang}${cleanPath}` - 用
next({ path: newPath, query: to.query, hash: to.hash })显式传递所有参数 - 注意:如果路由配置启用了
history: createWebHistory('/')且使用子路径部署(如部署在/app/下),语言前缀实际应为/app/zh/...,需结合router.options.history.base处理
避免循环重定向和死链
守卫中必须设置安全出口,否则可能陷入重定向循环:
立即学习“前端免费学习笔记(深入)”;
- 对已带正确语言前缀的路径(如
to.path.startsWith('/en')且i18n.locale === 'en'),直接next() - 排除白名单路径(如登录页
/login、错误页/404)不做语言前缀处理 - 若目标路径本身无语言前缀(如
to.path === '/product/123'),才执行补前缀逻辑;否则只做校验 - 建议在
beforeEach中统一处理,不要在beforeResolve或组件内守卫重复干预
配合路由配置启用多语言路径模式
仅靠守卫不够,路由定义本身要支持动态语言前缀:
- 使用带参数的路径:
{ path: '/:lang(en|zh|ja)/:pathMatch(.*)*', name: 'LocaleLayout', component: LocaleLayout } - 或在根级路由下嵌套语言子路由,再通过
children统一匹配 - 这样守卫中才能安全地解析和替换语言段,而不是硬编码字符串切割
- 同时,
router.push和<router-link>应始终基于命名路由 +params.lang构建,而非拼接字符串,以保证源头一致


















