这套方案没有维护三套 HTML,也没有引入 i18n 框架。页面只有一份,原文全部是简体中文。繁体中文和英文,是浏览器打开页面后由一段 JavaScript 现场替换出来的。清理之后,真正参与运行的只有两个文件:yuyan/├─ index.php└─ runtime/ └─ dashboard-i18n.js就这两个。没有后端翻译接口,没有额外字典请求,也

扫码分享
二维码

详细介绍


这套方案没有维护三套 HTML,也没有引入 i18n 框架。页面只有一份,原文全部是简体中文。繁体中文和英文,是浏览器打开页面后由一段 JavaScript 现场替换出来的。

清理之后,真正参与运行的只有两个文件:

yuyan/
├─ index.php
└─ runtime/
  └─ dashboard-i18n.js

就这两个。没有后端翻译接口,没有额外字典请求,也不需要每次切换都刷新页面。

PHP 只决定“从哪种语言开始”

index.php 不负责翻译。它只做三件事:

  1. 读取 URL 里的 ?lang=;

  1. 只接受 zh、zh-Hant、en 三个值,其它值一律回退到简体;

  1. 把语言写进 <html lang="..."> 和 data-ui-language="..."。

真正干活的是 runtime/dashboard-i18n.js。

页面启动时,语言按这个顺序确定:

URL 的 ?lang= 参数
       ↓ 没有就用
localStorage 里的 wb-lang
       ↓ 没有就用
HTML 根节点的 data-ui-language
       ↓ 还没有
简体中文 zh

这个顺序很实用。分享测试链接时,?lang=en 能强制指定语言;用户自己点过按钮后,选择会存进 localStorage,下次不带参数打开还是上次的语言;服务端则可以通过 data-ui-language 设置实例默认值。

点击按钮以后发生了什么

用户点击“English”时,页面不会跳转,也不会重新请求服务器。运行时只做几件事:

  • 把当前语言改成 en;

  • 把 en 写入 localStorage['wb-lang'];

  • 更新 <html> 上的 lang 和 data-lang;

  • 扫描页面文本节点和指定属性,把简体中文替换成英文。

切回简体时,它不会拿英文反向翻译。第一次看到简体原文时,原文已经被缓存下来了,切回简体只是把缓存的内容还原。这一点很关键。靠反向翻译恢复原文,迟早会丢信息,尤其是多义词、数字和专有名词。

简体和繁体,不是同一套逻辑

简体是源语言,页面原本写什么就是什么,理论上无需翻译。

繁体不是简单的“一个字换一个字”。它按三层处理:

  1. 先查完整的繁体词组表 HANT_PHRASES;

  1. 词组没命中,再查术语表 HANT_TERMS;

  1. 还没命中,才用单字表 HANT_CHARS 兜底。

先查长词组是为了避免把词拆坏。比如“网关设置”这种内容,如果先按单字转换,很可能得到一组意思不对的字。词组表负责准确性,单字表只负责兜底。

英文靠最长匹配和动态规则

英文使用 DICT 精确匹配,再配合一组动态规则 RULES。它的策略是“最长词条优先扫描”,没有严格的英文词边界判断。

这样做的好处是部署简单,不需要构建工具,也不需要加载外部语言包。缺点是词条顺序和完整性必须认真维护。长词条如果排在短词条后面,就可能被短词条先吃掉,出现半截英文、半截中文的情况。

所以英文词表不是随便塞进去就能用,必须按实际界面文案整理。

哪些内容绝对不能翻译

用户昵称、日志正文、订单号、文件路径、用户输入内容,这些都不能进入翻译流程。

页面里只要给节点加上:

<span data-no-i18n>西安钟楼流浪猫</span>

运行时就会跳过它。语言按钮本身也加了这个标记,否则“简体”“繁體”可能会被当成界面文案翻译掉。

这是一个边界问题,不是可选优化。用户数据被翻译,用户看到的就是错误信息,而且很难排查。

动态内容怎么处理

页面不是一次性渲染完的。后续插入的按钮、表格内容、状态文字,运行时也能处理,因为它会监听 DOM 变化,对新出现的节点重新执行翻译。

这也是它不需要“刷新页面才能切换语言”的原因。

但动态页面仍然有一个前提:页面源文案要保持简体中文。如果某个组件自己先写入了英文,再指望切回简体时恢复,运行时没有原文可还原,结果就会失控。

为什么只保留两个文件

因为字典已经内嵌在 dashboard-i18n.js 里了。页面加载这个脚本后,不需要再请求 en.json、zh-Hant.phrases.json 之类的文件。

代价也很直接:

  • 运行时文件大约 170 KB,首次加载比纯页面大;

  • 修改翻译词条要改 JavaScript 文件;

  • 不适合需要翻译平台、在线协作和版本管理的大型产品。

但对一个演示页、内部工具或小型面板来说,这种做法的优点很明确:部署简单,复制两个文件就能跑,不需要额外配置。

可以直接试

http://127.0.0.1:8080/index.php?lang=zh
http://127.0.0.1:8080/index.php?lang=zh-Hant
http://127.0.0.1:8080/index.php?lang=en

打开页面后点底部的“简体 / 繁體 / English”,文字会立即变化。之后访问不带参数的地址,仍会沿用上次选择;但 URL 里的 ?lang= 优先级更高,会覆盖本地记忆。

这套方案没有什么神秘机制。它只是把三件事分清楚了:页面只维护一份简体原文,语言选择有明确优先级,用户数据有明确的不翻译边界。三件事里任何一件搞混,按钮做得再漂亮,切换结果也会出问题。

附件下载地址:https://www.diezanrpa.com/static/upload/other/20261021/1792549176941673.rar