WP 博客多语言化实操
(5) 博客菜单翻译实操
昨天,我已经完成了一批 Gutenberg + Code Block Pro 历史文章的中文摘要补全和英文覆盖翻译。
原本我对今天的预期很简单:
- 找出使用其他代码块格式、且中文摘要为空的历史文章;
- 将旧代码块转换为 Code Block Pro;
- 复用昨天已经验证成功的摘要生成和覆盖翻译流程;
- 逐批处理剩余历史文章。
今天首先处理的是 Gutenberg 编辑器中的 SyntaxHighlighter Evolved 代码块。
实际结果是,这一批最终顺利完成了:
- 固定批次:20 篇
- 中文摘要写入成功:20 篇
- 英文覆盖翻译成功:20 篇
- 最终状态为
completed:20 篇 - 未完成:0 篇
不过,中间也出现了一段明显的过度设计。好在发现问题后及时回退,最终重新回到了更简单、可长期维护的方案。
一、昨天已经具备稳定的下游处理流程
昨天建立的核心流程已经可以处理 Gutenberg + Code Block Pro 文章:
固定中文候选文章
→ 生产环境只读预检
→ GLM 生成中文摘要
→ 写入中文文章摘要
→ 触发 SlyTranslate
→ 覆盖对应英文文章
→ 保存 completed 状态
实际执行入口是:
bin/execute-single-candidate.py
它已经负责:
- 校验中文和英文文章 ID;
- 校验 Polylang 关联关系;
- 生成中文摘要;
- 写入中文摘要;
- 保存写入前备份;
- 触发 SlyTranslate;
- 保存执行状态;
- 在部分翻译阶段失败后继续恢复。
因此,今天面对 SyntaxHighlighter 时,真正需要新增的并不是另一套摘要和翻译管线。
需要变化的只有上游:
识别 SyntaxHighlighter
→ 转换为 Code Block Pro
→ 验证转换结果
转换完成之后,后续应继续使用昨天的执行机制。
二、识别真正的 Gutenberg SyntaxHighlighter 区块
生产文章中主要使用的结构如下:
<!-- wp:syntaxhighlighter/code {"language":"php"} -->
<pre class="wp-block-syntaxhighlighter-code">
...
</pre>
<!-- /wp:syntaxhighlighter/code -->
这与传统文章中单纯依靠短代码或 HTML class 判断不同。
为了避免误判,本次识别以完整的 Gutenberg 区块边界为准,而不是简单搜索 syntaxhighlighter 关键词。
生产环境只读统计发现:
- 存在完整 SyntaxHighlighter Gutenberg 区块的文章:815 篇
- SyntaxHighlighter 区块总数:4608 个
- 其中部分文章还混合其他旧格式
- 可以直接作为当前阶段候选的
ready文章:98 篇

这意味着,SyntaxHighlighter 是当前历史文章中数量较大的一类代码块格式,值得单独建立识别和转换规则。
但这里的“单独规则”,只应覆盖识别和转换,不应扩展到摘要生成和翻译阶段。
三、先用一篇文章完成试点
正式建立批次前,我先选择了一篇文章进行试点:
- 中文文章 ID:
17586 - 英文文章 ID:
17641 - 转换前 SyntaxHighlighter:1 个
- 转换前 Code Block Pro:0 个
手动打开 Gutenberg 编辑器后,将原 SyntaxHighlighter 区块转换为 Code Block Pro,并确认:
- SyntaxHighlighter 数量由 1 变为 0;
- Code Block Pro 数量由 0 变为 1;
- 原代码文本保持不变;
- 中文标题未变化;
- 中文摘要仍为空;
- Gutenberg 结构完整;
- Polylang 中英文关联正常。
随后复用现有单篇执行器,成功完成:
- 中文摘要生成;
- 中文摘要写入;
- 英文文章覆盖翻译;
- 最终状态记录为
completed。

