没有不值得去解决的问题,也没有不值得去学习的技术!

WordPress 历史文章迁移终于收尾:全量审计 1438 篇中文文章,并停用 SyntaxHighlighter Evolved

【图1:历史文章迁移最终状态,67 个固定批次、1281 篇文章全部完成】

作者:

在

WordPress AI 翻译工程实战

WordPress 经典编辑器代码块无损迁移:批量转换 SyntaxHighlighter 短代码为 Gutenberg 区块

(1) WordPress 经典编辑器代码块无损迁移:批量转换 SyntaxHighlighter 短代码为 Gutenberg 区块

点击翻译按钮后,遇到一个弹窗“神秘”闪退问题及解决方法

(2) 点击翻译按钮后,遇到一个弹窗“神秘”闪退问题及解决方法

图5:DeepL API 注册页面,国家或地区列表中没有中国大陆

(3) 中国大陆 WordPress 博客想提升英文翻译质量,为什么这么麻烦?一次 Polylang + AutoPoly + DeepL API 排查复盘

图5:DeepSeek 的评分结果截图

(4) Chrome Built-in AI、Yandex Translate、ChatGPT Plus 翻译质量对比:我为什么决定重点英文文章改用 ChatGPT Plus

[截图 2:浏览器 Network 中直接请求 translate.yandex.net]

(5) 从 AutoPoly 到 Yandex 网页版:一次 WordPress 英文自动翻译质量验证

【图1:AutoPoly Free 与 Pro 功能对比截图】

(6) AutoPoly Pro + OpenAI API 能否自动化 WordPress 英文翻译?一次从技术到支付的可行性分析

【图2:点击“立即试用”后,ChatGPT 输入框中出现“代理模式”】

(7) ChatGPT Agent 能否替代 ChatGPT Plus 完成 WordPress 英文重译?

【图 7,SlyTranslate 显示翻译完成并创建文章 19426】

(8) SlyTranslate + 智谱 GLM-5.2 长文翻译排障:从 600 秒超时到完整生成英文 WordPress 文章

【图 5,54 个代码块精确匹配、差异数量为 0】

(9) WordPress SlyTranslate + GLM-5.2 长文单次翻译实战:排查 invalid_translation_runaway_output 假失败

【图 2,SlyTranslate 的 Additional Instructions 保持为空】

(10) SlyTranslate + GLM-5.2 翻译质量继续优化:从关闭随机采样、内置提示词到深度思考与模型 A/B 测试

【图6,终端中的完整测试结果】

(11) 在 GLM 5.2 之后测试 DeepSeek:一次面向 WordPress 长文翻译的模型对比与取舍

【图 4,“英文博客翻译质量优化”项目中已经整理完成的会话列表】

(12) 为英文博客翻译质量优化建立独立 ChatGPT 项目:整理历史会话并统一后续评测标准

【图3:Gemini 3.5 Flash 首次成功调用结果】

(13) 暂缓 OpenAI 后,我在本地测试了 Gemini:与 GLM 5.2 的 WordPress 技术文章翻译对比

图3:清理英文 Host 下的对象与术语关系缓存后,英文文章重新显示 SEO Tools、Yoast SEO 和 Blog SEO Log

(14) 为 SlyTranslate 的 GLM 5.2 整篇翻译补上 Plaintext 智能处理,并修复 Code Block Pro 区块失效

图5:英文文章发布后,前台特色图片、分类、标签和 Series 顺序均正常

(15) SlyTranslate + GLM-5.2 翻译 WordPress 长文章后,分类、标签、Series 与特色图片同步问题排查

图1:Codex 输出 Token 校验诊断结果

(16) SlyTranslate 全文翻译报错排查:完善 GLM 5.2 的段落与占位符约束

图1:创建 wordpress-ai-translation-pipeline 私有 GitHub 仓库

(17) 将 WordPress AI 翻译优化项目提交到 GitHub:一次阶段性的收尾

