fix(i18n): H5 路由 meta.title 改为 i18n key 并随语言切换刷新

两端守卫用 t() 解析 document.title,补齐 10 语种 route 文案。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
bootx
2026-07-20 16:06:41 +08:00
parent dc196aca8f
commit 63d7aa32b9
25 changed files with 214 additions and 33 deletions

View File

@@ -8,7 +8,7 @@ export const ErrorPageRoute: RouteRecordRaw = {
name: 'ErrorPage',
component: Layout,
meta: {
title: 'ErrorPage',
title: 'route.errorPage', // 页面不存在
hideBreadcrumb: true,
},
children: [
@@ -17,7 +17,7 @@ export const ErrorPageRoute: RouteRecordRaw = {
name: 'ErrorPageSon',
component: () => import('@/mobile/views/exception/404.vue'),
meta: {
title: 'ErrorPage',
title: 'route.errorPage', // 页面不存在
hideBreadcrumb: true,
},
},

View File

@@ -11,7 +11,7 @@ const routeModuleList: Array<RouteRecordRaw> = [
name: 'Home',
component: Layout,
meta: {
title: '首页',
title: 'route.home', // 首页
},
children: [
{
@@ -30,7 +30,7 @@ const routeModuleList: Array<RouteRecordRaw> = [
name: 'Cashier',
component: Layout,
meta: {
title: '收银台',
title: 'route.cashier', // 收银台
},
children: [
{
@@ -59,7 +59,7 @@ const routeModuleList: Array<RouteRecordRaw> = [
component: Layout,
// 父级声明 title子路由unsupported / 各环境页 / entry由 vue-router 的 to.meta 合并自动继承
meta: {
title: '收银台',
title: 'route.cashier', // 收银台
},
children: [
// 非宿主提示:静态 path 段
@@ -106,7 +106,7 @@ const routeModuleList: Array<RouteRecordRaw> = [
name: 'CodePayWechat',
component: Layout,
meta: {
title: '码牌支付',
title: 'route.codePay', // 码牌支付
},
children: [
{
@@ -122,7 +122,7 @@ const routeModuleList: Array<RouteRecordRaw> = [
name: 'CodePayAlipay',
component: Layout,
meta: {
title: '码牌支付',
title: 'route.codePay', // 码牌支付
},
children: [
{
@@ -138,7 +138,7 @@ const routeModuleList: Array<RouteRecordRaw> = [
name: 'CodePayUnion',
component: Layout,
meta: {
title: '码牌支付',
title: 'route.codePay', // 码牌支付
},
children: [
{
@@ -154,7 +154,7 @@ const routeModuleList: Array<RouteRecordRaw> = [
name: 'CodePayDouyin',
component: Layout,
meta: {
title: '码牌支付',
title: 'route.codePay', // 码牌支付
},
children: [
{
@@ -170,7 +170,7 @@ const routeModuleList: Array<RouteRecordRaw> = [
name: 'CodePay',
component: Layout,
meta: {
title: '码牌支付',
title: 'route.codePay', // 码牌支付
},
children: [
{
@@ -186,7 +186,7 @@ const routeModuleList: Array<RouteRecordRaw> = [
name: 'Protocol',
component: Layout,
meta: {
title: '协议',
title: 'route.protocol', // 协议
},
children: [
{
@@ -202,7 +202,7 @@ const routeModuleList: Array<RouteRecordRaw> = [
name: 'AlipayAuth',
component: () => import('@/mobile/views/auth/alipay/index.vue'),
meta: {
title: '支付宝认证',
title: 'route.alipayAuth', // 支付宝认证
},
},
// 支付宝代运营授权落地页(移动独占:授权回跳换 app_auth_token
@@ -211,7 +211,7 @@ const routeModuleList: Array<RouteRecordRaw> = [
name: 'AlipayIsvAuth',
component: () => import('@/mobile/views/isv-auth/alipay/index.vue'),
meta: {
title: '支付宝代运营授权',
title: 'route.alipayIsvAuth', // 支付宝代运营授权
},
},
// 微信认证落地页(跨端:与 PC 端同 path 各指各 view微信公众号 OAuth 重定向回调取 code
@@ -220,7 +220,7 @@ const routeModuleList: Array<RouteRecordRaw> = [
name: 'WechatAuth',
component: () => import('@/mobile/views/auth/wechat/index.vue'),
meta: {
title: '微信认证',
title: 'route.wechatAuth', // 微信认证
},
},
// 抖音认证落地页(移动独占:抖音 silent_auth 重定向回调取 code
@@ -229,7 +229,7 @@ const routeModuleList: Array<RouteRecordRaw> = [
name: 'DouyinAuth',
component: () => import('@/mobile/views/auth/douyin/index.vue'),
meta: {
title: '抖音认证',
title: 'route.douyinAuth', // 抖音认证
},
},
]

View File

@@ -1,11 +1,22 @@
import type { Router } from 'vue-router'
import NProgress from 'nprogress'
import { watch } from 'vue'
import { isNavigationFailure } from 'vue-router'
import i18n, { t } from '@/shared/locales'
import { useRouteStoreWithOut } from '@/shared/store/modules/route'
import 'nprogress/nprogress.css'
NProgress.configure({ parent: '#app' })
/** 根据路由 meta.titlei18n key设置浏览器标题 */
function applyRouteDocumentTitle(router: Router) {
const key = router.currentRoute.value.meta?.title as string | undefined
if (key) {
// 路由页标题
document.title = t(key)
}
}
export function createRouterGuards(router: Router) {
router.beforeEach(() => {
NProgress.start()
@@ -15,8 +26,11 @@ export function createRouterGuards(router: Router) {
// 进入某个路由之后触发的钩子
router.afterEach((to, _, failure) => {
// 设置每个页面的 title
document.title = (to?.meta?.title as string) || document.title
// 设置每个页面的 titlemeta.title 存 i18n key
const titleKey = to?.meta?.title as string | undefined
if (titleKey) {
document.title = t(titleKey)
}
if (isNavigationFailure(failure)) {
console.warn('failed navigation', failure)
@@ -49,6 +63,14 @@ export function createRouterGuards(router: Router) {
NProgress.done()
})
// 切换语言时刷新当前页 document.title
watch(
() => i18n.global.locale.value,
() => {
applyRouteDocumentTitle(router)
},
)
router.onError((error) => {
console.error(error, '路由错误')
})

View File

@@ -25,73 +25,73 @@ const routes: RouteRecordRaw[] = [
path: RoutePath.CASHIER,
name: 'PcCashier',
component: () => import('@/pc/views/cashier/Index.vue'),
meta: { title: '收银台' },
meta: { title: 'route.cashier' }, // 收银台
},
// 聚合「非宿主」提示:须在 /aggregate/:orderNo 之前注册,避免 path 段 "unsupported" 被当成 orderNo 查单
{
path: RoutePath.AGGREGATE_UNSUPPORTED,
name: 'PcAggregateUnsupported',
component: () => import('@/pc/views/aggregate/Unsupported.vue'),
meta: { title: '收银台' },
meta: { title: 'route.cashier' }, // 收银台
},
// 聚合扫码支付(跨端)
{
path: RoutePath.AGGREGATE,
name: 'PcAggregate',
component: () => import('@/pc/views/aggregate/Index.vue'),
meta: { title: '收银台' },
meta: { title: 'route.cashier' }, // 收银台
},
// 商户对账单PC 独占:移动端由注册表派生 device-only 存根)
{
path: RoutePath.MERCHANT_STATEMENT,
name: 'MerchantStatement',
component: () => import('@/pc/views/statement/Index.vue'),
meta: { title: '商户对账单' },
meta: { title: 'route.merchantStatement' }, // 商户对账单
},
// 协议展示页(跨端:与移动端同 path 各指各 view链接可独立分享
{
path: RoutePath.PROTOCOL,
name: 'PcProtocol',
component: () => import('@/pc/views/protocol/Index.vue'),
meta: { title: '协议' },
meta: { title: 'route.protocol' }, // 协议
},
// 微信认证落地页(跨端:与移动端同 path 各指各 viewPC 微信内置浏览器可访问)
{
path: RoutePath.AUTH_WECHAT,
name: 'PcWechatAuth',
component: () => import('@/pc/views/auth/wechat/Index.vue'),
meta: { title: '微信认证' },
meta: { title: 'route.wechatAuth' }, // 微信认证
},
// 码牌支付PC 仅展示扫码引导(静态段须在 /h/:code 之前)
{
path: RoutePath.CODE_PAY_WECHAT,
name: 'PcCodePayWechat',
component: () => import('@/pc/views/code-pay/Index.vue'),
meta: { title: '码牌支付' },
meta: { title: 'route.codePay' }, // 码牌支付
},
{
path: RoutePath.CODE_PAY_ALIPAY,
name: 'PcCodePayAlipay',
component: () => import('@/pc/views/code-pay/Index.vue'),
meta: { title: '码牌支付' },
meta: { title: 'route.codePay' }, // 码牌支付
},
{
path: RoutePath.CODE_PAY_UNION,
name: 'PcCodePayUnion',
component: () => import('@/pc/views/code-pay/Index.vue'),
meta: { title: '码牌支付' },
meta: { title: 'route.codePay' }, // 码牌支付
},
{
path: RoutePath.CODE_PAY_DOUYIN,
name: 'PcCodePayDouyin',
component: () => import('@/pc/views/code-pay/Index.vue'),
meta: { title: '码牌支付' },
meta: { title: 'route.codePay' }, // 码牌支付
},
{
path: RoutePath.CODE_PAY,
name: 'PcCodePay',
component: () => import('@/pc/views/code-pay/Index.vue'),
meta: { title: '码牌支付' },
meta: { title: 'route.codePay' }, // 码牌支付
},
...mobileOnlyStubs,
// 兜底:移动端专属路径(如 /home/index或任何未匹配路径渲染 PC 404 页

View File

@@ -1,10 +1,21 @@
import type { Router } from 'vue-router'
import { watch } from 'vue'
import i18n, { t } from '@/shared/locales'
/** 根据路由 meta.titlei18n key设置浏览器标题 */
function applyRouteDocumentTitle(router: Router) {
const key = router.currentRoute.value.meta?.title as string | undefined
if (key) {
// 路由页标题
document.title = t(key)
}
}
/**
* PC 端路由守卫
*
* 仅处理 document.title 切换:当目标路由(或其 matched 链上任意父级)
* 声明了 meta.title 时,更新为该标题;否则保留当前 title通常为
* 声明了 meta.titlei18n key用 t() 解析后更新;否则保留当前 title通常为
* 站点 systemName由 [applyWebsiteBranding] 设置)。
*
* 与 mobile/router/router-guards.ts 对称实现,去掉 keepAlive 逻辑
@@ -12,10 +23,18 @@ import type { Router } from 'vue-router'
*/
export function createPcRouterGuards(router: Router) {
router.afterEach((to) => {
// 设置每个页面的 title
const title = to?.meta?.title as string | undefined
if (title) {
document.title = title
// 设置每个页面的 titlemeta.title 存 i18n key
const titleKey = to?.meta?.title as string | undefined
if (titleKey) {
document.title = t(titleKey)
}
})
// 切换语言时刷新当前页 document.title
watch(
() => i18n.global.locale.value,
() => {
applyRouteDocumentTitle(router)
},
)
}

View File

@@ -8,6 +8,7 @@ import home from './home.json'
import http from './http.json'
import isvAuth from './isv-auth.json'
import protocol from './protocol.json'
import route from './route.json'
import statement from './statement.json'
export default {
@@ -18,6 +19,7 @@ export default {
cashier,
codePay,
protocol,
route,
statement,
home,
error,

View File

@@ -0,0 +1,12 @@
{
"home": "Home",
"cashier": "Cashier",
"codePay": "QR Code Payment",
"protocol": "Agreement",
"alipayAuth": "Alipay Auth",
"alipayIsvAuth": "Alipay Agent Authorization",
"wechatAuth": "WeChat Auth",
"douyinAuth": "Douyin Auth",
"merchantStatement": "Merchant Statement",
"errorPage": "Page Not Found"
}

View File

@@ -8,6 +8,7 @@ import home from './home.json'
import http from './http.json'
import isvAuth from './isv-auth.json'
import protocol from './protocol.json'
import route from './route.json'
import statement from './statement.json'
export default {
@@ -18,6 +19,7 @@ export default {
cashier,
codePay,
protocol,
route,
statement,
home,
error,

View File

@@ -0,0 +1,12 @@
{
"home": "Beranda",
"cashier": "Kasir",
"codePay": "Pembayaran Kode QR",
"protocol": "Perjanjian",
"alipayAuth": "Autentikasi Alipay",
"alipayIsvAuth": "Otorisasi agen Alipay",
"wechatAuth": "Autentikasi WeChat",
"douyinAuth": "Autentikasi Douyin",
"merchantStatement": "Pernyataan Pedagang",
"errorPage": "Halaman tidak ditemukan"
}

View File

@@ -8,6 +8,7 @@ import home from './home.json'
import http from './http.json'
import isvAuth from './isv-auth.json'
import protocol from './protocol.json'
import route from './route.json'
import statement from './statement.json'
export default {
@@ -18,6 +19,7 @@ export default {
cashier,
codePay,
protocol,
route,
statement,
home,
error,

View File

@@ -0,0 +1,12 @@
{
"home": "ホーム",
"cashier": "レジ",
"codePay": "QRコード決済",
"protocol": "合意",
"alipayAuth": "Alipay認証",
"alipayIsvAuth": "Alipay代理店承認",
"wechatAuth": "WeChat認証",
"douyinAuth": "Douyin認証",
"merchantStatement": "販売者の声明",
"errorPage": "ページが見つかりません"
}

View File

@@ -8,6 +8,7 @@ import home from './home.json'
import http from './http.json'
import isvAuth from './isv-auth.json'
import protocol from './protocol.json'
import route from './route.json'
import statement from './statement.json'
export default {
@@ -18,6 +19,7 @@ export default {
cashier,
codePay,
protocol,
route,
statement,
home,
error,

View File

@@ -0,0 +1,12 @@
{
"home": "홈",
"cashier": "계산대",
"codePay": "QR 코드 결제",
"protocol": "합의",
"alipayAuth": "Alipay 인증",
"alipayIsvAuth": "Alipay 대리점 승인",
"wechatAuth": "WeChat 인증",
"douyinAuth": "Douyin 인증",
"merchantStatement": "판매자 명세서",
"errorPage": "페이지를 찾을 수 없음"
}

View File

@@ -8,6 +8,7 @@ import home from './home.json'
import http from './http.json'
import isvAuth from './isv-auth.json'
import protocol from './protocol.json'
import route from './route.json'
import statement from './statement.json'
export default {
@@ -18,6 +19,7 @@ export default {
cashier,
codePay,
protocol,
route,
statement,
home,
error,

View File

@@ -0,0 +1,12 @@
{
"home": "Laman Utama",
"cashier": "Kaunter",
"codePay": "Pembayaran Kod QR",
"protocol": "Perjanjian",
"alipayAuth": "Pengesahan Alipay",
"alipayIsvAuth": "Keizinan ejen Alipay",
"wechatAuth": "Pengesahan WeChat",
"douyinAuth": "Pengesahan Douyin",
"merchantStatement": "Penyata Peniaga",
"errorPage": "Halaman tidak dijumpai"
}

View File

@@ -8,6 +8,7 @@ import home from './home.json'
import http from './http.json'
import isvAuth from './isv-auth.json'
import protocol from './protocol.json'
import route from './route.json'
import statement from './statement.json'
export default {
@@ -18,6 +19,7 @@ export default {
cashier,
codePay,
protocol,
route,
statement,
home,
error,

View File

@@ -0,0 +1,12 @@
{
"home": "หน้าแรก",
"cashier": "แคชเชียร์",
"codePay": "ชำระเงินด้วยคิวอาร์โค้ด",
"protocol": "ข้อตกลง",
"alipayAuth": "การยืนยันตัวตน Alipay",
"alipayIsvAuth": "การอนุญาตตัวแทน Alipay",
"wechatAuth": "การยืนยันตัวตน WeChat",
"douyinAuth": "การยืนยันตัวตน Douyin",
"merchantStatement": "คำชี้แจงของผู้ขาย",
"errorPage": "ไม่พบหน้า"
}

View File

@@ -8,6 +8,7 @@ import home from './home.json'
import http from './http.json'
import isvAuth from './isv-auth.json'
import protocol from './protocol.json'
import route from './route.json'
import statement from './statement.json'
export default {
@@ -18,6 +19,7 @@ export default {
cashier,
codePay,
protocol,
route,
statement,
home,
error,

View File

@@ -0,0 +1,12 @@
{
"home": "Trang chủ",
"cashier": "Thu ngân",
"codePay": "Thanh toán mã QR",
"protocol": "Hiệp định",
"alipayAuth": "Xác thực Alipay",
"alipayIsvAuth": "Ủy quyền đại lý Alipay",
"wechatAuth": "Xác thực WeChat",
"douyinAuth": "Xác thực Douyin",
"merchantStatement": "Tuyên bố của người bán",
"errorPage": "Không tìm thấy trang"
}

View File

@@ -8,6 +8,7 @@ import home from './home.json'
import http from './http.json'
import isvAuth from './isv-auth.json'
import protocol from './protocol.json'
import route from './route.json'
import statement from './statement.json'
export default {
@@ -18,6 +19,7 @@ export default {
cashier,
codePay,
protocol,
route,
statement,
home,
error,

View File

@@ -0,0 +1,12 @@
{
"home": "首页",
"cashier": "收银台",
"codePay": "码牌支付",
"protocol": "协议",
"alipayAuth": "支付宝认证",
"alipayIsvAuth": "支付宝代运营授权",
"wechatAuth": "微信认证",
"douyinAuth": "抖音认证",
"merchantStatement": "商户对账单",
"errorPage": "页面不存在"
}

View File

@@ -8,6 +8,7 @@ import home from './home.json'
import http from './http.json'
import isvAuth from './isv-auth.json'
import protocol from './protocol.json'
import route from './route.json'
import statement from './statement.json'
export default {
@@ -18,6 +19,7 @@ export default {
cashier,
codePay,
protocol,
route,
statement,
home,
error,

View File

@@ -0,0 +1,12 @@
{
"home": "首頁",
"cashier": "收銀台",
"codePay": "碼牌支付",
"protocol": "協議",
"alipayAuth": "支付寶認證",
"alipayIsvAuth": "支付寶代運營授權",
"wechatAuth": "微信認證",
"douyinAuth": "抖音認證",
"merchantStatement": "商户對賬單",
"errorPage": "頁面不存在"
}

View File

@@ -8,6 +8,7 @@ import home from './home.json'
import http from './http.json'
import isvAuth from './isv-auth.json'
import protocol from './protocol.json'
import route from './route.json'
import statement from './statement.json'
export default {
@@ -18,6 +19,7 @@ export default {
cashier,
codePay,
protocol,
route,
statement,
home,
error,

View File

@@ -0,0 +1,12 @@
{
"home": "首頁",
"cashier": "收銀台",
"codePay": "碼牌支付",
"protocol": "協議",
"alipayAuth": "支付寶認證",
"alipayIsvAuth": "支付寶代運營授權",
"wechatAuth": "微信認證",
"douyinAuth": "抖音認證",
"merchantStatement": "商戶對賬單",
"errorPage": "頁面不存在"
}