A reescrita de links de afiliados (e qualquer hook post_process_cooked) é ignorada para conteúdo de posts localizado/traduzido

Resumo

Quando a Localização de Conteúdo está habilitada, a tag da Amazon do plugin de afiliados (e, de modo mais geral, qualquer plugin que reescreva HTML processado via o evento post_process_cooked) é aplicada ao HTML processado original de uma publicação, mas não ao HTML processado traduzido PostLocalization. Os leitores que visualizam uma publicação em um idioma traduzido, portanto, veem o link cru e sem tag, o que significa que a comissão de afiliado é perdida em cada impressão traduzida.

A causa raiz é que o conteúdo traduzido é processado por meio de um segundo processador separado (LocalizedCookedPostProcessor) que nunca aciona o evento post_process_cooked.

Ambiente

  • Discourse: core main @ 978e9b2e5dc (2026-07-15); também confirmado na linha 2026.7.0 @ 7c06c1528 (2026-07-10). Nenhuma mudança relevante entre eles.
  • Plugin: discourse-affiliate (distribuído no diretório plugins/ do core), com affiliate_amazon_de (ou qualquer affiliate_amazon_*) definido para uma tag válida.
  • Configurações: content_localization_enabled = true, content_localization_supported_locales inclui pelo menos um idioma diferente do original da publicação.
  • Escopo: lado do servidor (processamento de publicações). Independente de dispositivo/SO/navegador; reproduz no Modo Seguro e sem tema, já que ocorre no pipeline de processamento, não na interface.

Passos para reproduzir

  1. Habilite content_localization_enabled e adicione um segundo idioma suportado (por exemplo, publicações originais em de, tradução para en).
  2. Configure discourse-affiliate: defina a tag da Amazon para o marketplace relevante (por exemplo, affiliate_amazon_de = mytag-21).
  3. Crie uma publicação cujo texto bruto contenha um link de produto da Amazon, por exemplo, https://www.amazon.de/-/en/…/dp/B0C3WGSSWC.
  4. Visualize a publicação em seu idioma original e inspecione o atributo href da âncora da Amazon.
  5. Gere/serve a versão traduzida da mesma publicação (via seletor de idioma ou deixando que a tradução seja criada) e inspecione o atributo href da mesma âncora.

Resultado atual

  • HTML processado original: …/dp/B0C3WGSSWC?tag=mytag-21 — tag de afiliado presente. :white_check_mark:
  • HTML processado PostLocalization (traduzido): …/dp/B0C3WGSSWC — sem tag, sem reescrita de afiliado. :cross_mark:

(Confirmado diretamente no banco de dados: para uma publicação afetada, posts.cooked contém a URL com tag, enquanto cada linha post_localizations.cooked para essa publicação contém a URL sem tag.)

Resultado esperado

O HTML processado traduzido deve receber a mesma reescrita de links que o original, para que a tag de afiliado (e qualquer outra transformação post_process_cooked) esteja presente em todos os idiomas que um leitor pode visualizar.

Causa raiz

O plugin de afiliados reescreve links apenas dentro do evento post_process_cooked:

# 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

Esse evento é acionado de exatamente um lugar, o processamento do idioma original:

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

No entanto, o conteúdo traduzido é processado por um processador diferente, enfileirado de PostLocalizationCreator/PostLocalizationUpdater como Jobs::ProcessLocalizedCooked:

# 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 nunca aciona post_process_cooked, e não há nenhum DiscourseEvent.trigger em nenhum lugar do caminho de processamento de localização — portanto, nenhum plugin que dependa desse evento participa do conteúdo traduzido. Esta é uma lacuna geral: afeta a marcação de afiliados hoje, mas igualmente qualquer plugin que mutue HTML processado por meio de post_process_cooked (decoradores de links, reescritas de badges/menções, etc.).

Correção sugerida

Faça com que o processamento de localização participe da mesma reescrita de links/DOM que o processamento original. Qualquer uma das opções resolve o problema:

  1. Emitir um evento acionável do processador de localização — acionar post_process_cooked (ou um post_process_localized_cooked dedicado) dentro de LocalizedCookedPostProcessor#post_process, para que plugins existentes funcionem em traduções sem alterações por plugin. (Se um novo evento for preferido para evitar efeitos colaterais de processamento duplo, os plugins podem optar por participar.)
  2. Executar a reescrita de afiliados no caminho de localização, por exemplo, reutilizar AffiliateProcessor.apply sobre @doc.css("a[href]") em LocalizedCookedPostProcessor#post_process após as passagens de onebox/imagem.

A opção 1 é a correção mais geral, já que a mesma lacuna afeta todos os consumidores de post_process_cooked, não apenas afiliados.

Notas adicionais

  • Um site que já possui traduções afetadas precisará reprocesar as linhas PostLocalization existentes após a correção (por exemplo, re-enfileirar Jobs::ProcessLocalizedCooked com recook: true) para adicionar tags às publicações já traduzidas.
  • Reproduz consistentemente (não intermitente) sempre que uma publicação com um link elegível para afiliado é servida em um idioma traduzido.