图1:文章列表中因摘要为空而重复出现两个 Post Views

(18) 从空摘要、历史格式混杂到重新翻译:我如何规划 WordPress AI 翻译工程的下一阶段

图4:最终批处理输出 42/42 完成、待处理 0、异常状态 0。

(19) 从只读审计到 42/42 完成:用 GLM 与 SlyTranslate 安全补全 WordPress 历史文章摘要

图3:GitHub 已正确识别仓库的 MIT License。

(20) 将 WordPress AI 翻译优化仓库从私有切换为公共:从敏感信息审计到最小改动发布

图1:仓库显示所有历史批次已经完成,并允许创建下一批。

(21) 每天批量处理 20 篇 WordPress 历史文章:代码块迁移、摘要补全与英文覆盖翻译完整 SOP

图 2:复杂 Classic 一次转换成多个 Gutenberg 区块

(22) 每天批量处理 20 篇 Mixed WordPress 历史文章:Classic 转 Gutenberg、SyntaxHighlighter 迁移、摘要补全与英文覆盖翻译完整 SOP

GLM-5.2 整篇翻译再次出现 Protected Token 校验失败:从尾部 Token 丢失到 Plaintext 结构重排的完整排查记录

(23) GLM-5.2 整篇翻译再次出现 Protected Token 校验失败:从尾部 Token 丢失到 Plaintext 结构重排的完整排查记录

图 1:历史文章 4652 在 GLM-5.2 整篇翻译时返回 HTTP 400 安全检测错误

(24) GLM-5.2 整篇翻译持续返回 HTTP 400:从安全检测拦截到 Plaintext 载荷缩减的完整排查与修复

图 1:历史文章批处理返回 HTTP 400,并提示内容安全检查未通过。

(25) GLM-5.2 整篇翻译返回 400:一次内容安全误拦截的逐步定位与恢复记录

图 5:文章最终已经 completed,但原来的 excerpt_generation_failed、HTTP 400 和人工完成记录同时保留。

(26) WordPress 历史文章自动化遇到 GLM 1301:从 HTTP 400 到 ChatGPT 人工兜底完成

图 1:index 814 的 INLINE Token 换序及中英文 Gutenberg 对照

(27) WordPress AI 翻译排错实战:一次合法的行内代码换序,为什么会阻断尾部结构自动修复?

图 1:完整文章首次整篇翻译失败,SlyTranslate 返回受保护标记校验错误

(28) WordPress 超长 Gutenberg 文章整篇 AI 翻译踩坑:从 1000+ 受保护标记到完整翻译成功

【图1:历史文章迁移最终状态,67 个固定批次、1281 篇文章全部完成】

(29) WordPress 历史文章迁移终于收尾:全量审计 1438 篇中文文章,并停用 SyntaxHighlighter Evolved

图1:SlyTranslate 使用 GLM-5.2 翻译文章时出现 Paragraph Run 错误

(30) SlyTranslate 翻译报错:修复 Paragraph Run 无法识别带属性的问题

前段时间,我一直在处理 WordPress 站点中的历史文章,包括中文摘要回填、旧代码格式迁移、SyntaxHighlighter 短代码处理,以及对应英文文章的覆盖翻译。

此前相关处理过程可以参考:

这项工作持续了相当长一段时间。历史文章中同时存在 Gutenberg、Classic Editor、Code Block Pro、SyntaxHighlighter、<pre>、<code> 等不同格式,还有不少 mixed 内容,因此很难通过一次简单的批量替换全部解决。

到现在,这一轮历史文章迁移终于正式收尾。

而且在准备发布本文之前,我也已经正式停用了 SyntaxHighlighter Evolved。

暂时只是停用,还没有立即删除插件文件。接下来准备等待大约 5 天,让此前生成的旧页面缓存自然过期,再彻底删除插件。

