التعامل مع رموز اللغات غير المدعومة

المشكلة

يستخدم التطبيق مسار URL (مثل /en/، /fr/) لتحديد اللغة، ولكن يمكن للمستخدمين كتابة أي قيمة يدويًا، مثل /xx/about. عندما لا تتطابق هذه القيمة مع لغة مدعومة، قد يتعطل التطبيق، أو يعرض خطأً عامًا، أو يعرض محتوى غير مترجم، مما يفشل في توجيه المستخدم مرة أخرى إلى تجربة صالحة.

الحل

استخدم وسيطًا (middleware) لاعتراض جميع الطلبات الواردة. سيقوم هذا الوسيط بالتحقق من صحة رمز اللغة من URL مقابل قائمة نهائية من اللغات المدعومة. إذا كان الرمز غير مدعوم، ستتم إعادة كتابة الطلب إلى صفحة "غير موجود" قبل وصوله إلى منطق التطبيق.

الخطوات

1. تحديد اللغات المدعومة

قم بإنشاء ملف تكوين مركزي لتخزين قائمة رموز اللغات الصالحة (اللغات المحلية). هذا يجعل القائمة قابلة لإعادة الاستخدام للوسيط وأجزاء أخرى من تطبيقك.

// i18n.config.ts
export const locales = ['en', 'es', 'fr'];

2. إنشاء ملف الوسيط

قم بإنشاء ملف جديد باسم middleware.ts في جذر مشروعك (أو في دليل src/). سيكتشف Next.js هذا الملف تلقائيًا ويشغله على الطلبات.

// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { locales } from './i18n.config';

export function middleware(request: NextRequest) {
  // سيتم وضع المنطق هنا في الخطوة التالية
}

3. إضافة منطق التحقق

داخل وظيفة middleware، احصل على pathname من الطلب. نحتاج إلى التحقق من الجزء الأول من المسار (مثل en في /en/about) ومعرفة ما إذا كانت لغة صالحة ومدعومة.

// middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { locales } from './i18n.config';

export function middleware(request: NextRequest) {
  const { pathname } = request.nextUrl;

  // 1. التعامل مع المسار الجذر بشكل منفصل
  // (سيتم التعامل مع هذا في الوصفة التالية: "اكتشاف اللغة المفضلة للمستخدم").
  // في الوقت الحالي، نسمح له بالمرور.
  if (pathname === '/') {
    return NextResponse.next();
  }

  // 2. استخراج رمز اللغة من المسار
  const langCode = pathname.split('/')[1];

  // 3. التحقق مما إذا كان رمز اللغة في قائمتنا
  if (locales.includes(langCode)) {
    // اللغة صالحة، استمر إلى الصفحة المطلوبة
    return NextResponse.next();
  }

  // 4. إذا كانت اللغة غير صالحة، أعد الكتابة إلى صفحة 404
  // هذا يحافظ على عرض عنوان URL غير الصالح في شريط المتصفح
  const url = request.nextUrl.clone();
  url.pathname = `/404`; // يفترض أن لديك ملف app/404.tsx
  return NextResponse.rewrite(url);
}

يتحقق هذا المنطق من كل طلب. إذا كان عنوان URL هو /fr/about، فإن langCode هو fr، ويتم العثور عليه في locales، ويستمر الطلب. إذا كان عنوان URL هو /xx/about، فإن langCode هو xx، وهو غير موجود، ويتم عرض صفحة 404 للمستخدم دون أن يحاول التطبيق معالجة الطلب غير الصالح.

4. تكوين مطابق الوسيط

لجعل الوسيط الخاص بك أكثر كفاءة، يجب أن تخبره أي مسارات يجب أن يعمل عليها. نريد أن يعمل على طلبات الصفحة ولكن يتخطى الملفات الثابتة ومسارات واجهة برمجة التطبيقات (API).

أضف كائن config إلى أسفل ملف middleware.ts الخاص بك.

// middleware.ts

// ... (دالة الوسيط من الأعلى)

export const config = {
  matcher: [
    // تخطي جميع المسارات التي تبدأ بـ:
    // - api (مسارات API)
    // - _next/static (الملفات الثابتة)
    // - _next/image (ملفات تحسين الصور)
    // - favicon.ico (ملف الأيقونة المفضلة)
    '/((?!api|_next/static|_next/image|favicon.ico).*)',
  ],
};

يخبر هذا التعبير المنتظم الوسيط بالعمل على جميع المسارات باستثناء تلك المخصصة عادةً للأصول الثابتة أو استدعاءات API. هذا يمنع التحقق غير الضروري لكل صورة أو خط أو طلب بيانات.