ملخص
عند تمكين “توطين المحتوى” (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على الأقل لغة واحدة غير لغة المنشور الأصلية. - النطاق: جانب الخادم (طهي المنشورات). مستقل عن الجهاز/نظام التشغيل/المتصفح؛ يمكن إعادة إنتاج المشكلة في الوضع الآمن وبدون أي سمة، لأنها تحدث في خط الطهي وليس في الواجهة الأمامية.
خطوات إعادة الإنتاج
- فعّل
content_localization_enabledوأضف لغة مدعومة ثانية (مثلاً: المنشورات الأصلية بالألمانيةde، والترجمة إلى الإنجليزيةen). - اضبط
discourse-affiliate: قم بتعيين وسام أمازون لسوق التجارة الإلكترونية ذي الصلة (مثلاًaffiliate_amazon_de = mytag-21). - أنشئ منشورًا يحتوي في نصه الخام على رابط منتج أمازون، مثل
https://www.amazon.de/-/en/…/dp/B0C3WGSSWC. - اعرض المنشور بـ لغته الأصلية وتفحص خاصية
hrefلوسم الأمازون. - أنشئ/اعرض النسخة المترجمة من نفس المنشور (عبر مفتاح تبديل اللغة، أو عن طريق السماح بإنشاء الترجمة) وتفحص خاصية
hrefلنفس الوسم.
النتيجة الفعلية
- المطبوخ الأصلي:
…/dp/B0C3WGSSWC?tag=mytag-21— موجود وسام الأفلييت.
PostLocalizationالمطبوخ (المترجم):…/dp/B0C3WGSSWC— لا يوجدtag، ولا أي إعادة كتابة للأفلييت على الإطلاق.
(تم التأكيد مباشرة في قاعدة البيانات: بالنسبة للمنشور المتأثر، تحمل عمود 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 مثل الطهي الأصلي. أي من الخيارين يحل المشكلة:
- إطلاق حدث قابل للتوصيل من المعالج المتوطين — قم بتشغيل
post_process_cooked(أو حدث مخصصpost_process_localized_cooked) داخلLocalizedCookedPostProcessor#post_process، بحيث تعمل الإضافات الحالية على الترجمات دون الحاجة إلى تغيير لكل إضافة. (إذا تفضيل حدث جديد لتجنب آثار المعالجة المزدوجة، يمكن للإضافات الاشتراك فيه.) - تشغيل إعادة كتابة الأفلييت في مسار التوطين، على سبيل المثال، أعد استخدام
AffiliateProcessor.applyعلى@doc.css("a[href]")فيLocalizedCookedPostProcessor#post_processبعد عمليات onebox والصور.
الخيار 1 هو الحل الأكثر عمومية، لأن نفس الفجوة تؤثر على كل مستهلك لـ post_process_cooked، وليس فقط الأفلييت.
ملاحظات إضافية
- ستحتاج المواقع التي تحتوي بالفعل على ترجمات متأثرة إلى إعادة طهي صفوف
PostLocalizationالموجودة بعد الإصلاح (على سبيل المثال، إعادة تعريقJobs::ProcessLocalizedCookedمعrecook: true) لملء الوسوم في المنشورات المترجمة مسبقًا. - يمكن إعادة إنتاج المشكلة بشكل ثابت (وليس متقطعًا) كلما تم عرض منشور يحتوي على رابط مؤهل للأفلييت بلغة مترجمة.