موقع Next.js متعدّد اللغات فعلاً مع next-intl
توجيه مُوطَّن، وعرض ثابت، وhreflang، وتبديل اللغة: كيف أبني موقع Next.js بعشر لغات دون التضحية بالأداء أو الـ SEO.
لماذا تعدّد اللغات مسألة معمارية حقيقية
ترجمة الواجهة أمر سهل. أما بناء موقع متعدّد اللغات سليم — قابل للفهرسة، وسريع، وقابل للصيانة — فهو قرار معماري يُتّخذ في البداية، لا في النهاية. هذه المحفظة موجودة بعشر لغات، وإليك الخيارات التي تصمد على نطاق واسع.
التوجيه عبر مقطع اللغة
المقاربة الأكثر متانة مع App Router: مقطع ديناميكي [locale] في الجذر. كل صفحة تعيش تحت app/[locale]/…، وتصبح اللغة بياناً من الدرجة الأولى في الرابط (/fr/projects، /en/projects).
مع next-intl، يُتحقَّق من هذا المقطع أثناء العرض:
- اللغات المدعومة تُدرَج في إعداد
routingمركزي. - لغة غير معروفة تُطلق
notFound()نظيفاً بدل صفحة معطوبة. - يمرّ التنقّل عبر
Linkمُوطَّن يضع بادئة اللغة الصحيحة تلقائياً.
الفائدة: لا تتعامل المكوّنات مع اللغة «يدوياً» أبداً. تطلب ترجمة، ويتكفّل النظام بالباقي.
فخّ العرض الثابت
إنه الخطأ الأغلى ثمناً في الإنتاج. إذا استدعيت الترجمات دون تثبيت اللغة أولاً، يقرأ next-intl ترويسات الطلب. النتيجة: تنقلب الصفحة إلى عرض ديناميكي، فتفقد التوليد المسبق الثابت — أحياناً مع خطأ DYNAMIC_SERVER_USAGE في الإنتاج.
العلاج يتّسع في سطر واحد، في أعلى كل صفحة:
setRequestLocale(locale);
عند استدعائه قبل أي getTranslations، يضمن عرضاً ثابتاً بالكامل. ومقروناً بـ generateStaticParams يُقاطع locale × slug، يولّد مسبقاً كل صفحة بكل لغة عند البناء.
تعدّد اللغات الثابت ليس أبطأ من أحادية اللغة. إنه فقط أكثر تطلّباً بشأن ترتيب الاستدعاءات.
الـ hreflang، أو كيف تتجنّب منافسة نفسك
دون أي إشارة، يعامل Google نسخك اللغوية العشر كعشر صفحات متنافسة على الكلمات المفتاحية نفسها. الحل هو hreflang: كل صفحة تُعلن مجموع متغايراتها.
موضعان يجب أن يبقيا متزامنَين:
- البيانات الوصفية لكل صفحة — عبر مساعد
generateAlternatesيُنتج وسومalternate. - خريطة الموقع — كل رابط يُدرِج فيها لغاته و
x-default.
الاتساق بين هذين المصدرين هو ما يجعل بحثاً بالإسبانية يحطّ على /es لا على /fr.
تبديل اللغة، من جانب المستخدم
على مُحدِّد اللغة أن يغيّر اللغة دون فقدان الصفحة الحالية. الردّة الساذجة — إعادة المستخدم إلى الصفحة الرئيسية — مُحبِطة. مع usePathname المُوطَّن في next-intl، تسترجع المسار دون بادئة، وتُعيد إصداره باللغة المختارة. يبقى المستخدم بالضبط حيث كان.
ما أحتفظ به
- مقطع
[locale]في الجذر هو الأساس؛ ومنه ينبع كل شيء. setRequestLocaleقبل الترجمات: غير قابل للتفاوض للحفاظ على الثبات.- تُدار الـ
hreflangمزدوجةً (البيانات الوصفية وخريطة الموقع)، متزامنةً دائماً. - يُدار اتجاه النص (RTL للعربية) على مستوى
<html dir>، لا صفحةً صفحة.
حين يُنجَز جيداً، يصبح تعدّد اللغات غير مرئي: يشعر كل زائر أن الموقع كُتب من أجله، ويعرف Google تماماً أيّ باب يفتحه له.