# 本地化/翻译后的帖子内容会跳过附属链接重写（以及任何 post\_process\_cooked 钩子）

**URL:** https://meta.discourse.org/t/affiliate-link-rewriting-and-any-post-process-cooked-hook-is-skipped-for-localized-translated-post-content/407688
**Category:** Bug
**Tags:** affiliate, fixed, content-localization
**Created:** [2026年七月15日 12:44 UTC](https://meta.discourse.org/t/affiliate-link-rewriting-and-any-post-process-cooked-hook-is-skipped-for-localized-translated-post-content/407688 "2026-07-15T12:44:17Z")
**Posts on this page:** 1
**Showing post:** 1

<div class="post-metadata">

### Author: ![Overgrow](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/overgrow/32/478189_2.png) [@Overgrow](https://meta.discourse.org/u/Overgrow)
#### Post date: [2026年七月15日 12:44 UTC](https://meta.discourse.org/t/affiliate-link-rewriting-and-any-post-process-cooked-hook-is-skipped-for-localized-translated-post-content/407688/1 "2026-07-15T12:44:17Z")

</div>

## 摘要

当启用内容本地化时，联盟插件的 Amazon 标签（以及更广泛地说， **任何通过 `post_process_cooked` 事件重写已处理 HTML 的插件** ）会应用于帖子的 **原始** 已处理 HTML，但 **不会** 应用于其 **翻译** 后的 `PostLocalization` 已处理 HTML。因此，以翻译语言查看帖子的读者会看到未经处理的原始链接，这意味着每次翻译内容的展示都会损失联盟佣金。

根本原因是翻译内容是通过第二个独立的处理器（`LocalizedCookedPostProcessor`）进行烘焙的，该处理器从未触发 `post_process_cooked` 事件。

## 环境

- **Discourse：** 核心 `main` 分支 @ `978e9b2e5dc`（2026-07-15）；在 `2026.7.0` 分支 @ `7c06c1528`（2026-07-10）上也已确认。两者之间无相关变更。
- **插件：** `discourse-affiliate`（包含在核心的 `plugins/` 目录中），并设置了有效的 Amazon 标签（如 `affiliate_amazon_de` 或任何 `affiliate_amazon_*`）。
- **设置：** `content_localization_enabled = true`，`content_localization_supported_locales` 至少包含一个不同于帖子原始语言的语言环境。
- **范围：** 服务器端（帖子烘焙）。与设备/操作系统/浏览器无关；在安全模式下且无主题时也能复现，因为它发生在烹饪管道中，而非前端。

## 复现步骤

1. 启用 `content_localization_enabled` 并添加第二个支持的语言环境（例如，原始帖子为 `de`，翻译为 `en`）。
2. 配置 `discourse-affiliate`：为相关市场设置 Amazon 标签（例如 `affiliate_amazon_de = mytag-21`）。
3. 创建一个原始内容包含 Amazon 产品链接的帖子，例如 `https://www.amazon.de/-/en/…/dp/B0C3WGSSWC`。
4. 以 **原始** 语言环境查看该帖子，并检查 Amazon 锚点的 `href`。
5. 生成/提供同一帖子的 **翻译** 版本（通过语言切换器，或等待翻译创建），并检查相同锚点的 `href`。

## 实际结果

- **原始已处理内容：** `…/dp/B0C3WGSSWC?tag=mytag-21` — 包含联盟标签。✅
- **`PostLocalization` 已处理内容（翻译）：** `…/dp/B0C3WGSSWC` — 无 `tag`，完全未进行联盟重写。❌

（直接在数据库中确认：对于受影响的帖子，`posts.cooked` 包含带标签的 URL，而该帖子的每个 `post_localizations.cooked` 行都包含裸 URL。）

## 预期结果

翻译后的已处理 HTML 应接收与原始内容相同的链接重写，以便联盟标签（以及任何其他 `post_process_cooked` 转换）出现在读者可查看的每种语言环境中。

## 根本原因

联盟插件仅在 `post_process_cooked` 事件内部重写链接：

```ruby
# plugins/discourse-affiliate/plugin.rb
on(:post_process_cooked) do |doc, post|
  doc.css("a[href]").each { |a| a["href"] = AffiliateProcessor.apply(a["href"]) }
  true
end

```

该事件仅从原始语言烹饪的一个位置触发：

```ruby
# lib/cooked_post_processor.rb:50
DiscourseEvent.trigger(:post_process_cooked, @doc, @post)

```

然而，翻译内容是由 **不同** 的处理器烘焙的，由 `PostLocalizationCreator`/`PostLocalizationUpdater` 入队为 `Jobs::ProcessLocalizedCooked`：

```ruby
# lib/localized_cooked_post_processor.rb
def post_process
  post_process_oneboxes
  post_process_images
  @post_localization.link_post_uploads(fragments: @doc)
end

```

`LocalizedCookedPostProcessor#post_process` 从未触发 `post_process_cooked`，并且在本地化烘焙路径中 **没有任何地方存在 `DiscourseEvent.trigger`** — 因此任何依赖该事件的插件都不参与翻译内容。这是一个普遍存在的缺陷：目前影响联盟标记，但同样影响任何通过 `post_process_cooked` 修改已处理 HTML 的插件（链接装饰器、徽章/提及重写等）。

## 建议的修复方案

让本地化烘焙参与与原始烹饪相同的链接/DOM 重写。以下任一选项均可解决此问题：

1. **从本地化处理器发出可挂钩的事件** — 在 `LocalizedCookedPostProcessor#post_process` 内部触发 `post_process_cooked`（或专用的 `post_process_localized_cooked`），以便现有插件无需针对每个插件进行修改即可在翻译上工作。（如果为了双重处理副作用而首选新事件，插件可以选择加入。）
2. **在本地化路径中运行联盟重写** ，例如在 `LocalizedCookedPostProcessor#post_process` 中，在 onebox/图片处理之后，对 `@doc.css("a[href]")` 重用 `AffiliateProcessor.apply`。

选项 1 是更通用的修复方案，因为同样的缺陷影响每一个 `post_process_cooked` 消费者，而不仅仅是联盟插件。

## 补充说明

- 已经拥有受影响翻译的网站需要在修复后重新烘焙现有的 `PostLocalization` 行（例如，重新入队 `Jobs::ProcessLocalizedCooked` 并设置 `recook: true`），以便将标签回填到已翻译的帖子中。
- 只要以翻译语言环境提供包含联盟资格链接的帖子，该问题就会一致复现（非间歇性）。

---

_[View the full topic](https://meta.discourse.org/t/affiliate-link-rewriting-and-any-post-process-cooked-hook-is-skipped-for-localized-translated-post-content/407688)._