一、67 个固定批次、1281 篇历史文章全部处理完成

最终的 history migration 状态为:

  • 固定批次:67
  • 固定文章:1281
  • remaining=0
  • integrity=ok
  • 最新未完成批次:无
  • 所有批次均已完成

执行证据中保留了:

  • completed=1279
  • failed=2
  • pending=0
  • translation_started=0

这里的 2 条 failed 属于历史执行证据,并不代表当前还有两篇文章没有处理。

最终流程状态已经全部收敛,remaining=0,而且当前不存在未完成批次。

【图1:历史文章迁移最终状态,67 个固定批次、1281 篇文章全部完成】
【图1:历史文章迁移最终状态,67 个固定批次、1281 篇文章全部完成】

完成历史文章迁移以后,我开始考虑另外一个已经拖了很久的问题:

SyntaxHighlighter Evolved 是否终于可以退出这个 WordPress 站点了?

二、为什么不能直接删除 SyntaxHighlighter

之前的大量历史文章已经完成代码格式迁移,但我仍然担心正文中残留 [text]、[php]、[json]、[js],以及其他 SyntaxHighlighter shortcode。

如果某篇文章原本就是依靠下面这样的短代码生成代码高亮:

Plaintext
[bash]
真正的代码或终端输出
[/bash]

那么直接删除插件以后,这些短代码就可能重新作为普通文字出现在页面中,原来的代码块也会失去正常展示效果。

因此,在真正让 SyntaxHighlighter 退出之前,我决定在历史迁移全部完成之后,再做一次独立的:

SyntaxHighlighter retirement audit

也就是 SyntaxHighlighter 退役前审计。

这一次不再自动修改文章,只负责把所有值得人工检查的中文文章找出来。

三、不能只搜索 [text]、[php]、[json] 和 [js]

最开始我想到的,只是重新搜索几个以前比较常见的短代码。

但真正检查生产环境中 SyntaxHighlighter Evolved 3.7.2 的运行时注册情况以后,发现远比这复杂。

除了三个通用 shortcode:

  • sourcecode
  • source
  • code

不同 brush 还注册了大量语言别名,例如:

  • bash
  • shell
  • php
  • go
  • golang
  • js
  • javascript
  • sql
  • text
  • plain
  • python
  • java
  • html
  • xml
  • yaml

等等。

最终确认生产运行时实际需要考虑 65 个 shortcode。

这也意味着,如果只是手工搜索几个我印象中的字符串,很容易漏掉一些真正仍然依赖插件的历史文章。

因此这次没有简单使用几个固定关键字进行 grep,而是单独增加了一套 retirement audit scanner,根据生产插件实际注册的 shortcode 和 alias 进行扫描。

四、重新同步生产数据,而不是继续使用旧快照

由于之前的历史迁移已经持续了一段时间,期间我又人工修改过不少文章,所以这次没有继续使用历史阶段保存的旧 raw 数据。

而是重新从生产 WordPress 中读取当前最新的:

  • post_type=post
  • post_status=publish
  • Polylang 中文文章

英文文章没有单独扫描。

原因是如果中文文章需要修改,我会直接在 WordPress 后台修改中文,然后再使用现有翻译流程覆盖同步英文文章。

最终一共重新读取:

1438 篇中文已发布文章。

整个数据同步被分成 15 页:

  • 前 14 页各 100 篇
  • 最后一页 38 篇

每一页都进行了远程与本地 SHA-256、记录数、字节数、JSONL scope 和 schema 等检查。

最终:

  • duplicate post_id:无
  • 分页 overlap:无
  • cursor 异常:无
  • 所有页面均通过完整性校验

完成这次全量扫描以后,结果反而比我预计的轻很多。

五、1438 篇文章,最终只有 14 篇需要人工检查

