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

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

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

作者:

,

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

最近我一直在优化 WordPress 中文技术文章的英文翻译流程。

目前使用的基础方案是:

  • WordPress + Polylang
  • SlyTranslate 1.9.0
  • 智谱 GLM 5.2
  • 自定义 MU 插件
  • 一次性整篇正文翻译
  • 保留 Gutenberg 区块、HTML、短代码和代码块

前面的测试已经证明,GLM 5.2 在技术准确性、英文自然度和长文章稳定性方面表现不错。但在进一步处理 Plaintext 代码块时,又暴露出了几个比较隐蔽的问题:

  1. Plaintext 中的自然语言是否应该翻译;
  2. URL、域名、路径等机器内容不能被修改;
  3. 让模型看到 Plaintext 后,不能破坏 Gutenberg 区块顺序;
  4. Code Block Pro 区块前台虽然正常,重新打开编辑器却会提示无效;
  5. 分类、系列和标签虽然写入数据库,前台缓存却可能没有及时更新。

这篇文章记录这一轮完整的排查与修复过程。


一、为什么要单独处理 Plaintext 代码块

技术文章中的 Plaintext 并不都是同一种内容。

有些 Plaintext 只包含 URL、域名或文件路径:

Plaintext
https://en.shuijingwanwq.com/sitemap_index.xml
Plaintext
/data/wwwroot/www.shuijingwanwq.com/

这些内容当然不能翻译。

但也有一些 Plaintext 实际上是界面提示、错误信息或操作结果,例如:

Plaintext
区块包含未预料的或无效的内容。

如果整块保护,英文文章中就会残留中文。

因此,理想方案不是简单地规定:

Plaintext 全部翻译。

也不是:

Plaintext 全部不翻译。

而是让模型结合上下文判断:

  • URL、域名、路径、命令和机器数据保持原样;
  • 自然语言说明翻译为英文;
  • 真实界面证据根据上下文决定是否保留。

这也是这一轮优化的核心目标之一。


二、原生 SlyTranslate 如何保护代码块

SlyTranslate 原有流程会把完整代码块替换成占位符。

例如 Bash、PHP、HTML 等 Code Block Pro 区块,会被替换为类似:

Plaintext
SWQBLOCK000001END

模型看不到代码块内部内容,因此不会误改代码、命令和 HTML。

这种方式对于真正的代码很安全,但用于 Plaintext 时会带来一个问题:

模型完全看不到 Plaintext 中的内容,也无法结合上下文判断其中是否需要翻译。

因此,我在自定义 MU 插件中对 Plaintext 使用了不同处理方式。


三、Plaintext 使用前后标记开放给模型

Plaintext 不再整块替换为单个占位符,而是把其中的文本暴露给模型:

Plaintext
SWQPLAINSTART000001END
这里是 Plaintext 中的内容
SWQPLAINSTOP000001END

模型可以看到中间的文本,也能看到它前后的文章上下文。

这样就能处理类似下面的句子:

本次调整后,在网域资源 shuijingwanwq.com 中提交以下 Sitemap。

其中域名和 Sitemap URL 保持不变,普通说明文字则翻译为英文。

对于 Bash、PHP、HTML 等真正的代码块,仍继续使用完整区块占位,不开放内部内容。


四、第一次遇到的问题:模型交换了相邻代码块

测试一篇包含大量 URL、域名和 Plaintext 的长文章时,模型返回的占位符数量完全正确,但两个相邻代码块的顺序发生了交换。

源文结构大致是:

Plaintext
在网域资源:
[域名代码块]

中提交:
[Sitemap URL 代码块]

模型为了适应英文语序,将其改写成:

Plaintext
Submitted:
[Sitemap URL 代码块]

to the domain property:
[域名代码块]

从英文语义看并不错误,但 Gutenberg 区块顺序已经变化。

最终校验结果是:

Plaintext
expected_count=139
actual_count=139
fixed_order_valid=false

占位符没有丢失,也没有重复,只是两个相邻区块交换了位置。

