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

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

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

作者:

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 历史文章摘要

最近,我完成了一次 WordPress 历史文章摘要补全。

这次任务最终处理了 42 篇中文历史文章,并同步补全了对应英文文章的摘要。最终结果为:

  • 已完成:42/42
  • 待处理:0
  • 异常状态:0

执行过程中出现过 GLM 请求超时、WordPress REST API 连接中断、Polylang SSH 检查超时,以及 SlyTranslate 返回 HTTP 500 等问题,但都通过状态记录、断点恢复和只读核验机制安全处理,没有重复生成摘要,也没有误改文章关系。

这次实践让我更加确定:批量修改 WordPress 历史内容时,真正重要的并不是“能否调用大模型生成一段文字”,而是能否建立一套可审计、可恢复、可验证,并且不会误伤现有内容的生产流程。

一、为什么要补全历史文章摘要

我的 WordPress 网站已经积累了大量技术文章。

其中一部分早期文章没有填写摘要。中文文章的摘要为空,对应的英文翻译文章摘要通常也是空的。

这会带来几个问题:

  1. 文章列表页只能临时截取正文作为摘要。
  2. SEO 插件可能无法直接使用稳定的文章摘要。
  3. 英文站文章缺少可控的英文简介。
  4. 后续进行文章推荐、内容聚合和结构化输出时,摘要字段无法直接使用。
  5. 如果未来继续进行批量内容维护,空摘要会成为长期遗留问题。

最简单的处理方式,是遍历所有空摘要文章,调用大模型生成摘要,然后写入数据库。

但这种方案风险很高。

网站中并不是所有空摘要文章都适合直接修改。有些文章可能没有英文翻译,有些文章的中英文关系可能已经异常,还有些文章可能使用特殊 Gutenberg 区块、Code Block Pro 代码块或其他复杂内容结构。

因此,这次没有直接从“批量写入”开始,而是先进行了完整的只读盘点。

二、先建立固定候选清单

第一阶段只读取生产环境数据,不进行任何写入。

候选文章必须同时满足以下条件:

  • 中文文章已经发布;
  • 中文摘要为空;
  • 使用 Gutenberg 编辑器;
  • 正文包含 Code Block Pro 等需要特别保护的结构;
  • 存在对应的英文翻译文章;
  • 英文文章已经发布;
  • 英文摘要为空;
  • Polylang 中英文关系正确;
  • 中英文文章 ID 明确;
  • 文章当前状态、正文和标题可以计算固定哈希。

经过筛选后,得到了一份固定候选清单,共 42 组中英文文章。

另外还有 46 篇已经存在中文摘要的文章。这些文章被明确排除在候选清单之外,后续脚本不会修改它们。

固定候选清单的意义在于:正式执行时不再重新扫描整个 WordPress 数据库,而是只允许处理审计阶段确认过的文章 ID。

即使网站后续新增了文章,或者其他文章状态发生变化,也不会被自动纳入本次批处理。

三、中文摘要与英文摘要采用不同处理方式

这次流程并不是直接让一个模型同时生成中英文摘要。

实际处理分为两个阶段。

1. 使用 GLM 4.7 生成中文摘要

GLM 4.7 只负责根据中文文章标题和正文生成中文摘要。

摘要要求包括:

  • 只返回一段纯文本;
  • 不使用 Markdown;
  • 不使用项目符号;
  • 不添加“本文介绍了”之外的额外说明;
  • 长度控制在 160~240 个中文字符左右;
  • 最低不能少于 80 个字符;
  • 最高不能超过 300 个字符;
  • 不包含代码、命令或 Gutenberg 区块标记;
  • 保持个人技术博客的真实和克制,不使用营销表达。

生成摘要前,脚本会先从正文中移除:

  • Gutenberg 区块注释;
  • HTML 标签;
  • Code Block Pro 代码内容;
  • 普通代码块;
  • 短代码;
  • URL;
  • 文件路径;
  • 其他不适合作为摘要上下文的结构。