最终 retirement audit 的统计为:

  • 中文 published posts:1438
  • JSONL pages:15
  • 命中文章:14
  • shortcode 总命中:58
  • 最早命中文章:2018-09-01 17:34:44
  • 最新命中文章:2026-07-21 12:36:24

真正出现的 shortcode 只有 8 种:

Shortcode命中次数涉及文章
source196
php102
go82
sql81
text52
sourcecode41
bash21
code21
【图2:SyntaxHighlighter retirement audit 最终统计,1438 篇文章中只有 14 篇命中】
【图2:SyntaxHighlighter retirement audit 最终统计,1438 篇文章中只有 14 篇命中】

这个结果非常重要。

因为它意味着,在经历前面的大量历史迁移以后,真正还需要我人工打开确认的文章只剩:

14 篇。

此时继续开发复杂的自动迁移逻辑已经没有多少意义。

直接人工逐篇检查,反而更安全,也更加高效。

六、命中 shortcode,不代表一定要修改

这次 retirement audit 和之前自动 migration detector 最大的区别,就是:

只负责找候选,不负责判断这篇文章一定有问题。

实际检查过程中,很快就遇到了一个非常典型的例子。

某篇文章正文正在介绍短代码检测问题,其中专门写了:

Plaintext
[sourcecode]...[/sourcecode]

这本身就是文章准备展示给读者看的文本。

【图3:文章正文中 [sourcecode]...[/sourcecode] 本身就是需要展示的示例文本】
【图3:文章正文中 [sourcecode]...[/sourcecode] 本身就是需要展示的示例文本】

但是在当时 SyntaxHighlighter Evolved 仍然启用的情况下,前台会把它当成真正的 shortcode 执行。

结果原本应该显示:

Plaintext
[sourcecode]...[/sourcecode]

的地方,被 SyntaxHighlighter 渲染成了一个代码区域,只剩下中间的:

Plaintext
...

从文章语义来看,这篇文章其实完全不应该修改。

真正应该退出的是 SyntaxHighlighter 对这段文字的解析,而不是修改文章原文。

因此,这篇文章虽然被 retirement audit 命中,但最终人工判断是:

保留原文,不修改。

现在 SyntaxHighlighter Evolved 已经停用,这种本来就是为了展示 shortcode 本身的文字,也就不会再继续被插件当成代码高亮短代码处理。

这也是为什么我从一开始就没有把“shortcode 残留必须归零”当成 SyntaxHighlighter 退役条件。

有些 shortcode 外观,本来就是文章内容的一部分。

七、另一类文章则必须真正迁移

另外一篇文章就完全不同。

后台正文中保存的是:

Plaintext
[bash]
真正的终端输出
[/bash]

这里的 [bash]...[/bash] 并不是文章为了向读者展示 shortcode 本身,而是在真正使用 SyntaxHighlighter 完成代码高亮。

【图4:停用 SyntaxHighlighter 前,仍然依赖 [bash]...[/bash] shortcode 展示终端输出的历史文章】
【图4:停用 SyntaxHighlighter 前,仍然依赖 [bash]...[/bash] shortcode 展示终端输出的历史文章】

此前前台之所以能正常显示代码块,正是因为 SyntaxHighlighter 负责解析这段 shortcode。

如果停用插件之前不处理,那么原来的:

Plaintext
[bash]
...
[/bash]

就会重新作为普通文本暴露出来。

因此,这一类文章必须真正迁移。

我的处理方式是:

  1. 新建 Code Pro 区块;
  2. 只复制
Plaintext
[bash] 与 [/bash]

中间真正的代码内容;

不再保留 SyntaxHighlighter shortcode;

删除原来的简码区块;

保存中文文章;

再通过后台覆盖同步对应的英文文章。

最终 Code Pro 中保存的是实际代码,例如:

Plaintext
[root@server example.com]# php example.php
PHP Fatal error: ...
Stack trace:
...

而不再把

Plaintext
[bash] 和 [/bash]

保存进去。