这说明:

仅检查占位符数量还不够,还必须检查顺序。


五、增加 Gutenberg 结构占位符

为避免模型合并段落、删除区块边界或交换代码块,我又增加了:

Plaintext
SWQSTRUCT000001END

所有 Gutenberg 开始和结束注释,例如:

HTML
<!-- wp:paragraph -->
<!-- /wp:paragraph -->

都会先转换成固定顺序的结构标记。

模型必须保持:

  • 标记数量不变;
  • 标记顺序不变;
  • 不得合并两个 Gutenberg 区块;
  • 不得移动代码块边界。

修复后重新测试,源文和译文的 Gutenberg 区块数量均为:

Plaintext
350

并且:

Plaintext
block_signature_identical=YES

代码块之外的中文残留也降为:

Plaintext
han_outside_code_blocks=0

从文章结构来看,这一阶段已经成功。


六、英文前台正常,编辑器却提示代码块无效

英文文章发布后,前台页面显示完全正常。

但重新打开 WordPress 区块编辑器时,所有 Code Block Pro 区块都出现提示:

区块包含未预料的或无效的内容。

图1:英文文章编辑器中,Code Block Pro 区块提示包含无效内容
图1:英文文章编辑器中,Code Block Pro 区块提示包含无效内容

一开始我怀疑是复制按钮的无障碍属性被翻译了。

中文代码块中保存的是:

HTML
aria-label="复制"

英文文章中被改成:

HTML
aria-label="Copy"

于是先将 79 处 Copy 恢复成 复制

结果编辑器仍然提示无效,说明问题并不只在 aria-label


七、逐字节对比后发现 Code Block Pro 被重新生成

我对比了中文文章和英文文章中的第一个 Code Block Pro 区块。

结果如下:

Plaintext
source_bytes=2903
target_bytes=2241
byte_identical=NO

第一处差异出现在 codeHTML

原始区块中包含:

HTML
tabindex="0"

英文区块中这一属性已经丢失。

继续比较 PHP 代码块后,又发现:

Plaintext
\u003e

被重新转义成:

Plaintext
\u0026gt;

也就是说,问题不是模型修改了代码,而是代码块在恢复或保存阶段被重新序列化了。

Code Block Pro 的同一份内容并不只保存一次,而是同时存在于:

  1. Gutenberg 区块 JSON 中的 code
  2. Gutenberg 区块 JSON 中的 codeHTML
  3. <textarea>
  4. <pre class="shiki">
  5. 实际显示代码所使用的 <code><span>

只要其中一个位置的格式、转义方式或属性顺序发生变化,Gutenberg 就可能认为区块无效。


八、用 GLM 5.1 做对照测试

为了确认问题来自 SlyTranslate 原生插件,还是自定义的 GLM 5.2 整篇翻译流程,我又做了一次对照测试。

我选择一篇中文草稿,使用 SlyTranslate 原生流程和 GLM 5.1 翻译。

翻译后的 Plaintext 和 PHP 代码块在编辑器中完全正常,没有出现无效提示。

图2:使用 SlyTranslate 原生流程和 GLM 5.1 翻译后,Code Block Pro 正常显示
图2:使用 SlyTranslate 原生流程和 GLM 5.1 翻译后,Code Block Pro 正常显示

这次对照基本确认:

问题不在 Code Block Pro,也不在 SlyTranslate 原生保存逻辑,而在自定义的 GLM 5.2 整篇翻译流程。


九、确认 SlyTranslate 输入阶段没有修改代码块

随后检查 SlyTranslate 的 prepare_single()

源文和准备出的正文单元结果为:

Plaintext
source_chars=377043
unit_chars=377043
whole_content_identical=YES

Code Block Pro 的结果为:

Plaintext
source_code_blocks=79
unit_code_blocks=79
code_blocks_identical=79
code_blocks_different=0

这证明 SlyTranslate 在进入模型翻译之前,并没有修改任何代码块。

真正的问题发生在模型返回后的恢复和保存阶段。


