菜单多语言配置

This commit is contained in:
2026-03-17 09:52:21 +08:00
parent 425e9feb56
commit 8e51ca8930
9 changed files with 138 additions and 31 deletions

View File

@@ -11,6 +11,62 @@ import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import i18n, { $t } from '@/locales'
/**
* 路径到菜单 i18n key 的映射
* 当后端返回的菜单名为中文或非 i18n key 时,根据 path 仍可显示多语言
*/
export const MAP_PATH_TO_MENU_I18N_KEY: Record<string, string> = {
'/dashboard': 'menus.dashboard.title',
'/dashboard/console': 'menus.dashboard.console',
'/dashboard/user-center': 'menus.userCenter.title',
'/system': 'menus.system.title',
'/system/user': 'menus.system.user',
'/system/role': 'menus.system.role',
'/system/user-center': 'menus.system.userCenter',
'/system/menu': 'menus.system.menu',
'/system/dept': 'menus.system.dept',
'/system/post': 'menus.system.post',
'/system/config': 'menus.system.config',
'/safeguard': 'menus.safeguard.title',
'/safeguard/dict': 'menus.safeguard.dict',
'/safeguard/server': 'menus.safeguard.server',
'/safeguard/oper-log': 'menus.safeguard.operLog',
'/safeguard/login-log': 'menus.safeguard.loginLog',
'/safeguard/email-log': 'menus.safeguard.emailLog',
'/safeguard/database': 'menus.safeguard.database',
'/safeguard/cache': 'menus.safeguard.cache',
'/safeguard/attachment': 'menus.safeguard.attachment',
'/tool': 'menus.tool.title',
'/tool/crontab': 'menus.tool.crontab',
'/tool/code': 'menus.tool.code',
'/dice': 'menus.dice.title',
'/dice/lottery_pool_config': 'menus.dice.lotteryPoolConfig',
'/dice/lottery_pool_config/index': 'menus.dice.lotteryPoolConfig',
'/dice/player': 'menus.dice.player',
'/dice/player/index': 'menus.dice.player',
'/dice/player_wallet_record': 'menus.dice.playerWalletRecord',
'/dice/player_wallet_record/index': 'menus.dice.playerWalletRecord',
'/dice/play_record': 'menus.dice.playRecord',
'/dice/play_record/index': 'menus.dice.playRecord',
'/dice/player_ticket_record': 'menus.dice.playerTicketRecord',
'/dice/player_ticket_record/index': 'menus.dice.playerTicketRecord',
'/dice/reward_config': 'menus.dice.rewardConfig',
'/dice/reward_config/index': 'menus.dice.rewardConfig',
'/dice/reward': 'menus.dice.reward',
'/dice/reward/index': 'menus.dice.reward',
'/dice/reward_config_record': 'menus.dice.rewardConfigRecord',
'/dice/reward_config_record/index': 'menus.dice.rewardConfigRecord',
'/dice/play_record_test': 'menus.dice.playRecordTest',
'/dice/play_record_test/index': 'menus.dice.playRecordTest',
'/dice/config': 'menus.dice.config',
'/dice/config/index': 'menus.dice.config',
'/result/success': 'menus.result.success',
'/result/fail': 'menus.result.fail',
'/exception/403': 'menus.exception.forbidden',
'/exception/404': 'menus.exception.notFound',
'/exception/500': 'menus.exception.serverError'
}
/** 扩展的路由配置类型 */
export type AppRouteRecordRaw = RouteRecordRaw & {
hidden?: boolean
@@ -34,28 +90,42 @@ export const setPageTitle = (to: RouteLocationNormalized): void => {
const { title } = to.meta
if (title) {
setTimeout(() => {
document.title = `${formatMenuTitle(String(title))} - ${AppConfig.systemInfo.name}`
document.title = `${formatMenuTitle(String(title), to.path)} - ${AppConfig.systemInfo.name}`
}, 150)
}
}
/**
* 根据路径获取对应的菜单 i18n key若有
*/
export const getMenuI18nKeyByPath = (path: string): string | undefined => {
if (!path) return undefined
const normalized = path.replace(/\?.*$/, '').replace(/#.*$/, '').replace(/\/$/, '') || '/'
return MAP_PATH_TO_MENU_I18N_KEY[normalized]
}
/**
* 格式化菜单标题
* @param title 菜单标题,可以是 i18n 的 key,也可以是字符串
* @param title 菜单标题,可以是 i18n 的 key(如 menus.dashboard.title也可以是中文等纯文本
* @param path 可选,当前菜单路由 path当 title 非 i18n key 时,用 path 查表得到 key 再翻译,以实现多语言切换
* @returns 格式化后的菜单标题
*/
export const formatMenuTitle = (title: string): string => {
if (title) {
if (title.startsWith('menus.')) {
// 使用 te() 方法检查翻译键值是否存在,避免控制台警告
if (i18n.global.te(title)) {
return $t(title)
} else {
// 如果翻译不存在返回键值的最后部分作为fallback
return title.split('.').pop() || title
}
export const formatMenuTitle = (title: string, path?: string): string => {
if (!title) return ''
if (title.startsWith('menus.')) {
if (i18n.global.te(title)) {
return $t(title)
}
return title
return title.split('.').pop() || title
}
return ''
if (path) {
const i18nKey = getMenuI18nKeyByPath(path)
if (i18nKey && i18n.global.te(i18nKey)) {
return $t(i18nKey)
}
}
return title
}