这样代码展示就不再依赖 SyntaxHighlighter。

八、14 篇人工检查,真正需要修改的不到 5 篇

最终,我把这 14 篇候选全部人工检查了一遍。

实际真正需要修改的文章甚至不到 5 篇。

也就是说,这次最终结果大致是:

Plaintext
1438 篇最新中文文章
        ↓
14 篇 shortcode 候选
        ↓
全部人工检查
        ↓
真正修改不到 5 篇

这个结果也再次说明,自动扫描和人工判断应该承担不同的职责。

自动化非常适合解决:

“我有没有漏掉什么?”

但对于:

“这个 [text] 到底是需要迁移的历史 shortcode,还是文章本来就准备展示的文字?”

人工结合文章语义判断,反而更可靠。

最终不需要强行把所有 shortcode-looking text 清理到 0。

九、Retirement audit 独立于历史迁移流程

这一次没有继续往原来的 history migration 状态机中增加逻辑。

而是单独增加了:

Plaintext
bin/build-syntaxhighlighter-retirement-audit.py

以及对应配置:

Plaintext
config/syntaxhighlighter-retirement.json

这样做的原因也比较明确。

历史 migration detector 的目标是:

安全地判断一篇文章是否适合自动迁移。

因此它会主动保护或屏蔽:

  • Code Block Pro
  • Gutenberg code block
  • <pre>
  • <code>
  • 某些代码区域中的 shortcode-looking text

而 retirement audit 的目标完全不同。

它更关注:

只要可能值得人工看一眼,就把文章列出来。

因此即使一个 shortcode 出现在 Code Block Pro、<pre>、<code> 或其他复杂区域中,也没有必要过早自动排除。

最终由人工判断即可。

这也是这次 1438 篇全量扫描最终能够缩小到 14 篇人工候选的重要原因。

十、项目代码也一起完成最终收口

完成 1438 篇文章的 retirement audit、14 篇人工检查和必要的文章修改以后,我又把这次新增的审计工具,以及最后一批历史 migration state,一起完成了 Git 收口。

最终提交:

Plaintext
e2fd42f

提交信息:

Plaintext
feat: 增加 SyntaxHighlighter 退役审计

这次还运行了完整自动化测试:

Plaintext
Ran 503 tests
OK

最终历史迁移状态:

Plaintext
67 fixed batches
1281 fixed posts
remaining=0
integrity=ok

SyntaxHighlighter retirement audit:

Plaintext
1438 Chinese published posts
14 candidates
58 matches

最终 Git 状态:

Plaintext
## main...origin/main

工作树干净。

【图5:最终 Git 提交、503 项测试、历史迁移与 SyntaxHighlighter retirement audit 全部收口】
【图5:最终 Git 提交、503 项测试、历史迁移与 SyntaxHighlighter retirement audit 全部收口】

至此,这个持续了很长时间的 WordPress 历史文章处理阶段,终于可以真正停下来了。

十一、为什么在发布本文之前就停用了 SyntaxHighlighter Evolved

原本我的计划是:

先完成全部人工检查和修改,然后继续保持 SyntaxHighlighter Evolved 启用大约 5 天,等待缓存自然过期,最后再卸载插件。

但在真正准备本文时,我发现还有一个很现实的问题。

本文本身就需要展示大量历史 shortcode,例如:

Plaintext
[sourcecode]...[/sourcecode]

[bash]...[/bash]

[text]
[php]
[code]

如果 SyntaxHighlighter Evolved 仍然处于启用状态,那么这些原本只是为了向读者展示的文本,就可能再次被插件当成真正的 shortcode 解析。

前面 [sourcecode]...[/sourcecode] 的实际案例已经证明,这并不是理论上的风险。

因此,在正式发布本文之前,我已经将:

SyntaxHighlighter Evolved 停用。

这样,从现在开始新生成的 WordPress 页面不再执行 SyntaxHighlighter 注册的 shortcode。

