Skip to main content

الدليل الشامل لتدويل Next.js

أعدّ next-intl مع App Router، وهيّئ توجيه الإعدادات المحلية، وأتمت الترجمات بالذكاء الاصطناعي.

1

تثبيت next-intl

next-intl هي حزمة واحدة تتولى توجيه الإعدادات المحلية، وتحميل الرسائل، وخطافات الترجمة لـ Next.js App Router.

Terminal
npm install next-intl
لماذا next-intl بدلاً من next-i18next؟ صُمّمت next-intl لـ App Router ولمكوّنات الخادم. أمّا next-i18next فقد صُمّمت لـ Pages Router وتوفّر دعماً محدوداً لـ App Router.
2

إنشاء تهيئة طلب i18n

أنشئ ملفين: src/i18n/request.ts لتحميل الرسائل وsrc/i18n/routing.ts لتعريف الإعدادات المحلية. يحددان كيفية حل next-intl للرسائل وكيفية التوجيه.

src/i18n/routing.ts
// src/i18n/routing.ts
import { defineRouting } from 'next-intl/routing';
import { createNavigation } from 'next-intl/navigation';

export const routing = defineRouting({
  locales: ['en', 'de', 'ja', 'es'],
  defaultLocale: 'en',
  localePrefix: 'as-needed',  // /about for en, /de/about for de
});

export const { Link, redirect, usePathname, useRouter } =
  createNavigation(routing);
يتطلب Turbopack (أداة التجميع الافتراضية في Next.js 15) إعداد experimental.turbo.resolveAlias في next.config.js. بدونه، ستظهر أخطاء "Couldn't find next-intl config file".
3

تهيئة middleware

أضف middleware.ts للتعامل مع اكتشاف الإعدادات المحلية، وإعادة كتابة URL، وعمليات إعادة التوجيه. تعترض middleware كل طلب وتضمن تطبيق الإعدادات المحلية الصحيحة.

middleware.ts
// middleware.ts  <- Must be in project ROOT, not src/
import createMiddleware from 'next-intl/middleware';
import { routing } from './src/i18n/routing';

export default createMiddleware(routing);

export const config = {
  matcher: ['/((?!api|_next|.*\\..*).*)'],
};
يجب أن يكون middleware.ts في الدليل الجذري للمشروع، وليس داخل src/. هذا هو خطأ التهيئة الأكثر شيوعاً مع next-intl.
4

إعداد بنية مجلد [locale]

انقل مسارات التطبيق داخل app/[locale]/. أضف generateStaticParams لتوليد صفحات لكل إعدادات محلية وقت البناء. يؤدي ذلك إلى بنية URL مثل /en/about، /de/about، وغيرها.

app/[locale]/layout.tsx
// app/[locale]/layout.tsx
import { routing } from '@/i18n/routing';

export function generateStaticParams() {
  return routing.locales.map((locale) => ({ locale }));
}
يجب استدعاء setRequestLocale(locale) في كل page.tsx وlayout.tsx تستخدم الترجمات. بدونه، يعود Next.js إلى العرض الديناميكي ويتدهور أداء البناء بشكل ملحوظ.
5

تحديث Root Layout

حمّل الرسائل باستخدام getMessages() ومرّرها إلى NextIntlClientProvider ضمن تخطيط الإعدادات المحلية الجذري. عيّن سمة html lang من معامل الإعدادات المحلية.

app/[locale]/layout.tsx
// app/[locale]/layout.tsx
import { NextIntlClientProvider } from 'next-intl';
import { getMessages, setRequestLocale } from 'next-intl/server';
import { routing } from '@/i18n/routing';
import { notFound } from 'next/navigation';

export function generateStaticParams() {
  return routing.locales.map((locale) => ({ locale }));
}

export default async function LocaleLayout({
  children,
  params,
}: {
  children: React.ReactNode;
  params: { locale: string };
}) {
  const { locale } = await params;
  if (!routing.locales.includes(locale as any)) notFound();

  setRequestLocale(locale);
  const messages = await getMessages();

  return (
    <html lang={locale}>
      <body>
        <NextIntlClientProvider locale={locale} messages={messages}>
          {children}
        </NextIntlClientProvider>
      </body>
    </html>
  );
}
يتطلب NextIntlClientProvider خاصية locale صريحة. يؤدي حذفها إلى أخطاء خفية في مكوّنات العميل يصعب تتبّعها.
6

استخدام الترجمات في المكوّنات

تستخدم مكوّنات الخادم getTranslations (async، await). وتستخدم مكوّنات العميل useTranslations (hook). اختر وفقاً لمكان عرض المكوّن — فمكوّنات الخادم تُبقي الترجمات خارج حزمة JavaScript الخاصة بالعميل بالكامل.

app/[locale]/page.tsx
// Server Component (default)
import { getTranslations, setRequestLocale } from 'next-intl/server';

