grepWin 为什么能一键切换 28 种语言,还不用重启?
grepWin 为什么能一键切换 28 种语言,还不用重启?
【免费下载链接】grepWinA powerful and fast search tool using regular expressions项目地址: https://gitcode.com/gh_mirrors/gr/grepWin
grepWin 是一款基于正则表达式的 Windows 文件搜索工具。这篇文章只讲一件事:它的多语言支持是怎么做的——28 个.lang文件如何驱动整个界面换肤,以及为什么加一种新语言不用改一行 C++。读完你会对"桌面应用做国际化"有一套可抄的参考。
一、它要解决什么问题
没有国际化的做法是把所有按钮文字、菜单项、提示语写死在源码里。后果是:换个语言要重新编译、重新打包,翻译人员也插不上手。grepWin 面对的局面是 28 种语言只发一个二进制,所以必须把"文案"和"代码"彻底分开。
二、整体架构:一张图看懂
整条链路很短,只有三个角色:
| 谁 | 负责什么 |
|---|---|
translations/*.lang | 语言资源文件,一种语言一个文件,格式是msgid/msgstr键值对 |
CLanguage单例(来自 sktoolslib 库) | 解析 lang 文件,提供查词、重画界面两组接口 |
| 主窗口 / 对话框 / 右键菜单 | 初始化时和切换语言时调用翻译接口,把控件文字刷一遍 |
一句话链路:选定语言文件 → 载入内存 → 重刷当前窗口的每个控件。
三、关键设计拆解
3.1 文案全部外置到 .lang 文件
lang 文件里的键和代码里的字符串资源一一对应。新增语言 = 多一个文件,核心代码零改动。语言文件目录 下目前躺着 28 个这样的文件,从简体中文到越南语。
3.2 记住语言文件,启动时读取
启动逻辑只做一件事:把上次记住的语言文件路径读出来、加载。
// src/grepWin.cpp:便携版从 ini 取路径,安装版从注册表取,加载语言文件 CLanguage::Instance().LoadFile(bPortable ? ... : ...);为什么这样设计?因为"用户选了哪种语言"本质上只是一个文件路径,存 ini 还是注册表只是持久化方式的区别,加载入口始终只有一个。
3.3 切换语言 = 重新翻译,而不是重启
在设置里选中新语言点确定,代码就两行:
// src/Settings.cpp CLanguage::Instance().LoadFile(langPath); // 载入新语言文件 CLanguage::Instance().TranslateWindow(::GetParent(*this)); // 重刷主窗口全部控件TranslateWindow管"整窗批量刷";更细粒度的地方则用TranslatedString一次翻一个字符串,比如右键菜单的每个条目:
// src/ShellContextMenu.cpp:菜单项文字逐个翻译 ::InsertMenu(m_menu, 1, MF_BYPOSITION | MF_STRING, 1, TranslatedString(g_hInst, IDS_OPENCONTAININGFOLDER).c_str());两层接口覆盖了绝大多数场景:静态控件走批量,动态生成的内容(菜单、工具提示)走单条翻译。
四、实际运行效果
切换后你会看到:标签、复选框、状态栏文字立刻变成新语言,连工具提示和右键菜单也跟着变,不用重启进程。
五、动手上手
想给 grepWin 加一种新语言,三步:
- 复制 translations/English.lang 一份,改名为你的语言
- 只翻译
msgstr后面的内容,msgid保持不动 - 在设置的语言下拉框里选中新文件,对照界面检查
六、写在最后
"文案外置成资源文件 + 切换时重刷界面"这套思路,任何需要国际化的桌面程序都能照搬:先把文字从代码里赶出去,再把"换语言"变成一次"刷新"。延伸想一想:怎么在发布前自动校验某个 lang 文件有没有漏翻的msgid?
【免费下载链接】grepWinA powerful and fast search tool using regular expressions项目地址: https://gitcode.com/gh_mirrors/gr/grepWin
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