这一步实际上已经证明:
SyntaxHighlighter 文章转换为 Code Block Pro 后,可以直接进入昨天的处理流程。
四、建立第一批固定的 20 篇文章
试点成功后,从 ready 候选中建立了第一批固定清单。
这一批共 20 篇,其中:
- 18 篇各包含 1 个 SyntaxHighlighter 区块;
- 2 篇各包含 2 个 SyntaxHighlighter 区块;
- 试点文章
17586不再进入正式批次; - 不与昨天处理过的 42 篇文章重复;
- 中文摘要全部为空;
- 中英文文章均为
publish; - Polylang 双向关系正常。
批次一旦生成,就不再自动补选或替换文章。
这样做的原因是,手动转换已经成为批次的一部分。如果执行过程中重新选择候选,很容易导致清单、快照和人工操作对象不一致。
五、手动转换时需要特别检查代码语言
实际转换过程中发现,打开 Gutenberg 编辑器后,有些 SyntaxHighlighter 区块会被现有配置自动转换成 Code Block Pro,有些则不会。
因此,每篇文章采用以下处理方式:
- 自动转换成功:检查后保存;
- 没有自动转换:手动转换;
- 保存前检查 Code Block Pro 数量;
- 检查每个代码块的语言。
语言检查尤其重要。
Code Block Pro 有时会继承上一次编辑过的代码块语言,而不是原 SyntaxHighlighter 中声明的语言。
因此采用以下规则:
- 原区块明确声明
php、bash、sql、yaml等语言时,Code Block Pro 设置为对应语言; - 原区块没有声明语言时,设置为
Plaintext; - Mermaid 代码块继续使用
mermaid; - HTML 代码块继续使用
html。

需要说明的是,Plaintext 并不等于绝对禁止翻译。
如果其中是命令、参数、路径、配置或代码,应保持不变;如果其中本身是自然语言说明,则可能根据翻译提示词正常翻译。不能仅因为中英文 Plaintext 内容哈希不同,就判断翻译异常。
六、20 篇转换结果全部通过只读验收
手动转换完成后,对固定的 20 篇进行了生产环境只读验收。
最终结果:
ready:20
pending:0
abnormal:0
全部文章满足:
- 中文文章仍为
publish; - 中文语言为
zh; - 中文标题未变化;
- 中文摘要仍为空;
- 转换后正文哈希与转换前不同;
- Gutenberg 区块结构完整;
- SyntaxHighlighter 数量为 0;
- Code Block Pro 数量符合预期;
- Code Block Pro 内容非空;
- 没有未知代码格式混用;
- 英文文章仍为
publish; - Polylang 双向关系正常。

ready 的只读验收结果。至此,这一批已经具备执行摘要生成和覆盖翻译的条件。
七、中间一度出现了过度设计
进行到这里时,原本应该直接复用现有单篇执行器。
但中间一度将“新的代码块格式”误认为“新的执行管线”,先后设计或实现了:
- 新的批次执行器;
- 新的执行清单生成器;
- 新的 execution snapshot;
- 新的整批状态控制;
- 新的自动重试逻辑;
- 更严格的英文正文验收。
这些功能单独看并非完全没有价值,但放在当前项目中属于重复设计。
因为下游流程已经存在:
execute-single-candidate.py
SyntaxHighlighter 与 Code Block Pro 的差异,在手动转换保存之后就已经消失了。
正确的架构应该是:
不同历史代码块格式
↓
各自完成识别和转换
↓
统一成为 Gutenberg + Code Block Pro
↓
复用同一套摘要生成和覆盖翻译流程
因此,尚未提交的新批次执行代码被全部撤销,仓库重新恢复到远端 main 的稳定状态。
撤销后:
Ran 238 tests
OK
Git 工作树也重新保持干净:
## main...origin/main
这次回退非常重要。
它避免了今后每遇到一种旧代码块格式,就新增一套执行器、状态机和测试体系。
八、正式执行时,18 篇一次成功
回到现有单篇执行器后,通过 Shell 循环按固定清单顺序执行 20 篇文章。
前 20 篇中有 18 篇顺利完成,包括:
- 中文摘要生成;
- 中文摘要写入;
- SlyTranslate 覆盖翻译;
- 本地状态记录为
completed。

