كيفية بناء مكون تبديل اللغة في Next.js (Pages Router) الإصدار 16
تبديل اللغات مع البقاء على نفس الصفحة
المشكلة
يتوقع المستخدمون من مبدلات اللغة الحفاظ على موقعهم الحالي. عندما يشاهد شخص ما صفحة منتج باللغة الإنجليزية ويبدل إلى الإسبانية، فإنه يريد رؤية نفس صفحة المنتج بالإسبانية، وليس إعادة توجيهه إلى الصفحة الرئيسية. كسر هذا التوقع يخلق احتكاكاً ويجبر المستخدمين على التنقل مرة أخرى إلى حيث كانوا، مما يؤدي إلى تدهور التجربة وربما يتسبب في تخليهم عن المهمة بالكامل.
تفشل العديد من تطبيقات مبدلات اللغة لأنها تتعامل مع اختيار اللغة كتنقل بسيط بدلاً من كونه تحويلاً للعرض الحالي. بدون الوصول إلى معلومات التوجيه الخاصة بالصفحة الحالية، لا يمكن للمبدل سوى الربط بوجهات ثابتة، مما يفقد سياق المستخدم في هذه العملية.
الحل
قم ببناء مبدل لغة يقرأ مسار المسار الحالي ومعاملات الاستعلام من الموجه، ثم يولد روابط لكل لغة مدعومة تحافظ على معلومات التوجيه هذه مع تغيير اللغة المحلية فقط. من خلال تمرير المسار والاستعلام إلى واجهة برمجة التطبيقات للتنقل مع اللغة المحلية المستهدفة، يضمن المبدل بقاء المستخدمين على الصفحة المكافئة باللغة الجديدة.
الخطوات
1. إنشاء مكون مبدل لغة يقرأ المسار الحالي
يوفر كائن الموجه pathname وasPath وquery وlocale وlocales الخصائص التي تحتوي على جميع المعلومات اللازمة لبناء روابط واعية باللغة المحلية.
import { useRouter } from "next/router";
import Link from "next/link";
export default function LanguageSwitcher() {
const router = useRouter();
const { locale, locales, pathname, asPath, query } = router;
return (
<nav>
{locales?.map((loc) => (
<Link key={loc} href={{ pathname, query }} as={asPath} locale={loc}>
{loc.toUpperCase()}
</Link>
))}
</nav>
);
}
يقبل مكون Link خاصية locale للانتقال إلى لغة محلية مختلفة عن اللغة النشطة حالياً. تمرير pathname وquery ككائن إلى href يحافظ على جميع معلومات التوجيه بما في ذلك قيم استعلام المسار الديناميكي.
2. تنسيق اللغة النشطة لتوفير ملاحظات بصرية
قم بتمييز اللغة الحالية حتى يعرف المستخدمون اللغة التي يشاهدونها.
import { useRouter } from "next/router";
import Link from "next/link";
export default function LanguageSwitcher() {
const router = useRouter();
const { locale, locales, pathname, asPath, query } = router;
return (
<nav>
{locales?.map((loc) => {
const isActive = loc === locale;
return (
<Link
key={loc}
href={{ pathname, query }}
as={asPath}
locale={loc}
style={{
fontWeight: isActive ? "bold" : "normal",
textDecoration: isActive ? "none" : "underline",
marginRight: "1rem",
}}
>
{loc.toUpperCase()}
</Link>
);
})}
</nav>
);
}
تحدد مقارنة كل لغة بقيمة locale الحالية اللغة النشطة وتطبق تنسيقاً مميزاً لتمييزها عن البدائل المتاحة.
3. إضافة تسميات يمكن الوصول إليها باستخدام react-intl
استبدل رموز اللغات بأسماء لغات يمكن قراءتها لتحسين سهولة الاستخدام.
import { useRouter } from "next/router";
import { useIntl } from "react-intl";
import Link from "next/link";
const localeNames: Record<string, string> = {
en: "English",
es: "Español",
fr: "Français",
de: "Deutsch",
};
export default function LanguageSwitcher() {
const router = useRouter();
const intl = useIntl();
const { locale, locales, pathname, asPath, query } = router;
return (
<nav
aria-label={intl.formatMessage({
id: "languageSwitcher.label",
defaultMessage: "Select language",
})}
>
{locales?.map((loc) => {
const isActive = loc === locale;
return (
<Link
key={loc}
href={{ pathname, query }}
as={asPath}
locale={loc}
aria-current={isActive ? "true" : undefined}
style={{
fontWeight: isActive ? "bold" : "normal",
textDecoration: isActive ? "none" : "underline",
marginRight: "1rem",
}}
>
{localeNames[loc] || loc}
</Link>
);
})}
</nav>
);
}
يوفر خطاف useIntl إمكانية الوصول إلى دوال التنسيق لترجمة تسميات واجهة المستخدم. تعمل سمتا aria-label و aria-current على تحسين إمكانية الوصول لمستخدمي قارئات الشاشة.