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

المشكلة

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

الحل

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

الخطوات

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

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

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

2. أنشئ ملف الـ middleware

أنشئ ملفًا جديدًا باسم 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) {
  // Logic will go here in the next step
}

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. Handle the root path separately
  // (This will be handled by the next recipe: "Detecting a user's
  // preferred language"). For now, we just let it pass.
  if (pathname === '/') {
    return NextResponse.next();
  }

  // 2. Extract the language code from the path
  const langCode = pathname.split('/')[1];

  // 3. Check if the language code is in our list
  if (locales.includes(langCode)) {
    // Language is valid, continue to the requested page
    return NextResponse.next();
  }

  // 4. If the language is not valid, rewrite to a 404 page
  // This keeps the invalid URL in the browser bar
  const url = request.nextUrl.clone();
  url.pathname = `/404`; // Assumes you have an app/404.tsx file
  return NextResponse.rewrite(url);
}

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

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

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

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

// middleware.ts

// ... (the middleware function from above)

export const config = {
  matcher: [
    // Skip all paths that start with:
    // - api (API routes)
    // - _next/static (static files)
    // - _next/image (image optimization files)
    // - favicon.ico (favicon file)
    '/((?!api|_next/static|_next/image|favicon.ico).*)',
  ],
};

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