Files
sub2api/frontend/src/i18n/index.ts
wucm667 82fbf452a8 feat(i18n): 切换语言时同步更新页面标题
- resolveDocumentTitle() 新增 titleKey 参数,优先通过 i18n 翻译
- router beforeEach 中将路由 meta.titleKey 传入标题解析函数
- setLocale() 切换语言后同步刷新 document.title
2026-02-26 14:04:13 +08:00

92 lines
2.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { createI18n } from 'vue-i18n'
type LocaleCode = 'en' | 'zh'
type LocaleMessages = Record<string, any>
const LOCALE_KEY = 'sub2api_locale'
const DEFAULT_LOCALE: LocaleCode = 'en'
const localeLoaders: Record<LocaleCode, () => Promise<{ default: LocaleMessages }>> = {
en: () => import('./locales/en'),
zh: () => import('./locales/zh')
}
function isLocaleCode(value: string): value is LocaleCode {
return value === 'en' || value === 'zh'
}
function getDefaultLocale(): LocaleCode {
const saved = localStorage.getItem(LOCALE_KEY)
if (saved && isLocaleCode(saved)) {
return saved
}
const browserLang = navigator.language.toLowerCase()
if (browserLang.startsWith('zh')) {
return 'zh'
}
return DEFAULT_LOCALE
}
export const i18n = createI18n({
legacy: false,
locale: getDefaultLocale(),
fallbackLocale: DEFAULT_LOCALE,
messages: {},
// 禁用 HTML 消息警告 - 引导步骤使用富文本内容driver.js 支持 HTML
// 这些内容是内部定义的,不存在 XSS 风险
warnHtmlMessage: false
})
const loadedLocales = new Set<LocaleCode>()
export async function loadLocaleMessages(locale: LocaleCode): Promise<void> {
if (loadedLocales.has(locale)) {
return
}
const loader = localeLoaders[locale]
const module = await loader()
i18n.global.setLocaleMessage(locale, module.default)
loadedLocales.add(locale)
}
export async function initI18n(): Promise<void> {
const current = getLocale()
await loadLocaleMessages(current)
document.documentElement.setAttribute('lang', current)
}
export async function setLocale(locale: string): Promise<void> {
if (!isLocaleCode(locale)) {
return
}
await loadLocaleMessages(locale)
i18n.global.locale.value = locale
localStorage.setItem(LOCALE_KEY, 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 {
const current = i18n.global.locale.value
return isLocaleCode(current) ? current : DEFAULT_LOCALE
}
export const availableLocales = [
{ code: 'en', name: 'English', flag: '🇺🇸' },
{ code: 'zh', name: '中文', flag: '🇨🇳' }
] as const
export default i18n