البدء في استخدام Intlayer و Next.js 14 مع App Router
ما هو Intlayer؟
Intlayer هي مكتبة مفتوحة المصدر للترجمة (i18n) مصممة لتبسيط دعم اللغات المتعددة في تطبيقات الويب الحديثة. يتكامل Intlayer بسلاسة مع أحدث إطار عمل Next.js 14، بما في ذلك App Router القوي. تم تحسينه للعمل مع Server Components من أجل تقديم فعال ومتوافق تمامًا مع Turbopack (من Next.js >= 15).
مع Intlayer، يمكنك:
- إدارة الترجمات بسهولة باستخدام قواميس تعبيرية على مستوى المكونات.
- محليّة البيانات الوصفية والمسارات والمحتوى ديناميكياً.
- الوصول إلى الترجمات في كل من المكونات الجانبية والخادمة.
- ضمان دعم TypeScript مع أنواع تلقائية، مما يحسن الاكمال التلقائي وكشف الأخطاء.
- الاستفادة من ميزات متقدمة، مثل اكتشاف اللغة الديناميكي وتبديلها.
Intlayer متوافق مع Next.js 12 و 13 و 14 و 15. إذا كنت تستخدم Next.js Page Router، يمكنك الرجوع إلى هذا الدليل. ل Next.js 15 مع أو بدون turbopack، راجع هذا الدليل.
دليل خطوة بخطوة لإعداد Intlayer في تطبيق Next.js
الخطوة 1: تثبيت الاعتمادات
قم بتثبيت الحزم اللازمة باستخدام npm:
npm install intlayer next-intlayer
intlayer
الحزمة الأساسية التي توفر أدوات الترجمة لإدارة التكوين، والترجمة، وإعلان المحتوى، وtranspilation، وأوامر CLI.
next-intlayer
الحزمة التي تدمج Intlayer مع Next.js. توفر موفري السياق والهوكات لترجمة Next.js. بالإضافة إلى ذلك، تتضمن مكون Next.js المخصص لدمج Intlayer مع Webpack أو Turbopack، بالإضافة إلى المكونات الوسيطة لاكتشاف اللغة المفضلة للمستخدم، وإدارة الكوكيز، والتعامل مع إعادة توجيه URL.
الخطوة 2: تكوين مشروعك
أنشئ ملف تكوين لتحديد لغات تطبيقك:
import { Locales, type IntlayerConfig } from "intlayer";const config: IntlayerConfig = { internationalization: { locales: [ Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH, // لغات أخرى ], defaultLocale: Locales.ENGLISH, },};export default config;
من خلال هذا الملف التكويني، يمكنك إعداد روابط URL محلية، وتحويل المكونات الوسيطة، وأسماء الكوكيز، وموقع وإمتداد إعلانات المحتوى الخاصة بك، وتعطيل سجلات Intlayer في وحدة التحكم، والمزيد. للحصول على قائمة كاملة بالمعلمات المتاحة، يرجى الرجوع إلى توثيق التكوين.
الخطوة 3: دمج Intlayer في إعداد Next.js الخاص بك
قم بتكوين إعداد Next.js الخاص بك لاستخدام Intlayer:
import { withIntlayer } from "next-intlayer/server";/** @type {import('next').NextConfig} */const nextConfig = {};export default withIntlayer(nextConfig);
يتم استخدام مكون withIntlayer() الخاص بـ Next.js لدمج Intlayer مع Next.js. يضمن بناء ملفات إعلان المحتوى ورصدها في وضع التطوير. ويحدد متغيرات بيئة Intlayer داخل بيئات Webpack أو Turbopack. بالإضافة إلى ذلك، يوفر بدائل لتحسين الأداء وضمان التوافق مع مكونات الخادم.
الخطوة 4: تكوين المكونات الوسيطة لاكتشاف اللغة
قم بإعداد المكونات الوسيطة لاكتشاف اللغة المفضلة للمستخدم:
export { intlayerMiddleware as middleware } from "next-intlayer/middleware";export const config = { matcher: "/((?!api|static|assets|robots|sitemap|sw|service-worker|manifest|.*\\..*|_next).*)",};
يتم استخدام intlayerMiddleware لاكتشاف اللغة المفضلة للمستخدم وإعادة توجيههم إلى عنوان URL المناسب كما هو محدد في التكوين. بالإضافة إلى ذلك، يمكّن من حفظ اللغة المفضلة للمستخدم في الكوكي.
قم بتعديل معلمة matcher لتتناسب مع مسارات تطبيقك. لمزيد من التفاصيل، راجع توثيق Next.js حول تكوين matcher.
الخطوة 5: تحديد مسارات لغة ديناميكية
قم بإزالة كل شيء من RootLayout واستبدله بالشيفرة التالية:
import type { PropsWithChildren, FC } from "react";import "./globals.css";const RootLayout: FC<PropsWithChildren> = ({ children }) => children;export default RootLayout;
إن ترك مكون RootLayout فارغًا يسمح بتعيين سمات lang وdir لعلامة <html>.
لتنفيذ توجيه ديناميكي، قم بتوفير المسار للغة عن طريق إضافة تخطيط جديد في الدليل [locale] الخاص بك:
import type { Next14LayoutIntlayer } from "next-intlayer";import { Inter } from "next/font/google";import { getHTMLTextDir } from "intlayer";const inter = Inter({ subsets: ["latin"] });const LocaleLayout: Next14LayoutIntlayer = ({ children, params: { locale },}) => ( <html lang={locale} dir={getHTMLTextDir(locale)}> <body className={inter.className}>{children}</body> </html>);export default LocaleLayout;
يتم استخدام جزء المسار [locale] لتحديد اللغة. مثال: /en-US/about ستشير إلى en-US و/fr/about إلى fr.
ثم، نفّذ وظيفة generateStaticParams في تخطيط التطبيق الخاص بك.
export { generateStaticParams } from "next-intlayer"; // السطر لإدخالهconst LocaleLayout: Next14LayoutIntlayer = ({ children, params: { locale },}) => { /*... باقي الكود*/};export default LocaleLayout;
يضمن generateStaticParams أن يقوم تطبيقك بإنشاء الصفحات اللازمة لجميع اللغات مسبقًا، مما يقلل الحساب أثناء وقت التشغيل ويحسن تجربة المستخدم. لمزيد من التفاصيل، راجع توثيق Next.js حول generateStaticParams.
الخطوة 6: إعلان المحتوى الخاص بك
قم بإنشاء وإدارة إعلانات المحتوى الخاصة بك لتخزين الترجمات:
import { t, type DeclarationContent } from "intlayer";const pageContent = { key: "page", content: { getStarted: { main: t({ en: "Get started by editing", fr: "Commencez par éditer", es: "Comience por editar", }), pageLink: "src/app/page.tsx", }, },} satisfies DeclarationContent;export default pageContent;
يمكن تعريف إعلانات المحتوى الخاصة بك في أي مكان داخل تطبيقك طالما أنها مضمنة في دليل contentDir (افتراضيًا، ./src). وتطابق امتداد ملف إعلان المحتوى (افتراضيًا، .content.{ts,tsx,js,jsx,mjs,cjs}). لمزيد من التفاصيل، يرجى الرجوع إلى توثيق إعلان المحتوى.
الخطوة 7: استخدام المحتوى في الشيفرة الخاصة بك
يمكنك الوصول إلى قواميس المحتوى الخاصة بك في جميع أنحاء تطبيقك:
import { ClientComponentExample } from "@components/ClientComponentExample";import { ServerComponentExample } from "@components/ServerComponentExample";import { type Next14PageIntlayer, IntlayerClientProvider } from "next-intlayer";import { IntlayerServerProvider, useIntlayer } from "next-intlayer/server";const Page: Next14PageIntlayer = ({ params: { locale } }) => { const content = useIntlayer("page", locale); return ( <> <p> {content.getStarted.main} <code>{content.getStarted.pageLink}</code> </p> <IntlayerServerProvider locale={locale}> <IntlayerClientProvider locale={locale}> <ServerComponentExample /> <ClientComponentExample /> </IntlayerClientProvider> </IntlayerServerProvider> </> );};export default Page;
- IntlayerClientProvider يستخدم لتوفير اللغة لمكونات الجانب العميل. يمكن وضعه في أي مكون أبوي، بما في ذلك التخطيط. ومع ذلك، يوصى بوضعه في تخطيط لأنه يشارك كود التخطيط عبر الصفحات في Next.js، مما يجعله أكثر كفاءة. من خلال استخدام IntlayerClientProvider في التخطيط، يمكنك تجنب إعادة تهيئته لكل صفحة، مما يحسن الأداء ويحافظ على سياق الترجمة المتسق في جميع أنحاء تطبيقك.
IntlayerServerProvider يستخدم لتوفير اللغة للأطفال من الخادم. لا يمكن تعيينه في التخطيط.
لا يمكن أن يشارك التخطيط والصفحة سياق خادم مشترك لأن نظام سياق الخادم يعتمد على تخزين بيانات لكل طلب (من خلال آلية ذاكرة التخزين المؤقت لـ React)، مما يؤدي إلى إعادة إنشاء كل "سياق" لأجزاء مختلفة من التطبيق. قد يؤدي وضع الموفر في تخطيط مشترك إلى كسر هذه العزلة، مما يمنع التوزيع الصحيح لقيم سياق الخادم إلى مكونات الخادم الخاصة بك.
"use client";import type { FC } from "react";import { useIntlayer } from "next-intlayer";const ClientComponentExample: FC = () => { const content = useIntlayer("client-component-example"); // أنشئ إعلان المحتوى ذي الصلة return ( <div> <h2>{content.title} </h2> <p>{content.content}</p> </div> );};
import type { FC } from "react";import { useIntlayer } from "next-intlayer/server";const ServerComponentExample: FC = () => { const content = useIntlayer("server-component-example"); // أنشئ إعلان المحتوى ذي الصلة return ( <div> <h2>{content.title} </h2> <p>{content.content}</p> </div> );};
إذا كنت ترغب في استخدام المحتوى الخاص بك في سمة string، مثل alt أو title أو href أو aria-label، يجب عليك استدعاء قيمة الوظيفة، مثل:
jsx<img src={content.image.src.value} alt={content.image.value} />
لمعرفة المزيد عن هوك useIntlayer، يرجى الرجوع إلى التوثيق.
(اختياري) الخطوة 8: دولنة البيانات الوصفية الخاصة بك
في حال كنت ترغب في دولنة بياناتك الوصفية، مثل عنوان صفحتك، يمكنك استخدام وظيفة generateMetadata التي توفرها Next.js. داخل الوظيفة، استخدم وظيفة getTranslationContent لترجمة بياناتك الوصفية.
import { type IConfigLocales, getTranslationContent, getMultilingualUrls,} from "intlayer";import type { Metadata } from "next";import type { LocalParams } from "next-intlayer";export const generateMetadata = ({ params: { locale },}: LocalParams): Metadata => { const t = <T>(content: IConfigLocales<T>) => getTranslationContent(content, locale); /** * يولد كائنًا يحتوي على جميع الروابط لكل لغة. * * مثال: * ```ts * getMultilingualUrls('/about'); * * // يرجع * // { * // en: '/about', * // fr: '/fr/about', * // es: '/es/about', * // } * ``` */ const multilingualUrls = getMultilingualUrls("/"); return { title: t<string>({ en: "My title", fr: "Mon titre", es: "Mi título", }), description: t({ en: "My description", fr: "Ma description", es: "Mi descripción", }), alternates: { canonical: "/", languages: { ...multilingualUrls, "x-default": "/" }, }, openGraph: { url: multilingualUrls[locale], }, };};// ... بقية الكود
تعلم المزيد حول تحسين البيانات الوصفية في مستندات Next.js الرسمية.
(اختياري) الخطوة 9: دولنة sitemap.xml و robots.txt الخاص بك
لتدويل sitemap.xml و robots.txt الخاصة بك، يمكنك استخدام وظيفة getMultilingualUrls التي يوفرها Intlayer. تتيح لك هذه الوظيفة إنشاء روابط متعددة اللغات لخريطة الموقع الخاصة بك.
import { getMultilingualUrls } from "intlayer";import type { MetadataRoute } from "next";const sitemap = (): MetadataRoute.Sitemap => [ { url: "https://example.com", alternates: { languages: getMultilingualUrls("https://example.com"), }, }, { url: "https://example.com/login", alternates: { languages: getMultilingualUrls("https://example.com/login"), }, }, { url: "https://example.com/register", alternates: { languages: getMultilingualUrls("https://example.com/register"), }, },];export default sitemap;
import type { MetadataRoute } from "next";import { getMultilingualUrls } from "intlayer";const getAllMultilingualUrls = (urls: string[]) => urls.flatMap((url) => Object.values(getMultilingualUrls(url)) as string[]);const robots = (): MetadataRoute.Robots => ({ rules: { userAgent: "*", allow: ["/"], disallow: getAllMultilingualUrls(["/login", "/register"]), }, host: "https://example.com", sitemap: `https://example.com/sitemap.xml`,});export default robots;
تعرف أكثر عن تحسين خريطة الموقع في مستندات Next.js الرسمية. تعرف أكثر عن تحسين robots.txt في مستندات Next.js الرسمية.
(اختياري) الخطوة 10: تغيير لغة محتواك
لتغيير لغة المحتوى الخاص بك، يمكنك استخدام وظيفة setLocale المقدمة من هوك useLocale. تتيح لك هذه الوظيفة تعيين لغة التطبيق وتحديث المحتوى وفقًا لذلك.
"use client";import { Locales, getHTMLTextDir, getLocaleName, getLocalizedUrl,} from "intlayer";import { useLocale } from "next-intlayer";import { type FC } from "react";const LocaleSwitcher: FC = () => { const { locale, pathWithoutLocale, availableLocales, setLocale } = useLocale(); return ( <ol> {availableLocales.map((localeItem) => ( <li key={localeItem}> <a href={getLocalizedUrl(pathWithoutLocale, localeItem)} hrefLang={localeItem} aria-current={locale === localeItem ? "page" : undefined} onClick={(e) => { e.preventDefault(); setLocale(localeItem); }} > <span> {/* اللغة بلغة محلية خاصة بها - على سبيل المثال: Français */} {getLocaleName(localeItem, locale)} </span> <span dir={getHTMLTextDir(localeItem)} lang={localeItem}> {/* اللغة بلغة محلية حاليًا - على سبيل المثال: Francés مع تعيين اللغة الحالية إلى Locales.SPANISH */} {getLocaleName(localeItem)} </span> <span dir="ltr" lang={Locales.ENGLISH}> {/* اللغة باللغة الإنجليزية - على سبيل المثال: French */} {getLocaleName(localeItem, Locales.ENGLISH)} </span> <span> {/* اللغة بلغة محلية خاصة بها - على سبيل المثال: FR */} {localeItem} </span> </a> </li> ))} </ol> );};
المراجع الوثائقية:
تكوين TypeScript
يستخدم Intlayer تكبير الوحدة للحصول على فوائد TypeScript وجعل قاعدة الشيفرة الخاصة بك أقوى.
تأكد من أن إعداد TypeScript الخاص بك يتضمن الأنواع التي تم إنشاؤها تلقائيًا.
{ // ... إعدادات TypeScript الحالية الخاصة بك "include": [ // ... إعدادات TypeScript الحالية الخاصة بك "types", // تضمين الأنواع التي تم إنشاؤها تلقائيًا ],}
تكوين Git
يوصى بتجاهل الملفات التي تم إنشاؤها بواسطة Intlayer. سيسمح لك ذلك بتجنب دفعها إلى مستودع Git الخاص بك.
للقيام بذلك، يمكنك إضافة التعليمات التالية إلى ملف .gitignore الخاص بك:
# تجاهل الملفات التي تم إنشاؤها بواسطة Intlayer.intlayer
إذا كان لديك فكرة لتحسين هذه الوثيقة، فلا تتردد في المساهمة من خلال تقديم طلب سحب على GitHub.
رابط GitHub للتوثيق