요약
콘텐츠 로컬라이제이션(Content Localization)이 활성화되어 있으면, 제휴 플러그인의 Amazon 태그(그리고 더 일반적으로 post_process_cooked 이벤트를 통해 cooked HTML을 재작성하는 모든 플러그인)는 게시물의 원본 cooked HTML에는 적용되지만, 번역된 PostLocalization cooked HTML에는 적용되지 않습니다. 따라서 번역된 언어로 게시물을 보는 독자는 태그가 없는 원본 링크를 보게 되어, 모든 번역된 노출마다 제휴 수수료가 손실됩니다.
그 원인은 번역된 콘텐츠가 post_process_cooked 이벤트를 절대 트리거하지 않는 두 번째, 별개의 프로세서(LocalizedCookedPostProcessor)를 통해 처리된다는 것입니다.
환경
- 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에는 게시물의 원본 언어 외 최소 한 가지 이상의 로케일이 포함됨. - 범위: 서버 사이드(게시물 베이킹). 장치/OS/브라우저와 무관하며, 쿡 파이프라인에서 발생하므로 프론트엔드와 무관합니다. 세이프 모드와 테마가 없는 상태에서도 재현됩니다.
재현 방법
content_localization_enabled를 활성화하고 두 번째 지원 로케일을 추가합니다 (예: 원본 게시물이de, 번역 대상이en).discourse-affiliate를 구성합니다: 관련 마켓플레이스에 대한 Amazon 태그를 설정합니다 (예:affiliate_amazon_de = mytag-21).- Amazon 제품 링크가 포함된 게시물을 생성합니다. 예:
https://www.amazon.de/-/en/…/dp/B0C3WGSSWC. - 게시물을 원본 로케일로 보고 Amazon 앵커의
href를 검사합니다. - 동일한 게시물의 번역된 버전을 생성/서빙합니다 (언어 전환기를 사용하거나 번역이 생성되도록 두면 됨) 그리고 동일한 앵커의
href를 검사합니다.
실제 결과
- 원본 cooked:
…/dp/B0C3WGSSWC?tag=mytag-21— 제휴 태그 존재.
PostLocalizationcooked (번역됨):…/dp/B0C3WGSSWC—tag없음, 제휴 재작성 없음.
(DB에서 직접 확인: 영향받는 게시물의 경우, posts.cooked에는 태그가 포함된 URL이 있고, 해당 게시물의 모든 post_localizations.cooked 행에는 태그가 없는 URL이 있습니다.)
기대 결과
번역된 cooked HTML에도 원본과 동일한 링크 재작성이 적용되어야 하며, 독자가 볼 수 있는 모든 로케일에 제휴 태그(그리고 기타 post_process_cooked 변환)가 존재해야 합니다.
근본 원인
제휴 플러그인은 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
해당 이벤트는 정확히 한 곳에서만 트리거됩니다. 원본 언어 쿡입니다:
# lib/cooked_post_processor.rb:50
DiscourseEvent.trigger(:post_process_cooked, @doc, @post)
반면, 번역된 콘텐츠는 PostLocalizationCreator/PostLocalizationUpdater에서 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는 post_process_cooked를 트리거하지 않으며, 로컬라이제이션 베이킹 경로 어디에도 DiscourseEvent.trigger가 없습니다 — 따라서 해당 이벤트에 의존하는 플러그인은 번역된 콘텐츠에 참여하지 않습니다. 이는 일반적인 결함입니다: 현재는 제휴 태그링에 영향을 미치지만, post_process_cooked를 통해 cooked HTML을 변경하는 모든 플러그인(링크 데코레이터, 배지/멘션 재작성 등)에도 동일하게 영향을 미칩니다.
권장 수정 사항
로컬라이제이션 베이킹이 원본 쿡과 동일한 링크/DOM 재작성에 참여하도록 합니다. 다음 중 어느 옵션으로든 해결할 수 있습니다:
- 로컬라이제이션 프로세서에서 훅 가능한 이벤트를 발화합니다 —
LocalizedCookedPostProcessor#post_process내에서post_process_cooked(또는 전용post_process_localized_cooked)를 트리거하여, 플러그인별 변경 없이 기존 플러그인이 번역본에서도 작동하도록 합니다. (이중 처리 부작용을 피하기 위해 새로운 이벤트를 선호하는 경우, 플러그인이 옵트인할 수 있습니다.) - 로컬라이제이션 경로에서 제휴 재작성을 실행합니다, 예를 들어
LocalizedCookedPostProcessor#post_process에서 원박스/이미지 패스 후에@doc.css("a[href]")에 대해AffiliateProcessor.apply를 재사용합니다.
옵션 1이 더 일반적인 수정 사항입니다. 이는 제휴뿐 아니라 모든 post_process_cooked 사용자에게 동일한 결함이 영향을 미치기 때문입니다.
추가 참고 사항
- 이미 영향받은 번역이 있는 사이트의 경우, 수정 후 기존
PostLocalization행을 다시 베이킹해야 합니다 (예:recook: true로Jobs::ProcessLocalizedCooked를 다시 큐에 추가) 이미 번역된 게시물에 태그를 백필하기 위해. - 제휴 대상 링크가 포함된 게시물이 번역된 로케일로 서빙될 때마다 일관되게 재현됩니다 (간헐적이지 않음).