十、Plaintext 原来的恢复方式存在隐患

此前 Plaintext 翻译完成后,插件会调用类似:

PHP
rebuild_plaintext_code_block_pro()

重新构建整个 Code Block Pro 区块。

其中包括:

  • 重新解析 Gutenberg JSON;
  • 修改 code
  • 重建 codeHTML
  • 重建 <textarea>
  • 重建 Shiki <pre>
  • 重新序列化区块属性。

这种方式虽然能够更新 Plaintext 内容,但很容易改变原始区块中的其他细节。

最终方案需要区分两类 Plaintext。

1. 机器型 Plaintext

例如:

Plaintext
https://en.shuijingwanwq.com/
Plaintext
/data/wwwroot/www.shuijingwanwq.com/

模型可以看到这些内容,以理解文章上下文。

但恢复时直接放回完整原始 Code Block Pro 区块,不重新生成任何 JSON 或 HTML。

2. 自然语言 Plaintext

例如错误提示、操作输出或说明文字。

这些内容仍交给 GLM 5.2 判断并翻译。

同时保留 Plaintext 智能翻译能力,而不是退回到整块不翻译。


十一、最终问题出现在 WordPress 保存过滤器

SlyTranslate 的 Polylang 适配器最终使用:

PHP
wp_update_post( wp_slash( $update_data ) );

保存英文正文。

WordPress 在保存正文时,可能经过 content_save_pre、KSES 或其他过滤器。

SlyTranslate 自己的源码注释中也明确提到,KSES 可能:

  • 删除 tabindex
  • 删除自定义区块的 data-* 属性;
  • 修改区分大小写的 SVG 属性;
  • 导致 Code Block Pro 被 Gutenberg 判定无效。

虽然当前登录用户是管理员,但自定义整篇翻译流程最终生成的正文,仍可能在完整保存过程中发生变化。

因此,仅靠占位符恢复还不够。

还需要保证:

已经校验通过的最终正文,写入数据库后必须与保存前逐字节一致。


十二、增加最终精确写回和 SHA-256 校验

在 MU 插件 2026.07.16.12 中,最终采用了两阶段保存。

第一阶段:仍由 SlyTranslate 正常处理

SlyTranslate 继续负责:

  • 创建或覆盖英文文章;
  • 设置文章状态;
  • 设置 Polylang 语言;
  • 建立中英文文章关联;
  • 复制分类、系列和标签;
  • 保存 Meta。

第二阶段:精确写回正文

取得英文文章 ID 后,再将已经通过完整结构校验的英文正文直接写回 post_content

写回前计算:

Plaintext
expected_hash

重新读取数据库后再计算:

Plaintext
stored_hash

然后比较:

Plaintext
expected_hash === stored_hash

如果哈希不同,立即返回错误,不再把这次翻译视为成功。

这一做法避开了最终保存过滤器对 Code Block Pro 区块的再次改写,同时不影响 SlyTranslate 原有的文章、语言和术语处理流程。


十三、最终验证结果

修复后重新覆盖翻译文章:

Plaintext
中文文章 ID:19383
英文文章 ID:19494

英文编辑器中的所有 Code Block Pro 区块恢复正常,不再提示无效内容。

最终逐区块比较结果:

Plaintext
source_total=79
target_total=79

bash: total=5, identical=5, different=0
html: total=3, identical=3, different=0
php: total=3, identical=3, different=0
plaintext: total=68, identical=47, different=21

这个结果基本符合预期:

  • 5 个 Bash 区块全部逐字节一致;
  • 3 个 HTML 区块全部逐字节一致;
  • 3 个 PHP 区块全部逐字节一致;
  • 68 个 Plaintext 中:
    • 47 个保持原样;
    • 21 个根据上下文完成翻译。

也就是说:

真正的代码、URL、域名、路径和机器数据保持不变;Plaintext 中的自然语言由 GLM 5.2 智能判断并翻译。

这正是本轮优化最希望达到的结果。


