كيفية تذكر اختيار اللغة عبر الجلسات في React Router v7

تخزين اختيار اللغة الصريح للمستخدم

المشكلة

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

الحل

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

الخطوات

1. إنشاء ملف تعريف ارتباط لتخزين تفضيل اللغة

تحديد ملف تعريف ارتباط سيحتفظ باللغة المختارة للمستخدم مع وقت انتهاء صلاحية طويل.

import { createCookie } from "react-router";

export const languagePreference = createCookie("language-preference", {
  maxAge: 31536000,
  httpOnly: false,
  secure: process.env.NODE_ENV === "production",
  sameSite: "lax",
});

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

2. إضافة إجراء لتخزين اختيار اللغة

إنشاء إجراء يتعامل مع عمليات إرسال نموذج اختيار اللغة ويخزن الاختيار في ملف تعريف الارتباط.

import { redirect } from "react-router";
import type { Route } from "./+types/root";
import { languagePreference } from "./cookies";

export async function action({ request }: Route.ActionArgs) {
  const formData = await request.formData();
  const selectedLanguage = formData.get("language");

  if (typeof selectedLanguage === "string") {
    return redirect(`/${selectedLanguage}`, {
      headers: {
        "Set-Cookie": await languagePreference.serialize(selectedLanguage),
      },
    });
  }

  return redirect("/");
}

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

3. إنشاء مكون اختيار اللغة

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

import { Form } from "react-router";

export function LanguageSelector({
  currentLanguage,
}: {
  currentLanguage: string;
}) {
  return (
    <Form method="post">
      <select
        name="language"
        defaultValue={currentLanguage}
        onChange={(e) => e.currentTarget.form?.requestSubmit()}
      >
        <option value="en">English</option>
        <option value="es">Español</option>
        <option value="fr">Français</option>
        <option value="de">Deutsch</option>
      </select>
    </Form>
  );
}

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

4. التحقق من التفضيل المخزن في محمل المسار الجذر

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

import { redirect } from "react-router";
import type { Route } from "./+types/root";
import { languagePreference } from "./cookies";

export async function loader({ request }: Route.LoaderArgs) {
  const url = new URL(request.url);
  const cookieHeader = request.headers.get("Cookie");
  const storedLanguage = await languagePreference.parse(cookieHeader);

  if (url.pathname === "/" && storedLanguage) {
    return redirect(`/${storedLanguage}`);
  }

  return null;
}

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

5. التحقق من صحة اللغة المخزنة مقابل اللغات المدعومة

تأكد من أن التفضيل المخزن صالح قبل استخدامه لإعادة التوجيه.

import { redirect } from "react-router";
import type { Route } from "./+types/root";
import { languagePreference } from "./cookies";

const SUPPORTED_LANGUAGES = ["en", "es", "fr", "de"];

export async function loader({ request }: Route.LoaderArgs) {
  const url = new URL(request.url);
  const cookieHeader = request.headers.get("Cookie");
  const storedLanguage = await languagePreference.parse(cookieHeader);

  if (
    url.pathname === "/" &&
    storedLanguage &&
    SUPPORTED_LANGUAGES.includes(storedLanguage)
  ) {
    return redirect(`/${storedLanguage}`);
  }

  return null;
}

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