يتم تخطي إعادة كتابة روابط الأفلييت (وأي hook post_process_cooked) للمحتوى المحلي/المترجم للمشاركات

ملخص

عند تمكين “توطين المحتوى” (Content Localization)، يتم تطبيق وسام أمازون الخاص بإضافة الأفلييت (وبشكل عام، أي إضافة تعيد كتابة HTML المطبوخ عبر حدث post_process_cooked) على النص الأصلي المطبوخ للمنشور، لكن لا يتم تطبيقه على النص المترجم PostLocalization المطبوخ. لذلك، يرى القراء الذين يشاهدون المنشور بلغة مترجمة الرابط الخام غير الموسوم، مما يعني فقدان عمولة الأفلييت مع كل مشاهدة للمحتوى المترجم.

السبب الجذري هو أن المحتوى المترجم يُخضع لعملية “الطهي” (baking) عبر معالج ثانٍ منفصل (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 على الأقل لغة واحدة غير لغة المنشور الأصلية.
  • النطاق: جانب الخادم (طهي المنشورات). مستقل عن الجهاز/نظام التشغيل/المتصفح؛ يمكن إعادة إنتاج المشكلة في الوضع الآمن وبدون أي سمة، لأنها تحدث في خط الطهي وليس في الواجهة الأمامية.

خطوات إعادة الإنتاج

  1. فعّل content_localization_enabled وأضف لغة مدعومة ثانية (مثلاً: المنشورات الأصلية بالألمانية de، والترجمة إلى الإنجليزية en).
  2. اضبط discourse-affiliate: قم بتعيين وسام أمازون لسوق التجارة الإلكترونية ذي الصلة (مثلاً affiliate_amazon_de = mytag-21).
  3. أنشئ منشورًا يحتوي في نصه الخام على رابط منتج أمازون، مثل https://www.amazon.de/-/en/…/dp/B0C3WGSSWC.
  4. اعرض المنشور بـ لغته الأصلية وتفحص خاصية href لوسم الأمازون.
  5. أنشئ/اعرض النسخة المترجمة من نفس المنشور (عبر مفتاح تبديل اللغة، أو عن طريق السماح بإنشاء الترجمة) وتفحص خاصية href لنفس الوسم.

النتيجة الفعلية

  • المطبوخ الأصلي: …/dp/B0C3WGSSWC?tag=mytag-21 — موجود وسام الأفلييت. :white_check_mark:
  • PostLocalization المطبوخ (المترجم): …/dp/B0C3WGSSWC — لا يوجد tag، ولا أي إعادة كتابة للأفلييت على الإطلاق. :cross_mark:

(تم التأكيد مباشرة في قاعدة البيانات: بالنسبة للمنشور المتأثر، تحمل عمود posts.cooked الرابط الموسوم، بينما تحمل كل صف post_localizations.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 في أي مكان في مسار طهي التوطين — لذلك لا تشارك أي إضافة تعتمد على هذا الحدث في المحتوى المترجم. هذه فجوة عامة: تؤثر على وسوم الأفلييت اليوم، ولكن أيضًا على أي إضافة تغير HTML المطبوخ عبر post_process_cooked (زخارف الروابط، إعادة كتابة الشارات/الإشارات، إلخ).

الحل المقترح

اجعل عملية الطهي للتوطين تشارك في نفس إعادة كتابة الروابط/DOM مثل الطهي الأصلي. أي من الخيارين يحل المشكلة:

  1. إطلاق حدث قابل للتوصيل من المعالج المتوطين — قم بتشغيل post_process_cooked (أو حدث مخصص post_process_localized_cooked) داخل LocalizedCookedPostProcessor#post_process، بحيث تعمل الإضافات الحالية على الترجمات دون الحاجة إلى تغيير لكل إضافة. (إذا تفضيل حدث جديد لتجنب آثار المعالجة المزدوجة، يمكن للإضافات الاشتراك فيه.)
  2. تشغيل إعادة كتابة الأفلييت في مسار التوطين، على سبيل المثال، أعد استخدام AffiliateProcessor.apply على @doc.css("a[href]") في LocalizedCookedPostProcessor#post_process بعد عمليات onebox والصور.

الخيار 1 هو الحل الأكثر عمومية، لأن نفس الفجوة تؤثر على كل مستهلك لـ post_process_cooked، وليس فقط الأفلييت.

ملاحظات إضافية

  • ستحتاج المواقع التي تحتوي بالفعل على ترجمات متأثرة إلى إعادة طهي صفوف PostLocalization الموجودة بعد الإصلاح (على سبيل المثال، إعادة تعريق Jobs::ProcessLocalizedCooked مع recook: true) لملء الوسوم في المنشورات المترجمة مسبقًا.
  • يمكن إعادة إنتاج المشكلة بشكل ثابت (وليس متقطعًا) كلما تم عرض منشور يحتوي على رابط مؤهل للأفلييت بلغة مترجمة.