这样可以减少模型将代码、命令或 HTML 片段写入摘要的概率。

2. 使用 SlyTranslate 和 GLM 5.2 更新英文文章

中文摘要写入成功后,不再单独调用 GLM 4.7 生成英文摘要。

脚本会调用现有的 SlyTranslate 覆盖翻译接口,使用 GLM 5.2 重新处理对应的英文文章。

请求采用覆盖模式:

JSON
{
  "input": {
    "post_id": 18150,
    "source_language": "zh",
    "target_language": "en",
    "post_status": "publish",
    "overwrite": true,
    "translate_title": true,
    "model_slug": "glm-5.2"
  }
}

这样做有几个好处:

  • 继续复用已经调优的 SlyTranslate 翻译管线;
  • 保留原有 Gutenberg 区块保护逻辑;
  • 保留 Code Block Pro 代码块;
  • 保留 HTML、短代码、URL、路径和产品名;
  • 直接更新已有英文文章;
  • 不创建新的英文文章;
  • 不改变文章发布状态;
  • 不破坏 Polylang 中英文关联。

四、为什么不能直接批量执行

真正危险的部分并不是模型生成摘要,而是生产环境写入。

一次完整流程至少包含以下操作:

  1. 读取中文文章。
  2. 读取英文文章。
  3. 核对文章状态。
  4. 核对当前标题与正文哈希。
  5. 通过 SSH 加载 WordPress。
  6. 核对 Polylang 语言和双向关联。
  7. 调用 GLM 4.7。
  8. 校验生成摘要。
  9. 备份文章写入前数据。
  10. 通过 REST API 更新中文摘要。
  11. 再次读取中文文章确认写入结果。
  12. 再次核对 Polylang 关系。
  13. 调用 SlyTranslate 覆盖翻译。
  14. 读取英文文章确认英文摘要。
  15. 再次核对文章状态和中英文关系。
  16. 将执行状态标记为完成。

在这 16 个步骤中的任何一个位置,都可能发生网络超时、接口错误或者服务端断开连接。

如果只是用一个简单的循环执行,失败后很难判断:

  • 中文摘要是否已经写入;
  • 英文覆盖翻译是否已经执行;
  • SlyTranslate 是否已经成功,只是响应没有返回;
  • 是否应该重新生成中文摘要;
  • 是否应该重新调用覆盖翻译;
  • 是否可能对同一文章执行两次写入。

因此,我为每篇候选文章建立了独立的执行状态文件。

五、为每篇文章保存执行状态

每篇中文文章都有一个独立的状态文件,例如:

Plaintext
data/backups/single-candidate/chinese-18150.execution.json

状态文件会记录:

  • 中文文章 ID;
  • 英文文章 ID;
  • 写入前备份路径;
  • 任务开始时间;
  • 已生成的中文摘要;
  • 摘要生成尝试次数;
  • 当前执行状态;
  • 完成时间;
  • 最终英文文章 ID;
  • 网络或接口错误信息。

主要状态包括:

Plaintext
prepared
excerpt_rejected
chinese_excerpt_saved
translation_started
translation_failed
completed

这些状态并不只是为了显示进度,而是决定任务失败后应该从哪个位置恢复。

例如:

  • prepared:还没有写入中文摘要,可以重新调用 GLM;
  • chinese_excerpt_saved:中文摘要已经写入,不能再次生成,只能继续英文覆盖;
  • translation_failed:覆盖翻译明确失败,可以重新调用 SlyTranslate;
  • translation_started:覆盖请求已经发出,但最终结果不确定,必须先只读核验;
  • completed:所有检查通过,后续批次直接跳过。

六、写入前为每篇文章单独备份

每篇文章第一次进入真实执行流程时,都会保存一份写入前备份:

Plaintext
data/backups/single-candidate/chinese-18150.pre-write.json

备份文件权限固定为:

Plaintext
0600

备份内容包括执行前读取到的文章数据和安全检查需要的字段。

