كيفية بناء مكون محول اللغة في React Router v7

تبديل اللغات مع البقاء في نفس الصفحة

المشكلة

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

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

الحل

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

يعامل هذا النهج اللغة كمعلمة قابلة للاستبدال في بنية URL بدلاً من وجهة تنقل، مما يضمن أن التبديل من /en/products/shoes إلى /es/products/shoes يحافظ على سياق المستخدم.

الخطوات

1. إنشاء دالة مساعدة لبناء عناوين URL متوافقة مع اللغة

تحديد دالة تأخذ مسار الاسم الحالي واللغة المستهدفة، ثم تبني مسارًا جديدًا عن طريق استبدال جزء اللغة.

export function buildLocalePath(
  currentPath: string,
  newLocale: string,
): string {
  const segments = currentPath.split("/").filter(Boolean);

  if (segments.length === 0) {
    return `/${newLocale}`;
  }

  segments[0] = newLocale;
  return `/${segments.join("/")}`;
}

تقوم هذه الدالة بتقسيم اسم المسار إلى أجزاء، واستبدال الجزء الأول باللغة المستهدفة، وإعادة بناء المسار. وهي تتعامل مع الحالات الحدية مثل المسار الجذر وتضمن أن تكون اللغة دائمًا هي الجزء الأول.

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

قم بإنشاء كائن تكوين يسرد جميع اللغات التي يدعمها تطبيقك.

export const locales = [
  { code: "en", label: "English" },
  { code: "es", label: "Español" },
  { code: "fr", label: "Français" },
  { code: "de", label: "Deutsch" },
];

يعمل هذا التكوين كمصدر للحقيقة حول اللغات التي سيتم عرضها في أداة تبديل اللغة ويوفر تسميات سهلة الاستخدام لكل لغة.

3. بناء مكون مبدل اللغة

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

import { Link, useLocation, useParams } from "react-router";
import { locales, buildLocalePath } from "./i18n-config";

export function LanguageSwitcher() {
  const location = useLocation();
  const params = useParams();
  const currentLocale = params.locale || "en";

  return (
    <nav aria-label="Language switcher">
      <ul>
        {locales.map((locale) => {
          const isActive = locale.code === currentLocale;
          const newPath = buildLocalePath(location.pathname, locale.code);

          return (
            <li key={locale.code}>
              {isActive ? (
                <span aria-current="true">{locale.label}</span>
              ) : (
                <Link to={newPath}>{locale.label}</Link>
              )}
            </li>
          );
        })}
      </ul>
    </nav>
  );
}

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

4. الحفاظ على معلمات الاستعلام وأجزاء التجزئة

قم بتوسيع الدالة المساعدة للحفاظ على سلاسل الاستعلام وأجزاء URL عند تبديل اللغات.

export function buildLocalePath(
  currentPath: string,
  search: string,
  hash: string,
  newLocale: string,
): string {
  const segments = currentPath.split("/").filter(Boolean);

  if (segments.length === 0) {
    return `/${newLocale}${search}${hash}`;
  }

  segments[0] = newLocale;
  return `/${segments.join("/")}${search}${hash}`;
}

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

5. تحديث المكون لاستخدام الدالة المساعدة المحسنة

قم بتعديل محول اللغة لتمرير معلومات الموقع الكاملة إلى الدالة المساعدة.

import { Link, useLocation, useParams } from "react-router";
import { locales, buildLocalePath } from "./i18n-config";

export function LanguageSwitcher() {
  const location = useLocation();
  const params = useParams();
  const currentLocale = params.locale || "en";

  return (
    <nav aria-label="Language switcher">
      <ul>
        {locales.map((locale) => {
          const isActive = locale.code === currentLocale;
          const newPath = buildLocalePath(
            location.pathname,
            location.search,
            location.hash,
            locale.code,
          );

          return (
            <li key={locale.code}>
              {isActive ? (
                <span aria-current="true">{locale.label}</span>
              ) : (
                <Link to={newPath}>{locale.label}</Link>
              )}
            </li>
          );
        })}
      </ul>
    </nav>
  );
}

يقوم المكون الآن بتمرير location.search و location.hash إلى الدالة المساعدة، مما يضمن أن عناوين URL مثل /en/products?category=shoes#reviews تصبح /es/products?category=shoes#reviews عند التبديل إلى اللغة الإسبانية.