十四、分类、系列和标签前台未及时更新

英文文章编辑器中已经可以看到正确的英文分类、系列和标签。

数据库检查结果也完全正常:

Plaintext
category=SEO Tools | Yoast SEO
series=Blog SEO Log
post_tag=Cloudflare | English Subdomain | Polylang | Search Engine Submission | Thin Content Tags | W3 Total Cache | WordPress | XML Sitemap | Yoast SEO

但英文前台一开始仍显示:

Plaintext
Uncategorized

随机查询参数绕过页面缓存后,部分标签已经更新,但分类仍然是旧值。

最终在英文 Host 环境下清理:

  • 文章对象缓存;
  • 术语关系缓存;
  • category、series、post_tag 的关系缓存;

前台才恢复正确内容。

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

这说明:

分类、系列和标签没有丢失,真正的问题是英文域名对应的 W3 Total Cache / Redis 对象缓存没有及时失效。

后台执行“清除所有缓存”或单独清除页面缓存、对象缓存,并不一定能清理到英文 Host 对应的缓存空间。

这与此前英文站出现语言、Canonical 和分类链接缓存异常的问题属于同一类多域名缓存边界。


十五、系列顺序出现了新的异常

缓存清理完成后,英文文章已经正确出现在 Blog SEO Log 系列中。

但它被排到了系列第一篇,而不是最后一篇。

后台 PublishPress Series 的“当前部分”也显示:

Plaintext
当前没有部分编号
图4:英文文章加入 Blog SEO Log 后被排到系列第一位
图4:英文文章加入 Blog SEO Log 后被排到系列第一位
图5:后台没有设置当前部分编号
图5:后台没有设置当前部分编号

这个问题与 Code Block Pro、Plaintext 翻译和正文保存已经不是同一个问题。

目前可以确认的是:

  • 系列术语绑定正确;
  • 英文文章已经属于正确系列;
  • 文章没有明确的系列编号;
  • PublishPress Series 因此将其显示在第一位。

这一问题暂时留到后续单独排查,不继续混入本轮翻译插件优化。


十六、本轮最终稳定版本

当前使用的 MU 插件版本为:

Plaintext
2026.07.16.12

这一版本已经验证:

  • GLM 5.2 可以一次性翻译完整长文章;
  • Gutenberg 区块数量和顺序保持一致;
  • 区块边界不会被模型合并;
  • Bash、PHP、HTML 完整逐字节保留;
  • Plaintext 可以智能判断是否翻译;
  • URL、域名和路径保持原样;
  • Code Block Pro 编辑器不再提示无效内容;
  • 最终正文写入带 SHA-256 校验;
  • 分类、系列和标签可以正常写入数据库。

目前剩余的主要问题已经不再是翻译质量本身,而是:

  • 多域名环境下的对象缓存失效;
  • PublishPress Series 的文章顺序同步。

这两项更适合后续分别处理。


十七、最终体会

这一轮排查最重要的收获,是不能只根据前台页面判断 Gutenberg 内容是否安全。

前台能够正常显示,并不代表:

  • 区块结构仍然有效;
  • 编辑器可以继续修改;
  • Code Block Pro 的序列化内容没有变化;
  • JSON、HTML 和 Shiki 代码完全一致。

对于技术博客的自动翻译流程,真正需要同时满足的是:

  1. 英文自然;
  2. 技术内容准确;
  3. 代码不被修改;
  4. Gutenberg 结构完整;
  5. 编辑器可以正常重新打开;
  6. 数据库存储结果可验证;
  7. 分类、标签和系列关系能够正确刷新。

相比单纯追求某一篇文章更自然的英文,这些结构和保存层面的稳定性,才更决定自动翻译方案能否长期投入生产。

暂缓 OpenAI 后,我在本地测试了 Gemini:与 GLM 5.2 的 WordPress 技术文章翻译对比 SlyTranslate + GLM-5.2 翻译 WordPress 长文章后,分类、标签、Series 与特色图片同步问题排查

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

我是拥有 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