执行日志最终显示:
总数:20
成功:18
失败:2
两篇未立即完成的文章是:
- 中文文章
16033 - 中文文章
16967
这两篇并不是文章结构错误,而是不同阶段的网络超时。
批量过程中的 18 篇成功与两篇失败记录见终端日志。
九、16033:摘要写入前后出现网络超时
文章 16033 第一次执行时:
- GLM 已经生成摘要;
- 调用 WordPress REST 写入摘要时发生超时;
- 本地状态停留在
excerpt_generated; - 生产环境摘要仍为空;
- 英文文章未变化。
由于生产摘要实际上没有写入,因此它可以重新按首次执行处理。
恢复过程中又遇到过:
- WordPress REST 连接被远端断开;
- GLM 请求超时。
最终网络恢复后,再次执行成功:
{
"chinese_post_id": 16033,
"english_post_id": 16055,
"status": "completed"
}

这个过程说明,网络超时并不一定代表生产环境已经发生写入。
必须根据以下事实判断:
- 本地状态处于哪个阶段;
- 生产中文摘要是否已经变化;
- 英文文章是否已经变化;
- 是否存在翻译成功记录。
十、16967:POST 已成功,但验证 GET 断开
文章 16967 的情况更复杂。
最初执行时,GLM 请求曾经超时。后续重新执行后,摘要 POST 实际已经成功,但程序在写入后的 GET 验证阶段发生了:
RemoteDisconnected
之后再次从头执行时,程序报告:
live validation failed: chinese_excerpt_not_empty
这说明中文摘要已经存在,不能再按照首次执行流程重复生成。
只读核验发现:
- 本地生成摘要长度:140
- 生产中文摘要长度:140
- 本地摘要 SHA-256:
6e276ea2813791292eed299f4ff75c76eed21cbe7f18fd6cb2376103d258b8fc
- 生产摘要 SHA-256 完全相同;
- 两份摘要逐字符一致;
- 英文文章标题、摘要和正文仍与执行前快照一致;
- SlyTranslate 尚未执行;
- Polylang 关系正常。
因此可以确认:
WordPress 摘要 POST 已经成功,只是写入后的验证请求没有收到完整响应。
随后将本地状态从:
excerpt_generated
最小推进为:
chinese_excerpt_saved
再执行:
--execute --resume
最终成功完成英文覆盖翻译:
{
"chinese_post_id": 16967,
"english_post_id": 17021,
"status": "completed"
}

--resume 完成覆盖翻译。十一、不能仅根据“状态文件是否存在”决定是否 resume
这次还暴露了一个很重要的执行边界。
错误的判断方式是:
状态文件存在
→ 使用 --resume
实际上,当前执行状态包括:
prepared
excerpt_generated
chinese_excerpt_saved
translation_started
translation_failed
completed
现有 --resume 只支持从以下阶段继续:
chinese_excerpt_saved
translation_started
translation_failed
因此,正确判断必须结合状态值:
| 当前状态 | 处理方式 |
|---|---|
| 无状态文件 | 首次 --execute |
prepared | 先确认生产未写入,再清理或归档失败状态后重新执行 |
excerpt_generated | 检查生产摘要是否实际写入 |
chinese_excerpt_saved | 使用 --resume |
translation_started | 使用 --resume |
translation_failed | 使用 --resume |
completed | 跳过 |
尤其是 excerpt_generated,存在两种完全不同的结果:
- POST 没有成功,生产摘要仍为空;
- POST 已经成功,但后续 GET 验证失败。
不能只看本地异常信息,必须结合生产环境只读检查判断。
十二、第一批最终完成 20/20
两篇异常文章恢复后,第一批最终结果为:
中文摘要写入:20/20
英文覆盖翻译:20/20
completed:20/20
失败:0