export default async function AboutPage({
  params,
}: { params: { locale: string } }) {
  const { locale } = await params;
  setRequestLocale(locale);
  const t = await getTranslations('AboutPage');

  return <h1>{t('title')}</h1>;
}

// Client Component ('use client')
'use client';
import { useTranslations } from 'next-intl';

export default function SearchBar() {
  const t = useTranslations('SearchBar');
  return <input placeholder={t('placeholder')} />;
}
فضّل مكوّنات الخادم للمحتوى المترجم؛ فهي تُبقي سلاسل الترجمة خارج حزمة JavaScript للعميل، ما يقلل زمن التحميل للمستخدمين.
7

إضافة SEO: Metadata وHreflang

استخدم generateMetadata لإنتاج عناوين وأوصاف صفحات خاصة بكل إعدادات محلية. أضف alternates.languages لوسوم hreflang كي تكتشف محركات البحث جميع نسخ اللغة لكل صفحة.

app/[locale]/layout.tsx
// app/[locale]/layout.tsx or any page.tsx
import { getTranslations } from 'next-intl/server';
import { routing } from '@/i18n/routing';

export async function generateMetadata({
  params,
}: { params: { locale: string } }) {
  const { locale } = await params;
  const t = await getTranslations({ locale, namespace: 'Metadata' });

  return {
    title: t('title'),
    description: t('description'),
    alternates: {
      languages: Object.fromEntries(
        routing.locales.map((l) => [l, `/${l}`])
      ),
    },
  };
}
على Vercel، قد تولّد عمليات البناء localhost كعنوان canonical إذا لم يتم ضبط metadataBase. اضبط دائماً metadataBase في التخطيط الجذري على نطاق الإنتاج لديك.
8

التعامل مع صفحات الخطأ وصفحات غير الموجود

تتطلب error.tsx وnot-found.tsx معالجة خاصة لأنها قد تُعرَض خارج تخطيط الإعدادات المحلية المعتاد. يحتاج not-found.tsx الجذري إلى إعداد موفّر i18n خاص به لعرض رسائل خطأ مترجمة.

app/[locale]/error.tsx
// app/[locale]/error.tsx
'use client';
import { useTranslations } from 'next-intl';

export default function Error() {
  const t = useTranslations('Error');
  return (
    <div>
      <h1>{t('title')}</h1>
      <p>{t('description')}</p>
    </div>
  );
}

// app/not-found.tsx (root level -- needs own provider)
import { routing } from '@/i18n/routing';

export default async function GlobalNotFound() {
  return (
    <html lang={routing.defaultLocale}>
      <body>
        <h1>404 - Page Not Found</h1>
      </body>
    </html>
  );
}
لا يعرض Next.js صفحة 404 المترجمة لديك إلا عند استدعاء notFound() صراحةً في الشيفرة. أمّا المسارات غير المعروفة من دون صفحة مطابقة فتُظهر صفحة 404 الافتراضية في Next.js، وليس نسختك المترجمة.
9

أتمتة الترجمات

بعد اكتمال إعداد i18n، ترجم ملفات الرسائل باستخدام الذكاء الاصطناعي مباشرة من IDE، أو استخدم i18n Agent CLI ضمن خط CI/CD لأتمتة الترجمة مع كل عملية نشر.

Terminal
# In your IDE, ask your AI assistant:
> Translate messages/en.json to German, Japanese, and Spanish

✓ messages/de.json created (1.1s)
✓ messages/ja.json created (1.4s)
✓ messages/es.json created (1.0s)
استخدم next-intl-localechain لعمليات رجوع ذكية للإعدادات المحلية — إذ يرى مستخدم pt-BR ترجمات pt-PT بدلاً من الرجوع إلى الإنجليزية عندما لا تتوفر البرتغالية البرازيلية.

أتمتة جودة الترجمة

اكتشف المفاتيح المفقودة وplaceholders المعطوبة قبل الشحن باستخدام i18n-validate. اختبر واجهة المستخدم بترجمات مزيفة باستخدام i18n-pseudo قبل وصول الترجمات الحقيقية.

أدوات مفتوحة المصدر لـ Next.js i18n

تعالج هذه الحزم مفتوحة المصدر نقاط ألم شائعة في سير عمل تدويل Next.js.

next-intl-localechain

يرجع next-intl القياسي مباشرة إلى الإعدادات المحلية الافتراضية لديك عند غياب ترجمة. عندها يرى مستخدم البرتغالية البرازيلية الإنجليزية بدلاً من ترجمات pt-PT المتوفرة. يضيف next-intl-localechain سلاسل رجوع ذكية — إذ يدمج الترجمات بدمج عميق عبر إعدادات محلية ذات صلة، بحيث يرى المستخدمون الإقليميون دائماً أقرب ترجمة متاحة.

src/i18n/request.ts
import { getRequestConfig } from 'next-intl/server';
import { withLocaleChain } from 'next-intl-localechain';

