

يحتوي Next.js على صفحتين رسميتين من وثائق i18n تصفان نظامين مختلفين تمامًا، دون أي إحالة متبادلة بينهما.
أحدهما يتناول «موجه الصفحات» (Pages Router)، والآخر يتناول «موجه التطبيق» (App Router). ولا يشرح أي منهما كيفية ارتباطهما ببعضهما البعض، أو المكتبات التي يجب استخدامها، أو كيفية التعامل مع علامة hreflang من أجل تحسين محركات البحث لموقع متعدد اللغات .
سنقوم بربط كلا الموجهين. وسنتناول استراتيجيات التوجيه، واختيار المكتبات، وإعداد البرامج الوسيطة، وترجمات مكونات الخادم، وتحسين محركات البحث (SEO) لـ « متعدد اللغات ».
هدفنا هو لكي مورد مفيد للمطورين الذين طُلب لكي دعم لغوي لكي Next.js ويحتاجون إلى فهم واضح قبل اتخاذ لكي . فلنبدأ!
يتألف التوطين من ثلاث مستويات:
فقط Next.js فقط في توجيه الطلبات.
يحتوي موجه الصفحات على ميزة توجيه i18n مدمجة منذ الإصدار 10.0.0. ويتولى كتلة تكوين مكونة من ثلاثة حقول في ملف next.config.js مهام الكشف عن الإعدادات المحلية وإضافة البادئات إلى عناوين URL وإجراء عمليات إعادة التوجيه تلقائيًا.
يختلف «App Router» عن غيره. فصفحة وثائق الترجمة (i18n) الخاصة به توضح نمطًا يمكنك تجميعه بنفسك باستخدام برامج وسيطة، وهو [اللغة] جزء ديناميكي، ومكتبة.
بالنسبة للترجمة والتنسيق، عليك تولي الأمر بنفسك بغض النظر عن جهاز التوجيه الذي تستخدمه. تضم وثائق «App Router» قائمة بجميع المكتبات المتوافقة، لكنها لا تقدم أي إرشادات بشأن أيها يجب اختياره. ولا تتناول أي من صفحتي الوثائق علامات hreflang أو خرائط المواقع متعدد اللغات .
يتمثل نهج "Pages Router" في إجراء تغيير في التكوين. أضف كتلة i18n لكي ملف next.config.js تحتوي على ثلاثة حقول:
// next.config.js
module.exports = {
i18n: {
locales: ['en', 'fr', 'de'],
defaultLocale: 'en',
},
}هذا كل شيء.
يكتشف Next.js الإعدادات الإقليمية تلقائيًا من اللغة المقبولة العنوان، يراعي اللغة التالية تجاوز ملفات تعريف الارتباط، ويكشف عن الإعدادات اللغوية النشطة عبر useRouter().locale. لا تحتاج إلى أي برامج وسيطة أو إعادة هيكلة للمجلدات.
لا يوجد إعدادات مكافئة لـ App Router. عليك إنشاء التوجيه بنفسك من ثلاثة عناصر:
@formatjs/intl-localematcher و مفاوض لكي اللغة المقبولة الرؤوس. تترك الوثائق الرسمية منطق الكشف الفعلي على شكل علامة حذف: دالة getLocale(request) { ... }. سنقوم بتوضيح ذلك في القسم التالي.[اللغة] يحيط الجزء الديناميكي بكامل التطبيق/ الدليل. تصبح كل مسار قادرة على التعرف على الإعدادات المحلية من خلال بنية المجلدات.إنشاء المعلمات الثابتة يقوم بعرض كل نسخة من الإعدادات المحلية مسبقًا أثناء عملية البناء.من بين هذه العناصر الثلاثة، فإن `generateStaticParams` هي التي تحل محل ما كان يقوم به ما (Pages Router) تلقائيًا أثناء عملية البناء.
export function generateStaticParams() {
return [{ locale: 'en' }, { locale: 'fr' }, { locale: 'de' }]
}🚨 لا تعمل ميزة i18n المدمجة في "Pages Router" مع الإخراج: 'تصدير'. إذا كنت بحاجة إلى تصدير ثابت بالكامل، فستحتاج بدلاً من ذلك إلى توجيه يدوي قائم على المجلدات. ينطبق هذا القيد لكي المدمج فقط. يدعم كلا الموجهين عمليات التصدير الثابتة من خلال الإعداد اليدوي.
قبل اختيار مكتبة، حدد استراتيجية التوجيه. فهي تؤثر على تحسين محركات البحث (SEO) وإعداد نظام أسماء النطاقات (DNS) وكمية البرامج الوسيطة التي ستقوم بكتابتها:
التالي-دولي تدعمه باعتباره خيارًا متميزًا.بالنسبة للمواقع العامة التي يُعد فيها تحسين محركات البحث (SEO) أمرًا حيويًا، يُعد توجيه المسارات الفرعية هو الإعداد الافتراضي الأنسب. فقط يُستحق توجيه النطاق كل هذه التعقيدات فقط كانت الإشارات القوية للاستهداف الجغرافي متطلبًا محددًا.
إذا كنت تفضل عدم إدارة بنية عناوين URL يدويًّا، فإن الوكيل العكسي لـWeglot يتولى توجيه الدلائل الفرعية والنطاقات الفرعية تلقائيًّا، بما في ذلك إدراج علامة hreflang وعناوين URL المترجمة.
كما ذكرنا سابقًا، تقتصر الوثائق الرسمية على سرد المكتبات دون التوصية بأي منها. وفيما يلي مقارنة بين الخيارات الرئيسية:
يُعد next-intl المعيار الفعلي لموجه التطبيقات (App Router). فهو يدعم RSC بشكل مدمج، ويتميز بتكامل التوجيه، كما تعمل ميزة الإكمال التلقائي في TypeScript دون الحاجة إلى إعدادات إضافية.
يُعد React-i18next الخيار الأنسب إذا كنت تستخدم "Pages Router" أو كنت تستخدم i18next بالفعل في أجزاء أخرى من نظامك. يعمل دعم "App Router" ولكنه يتطلب أكثر الإعداد أكثر .
يتناسب Lingui مع الفرق التي لديها مسارات عمل قائمة تعتمد على ملفات .po. يتم استخراج الترجمات أثناء عملية البناء، وبالتالي لا يتم تضمين الرسائل غير المستخدمة أبدًا.
💡 لا يُعد Paraglide JS من بين اللاعبين الكبار في هذا المجال، لكنه يستحق الذكر باعتباره بديلاً يعتمد على المُجمِّع ويُنتج حزمًا أصغر حجمًا. ومع ذلك، إذا كنت مهتمًا به، فستحتاج لكي حقيقة أن نظامه البيئي أقل نضجًا من الأنظمة الأخرى.
بالنسبة لتنسيق التاريخ والأرقام، تقوم مكتبة next-intl بتغليف واجهات برمجة التطبيقات (API) الأصلية لـ Intl عبر استخدام useFormatter. أما المكتبات الأخرى فتقوم بتفويض المهمة لكي FormatJS أو تترك الأمر لكي لكي Intl.DateTimeFormat و Intl.NumberFormat مباشرةً.
💡 تتولى هذه المكتبات عملية العرض. ولا يزال يتعين على شخص ما إعداد الترجمات والحفاظ على تزامنها مع تغير المحتوى. Weglot تعمل على مستوى مختلف تمامًا، حيث تدير محتوى الترجمة عبر وكيل عكسي خارج قاعدة الكود. لا تعتبرها بديلاً عن المكتبة.
تم تغيير اسم ملف middleware.ts في Next.js 16 لكي proxy.ts. وقد تم ذلك لأن مصطلح «middleware» كان مضللاً ويشير ضمناً إلى منطق عام داخل التطبيق. وفي الواقع، يعمل الملف على حدود الشبكة، حيث يعترض الطلبات ويعدلها مثل الوكيل (proxy) قبل وصولها إلى التطبيق.
فيما يلي تطبيق كامل لاكتشاف الإعدادات المحلية وإعادة التوجيه، والذي يملأ الفراغ المذكور أعلاه في الوثائق الرسمية:
// proxy.ts
import { match } from '@formatjs/intl-localematcher'
import Negotiator from 'negotiator'
import { NextRequest, NextResponse } from 'next/server'
const locales = ['en', 'fr', 'de']
const defaultLocale = 'en'
function getLocale(request: NextRequest): string {
const cookie = request.cookies.get('NEXT_LOCALE')?.value
if (cookie && locales.includes(cookie)) return cookie
const headers = { 'accept-language': request.headers.get('accept-language') ?? '' }
const languages = new Negotiator({ headers }).languages()
return match(languages, locales, defaultLocale)
}
export function middleware(request: NextRequest) {
const { pathname } = request.nextUrl
const hasLocale = locales.some(l => pathname.startsWith(`/${l}/`) || pathname === `/${l}`)
if (hasLocale) return
const locale = getLocale(request)
request.nextUrl.pathname = `/${locale}${pathname}`
return NextResponse.redirect(request.nextUrl)
}
الملفات متداخلة تحت app/[اللغة]/، مع القواميس/ مجلد بجانب التخطيطات والصفحات الخاصة بك. يتلقى التخطيط الرئيسي الإعدادات الإقليمية كمعلمة ويقوم بتعيينها على html العلامة:
export default async function RootLayout({ children, params }) {
const { locale } = await params
return (
<html lang={locale}>
<body>{children}</body>
</html>
)
}
بالنسبة للترجمة، تُظهر الوثائق الرسمية نمط القاموس البسيط الذي لا يتطلب استخدام أي مكتبة:
const dictionaries = {
en: () => import('./dictionaries/en.json').then(m => m.default),
fr: () => import('./dictionaries/fr.json').then(m => m.default),
}
export const getDictionary = async (locale: string) => dictionaries[locale]()
هذا يعمل، لكنه لا يدعم صيغة الجمع أو الاستيفاء. التالي-دولي يغطي كلاهما عبر getTranslations() و useTranslations() في مكونات الخادم ومكونات العميل على التوالي.
في كلتا الحالتين، تتم معالجة ملفات الترجمة على الخادم ولا يصل إلى المتصفح فقط HTML الناتج، لذا لا يؤثر حجم ملف الرسالة على حجم الحزمة على جانب العميل.
بالنسبة لمكونات العميل، قم بتمرير السلاسل المترجمة كخصائص من مكون الخادم الأصلي حيثما أمكن ذلك. استخدم NextIntlClientProvider مع مجموعة فرعية محددة من الرسائل فقط عندما يحتاجعندما العميل لكي الترجمات مباشرةً.
في حالة أداة تبديل اللغة، يقوم مكون الخادم بعرض تسميات الإعدادات الإقليمية، بينما يتولى مكون العميل معالجة useRouter() اتصل بـ:
// LocaleSwitcher.tsx (Server Component)
import LocaleSwitcherClient from './LocaleSwitcherClient'
export default function LocaleSwitcher({ locale }) {
return <LocaleSwitcherClient locale={locale} labels={{ en: 'English', fr: 'Français' }} />
}يستمع العميل بشكل جزئي إلى تغييرات الاختيار ويقوم بإرسال مسار الإعدادات المحلية الجديد:
// LocaleSwitcherClient.tsx
'use client'
import { useRouter } from 'next/navigation'
export default function LocaleSwitcherClient({ locale, labels }) {
const router = useRouter()
return (
<select value={locale} onChange={e => router.push(`/${e.target.value}`)}>
{Object.entries(labels).map(([value, label]) => (
<option key={value} value={value}>{label}</option>
))}
</select>
)
}إذا كنت تستخدم Weglot، فلا ينطبق أي من هذا. Weglot يتضمن أداة مدمجة لتبديل اللغة ولا يتطلب أي تكوين للوكيل أو برامج وسيطة.
لا يدعم أي من الموجهين تحسين محركات البحث (SEO) الخاص بـ متعدد اللغات تلقائيًّا:
html lang بشكل صحيح، لكن الوثائق تشير إلى أن تطبيق hreflang "يعود لكي ".بفضل "App Router"، تتيح لك واجهة برمجة تطبيقات البيانات الوصفية (Metadata API) لكي أقصى لكي . قم بتحديد عناوين URL الخاصة بالإعدادات المحلية في إنشاء البيانات الوصفية عبر اللغات البديلة الكائن و"Next.js" تقوم بالحقن التلقائي رابط rel="alternate" hreflang="..." العلامات:
export async function generateMetadata({ params: { locale } }) {
return {
alternates: {
languages: {
'en': 'https://example.com/en',
'fr': 'https://example.com/fr',
'de': 'https://example.com/de',
},
},
}
}الجزء اليدوي يتمثل في جمع عنوان URL الصحيح لكل نسخة لغة لكل صفحة. هذا المنطق عليك لكي بنفسك.
هناك أمران آخران يتعين تنفيذهما يدويًّا بغض النظر عن جهاز التوجيه الذي تستخدمه. يجب لكي عناوين URL القياسية لكل لغة لكي إشارات المحتوى المكرر. خريطة الموقع.ts الاحتياجات xhtml:رابط إدخالات لكل نسخة لغة من كل صفحة.
في هرفلانج القيمة نفسها، الاستخدام hreflang="en-US" عندما منطقة معينة، و hreflang="en" عندما جميع المتحدثين باللغة الإنجليزية. إن الخلط بينهما يرسل إشارات متضاربة لكي محركات لكي .
التالي-دولي يضيف ميزة أتمتة جزئية واحدة: حيث يقوم الوكيل الخاص به بإدراج سمة hreflang تلقائيًا رابط رؤوس الاستجابة عندما توجيه مسارات الملفات المُترجمة. أما تكوينات التوجيه الأخرى، فلا تزال تتطلب التنفيذ يدويًّا.
وهذا يمثل عبئًا كبيرًا من أعمال الصيانة المستمرة مع نمو موقعك. لحسن الحظ، Weglotيتولى الوكيل العكسي الخاص بـ [الاسم] معالجة كل شيء تلقائيًا على الخادم، لذا فإن الصفحات المترجمة قابلة للفهرسة بالكامل دون الحاجة إلى كود إضافي.
في الواقع، Weglotيقوم الوكيل العكسي الخاص بـ [الاسم] بمعالجة كل ما تم تناوله في القسم السابق تلقائيًا: علامات hreflang، وعناوين URL المترجمة، وعلامات canonical، وإنشاء خريطة الموقع. يتم تقديم الصفحات المترجمة من جانب الخادم، لذا فهي قابلة للفهرسة بالكامل بواسطة محركات البحث.
⚠️ Weglotلا يوفر تكامل JavaScript snippet مزايا تحسين محركات البحث (SEO). الترجمة من جانب العميل غير قابلة للفهرسة. إذا كان تحسين محركات البحث (SEO) مهمًا، فيجب إعداد الوكيل العكسي.
ومن المزايا الثانوية مدة الإنشاء. Weglot يقدم الصفحات المترجمة من شبكة CDN الخاصة به بدلاً من إنشائها أثناء عملية البناء. ولا تؤثر إضافة 10 لغات إلى موقع Weglotلا تؤثر على المدة التي يستغرقها الإصدار التالي يستغرق.
يعتمد الاختيار الصحيح على ما إلى تحقيقه.
إذا كنت تقوم بالتطوير باستخدام App Router وتبدأ من الصفر، التالي-دولي هو الخيار الافتراضي. فهو يغطي التوجيه والترجمة والإكمال التلقائي في TypeScript ودعم RSC في حزمة واحدة.
إذا كنت تستخدم "Pages Router" أو كان لديك بالفعل i18next ضمن مكونات نظامك، react-i18next هو الطريق الأسهل.
إذا كانت تحسين محركات البحث (SEO) على موقع متعدد اللغات وإدارة الترجمة المستمرة هما الأولوية، فإن أياً من المكتبتين لا يحل المشكلة بالكامل. فستظل بحاجة إلى تطبيق علامة hreflang وخرائط المواقع، بالإضافة إلى سير عمل لضمان تحديث الترجمات كلما تغير المحتوى. Weglotيقوم الوكيل العكسي الخاص بـ [الاسم] بمعالجة كل ذلك تلقائيًّا.
Weglot ومكتبة على مستوى المكونات لا تتعارضان. Weglot تعمل على مستوى HTML وطبقة الوكيل، لذا يمكنها التعايش مع أي مكتبة تستخدمها مكوناتك.
إذا كان هذا النهج مناسبًا لحالتك، فاطلع على صفحة تكامل JavaScript على موقع Weglot كنقطة انطلاق، وجرب الإصدار التجريبي المجاني لمدة 14 يومًا!
سجلت النسخ المترجمة من هذه الصفحة 0 زيارة خلال الـ 90 يوماً الماضية
أفضل طريقة لفهم قوة Weglot هي أن ترى ذلك بنفسك. جربه مجانًا وبدون أي التزام.
يتوفر موقع إلكتروني تجريبي في لوحة التحكم الخاصة بك إذا لم تكن مستعدًا لربط موقعك الإلكتروني بعد.