completed,第一批 20 篇全部完成。这一批的完成,不只是处理了 20 篇历史文章,更重要的是明确了后续历史文章的统一处理方式。
十三、今后所有历史文章的标准处理流程
后续不再根据不同代码块格式,分别建设完整管线。
所有历史文章统一按照以下阶段处理。
第一阶段:识别文章格式
针对每种历史代码块格式,只增加必要的识别规则,例如:
- SyntaxHighlighter;
- 经典编辑器
<pre>; - WordPress Core Code;
- 旧插件生成的代码块;
- 其他未知或混合格式。
筛选条件至少包括:
- 中文文章;
- 已发布;
- 中文摘要为空;
- 存在对应英文文章;
- 代码块格式可以可靠识别;
- 不与已经处理过的批次重复。
第二阶段:建立固定批次
每次选择一个规模可控的固定批次,例如 20 篇。
批次固定后:
- 不自动补选;
- 不自动替换失败文章;
- 保存中英文 ID;
- 保存标题;
- 保存正文哈希;
- 保存代码块数量;
- 保存 Polylang 关系。
第三阶段:人工转换代码块
将旧代码块统一转换为 Gutenberg + Code Block Pro。
保存前检查:
- 旧代码块已经消失;
- Code Block Pro 数量正确;
- 代码内容未丢失;
- 代码语言正确;
- Gutenberg 没有无效区块;
- 标题和其他正文未被意外修改。
第四阶段:生产环境只读验收
正式生成摘要前,只读确认:
- 中文摘要仍为空;
- 中文正文哈希符合转换后基线;
- SyntaxHighlighter 或其他旧格式数量为 0;
- Code Block Pro 数量符合预期;
- 英文文章存在且状态正常;
- Polylang 关系正常。
第五阶段:复用现有单篇执行器
不再为每种旧格式开发新的摘要或翻译程序。
全部统一调用:
execute-single-candidate.py
完成:
- GLM 中文摘要生成;
- WordPress 中文摘要写入;
- SlyTranslate 英文覆盖翻译;
- 本地备份;
- 执行状态记录。
第六阶段:按状态恢复异常文章
网络异常后,不盲目重新执行。
先检查:
- 本地状态;
- 生产中文摘要;
- 英文文章是否变化;
- 本地摘要与生产摘要是否一致;
- Polylang 关系是否正常。
然后选择:
- 重新首次执行;
- 推进本地状态后
--resume; - 仅恢复翻译阶段;
- 已完成则直接跳过。
第七阶段:以 completed 作为流程完成标志
覆盖翻译完成后,不再进行过度严格的英文正文自动比对。
最终只需要确认:
- 中文摘要已写入;
- 对应英文文章 ID 正确;
- SlyTranslate 请求成功;
- 没有明显写入失败或回滚;
- 本地状态为
completed。
代码、命令、参数、路径和 URL 继续由翻译保护机制负责。
不因为 Plaintext 中的自然语言发生翻译,就自动判断正文异常。
十四、这次流程标准化的真正价值
今天最大的收获,并不是新增了多少脚本,而是明确了哪些代码应该新增,哪些代码不应该新增。
应该新增的是:
- 不同旧格式的识别器;
- 必要的批次生成规则;
- 转换完成后的只读验收。
不应该重复新增的是:
- 摘要生成器;
- WordPress 写入逻辑;
- SlyTranslate 调用逻辑;
- 备份和恢复流程;
- 每种代码块格式各自独立的执行器。
最终应形成一条稳定的主线:
识别旧格式
→ 固定候选批次
→ 人工转换为 Code Block Pro
→ 只读验收
→ 复用现有执行器
→ 按状态恢复异常
→ completed
这条流程既保留了必要的安全边界,也避免了为了理论上的完整性不断增加代码和维护成本。
后续无论遇到哪一种历史代码块格式,都可以继续沿用这套标准:只调整识别和转换部分,下游摘要生成与英文覆盖翻译保持不变。
WordPress 网站维护、性能优化与博客运营咨询
本站已持续运营超过 10 年,累计发布 1000+ 篇原创技术文章,长期实践 WordPress 网站建设、CDN / Cloudflare 配置、缓存优化、Google SEO、广告变现和多语言网站运营。
如果你的 WordPress 网站遇到访问慢、缓存异常、插件冲突、广告不显示、SEO 基础结构混乱、CDN 配置不确定等问题,可以联系我做一次远程技术排查。
适合以下用户:
✅ 个人博客站长
✅ WordPress 网站运营者
✅ 独立开发者与内容创作者
✅ SaaS 产品官网运营团队
✅ 希望优化网站速度与稳定性的站点
服务内容:
✅ WordPress 速度优化
✅ Cloudflare / CDN / 缓存配置排查
✅ 插件冲突与页面异常排查
✅ AdSense 广告显示问题排查
✅ SEO 基础结构检查
✅ 博客运营与商业化咨询
如需了解方案或交流相关问题,请直接联系我,并注明:WordPress 维护咨询。
联系方式:
Telegram:@shuijingwan
微信:13980074657
邮箱:shuijingwanwq@gmail.com


发表回复