最近在继续验证 WordPress 多语言、多域名缓存兼容性时,我发现一个新的问题:
英文译文已经发布,Polylang 中的中英文文章关系也已经建立,但对应的中文文章详情页仍然没有显示语言切换器,页面中的英文 hreflang 也没有出现。
这次排查最终确认,问题并不是简单的 W3 Total Cache Page Cache 没有清理,而是 Polylang 翻译关系对应的 Object Cache 在 www、en 和 admin 三个 Host 之间没有同步失效。
不过,考虑到这个问题目前主要导致语言切换器和 hreflang 延迟出现,而要实现真正可靠的跨 Host 精确清理需要进一步依赖 W3TC 内部机制,因此这一阶段没有继续增加生产修复逻辑。
这篇文章记录已经确认的现象、根因和暂时的取舍,方便以后需要继续优化时直接接着排查。
一、问题出现在英文译文发布以后
这次测试的中文文章是 21027,英文译文是 21034。
英文文章已经正常发布,而且通过 WP-CLI 查询,Polylang 关系也是正确的:
21027 → 21034
因此最开始可以排除一种情况:英文文章并不是因为没有建立翻译关系而缺少语言切换器。
一开始我怀疑的是中文文章详情页 Page Cache。
因为中文文章通常先发布,此时英文译文还不存在。如果详情页已经生成缓存,那么 HTML 中自然不会包含英文语言切换器。后来英文译文发布,如果这份 Page Cache 没有失效,看起来就会一直像“没有英文版”。
但实际检查很快排除了这个判断。
二、没有 Page Cache 时,Origin 仍然输出错误
检查 21027 对应的 W3TC Page Cache 文件时,第一次发现缓存文件并不存在。
随后直接绕过 CDN 请求本机 Origin,页面返回 HTTP 200,但 HTML 中:
- 英文文章
21034的 URL 出现次数为 0; hreflang出现次数为 0。
这意味着问题已经发生在 Page Cache 生成之前。
也就是说:
WordPress 动态生成中文文章页面时,本身就没有识别到对应英文译文。
公网请求当时同样返回 eo-cache-status: MISS,输出结果也一样,因此 EdgeOne 旧缓存也不是这次问题的来源。
问题范围由此缩小到了 WordPress、Polylang 和 Object Cache。
三、正常旧文章与异常新文章形成了明显对照
为了确认不是语言切换器本身失效,我又找了一篇能够正常显示语言切换器的旧文章 20612,对应英文文章为 20617。
正常文章的 Origin HTML 中:
- 对应英文文章 URL 出现 2 次;
hreflang出现 3 次;- 页面能够正常输出
20617的英文链接。
而异常文章 21027:
- 对应
21034URL 为 0; hreflang为 0。
随后又发现,最近十余篇中文文章存在类似情况。
这说明整个 Polylang 输出机制并没有失效,更像是近期新建立的翻译关系没有被某一层缓存及时感知。
四、真正的关键证据:WP-CLI 正常,www HTTP Runtime 错误
WP-CLI 中查询 21027 时,可以正常获得:
21027 → 21034
但 WP-CLI 和真实 PHP-FPM HTTP 请求不一定使用完全相同的 Object Cache 运行环境,因此我又通过真实 www Origin HTTP 请求调用了 pll_get_post()。
运行环境确认使用的是 W3 Total Cache Redis Object Cache:
W3TC\ObjectCache_WpObjectCache
正常旧文章仍然得到:
20612 → 20617
但异常文章却得到:
21027 → NONE
这一步基本确定了问题:
数据库中的 Polylang 翻译关系已经正确,但
wwwHost 的持久化 Object Cache 仍然保存着“21027 没有英文译文”的旧结果。
五、精确清理 relationship cache 后立即恢复
随后没有清空 Redis,也没有执行全局 Object Cache Flush,而是在真实 www HTTP Runtime 中对关联文章执行了 clean_object_term_cache()。
执行前:
pll_get_post( 21027, 'en' ) = 0
执行以后:
pll_get_post( 21027, 'en' ) = 21034
为了进一步缩小范围,又使用另一组异常文章 21018 → 21022 做了精确测试,只删除对应的 post_translations_relationships 缓存:
wp_cache_delete(
21018,
'post_translations_relationships'
);
wp_cache_delete(
21022,
'post_translations_relationships'
);
结果同样从:
before: 0
恢复到:
after: 21022
因此已经能够确认,真正陈旧的是:
post_translations_relationships
也就是 Polylang Post 翻译关系对应的 Object Cache。
六、为什么最终还会表现成页面长期没有语言切换器
Object Cache 只是第一层。
当 www Runtime 从旧的 post_translations_relationships 中读到“没有英文译文”以后,会生成一份没有英文语言切换器和 hreflang 的 HTML。
如果 W3TC Page Cache 随后缓存了这份 HTML,即使 Object Cache 后来已经自然过期,用户仍然可能继续看到错误页面,直到 Page Cache 自己过期或被清理。
这次在清理 relationship cache 后,又精确清除了 21027 的详情页 Page Cache。
重新生成 Origin 页面以后:
21034URL 出现 2 次;hreflang出现 3 次;- 中英文 alternate 链接恢复正常。
因此完整链路已经确认:
旧的 Polylang relationship Object Cache → pll_get_post() 返回无译文 → 生成缺少语言切换器的 HTML → W3TC Page Cache 再缓存这份 HTML。
七、为什么迁移到三个 Host 后才明显出现
以前英文站位于 www.shuijingwanwq.com/en/。
中英文虽然路径不同,但都运行在 www.shuijingwanwq.com 这个 Host 下。
现在则变成:
- 中文:
www.shuijingwanwq.com - 英文:
en.shuijingwanwq.com - 后台:
admin.shuijingwanwq.com
英文译文通常从 admin Host 创建和保存翻译关系,而 W3 Total Cache Redis Object Cache 又会让具体缓存项受到 Host namespace 的影响。
于是就可能出现:
中文文章还没有英文译文时,www 已经缓存了“无翻译”关系;随后 admin 创建英文译文并更新数据库,但 www 中原来的 relationship cache 没有同步失效。
这也解释了为什么以前单 Host 环境没有明显问题,迁移到多域名后才集中暴露。
八、为什么没有直接加入跨 Host 修复
确认根因以后,我让 Codex进一步检查了当前 W3TC 2.10.3 是否存在适合的 Host-aware Object Cache API。
结果没有找到一个公开、稳定的接口,可以从 admin 请求中指定:
“删除 www Host 下某个 post_translations_relationships key”。
实验也证明,在 admin Host 执行 wp_cache_flush_group( 'post_translations_relationships' ) 后,admin 自己可以读取新关系,但 www 仍然读取旧数据。
因此不能简单照搬此前 posts group 的处理方案。
理论上可以继续依赖 W3TC 内部 Redis key 构造规则,实现跨 Host 精确删除,但这会把 MU Plugin 与 W3TC 2.10.3 的私有实现绑定在一起。
为了解决一个语言切换器延迟问题,我认为这种维护成本和风险目前并不值得。
九、也没有为了这个问题修改 Object Cache 策略
当前 W3TC 实际配置是:
Object Cache 使用 Redis,lifetime 为 86400 秒,也就是 24 小时。
Page Cache 使用 file_generic,lifetime 为 345600 秒,也就是 4 天。
这意味着旧翻译关系可能在 Redis 中保留较长时间,而错误生成的详情页 HTML 还可能继续由 Page Cache 保存。
曾考虑过几个方案:
缩短 Object Cache TTL,可以让旧关系更快自然过期,但会影响整个 Object Cache,而不仅仅是 Polylang 翻译关系。
把 post_translations_relationships 设置成 non-persistent,可以彻底避开 Redis 中的跨 Host 旧关系,但意味着这类翻译关系以后会更频繁重新读取数据库。
把 Object Cache TTL 延长到 2 天或 4 天,可以降低自然过期频率,但也会让这类没有正确失效的旧数据保留更久。
综合来看,目前都没有必要。
因此继续保持:
Object Cache TTL = 1 天
Page Cache TTL = 4 天
十、当前为什么选择接受自然过期
这个问题确实存在,但影响范围需要和修复成本一起考虑。
目前更重要的是保证文章发布以后:
- 中文和英文首页能够及时更新;
- Sitemap 能够及时反映新内容;
- 文章正文正确;
- 页面语言正确;
- canonical 正确;
- 不因为缓存长期展示旧文章内容。
相比之下,中文文章详情页的语言切换器以及 hreflang 晚一些出现,虽然不够理想,但当前仍属于低优先级问题。
因此这一阶段选择不再继续增加生产逻辑。
不使用 W3TC 私有 Redis API,不直接拼 physical key,不执行 Redis DEL,也不改变整个 relationship group 的持久化策略。
先让现有缓存自然过期。
十一、这次排查留下的几个重要经验
这次最有价值的并不是最终有没有写一个 MU Plugin 修复,而是进一步确认了多 Host Object Cache 排查时的一些边界。
数据库已经更新,不代表所有 Host 的 PHP Runtime 都已经看到最新结果。
WP-CLI 返回正确,也不能直接证明真实 HTTP Runtime 正确。
同一个 WordPress 安装可能出现:
admin 正确、en 正确,但 www 仍然读取旧 Object Cache。
另外,全量清空 Object Cache 虽然很容易让问题暂时消失,却会同时删除故障现场,也可能产生明显的冷缓存阶段。
当天曾经执行过全量 Object Cache 清理,随后又出现几次 CPU 告警。目前还没有足够证据证明两者存在直接因果关系,因此没有因此修改 TTL。
以后再遇到类似问题,更适合先保留现场,从具体 Host、具体文章、具体 group 或 key 开始确认,而不是直接 Purge All Caches。
十二、当前阶段结论
这次已经确认:
Polylang 在数据库中已经建立中英文文章关系,但在多域名环境下,W3 Total Cache Redis Object Cache 中的 post_translations_relationships 可能在不同 Host 下留下不同状态。
英文译文从独立后台域名建立以后,www Host 中此前缓存的“没有英文译文”关系可能继续存在。
这会导致中文文章动态生成时不输出英文语言切换器和 hreflang,随后 W3TC Page Cache 又可能继续保存这份 HTML。
实际测试已经证明,在对应 www Runtime 中精确删除 post_translations_relationships 后,pll_get_post() 会立即恢复;再清理文章详情页 Page Cache,语言切换器和 hreflang 也能够恢复。
因此根因已经明确。
只是目前没有找到一个足够简单、稳定,而且不依赖 W3TC 私有内部实现的跨 Host 精确删除方案。
考虑到这个问题实际影响有限,当前决定暂时不继续修改生产环境,保持 Object Cache 1 天、Page Cache 4 天的现有配置,让语言切换器自然恢复。
如果以后这个问题变得更重要,可以直接从 post_translations_relationships 的跨 Host 精确失效继续研究,不需要重新从头排查。
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


发表回复