Tauri 应用窗口标题国际化:动态切换语言时标题不更新的排查与解决
Tauri 应用窗口标题国际化:动态切换语言时标题不更新的排查与解决
问题描述
在 Tauri v2 应用中实现国际化(i18n)后,切换语言时页面内容正常切换,但原生窗口标题栏始终不变,停留在初始语言。
根因分析
涉及三个层面的问题,需逐一解决:
1. document.title 无法更新原生窗口标题
Tauri 的窗口标题是操作系统原生控件,document.title 只修改 webview 内部的 document 标题,不会同步到原生窗口标题栏。
// ❌ 无效 - 只改了 webview 内部标题
document.title = t("app.name");
必须使用 Tauri Window API:
import { getCurrentWindow } from "@tauri-apps/api/window";
getCurrentWindow().setTitle(t("app.name"));
2. 缺少 Tauri 权限导致 API 静默失败
Tauri v2 的权限系统要求显式声明窗口操作权限。未授权时,setTitle() 调用不会报错,而是静默忽略,这是最难排查的一点。
解决: 在 src-tauri/capabilities/default.json 中添加权限:
{
"permissions": [
"core:window:allow-set-title"
]
}
关键提示: Tauri v2 的权限系统对未授权调用采用静默忽略策略,不会抛出异常或输出警告,极易误判为 API 本身的问题。
3. setTitle 放在了非全局组件中
当使用路由切换页面时(如从主页进入设置页),如果 setTitle 的逻辑放在某个路由组件中,切换到其他路由后该组件卸载,useEffect 不再触发。
// ❌ MainWindow 只在首页路由渲染,设置页不渲染
function App() {
if (routePath === "#/settings") return <SettingsPanel />;
return <MainWindow />; // setTitle 在这里,设置页不触发
}
解决: 将 setTitle 逻辑放在始终渲染的顶层组件中:
// ✅ App 组件始终渲染,无论当前路由
function App() {
const { t } = useTranslation();
const appTitle = t("app.name");
useEffect(() => {
getCurrentWindow().setTitle(appTitle);
}, [appTitle]);
// ...路由逻辑
}
完整解决方案
步骤 1:添加权限
src-tauri/capabilities/default.json:
{
"permissions": [
"core:window:allow-set-title"
]
}
步骤 2:在顶层组件中设置标题
import { getCurrentWindow } from "@tauri-apps/api/window";
import { useTranslation } from "react-i18next";
function App() {
const { t } = useTranslation();
const appTitle = t("app.name");
useEffect(() => {
getCurrentWindow().setTitle(appTitle);
}, [appTitle]);
// ...
}
步骤 3:默认标题配置
src-tauri/tauri.conf.json 中设置默认标题(应用启动时显示,JS 加载前可见):
{
"app": {
"windows": [
{ "title": "可可截图" }
]
}
}
排查清单
| 检查项 | 说明 |
|---|---|
是否使用了 getCurrentWindow().setTitle() |
document.title 对原生标题栏无效 |
是否添加了 core:window:allow-set-title 权限 |
Tauri v2 未授权调用静默失败 |
setTitle 是否在始终渲染的组件中 |
路由切换可能导致组件卸载 |
useEffect 依赖是否包含翻译结果 |
依赖 t("app.name") 的返回值而非 i18n.language |
tauri.conf.json 默认标题是否合理 |
JS 加载前显示的初始标题 |
适用范围
- Tauri v2.x
- react-i18next / i18next
- Windows / macOS / Linux