本文中用于说明历史格式的 shortcode 示例,也可以按照文章原意正常展示,而不是再次被插件解释成代码高亮内容。

十二、为什么只是停用,而不是立即彻底删除

虽然插件已经停用,但我目前还没有立即删除 SyntaxHighlighter Evolved 的插件文件。

这里主要考虑的仍然是缓存。

今天真正修改的不到 5 篇文章,在修改以前可能已经存在旧页面缓存。

那些旧缓存是在 SyntaxHighlighter 仍然启用、文章仍然依赖旧 shortcode 的状态下生成的。

我希望给这些旧页面缓存留出一个自然退出的时间窗口。

因此现在采用的是:

Plaintext
人工迁移完成
        ↓
停用 SyntaxHighlighter Evolved
        ↓
不主动清缓存
        ↓
保留插件文件约 5 天
        ↓
让此前生成的旧页面缓存自然过期
        ↓
再彻底删除 SyntaxHighlighter Evolved

这里需要特别区分“停用”和“删除”。

插件停用以后,新的 WordPress 页面已经不会再执行 SyntaxHighlighter 的 PHP 逻辑,也不会再注册相关 shortcode。

但插件文件暂时仍然保留在服务器上。

这样,即使某些此前生成的缓存页面仍然引用了 SyntaxHighlighter 的 CSS 或 JavaScript 静态资源,对应插件文件暂时仍然存在,不需要立即面对资源文件被删除的问题。

等大约 5 天以后,这轮修改以前的旧缓存基本完成自然退出,我再进行最终的插件删除。

十三、这次历史文章处理终于真正结束

从最初只是想给旧文章补充摘要,到后来逐渐发现:

  • Classic Editor 历史格式
  • Gutenberg
  • Code Block Pro
  • SyntaxHighlighter
  • mixed content
  • shortcode 误判
  • <pre> / <code>
  • 中文与英文覆盖翻译
  • 自动校验
  • execution evidence
  • failed recovery
  • production drift
  • 人工修复

整个问题最终演变成了一套相当完整的历史内容迁移流程。

好在到现在,最终状态已经非常明确:

  • 67 个固定批次全部结束;
  • 1281 篇固定历史文章全部处理完成;
  • 1438 篇最新中文文章重新完成 SyntaxHighlighter 全量审计;
  • 只有 14 篇进入人工检查;
  • 真正需要修改的不到 5 篇;
  • SyntaxHighlighter Evolved 已经停用;
  • retirement audit 工具已经加入仓库;
  • 503 项自动化测试通过;
  • Git 工作树已经完全干净。

至此,SyntaxHighlighter 已经不再参与新页面的内容生成。

接下来也不再继续折腾历史文章。

现在只剩最后一个非常简单的收尾动作:

继续保留已经停用的 SyntaxHighlighter Evolved 插件文件大约 5 天,让此前的旧页面缓存自然退出,然后彻底删除插件。

等这一步完成以后,这一段持续了很久的 WordPress 历史代码格式迁移,也就真正画上句号了。

WordPress 超长 Gutenberg 文章整篇 AI 翻译踩坑:从 1000+ 受保护标记到完整翻译成功 SlyTranslate 翻译报错:修复 Paragraph Run 无法识别带属性的问题

关于作者 · 持续学习与技术实践

我是一名拥有 15 年以上开发经验的技术从业者,自 2013 年起持续运营个人技术博客,记录工作与个人项目中遇到的真实问题,以及解决问题过程中的探索、实践和思考。

除了技术写作,我也在持续开发和维护自己的独立项目,探索新技术和新工具在实际场景中的应用。我始终相信,没有不值得去解决的问题,也没有不值得去学习的技术。

如果这篇文章对你有所帮助,欢迎浏览博客中的其他文章,也欢迎交流技术经验与想法。

关于我  ·  GitHub  ·  邮件联系