feat(i18n): 切换语言时同步更新页面标题
- resolveDocumentTitle() 新增 titleKey 参数,优先通过 i18n 翻译 - router beforeEach 中将路由 meta.titleKey 传入标题解析函数 - setLocale() 切换语言后同步刷新 document.title
This commit is contained in:
@@ -68,6 +68,14 @@ export async function setLocale(locale: string): Promise<void> {
|
|||||||
i18n.global.locale.value = locale
|
i18n.global.locale.value = locale
|
||||||
localStorage.setItem(LOCALE_KEY, locale)
|
localStorage.setItem(LOCALE_KEY, locale)
|
||||||
document.documentElement.setAttribute('lang', locale)
|
document.documentElement.setAttribute('lang', locale)
|
||||||
|
|
||||||
|
// 同步更新浏览器页签标题,使其跟随语言切换
|
||||||
|
const { resolveDocumentTitle } = await import('@/router/title')
|
||||||
|
const { default: router } = await import('@/router')
|
||||||
|
const { useAppStore } = await import('@/stores/app')
|
||||||
|
const route = router.currentRoute.value
|
||||||
|
const appStore = useAppStore()
|
||||||
|
document.title = resolveDocumentTitle(route.meta.title, appStore.siteName, route.meta.titleKey as string)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getLocale(): LocaleCode {
|
export function getLocale(): LocaleCode {
|
||||||
|
|||||||
@@ -41,7 +41,8 @@ const routes: RouteRecordRaw[] = [
|
|||||||
component: () => import('@/views/auth/LoginView.vue'),
|
component: () => import('@/views/auth/LoginView.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
requiresAuth: false,
|
requiresAuth: false,
|
||||||
title: 'Login'
|
title: 'Login',
|
||||||
|
titleKey: 'common.login'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -50,7 +51,8 @@ const routes: RouteRecordRaw[] = [
|
|||||||
component: () => import('@/views/auth/RegisterView.vue'),
|
component: () => import('@/views/auth/RegisterView.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
requiresAuth: false,
|
requiresAuth: false,
|
||||||
title: 'Register'
|
title: 'Register',
|
||||||
|
titleKey: 'auth.createAccount'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -86,7 +88,8 @@ const routes: RouteRecordRaw[] = [
|
|||||||
component: () => import('@/views/auth/ForgotPasswordView.vue'),
|
component: () => import('@/views/auth/ForgotPasswordView.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
requiresAuth: false,
|
requiresAuth: false,
|
||||||
title: 'Forgot Password'
|
title: 'Forgot Password',
|
||||||
|
titleKey: 'auth.forgotPasswordTitle'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -390,7 +393,7 @@ router.beforeEach((to, _from, next) => {
|
|||||||
|
|
||||||
// Set page title
|
// Set page title
|
||||||
const appStore = useAppStore()
|
const appStore = useAppStore()
|
||||||
document.title = resolveDocumentTitle(to.meta.title, appStore.siteName)
|
document.title = resolveDocumentTitle(to.meta.title, appStore.siteName, to.meta.titleKey as string)
|
||||||
|
|
||||||
// Check if route requires authentication
|
// Check if route requires authentication
|
||||||
const requiresAuth = to.meta.requiresAuth !== false // Default to true
|
const requiresAuth = to.meta.requiresAuth !== false // Default to true
|
||||||
|
|||||||
@@ -1,9 +1,19 @@
|
|||||||
|
import { i18n } from '@/i18n'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 统一生成页面标题,避免多处写入 document.title 产生覆盖冲突。
|
* 统一生成页面标题,避免多处写入 document.title 产生覆盖冲突。
|
||||||
|
* 优先使用 titleKey 通过 i18n 翻译,fallback 到静态 routeTitle。
|
||||||
*/
|
*/
|
||||||
export function resolveDocumentTitle(routeTitle: unknown, siteName?: string): string {
|
export function resolveDocumentTitle(routeTitle: unknown, siteName?: string, titleKey?: string): string {
|
||||||
const normalizedSiteName = typeof siteName === 'string' && siteName.trim() ? siteName.trim() : 'Sub2API'
|
const normalizedSiteName = typeof siteName === 'string' && siteName.trim() ? siteName.trim() : 'Sub2API'
|
||||||
|
|
||||||
|
if (typeof titleKey === 'string' && titleKey.trim()) {
|
||||||
|
const translated = i18n.global.t(titleKey)
|
||||||
|
if (translated && translated !== titleKey) {
|
||||||
|
return `${translated} - ${normalizedSiteName}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (typeof routeTitle === 'string' && routeTitle.trim()) {
|
if (typeof routeTitle === 'string' && routeTitle.trim()) {
|
||||||
return `${routeTitle.trim()} - ${normalizedSiteName}`
|
return `${routeTitle.trim()} - ${normalizedSiteName}`
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user