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

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

المشكلة

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

الحل

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

الخطوات

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;
}

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