状态文件与备份文件都不会保存:

  • 智谱 API Key;
  • WordPress 登录 Cookie;
  • REST API nonce;
  • Authorization 请求头;
  • 其他认证信息。

即使日志或备份文件被复制,也不会直接暴露生产环境凭证。

七、摘要验证失败时只重试生成阶段

早期测试中,GLM 偶尔会返回带有项目符号或类似 Markdown 的摘要。

例如,模型可能返回:

Plaintext
- 第一项内容
- 第二项内容

这种内容虽然可以阅读,但不符合 WordPress 摘要字段只保存单段纯文本的要求。

因此,脚本对生成结果执行严格校验。

只有出现摘要格式校验错误时,才允许重新调用 GLM,最多尝试 3 次。

被拒绝的结果会单独保存在:

Plaintext
data/backups/single-candidate/rejected/

文件权限同样为 0600

其他类型的错误,例如 WordPress 状态变化、内容哈希不一致或 Polylang 关系异常,不会触发模型重试,而是直接停止任务。

这样可以避免把真正的安全异常误判为普通模型输出问题。

八、恢复模式不再依赖 GLM API Key

执行过程中曾经出现过一个恢复逻辑问题。

某篇文章已经成功写入中文摘要,但 SlyTranslate 返回 HTTP 500。此时状态为:

Plaintext
translation_failed

正确操作应该是执行:

Bash
python3 bin/execute-single-candidate.py \
  --post-id 17945 \
  --execute \
  --resume

恢复流程不需要重新生成中文摘要,因此也不应该使用 GLM 4.7。

但最初的命令行程序会在进入恢复逻辑前直接构造 GLM 客户端,导致即使使用 --resume,仍然要求环境变量:

Plaintext
ZHIPU_API_KEY

后来将 GLM 客户端改为延迟导入和延迟实例化:

  • 普通 --execute 才构造 GLM 客户端;
  • --execute --resume 传入 glm=None
  • 恢复流程完全不读取智谱 API Key;
  • 普通执行缺少 API Key 时仍然拒绝执行。

这项修复完成后,针对性测试和完整测试全部通过,共计 204 项。

九、最危险的状态:translation_started

执行文章 18150 → 18156 时,出现了一个更复杂的边界情况。

流程已经完成:

  • GLM 4.7 生成中文摘要;
  • 中文摘要写入 WordPress;
  • SlyTranslate 覆盖翻译;
  • 英文摘要实际已经生成。

但是,在覆盖翻译完成后,程序再次读取英文文章进行最终校验时,连接被服务器断开:

Plaintext
RemoteDisconnected

状态文件停留在:

Plaintext
translation_started

此时不能直接判断覆盖翻译失败。

如果简单地对 translation_started 再次执行 SlyTranslate,有可能重复覆盖已经成功翻译的英文文章。

因此,我先进行了只读检查。

检查结果为:

Plaintext
zh_id: 18150
zh_status: publish
zh_excerpt_length: 154
en_id: 18156
en_status: publish
en_excerpt_length: 459

Polylang 双向关系也完全正确:

JSON
{
  "zh_language": "zh",
  "en_language": "en",
  "zh_translations": {
    "zh": 18150,
    "en": 18156
  },
  "en_translations": {
    "en": 18156,
    "zh": 18150
  }
}

这说明 SlyTranslate 实际已经成功,只是最终 REST 读取失败。

图1:英文摘要已经写入,但状态仍停留在 translation_started 的只读核验结果。
图1:英文摘要已经写入,但状态仍停留在 translation_started 的只读核验结果。

十、为 translation_started 增加只读收敛

为了解决这个问题,恢复逻辑再次进行了调整。

现在遇到 translation_started 时,不会立即重新调用 SlyTranslate,而是先执行只读收敛检查。