export default getRequestConfig(withLocaleChain({
  loadMessages: (locale) =>
    import(`../../messages/${locale}.json`).then(m => m.default),
  defaultLocale: 'en'
}));
يدمج الترجمات بدمج عميق عبر سلاسل الإعدادات المحلية تلقائياً
سلاسل مدمجة للبرتغالية والإسبانية والفرنسية والألمانية وغيرها
يتجاوز ملفات الرسائل المفقودة بسلاسة من دون أخطاء
إعداد بسطر واحد — يغلّف getRequestConfig الموجود لديك
عرض على GitHub

@i18n-agent/cli

أداة سطر أوامر لترجمة ملفات رسائل Next.js دون مغادرة الطرفية. ترجم الملفات مباشرةً، وتحقق من حالة المهام، ونزّل النتائج. تعمل ضمن خطوط CI/CD مع المصادقة بمفتاح API لتحقيق سير عمل توطين مؤتمت بالكامل.

Terminal
# Install the CLI
npm install -g @i18n-agent/cli

# Authenticate
i18nagent login

# Translate your message files
i18nagent translate ./messages/en.json --lang de,ja,es

# Or use in CI/CD with an API key
export I18N_AGENT_API_KEY=your-key-here
i18nagent translate ./messages/en.json --lang de,ja,es
ترجم JSON وYAML وPO وغيرها من تنسيقات ملفات i18n من الطرفية
جاهزة لـ CI/CD — مصادقة عبر متغير بيئة للخطوط المؤتمتة
تتبّع حالة المهام، واستأنف المهام الفاشلة، ونزّل النتائج
مخرجات JSON قابلة للقراءة آلياً لأغراض البرمجة النصية والأتمتة
عرض على GitHub

المشكلات الشائعة

"Unable to find next-intl locale"

لم تطابق middleware الطلب. تحقّق: هل middleware.ts في جذر المشروع؟ هل يستبعد نمط matcher الملفات الثابتة بشكل صحيح؟ هل الإعدادات المحلية مضمنة في مصفوفة locales ضمن تهيئة التوجيه؟

عرض ديناميكي غير متوقع

setRequestLocale(locale) مفقودة من صفحة أو تخطيط. بدونها، يستخدم next-intl headers/cookies لاكتشاف الإعدادات المحلية، ما يفرض العرض الديناميكي ويمنع التوليد الثابت.

تعطّل Parallel Routes مع i18n

توجد حالات عدم توافق معروفة بين parallel routes (@modal) وintercepting routes ((.)photo) وبين المقطع الديناميكي [locale]. استخدم التوجيه القائم على middleware كحل بديل لهذه أنماط التوجيه المتقدمة.

تبديل اللغة يفقد المسار الحالي

عند تبديل الإعدادات المحلية، حافظ على pathname الحالي باستخدام usePathname() واستبدل مقطع الإعدادات المحلية فقط. انتبه لمعلمات المسارات الديناميكية — إذ يلزم حلّها مجدداً للإعدادات المحلية الجديدة.

بنية الملفات الموصى بها

Project Structure
my-nextjs-app/
├── middleware.ts              # Locale routing (project root!)
├── next.config.mjs
├── messages/
│   ├── en.json                # Source messages
│   ├── de.json
│   └── ja.json
├── src/
│   ├── i18n/
│   │   ├── request.ts         # Message loading config
│   │   └── routing.ts         # Locale definitions
│   └── app/
│       └── [locale]/
│           ├── layout.tsx     # Root locale layout
│           ├── page.tsx       # Home page
│           ├── error.tsx      # Localized error page
│           ├── not-found.tsx  # Localized 404
│           └── about/
│               └── page.tsx
└── package.json

جرّب i18n Agent الآن

أفلت ملف الترجمة هنا

JSON, YAML, PO, XML, CSV, Markdown, Properties

أو انقر للاستعراض

اللغات المستهدفة

لا حاجة إلى التسجيلتقدير فوري

الرجوع إلى إعدادات محلية بديلة باستخدام next-intl-localechain

عندما يكون مفتاح الترجمة مفقوداً في إعدادات محلية إقليمية مثل pt-BR، يقفز next-intl مباشرة إلى الإعدادات المحلية الافتراضية بدلاً من التحقق أولاً من الإعدادات المحلية الأصلية pt.

Terminal
npm install next-intl-localechain
Configuration
import { withLocaleChain } from 'next-intl-localechain';

export default withLocaleChain({
  fallbacks: {
    'pt-BR': ['pt', 'en'],
    'zh-Hant-HK': ['zh-Hant', 'zh', 'en'],
  },
  defaultLocale: 'en',
  loadMessages: (locale) => import(`./messages/${locale}.json`),
});

اطّلع على دليل الرجوع إلى إعدادات محلية بديلة للاطّلاع على القائمة الكاملة للأطر المدعومة و75 سلسلة مدمجة. Learn more →

الأسئلة المتكررة