# Перезапись ссылок на партнерские программы (и любой хук 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:** [15.Июль.2026 12:44:17 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:** 3
**Page:** 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: [15.Июль.2026 12:44:17 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 плагина (и, в более общем смысле, **любой плагин, который переписывает готовый HTML через событие `post_process_cooked`** ) применяется к **исходному** готовому HTML поста, но **не** к его **переведенному** готовому HTML `PostLocalization`. Поэтому читатели, просматривающие пост в переведенной локали, видят «сырую» ссылку без тега, что приводит к потере партнерского вознаграждения при каждом просмотре переведенной версии.

Корень проблемы заключается в том, что переведенный контент обрабатывается вторым, отдельным процессором (`LocalizedCookedPostProcessor`), который никогда не вызывает событие `post_process_cooked`.

## Окружение

- **Discourse:** ядро `main` @ `978e9b2e5dc` (2026-07-15); также подтверждено на ветке `2026.7.0` @ `7c06c1528` (2026-07-10). Никаких существенных изменений между ними нет.
- **Плагин:** `discourse-affiliate` (поставляется в каталоге `plugins/` ядра), с установленным валидным тегом `affiliate_amazon_de` (или любым другим `affiliate_amazon_*`).
- **Настройки:** `content_localization_enabled = true`, `content_localization_supported_locales` включает хотя бы одну локаль, отличную от исходной.
- **Область:** серверная часть (обработка поста). Независимо от устройства/ОС/браузера; воспроизводится в [Safe Mode](https://meta.discourse.org/t/53504?silent=true) и без тем, поскольку происходит в конвейере обработки, а не на стороне клиента.

## Шаги для воспроизведения

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. Просмотрите пост в его **исходной** локали и проверьте атрибут `href` якоря Amazon.
5. Сгенерируйте/отобразите **переведенную** версию того же поста (через переключатель языка или путем создания перевода) и проверьте атрибут `href` того же якоря.

## Фактический результат

- **Исходный готовый HTML:** `…/dp/B0C3WGSSWC?tag=mytag-21` — партнерский тег присутствует. ✅
- **Готовый HTML `PostLocalization` (переведенный):** `…/dp/B0C3WGSSWC` — нет `tag`, вообще нет переписывания ссылок. ❌

(Подтверждено напрямую в БД: для затронутого поста поле `posts.cooked` содержит URL с тегом, тогда как каждая строка `post_localizations.cooked` для этого поста содержит «голый» URL.)

## Ожидаемый результат

Переведенный готовый HTML должен получать то же самое переписывание ссылок, что и исходный, чтобы партнерский тег (и любые другие преобразования `post_process_cooked`) присутствовал в каждой локали, доступной для чтения.

## Корень проблемы

Плагин affiliate переписывает ссылки только внутри события `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` в пути локализации** — поэтому ни один плагин, зависящий от этого события, не участвует в обработке переведенного контента. Это общая проблема: сегодня она затрагивает партнерские теги, но в равной степени влияет на любой плагин, который изменяет готовый HTML через `post_process_cooked` (декораторы ссылок, переписывание значков/упоминаний и т.д.).

## Предлагаемое решение

Заставьте локализацию участвовать в том же переписывании ссылок/DOM, что и исходная обработка. Любой из вариантов решает проблему:

1. **Генерация хукаемого события из локализационного процессора** — вызовите `post_process_cooked` (или выделенное `post_process_localized_cooked`) внутри `LocalizedCookedPostProcessor#post_process`, чтобы существующие плагины работали с переводами без изменений в каждом плагине. (Если предпочтительнее новое событие для избежания побочных эффектов двойной обработки, плагины могут подключиться к нему.)
2. **Запуск переписывания affiliate в пути локализации** , например, повторно используйте `AffiliateProcessor.apply` для `@doc.css("a[href]")` в `LocalizedCookedPostProcessor#post_process` после прохода onebox/изображений.

Вариант 1 является более общим решением, поскольку та же проблема затрагивает каждого потребителя `post_process_cooked`, а не только affiliate.

## Дополнительные примечания

- Сайтам, у которых уже есть затронутые переводы, потребуется повторная обработка существующих строк `PostLocalization` после исправления (например, повторная постановка в очередь `Jobs::ProcessLocalizedCooked` с флагом `recook: true`), чтобы добавить теги в уже переведенные посты.
- Воспроизводится стабильно (не прерывисто) каждый раз, когда пост со ссылкой, подходящей для партнерской программы, отображается в переведенной локали.

---

<div class="post-metadata">

### Author: ![zogstrip](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/zogstrip/32/512781_2.png) [@zogstrip](https://meta.discourse.org/u/zogstrip)
#### Post date: [16.Июль.2026 12:45:28 UTC](https://meta.discourse.org/t/affiliate-link-rewriting-and-any-post-process-cooked-hook-is-skipped-for-localized-translated-post-content/407688/3 "2026-07-16T12:45:28Z")

</div>

Спасибо за сообщение, @Overgrow 👍 Это будет исправлено в

> <https://github.com/discourse/discourse/pull/41770>
>
> Previously, affiliate link rewriting only ran via the \`:post\_process\_cooked\` eve…nt, which fires exclusively when baking a post's original cooked HTML — so readers viewing a translated post were served untagged links.
> 
> This change subscribes the same rewrite to the \`:post\_process\_localized\_cooked\` event fired by \`LocalizedCookedPostProcessor\`, so translated posts get affiliate links too. Existing localizations pick up the tags on their next rebake, since the recook path re-runs the localized post processor.
> 
> Reported at https://meta.discourse.org/t/407688

---

<div class="post-metadata">

### Author: ![zogstrip](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/zogstrip/32/512781_2.png) [@zogstrip](https://meta.discourse.org/u/zogstrip)
#### Post date: [18.Июль.2026 06:00:29 UTC](https://meta.discourse.org/t/affiliate-link-rewriting-and-any-post-process-cooked-hook-is-skipped-for-localized-translated-post-content/407688/5 "2026-07-18T06:00:29Z")

</div>

Эта тема была автоматически закрыта через 41 час. Новые ответы больше не принимаются.