检查内容包括:

  • 中文文章 ID 与固定清单一致;
  • 英文文章 ID 与固定清单一致;
  • 中英文文章仍为预期发布状态;
  • 中文标题和正文没有变化;
  • 已写入的中文摘要与状态文件一致;
  • 英文标题和正文非空;
  • 英文摘要是否已经生成;
  • 中文文章语言为 zh
  • 英文文章语言为 en
  • 中文到英文的 Polylang 关系正确;
  • 英文到中文的反向 Polylang 关系正确。

如果全部核验通过,并且英文摘要已经非空:

  • 不再次调用 SlyTranslate;
  • 直接将状态写为 completed
  • 写入 completed_at
  • 写入 translated_post_id

只有英文摘要仍为空时,才允许重新调用覆盖翻译接口。

如果文章 ID、发布状态、内容哈希或 Polylang 关系出现异常,则拒绝恢复,不调用 SlyTranslate,也不写入 WordPress。

这项修复完成后,完整测试数量增加到 208 项,全部通过。

十一、批量执行时出现的真实故障

最终批处理并不是一次完全无错误的执行。

在剩余文章的批处理中,主要出现了三类临时故障。

1. GLM 请求超时

文章 18488 → 1851318534 → 18610 第一次生成摘要时,GLM 请求出现:

Plaintext
TimeoutError: The read operation timed out

此时状态仍为:

Plaintext
prepared

说明:

  • 中文摘要尚未生成;
  • WordPress 尚未写入;
  • SlyTranslate 尚未调用。

批处理等待 10 秒后,根据最新状态重新执行普通模式,第二次均成功完成。

2. 最终 REST 读取连接中断

文章 18726 → 18746 已经执行覆盖翻译,但最终读取英文文章时出现:

Plaintext
RemoteDisconnected

状态变为:

Plaintext
translation_started

批处理等待 10 秒后自动切换到 --resume

新的只读收敛逻辑确认英文摘要已经存在,因此没有重复调用 SlyTranslate,直接将任务标记为完成。

3. SlyTranslate 返回 HTTP 500

文章 18815 → 18825 在覆盖翻译阶段返回:

Plaintext
HTTP request failed with status 500

状态变为:

Plaintext
translation_failed

批处理等待 10 秒后执行恢复模式,再次调用覆盖翻译,第二次成功完成。

这些故障说明,批量任务不能把“命令退出非零”简单理解为“整篇文章什么都没做”。

必须根据持久化状态决定下一步操作。

图2:GLM 请求超时后,任务保持 prepared,并在第二次执行中成功完成。
图2:GLM 请求超时后,任务保持 prepared,并在第二次执行中成功完成。

图3:SlyTranslate 返回 HTTP 500 后,从 translation_failed 状态恢复成功。
图3:SlyTranslate 返回 HTTP 500 后,从 translation_failed 状态恢复成功。

十二、最终批处理如何决定执行模式

最终批处理不会固定对每篇文章执行同一条命令,而是先读取状态文件。

状态与执行方式的对应关系如下:

Plaintext
none
prepared
excerpt_rejected

使用普通执行:

Bash
python3 bin/execute-single-candidate.py \
  --post-id <ID> \
  --execute

以下状态:

Plaintext
chinese_excerpt_saved
translation_started
translation_failed

使用恢复执行:

Bash
python3 bin/execute-single-candidate.py \
  --post-id <ID> \
  --execute \
  --resume

如果状态已经是:

Plaintext
completed

则直接跳过。

每篇文章最多尝试 3 次。

两次尝试之间等待 10 秒,并根据最新状态重新选择执行模式。

无法识别的状态不会被自动处理,而是立即停止整个批次。

整个批处理运行在子 Shell 中,即使任务失败,也不会关闭当前终端窗口。

十三、最终执行结果

最后一次批处理开始时,剩余 26 篇文章。

大多数文章第一次执行即成功。

其中:

  • 两篇文章遇到 GLM 超时,第二次普通执行成功;
  • 一篇文章在最终 REST 校验时断线,通过 translation_started 只读收敛成功;
  • 一篇文章遇到 SlyTranslate HTTP 500,通过 translation_failed 恢复成功。

