1. 桌面端汉化这件事,到底难在哪
Codex 桌面端汉化这个事,我前前后后折腾了差不多两周,中间踩的坑比想象中多得多。很多人第一反应是“不就是把英文换成中文吗”,但真动手才发现,桌面端应用的汉化跟网页汉化完全是两码事。网页汉化你改改 DOM、注入个脚本就完事了,桌面端你得面对打包后的资源文件、编译过的二进制、还有各种校验机制。
先说清楚这个项目是干什么的。Codex 桌面端本身是一个基于 Electron 或类似框架构建的跨平台应用,界面文本分散在多个资源包里,包括菜单栏、主界面、设置面板、弹窗提示等。汉化的目标就是把这些英文文本替换成中文,让不习惯英文界面的用户能够更顺畅地使用。适合谁来参考?如果你有基本的前端知识,懂一点 Node.js 和文件打包的概念,那这篇内容你基本能跟着走下来。完全零基础的话,建议先补一下 Electron 应用的基本结构。
核心关键词就几个:Codex、桌面端、汉化、i18n、ASAR。这几个词贯穿整个实现过程。i18n 是国际化的缩写,理论上如果原应用做好了 i18n,汉化就是加个语言包的事。但现实是,大部分桌面应用并没有完整的 i18n 支持,或者即使有,语言包也不对外开放。所以我们的思路就变成了:找到资源文件,直接替换文本,重新打包。
ASAR 是 Electron 应用的核心打包格式,全称是 Atom Shell Archive。你可以把它理解成一个把整个项目文件夹压缩成的归档文件,应用运行时从这个归档里读取资源。汉化的关键操作之一就是解包 ASAR、修改里面的文本、再重新打包。这个过程听起来简单,但实际操作中会遇到编码问题、路径问题、校验问题。
我试过几种不同的方案,从最粗暴的直接改安装目录下的文件,到解包 ASAR 后重新打包,再到写脚本批量替换。每种方案都有它的适用场景和局限性。下面我会把整个思路拆开,一步步讲清楚为什么这么做、怎么做、以及做完之后怎么验证。
提示:汉化操作前务必备份原始文件,尤其是 ASAR 包和主进程脚本。一旦改错,应用可能直接无法启动。
2. 汉化方案选型:为什么最终选了 ASAR 解包这条路
2.1 三种常见汉化路径的对比
在动手之前,我先梳理了一下桌面端应用汉化的几种主流方式,分别是:运行时注入、资源文件替换、ASAR 解包重打包。这三种方式各有优劣,我做了个对比表:
| 方案 | 原理 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| 运行时注入 | 通过脚本在应用启动时动态替换文本 | 不改动原始文件,可逆 | 需要注入时机精准,容易被校验拦截 | 应用有调试接口或插件机制 |
| 资源文件替换 | 直接替换安装目录下的语言文件 | 操作简单,见效快 | 只对未打包的资源有效 | 应用使用外部语言包 |
| ASAR 解包重打包 | 解包 ASAR,修改文本后重新打包 | 覆盖全面,可控性强 | 步骤多,容易出错 | 文本打包在 ASAR 内的应用 |
我一开始试的是运行时注入,想着不改文件最安全。但 Codex 桌面端的启动流程比较紧凑,注入脚本的时机很难卡准,而且它内部有一些完整性检查,注入的脚本容易被忽略或者报错。后来试了资源文件替换,发现安装目录下根本没有独立的语言文件,所有文本都打包在 ASAR 里。所以最终只能走 ASAR 解包重打包这条路。
2.2 ASAR 解包的核心原理
ASAR 的本质是一个归档格式,它把文件夹结构序列化成一个二进制文件,同时维护一个头部索引,记录每个文件的偏移量和大小。Electron 在运行时通过这个索引来读取文件。解包就是根据索引把文件还原出来,重打包就是重新生成索引和归档。
这里有个关键点:ASAR 的头部索引是 JSON 格式的,记录了文件路径、偏移量、大小等信息。如果你只改文件内容而不改文件大小,理论上可以直接在二进制层面替换,不需要重新打包。但汉化过程中,中文字符和英文字符的字节数不一样,文件大小必然会变,所以必须重新生成索引。
我用的工具是asar,这是 Electron 官方提供的命令行工具,安装很简单:
npm install -g asar安装完之后,解包命令是:
asar extract app.asar app_extracted重打包命令是:
asar pack app_extracted app_new.asar看起来很简单对吧?但实际操作中,asar pack默认会保留文件的原始权限和时间戳,有时候会导致打包后的文件比原始文件大很多,或者出现一些奇怪的权限问题。我的经验是,在打包前先清理一下解包目录里的多余文件,比如.DS_Store、Thumbs.db这些系统生成的垃圾文件。
2.3 为什么不用现成的汉化补丁
网上确实有一些现成的汉化补丁,但我建议谨慎使用。原因有几个:第一,补丁的来源不明,可能包含恶意代码;第二,补丁的版本和你安装的应用版本可能不匹配,导致应用崩溃;第三,补丁的翻译质量参差不齐,有些机翻痕迹明显,反而影响使用体验。
自己动手汉化的好处是,你可以完全控制翻译质量,而且过程中能深入理解应用的结构。万一出了问题,你也知道从哪里排查。我个人的习惯是,宁可花时间自己搞一遍,也不用来路不明的补丁。
注意:如果你决定使用第三方补丁,务必先在虚拟机或沙箱环境里测试,确认安全后再放到主力环境。
3. 核心细节拆解:从菜单到主界面的文本定位
3.1 菜单栏文本的定位与替换
菜单栏是汉化的第一站,因为它的文本最集中,也最容易验证效果。在 Electron 应用里,菜单通常是在主进程脚本里定义的,用的是Menu.buildFromTemplate这个方法。菜单项的文本一般长这样:
{ label: 'File', submenu: [ { label: 'New', accelerator: 'CmdOrCtrl+N' }, { label: 'Open', accelerator: 'CmdOrCtrl+O' } ] }汉化的思路很直接:把label字段的值换成中文。但问题是,这些代码在打包后可能被压缩或混淆了,你解包出来的文件可能是一堆难以阅读的代码。我的做法是先用搜索工具全局搜索label:这个关键词,找到所有包含菜单定义的文件。
搜索的时候要注意,有些文本可能是通过变量拼接的,比如label: i18n.t('menu.file'),这种情况下你就需要找到 i18n 的配置文件,直接改配置里的值。Codex 桌面端有一部分文本是硬编码的,有一部分走了 i18n,所以两种方式都要用上。
替换菜单文本时有个细节:加速键(accelerator)不要动。加速键是键盘快捷键的绑定,改了会导致快捷键失效。另外,菜单项的role属性也不要动,那是 Electron 内置的角色定义,改了可能影响功能。
3.2 主界面文本的批量处理
主界面的文本比菜单栏分散得多,可能分布在多个 JS 文件、HTML 文件、甚至 CSS 的content属性里。我的策略是分三步走:
第一步,全局搜索常见的英文文本模式。比如按钮上的 “Save”、“Cancel”、“Settings”,提示信息里的 “Are you sure”、“Loading”,等等。用正则表达式搜索效率更高,比如>[A-Z][a-z]+<可以匹配 HTML 标签之间的英文单词。
第二步,把搜到的文本整理成一张对照表。这张表包含三列:原始文本、中文翻译、所在文件。整理成表格的好处是,你可以批量替换,也方便后续检查有没有遗漏。
第三步,写一个脚本批量替换。用 Node.js 写个简单的脚本就行:
const fs = require('fs'); const path = require('path'); const replacements = [ { from: /Save/g, to: '保存' }, { from: /Cancel/g, to: '取消' }, { from: /Settings/g, to: '设置' } ]; function processFile(filePath) { let content = fs.readFileSync(filePath, 'utf8'); replacements.forEach(r => { content = content.replace(r.from, r.to); }); fs.writeFileSync(filePath, content, 'utf8'); }这个脚本很简单,但有几个坑要注意。第一,替换的时候要小心误伤,比如 “Save” 可能出现在变量名里,替换后会破坏代码。所以正则表达式要加边界,比如\bSave\b。第二,有些文本是拼接的,比如'Save' + 'As',这种要单独处理。第三,替换后要检查文件编码,确保是 UTF-8,否则中文会乱码。
3.3 弹窗和提示信息的处理
弹窗和提示信息是最容易被忽略的部分,但用户体验影响很大。这些文本通常出现在dialog.showMessageBox的调用里,或者前端框架的 toast 组件里。搜索关键词包括message:、title:、detail:、content:等。
有个特殊情况:有些提示信息是动态生成的,比如 “File ${filename} saved successfully”。这种文本汉化时要注意保留变量占位符,翻译成 “文件 ${filename} 保存成功”。如果占位符被误删,运行时就会报错。
另外,错误提示的翻译要特别小心。有些错误信息是给开发者看的,翻译成中文反而增加了排查难度。我的建议是,面向用户的提示翻译成中文,面向开发者的日志和错误堆栈保持英文。
实操心得:汉化弹窗文本时,建议先在应用里触发一遍所有弹窗,截图记录原始文本,然后对照着翻译。这样不容易遗漏,也方便验证。
4. 实操全流程:从解包到验证的完整步骤
4.1 环境准备与工具安装
动手之前,先把环境搭好。你需要的东西不多,但每一样都要装对版本。
- Node.js:建议用 LTS 版本,我用的 18.x,兼容性最好。安装完后用
node -v确认。 - asar:全局安装,命令是
npm install -g asar。装完后用asar --version确认。 - 文本编辑器:VS Code 就行,装个 “Chinese (Simplified) Language Pack” 插件,方便看中文。
- 搜索工具:推荐用
ripgrep,比系统自带的搜索快很多。Windows 上可以用scoop install ripgrep安装。
找到 Codex 桌面端的安装目录。Windows 上一般在C:\Users\你的用户名\AppData\Local\Programs\下面,macOS 上在/Applications/下面。进入安装目录后,找到resources文件夹,里面应该有一个app.asar文件。这个就是我们要处理的目标。
在动手之前,先把app.asar复制一份到安全的地方,命名为app.asar.bak。这个备份在出问题的时候能救命。
4.2 解包 ASAR 并定位文本
解包命令前面说过,这里补充几个细节。解包的时候最好指定一个干净的输出目录,比如:
asar extract app.asar ./extracted解包完成后,你会看到一堆文件夹和文件。先别急着改,先用ripgrep搜一下文本分布。比如搜 “Settings”:
rg -l "Settings" ./extracted这个命令会列出所有包含 “Settings” 的文件。你可以根据文件路径判断哪些是界面文本,哪些是代码逻辑。一般来说,renderer文件夹里的是前端界面,main文件夹里的是主进程逻辑,node_modules里的基本不用管。
定位文本的时候有个技巧:优先处理.json和.js文件,因为这两种文件里的文本最集中。.html文件里的文本通常比较少,但也不能漏掉。.css文件里偶尔会有content属性包含文本,也要检查一下。
4.3 批量替换与编码处理
替换文本的时候,编码是最大的坑。中文字符在 UTF-8 下占 3 个字节,而英文字符只占 1 个字节。如果替换后的文件编码不对,应用读取时就会乱码。
我的做法是,替换前先确认文件编码。用 VS Code 打开文件,右下角会显示编码格式。如果是 UTF-8 就没问题,如果是 GBK 或其他编码,先转成 UTF-8 再替换。批量转码可以用iconv命令:
iconv -f GBK -t UTF-8 input.js > output.js替换的时候,建议用脚本而不是手动改。手动改容易漏,而且改多了容易眼花。脚本的逻辑很简单:读文件、替换、写回。但要注意,写回的时候要指定编码为 UTF-8:
fs.writeFileSync(filePath, content, 'utf8');还有一个细节:有些文件里有 BOM(字节顺序标记),替换后 BOM 可能会丢失,导致应用读取异常。如果遇到这种情况,可以在写回的时候手动加上 BOM:
fs.writeFileSync(filePath, '\ufeff' + content, 'utf8');4.4 重新打包与替换
替换完成后,先别急着打包。用asar list命令检查一下解包目录的结构,确认没有多余文件:
asar list ./extracted确认无误后,重新打包:
asar pack ./extracted app_new.asar打包完成后,对比一下新旧文件的大小。如果新文件比旧文件大很多(比如超过 20%),可能是打包时包含了不必要的文件。检查一下解包目录里有没有node_modules里的缓存文件,或者.git文件夹。
替换的时候,先把原始的app.asar重命名为app.asar.old,然后把app_new.asar复制过去并改名为app.asar。启动应用,看看效果。
4.5 验证与回滚
验证分三步:第一,看菜单栏和主界面的文本是否变成中文;第二,点开各个设置面板和弹窗,确认没有遗漏;第三,测试核心功能是否正常,比如新建文件、保存、导出等。
如果应用启动失败,或者界面显示异常,立刻回滚。回滚的方法很简单:删掉新的app.asar,把app.asar.old改回app.asar。如果连原始备份都出问题了,就用最开始复制的app.asar.bak。
注意:替换 ASAR 文件后,如果应用有自动更新功能,更新后汉化可能会失效。建议在汉化完成后关闭自动更新,或者每次更新后重新汉化。
5. 常见问题与排查技巧实录
5.1 应用启动白屏或崩溃
这是最常见的问题,原因通常有三个:ASAR 打包不完整、文件编码错误、或者替换了关键的系统文件。
排查思路:先看应用的日志输出。Electron 应用启动时会在控制台输出错误信息,Windows 上可以用--enable-logging参数启动,macOS 上可以在终端里直接运行应用的可执行文件。日志里如果有 “Failed to load” 或 “Unexpected token” 之类的错误,基本就是文件损坏或编码问题。
解决方法:用asar list对比新旧 ASAR 的文件列表,确认没有遗漏。如果文件列表一致,检查替换过的文件编码,确保是 UTF-8 无 BOM。如果还不行,逐步回滚,每次只替换一个文件,定位到具体是哪个文件出了问题。
5.2 中文显示为乱码
乱码的原因通常是编码不匹配。应用读取文件时用的是 UTF-8,但文件实际是 GBK,或者反过来。
排查方法:用十六进制编辑器打开文件,看中文字符的字节序列。UTF-8 的中文字符通常以E4、E5开头,GBK 的以C4、C5开头。如果发现编码不对,用iconv转码。
还有一种情况是字体问题。有些应用的内置字体不支持中文,导致中文显示为方块。这种情况下,需要在 CSS 里指定一个支持中文的字体,比如"Microsoft YaHei", "PingFang SC", sans-serif。
5.3 部分文本没有替换成功
这种情况通常是文本被拆分或拼接了。比如'Set' + 'tings',或者文本在运行时动态生成。排查的时候,用ripgrep搜索文本的片段,比如搜'Set',看看有没有拼接的情况。
还有一种可能是文本在图片里。有些应用的按钮文本是做成图片的,这种就没法通过改文本汉化,只能替换图片。替换图片时要注意图片的尺寸和格式,保持和原始图片一致。
5.4 应用更新后汉化失效
这是预期内的行为。应用更新会覆盖app.asar,汉化自然就没了。解决方法有两个:一是关闭自动更新,二是每次更新后重新执行汉化流程。
关闭自动更新的方法因应用而异,有些应用在设置里有开关,有些需要改配置文件。如果找不到开关,可以尝试把更新程序的可执行文件重命名,让应用找不到它。
5.5 常见问题速查表
| 问题现象 | 可能原因 | 排查方法 | 解决方案 |
|---|---|---|---|
| 启动白屏 | ASAR 打包不完整 | 对比文件列表 | 重新打包,确保文件完整 |
| 中文乱码 | 文件编码不是 UTF-8 | 十六进制查看字节 | 用 iconv 转码 |
| 部分文本未替换 | 文本被拼接或动态生成 | 搜索文本片段 | 找到拼接逻辑,整体替换 |
| 更新后失效 | 更新覆盖了 ASAR | 检查更新日志 | 关闭自动更新或重新汉化 |
| 字体显示方块 | 内置字体不支持中文 | 检查 CSS 字体设置 | 指定支持中文的字体 |
实操心得:每次修改前先备份,每次修改后先测试。这个习惯能帮你省下大量重装应用的时间。
6. 汉化之外的延伸思考
汉化做完之后,我顺手研究了一下 Codex 桌面端的 i18n 机制。发现它其实有一套简单的多语言支持,只是没有对外开放语言包。它的 i18n 实现是基于 JSON 文件的,每种语言一个 JSON,键值对的形式。如果能把中文 JSON 加进去,理论上可以做到更干净的汉化,不用直接改代码。
具体做法是:找到 i18n 的加载逻辑,看看它是怎么读取语言文件的。然后在语言文件目录里加一个zh-CN.json,把英文的键值对翻译成中文。最后改一下默认语言设置,让它加载中文。这种方式的优点是,升级应用时只需要替换语言文件,不用重新打包整个 ASAR。
不过这种方式有个前提:应用得支持动态加载语言文件。如果语言文件是打包在 ASAR 里的,那还是得走解包重打包的路子。我试了一下,Codex 桌面端的语言文件确实是打包在 ASAR 里的,所以最终还是回到了 ASAR 方案。
另外,汉化过程中我还发现了一些硬编码的文本,这些文本没有走 i18n,直接写在代码里。这种文本的汉化只能靠替换,没有更好的办法。如果你打算长期维护汉化,建议把这些硬编码文本的位置记录下来,每次更新后重点检查这些地方。
最后分享一个小技巧:汉化完成后,可以用diff命令对比新旧 ASAR 的文件列表,快速找出所有被修改的文件。这样下次更新时,你只需要重新处理这些文件,不用从头再来一遍。
asar list app.asar.old > old_list.txt asar list app_new.asar > new_list.txt diff old_list.txt new_list.txt这个命令会列出所有新增、删除和修改的文件,非常实用。我每次更新后都用这招,效率提升明显。