最终汇总结果为:

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

这也证明了本次流程不仅能在理想网络环境下运行,也能应对实际生产环境中常见的临时失败。

十四、这次实现中最重要的几个原则

回顾整个过程,我认为以下原则比具体使用哪个模型更重要。

1. 先审计,再写入

不要让批处理脚本自行决定要修改哪些生产文章。

先生成固定候选清单,再只允许处理清单中的文章。

2. 一篇文章一个状态文件

不要只在终端显示进度。

状态必须持久化,程序重启后仍然能够判断上次停在哪一步。

3. 写入前必须备份

每篇文章在第一次写入前,都保存独立备份。

备份权限应限制为当前用户可读写。

4. 恢复不能等于重复执行

恢复流程必须根据状态决定:

  • 是否重新调用模型;
  • 是否重新写中文摘要;
  • 是否重新调用覆盖翻译;
  • 是否只需完成最终核验。

5. 请求失败不代表操作失败

POST 请求超时或者连接断开时,服务端可能已经完成操作。

尤其是在调用耗时较长的翻译接口时,必须先只读核验生产结果,再决定是否重试。

6. 双向验证 Polylang 关系

只确认中文文章指向英文文章还不够。

还要确认英文文章反向指向正确的中文文章。

7. 不要为了批量速度取消安全检查

这次只有 42 篇文章,逐篇执行会增加一些时间。

但相对于修复中英文文章关系、恢复错误摘要或处理重复翻译,这点时间成本完全可以接受。

十五、当前阶段的结论

这次摘要补全不是一个简单的 AI 文本生成任务,而是一次小型的 WordPress 内容迁移和生产数据修复。

GLM 4.7 负责生成中文摘要,SlyTranslate 和 GLM 5.2 负责更新英文翻译,但真正让流程可以安全落地的,是外围的工程控制:

  • 固定候选清单;
  • 内容哈希;
  • 写入前备份;
  • REST API 写入;
  • Polylang 双向检查;
  • 状态持久化;
  • 失败分类;
  • 安全恢复;
  • 只读收敛;
  • 自动重试;
  • 完整测试。

最终,42 组中英文文章全部完成,已有摘要文章没有被纳入修改范围,中英文文章 ID、发布状态和 Polylang 关系均保持不变。

至此,这次 WordPress 历史文章摘要补全可以正式告一段落。

更重要的是,这套流程已经不再是一次性的临时脚本。

它已经具备了继续扩展到其他历史内容维护任务的基础,例如:

  • 补全更多类型文章的摘要;
  • 检查中英文摘要一致性;
  • 审计历史文章 Meta Description;
  • 批量检查 Polylang 关联;
  • 对已有摘要进行只读质量评估;
  • 为其他 WordPress 内容字段建立可恢复的 AI 更新流程。

对于生产环境中的 AI 自动化,我现在更倾向于一个明确的判断:

模型输出质量固然重要,但真正决定方案能否长期运行的,是模型之外的安全边界、状态管理和恢复能力。

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

需要长期技术维护或远程问题排查?

我是拥有 15+ 年经验的 PHP / Go 后端工程师,长期关注已有系统维护、Bug 修复、性能优化、服务器排查、WordPress 网站维护和小功能迭代。

如果你的项目遇到以下情况,可以先从一次小问题排查开始合作:

  • ✅ PHP / Laravel / Yii2 老项目无人维护
  • ✅ Go / Gin 后端接口需要排查或优化
  • ✅ WordPress 网站访问慢、报错或插件冲突
  • ✅ Nginx / MySQL / Redis / Linux 服务器异常
  • ✅ CDN / Cloudflare / DNS / HTTPS 配置问题
  • ✅ 需要长期远程技术支持或兼职维护

更多介绍请查看:关于我 & 合作

微信:13980074657
邮箱:shuijingwanwq@gmail.com
Telegram:@shuijingwan
GitHub:https://github.com/shuijingwan

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理