البدء في التوطين (i18n) مع Intlayer و React Create App

    ما هو Intlayer؟

    Intlayer هو مكتبة توطين مفتوحة المصدر ومبتكرة (i18n) مصممة لتبسيط دعم اللغات المتعددة في تطبيقات الويب الحديثة.

    مع Intlayer، يمكنك:

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

    دليل خطوة بخطوة لإعداد Intlayer في تطبيق React

    الخطوة 1: تثبيت التبعيات

    قم بتثبيت الحزم الضرورية باستخدام npm:

    bash
    npm install intlayer react-intlayer react-scripts-intlayer
    • intlayer

      الحزمة الأساسية التي توفر أدوات التوطين لإدارة التكوين، والترجمة، إعلان المحتوى، التحويل، وأوامر CLI.

    • react-intlayer

      الحزمة التي تدمج Intlayer مع تطبيق React. يوفر موفري السياق وhooks لتوطين React. بالإضافة إلى ذلك، يتضمن البرنامج المساعد لتكامل Intlayer مع تطبيق تم إنشاؤه باستخدام Create React App.

    الخطوة 2: تكوين مشروعك

    قم بإنشاء ملف تكوين لتكوين لغات تطبيقك:

    intlayer.config.ts
    import { Locales, type IntlayerConfig } from "intlayer";const config: IntlayerConfig = {  internationalization: {    locales: [      Locales.ARABIC,      Locales.FRENCH,      Locales.SPANISH,      // اللغات الأخرى الخاصة بك    ],    defaultLocale: Locales.ARABIC,  },};export default config;

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

    الخطوة 3: دمج Intlayer في إعداد CRA الخاص بك

    قم بتغيير نصوصك لاستخدام react-intlayer

    package.json
      "scripts": {    "build": "react-scripts-intlayer build",    "start": "react-scripts-intlayer start",    "transpile": "intlayer build"  },

    تستند نصوص react-scripts-intlayer إلى craco. يمكنك أيضًا تنفيذ إعدادك الخاص بناءً على ملحق intlayer craco. شاهد المثال هنا.

    الخطوة 4: إعلان محتواك

    قم بإنشاء وإدارة إعلانات المحتوى الخاصة بك لتخزين الترجمات:

    src/app.content.tsx
    import { t, type DeclarationContent } from "intlayer";import React, { type ReactNode } from "react";const appContent = {  key: "app",  content: {    getStarted: t<ReactNode>({      ar: (        <>          قم بتحرير <code>src/App.tsx</code> واحفظ لإعادة التحميل        </>      ),      fr: (        <>          Éditez <code>src/App.tsx</code> et enregistrez pour recharger        </>      ),      es: (        <>          Edita <code>src/App.tsx</code> y guarda para recargar        </>      ),    }),    reactLink: {      href: "https://reactjs.org",      content: t({        ar: "تعلم React",        fr: "Apprendre React",        es: "Aprender React",      }),    },  },} satisfies DeclarationContent;export default appContent;

    يمكنك تعريف إعلانات المحتوى الخاصة بك في أي مكان في تطبيقك بمجرد تضمينها في دليل contentDir (بشكل افتراضي، ./src). وتطابق امتداد ملف إعلان المحتوى (بشكل افتراضي، .content.{ts,tsx,js,jsx,mjs,cjs}). لمزيد من التفاصيل، ارجع إلى وثائق إعلان المحتوى. إذا كان ملف المحتوى الخاص بك يتضمن رمز TSX، يجب أن تفكر في استيراد import React from "react"; في ملف المحتوى الخاص بك.

    الخطوة 5: استخدم Intlayer في كودك

    يمكنك الوصول إلى قواميس المحتوى الخاصة بك في جميع أنحاء تطبيقك:

    src/App.tsx
    import logo from "./logo.svg";import "./App.css";import type { FC } from "react";import { IntlayerProvider, useIntlayer } from "react-intlayer";const AppContent: FC = () => {  const content = useIntlayer("app");  return (    <div className="App">      <img src={logo} className="App-logo" alt="logo" />      {content.getStarted}      <a        className="App-link"        href={content.reactLink.href.value}        target="_blank"        rel="noopener noreferrer"      >        {content.reactLink.content}      </a>    </div>  );};const App: FC = () => (  <IntlayerProvider>    <AppContent />  </IntlayerProvider>);export default App;

    ملاحظة: إذا كنت ترغب في استخدام المحتوى الخاص بك في خاصية string، مثل alt، title، href، aria-label، إلخ، يجب عليك استدعاء قيمة الوظيفة، مثل:

    jsx
    <img src={content.image.src.value} alt={content.image.value} />

    لمعرفة المزيد عن hook useIntlayer، ارجع إلى الوثائق.

    (اختياري) الخطوة 6: تغيير لغة المحتوى الخاص بك

    لتغيير لغة المحتوى الخاص بك، يمكنك استخدام دالة setLocale المقدمة من hook useLocale. تتيح لك هذه الدالة تعيين اللغة الخاصة بالتطبيق وتحديث المحتوى وفقًا لذلك.

    src/components/LocaleSwitcher.tsx
    import { Locales } from "intlayer";import { useLocale } from "react-intlayer";const LocaleSwitcher = () => {  const { setLocale } = useLocale();  return (    <button onClick={() => setLocale(Locales.ARABIC)}>      تغيير اللغة إلى العربية    </button>  );};

    لمعرفة المزيد عن hook useLocale، ارجع إلى الوثائق.

    (اختياري) الخطوة 7: إضافة التوجيه المحلي إلى تطبيقك

    الغرض من هذه الخطوة هو إنشاء مسارات فريدة لكل لغة. وهذا مفيد لتحسين محركات البحث وعناوين URL المتوافقة مع تحسين محركات البحث. مثال:

    plaintext
    - https://example.com/about- https://example.com/ar/about- https://example.com/fr/about

    بشكل افتراضي، لا تُضاف البادئات للمسارات باللغة الافتراضية. إذا كنت تريد إضافة بادئة للغة الافتراضية، يمكنك تعيين خيار middleware.prefixDefault إلى true في تكوينك. راجع وثائق التكوين لمزيد من المعلومات.

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

    src/components/LocaleRouter.tsx
    // استيراد التبعيات والدوال اللازمةimport { Locales, getConfiguration, getPathWithoutLocale } from "intlayer"; // دوال وأنواع مساعد من 'intlayer'import type { FC, PropsWithChildren } from "react"; // أنواع React للمكونات الوظيفية والخصائصimport { IntlayerProvider } from "react-intlayer"; // مزود لسياق التوطينimport {  BrowserRouter,  Routes,  Route,  useParams,  Navigate,  useLocation,} from "react-router-dom"; // مكونات التوجيه لإدارة التنقل// تفكيك التكوين من Intlayerconst { internationalization, middleware } = getConfiguration();const { locales, defaultLocale } = internationalization;/** * مكون يدير التوطين ويغلف الأطفال بسياق اللغة المناسب. * يدير الكشف والتحقق من اللغة المعتمدة على عنوان URL. */const AppLocalized: FC<PropsWithChildren> = ({ children }) => {  const path = useLocation().pathname; // الحصول على مسار URL الحالي  const { locale } = useParams<{ locale: Locales }>(); // استخراج معلمة اللغة من عنوان URL  // تحديد اللغة الحالية، مع الرجوع إلى اللغة الافتراضية إذا لم يتم توفيرها  const currentLocale = locale ?? defaultLocale;  // إزالة بادئة اللغة من المسار لبناء مسار أساسي  const pathWithoutLocale = getPathWithoutLocale(    path // مسار URL الحالي  );  /**   * إذا كانت middleware.prefixDefault صحيحة، يجب أن تكون اللغة الافتراضية دائمًا مضافة   */  if (middleware.prefixDefault) {    // التحقق من اللغة    if (!locale || !locales.includes(locale)) {      // إعادة التوجيه إلى اللغة الافتراضية مع تحديث المسار      return (        <Navigate          to={`/${defaultLocale}/${pathWithoutLocale}`}          replace // استبدال مدخل السجل الحالي بالمدخل الجديد        />      );    }    // لف الأطفال بمزود Intlayer وتعيين اللغة الحالية    return (      <IntlayerProvider locale={currentLocale}>{children}</IntlayerProvider>    );  } else {    /**     * عندما تكون middleware.prefixDefault خاطئة، لا تُضاف اللغة الافتراضية كبادئة.     * التأكد من أن اللغة الحالية صالحة وليست اللغة الافتراضية.     */    if (      currentLocale.toString() !== defaultLocale.toString() &&      !locales        .filter(          (locale) => locale.toString() !== defaultLocale.toString() // استبعاد اللغة الافتراضية        )        .includes(currentLocale) // التحقق مما إذا كانت اللغة الحالية في قائمة اللغات الصالحة    ) {      // إعادة التوجيه إلى المسار بدون بادئة اللغة      return <Navigate to={pathWithoutLocale} replace />;    }    // لف الأطفال بمزود Intlayer وتعيين اللغة الحالية    return (      <IntlayerProvider locale={currentLocale}>{children}</IntlayerProvider>    );  }};/** * مكون توجيه يقيم مسارات محددة حسب اللغة. * يستخدم React Router لإدارة التنقل وعرض المكونات المخصصة للغة. */export const LocaleRouter: FC<PropsWithChildren> = ({ children }) => (  <BrowserRouter>    <Routes>      <Route        // نمط المسار لالتقاط اللغة (مثل، /ar/، /fr/) ومطابقة جميع المسارات اللاحقة        path="/:locale/*"        element={<AppLocalized>{children}</AppLocalized>} // يغلف الأطفال بإدارة اللغة      />      {        // إذا كانت إضافة بادئة للغة الافتراضية غير مفعلة، قم بعرض الأطفال مباشرة في المسار الجذري        !middleware.prefixDefault && (          <Route            path="*"            element={<AppLocalized>{children}</AppLocalized>} // يغلف الأطفال بإدارة اللغة          />        )      }    </Routes>  </BrowserRouter>);

    (اختياري) الخطوة 8: تغيير عنوان URL عندما تتغير اللغة

    لتغيير عنوان URL عندما تتغير اللغة، يمكنك استخدام خاصية onLocaleChange المقدمة من hook useLocale. بالتوازي، يمكنك استخدام hooks useLocation و useNavigate من react-router-dom لتحديث مسار URL.

    src/components/LocaleSwitcher.tsx
    import { useLocation, useNavigate } from "react-router-dom";import {  Locales,  getHTMLTextDir,  getLocaleName,  getLocalizedUrl,} from "intlayer";import { useLocale } from "react-intlayer";import { type FC } from "react";const LocaleSwitcher: FC = () => {  const location = useLocation(); // الحصول على مسار URL الحالي. مثال: /ar/about  const navigate = useNavigate();  const changeUrl = (locale: Locales) => {    // بناء عنوان URL مع اللغة المحدثة    // مثال: /fr/about مع تعيين اللغة إلى الفرنسية    const pathWithLocale = getLocalizedUrl(location.pathname, locale);    // تحديث مسار عنوان URL    navigate(pathWithLocale);  };  const { locale, availableLocales, setLocale } = useLocale({    onLocaleChange: changeUrl,  });  return (    <ol>      {availableLocales.map((localeItem) => (        <li key={localeItem}>          <a            href={getLocalizedUrl(location.pathname, localeItem)}            hrefLang={localeItem}            aria-current={locale === localeItem ? "page" : undefined}            onClick={(e) => {              e.preventDefault();              setLocale(localeItem);            }}          >            <span>              {/* اللغة في لغتها الخاصة - مثل. العربية */}              {getLocaleName(localeItem, locale)}            </span>            <span dir={getHTMLTextDir(localeItem)} lang={localeItem}>              {/* اللغة باللغة الحالية - مثل. العربية مع تعيين اللغة الحالية إلى Locales.ARABIC */}              {getLocaleName(localeItem)}            </span>            <span dir="ltr" lang={Locales.ENGLISH}>              {/* اللغة باللغة الإنجليزية - مثل. العربية */}              {getLocaleName(localeItem, Locales.ENGLISH)}            </span>            <span>              {/* اللغة في لغتها الخاصة - مثل. AR */}              {localeItem}            </span>          </a>        </li>      ))}    </ol>  );};

    مراجع الوثائق:

    تكوين TypeScript

    يستخدم Intlayer تعزيز الوحدات للاستفادة من TypeScript وجعل قاعدة الشيفرة لديك أقوى.

    alt text

    alt text

    تأكد من أن تكوين TypeScript لديك يتضمن الأنواع المولدة تلقائيًا.

    tsconfig.json
    {  // ... إعدادات TypeScript الحالية لديك  "include": [    // ... إعدادات TypeScript الحالية لديك    "types", // تضمين الأنواع المولدة تلقائيًا  ],}

    تكوين Git

    من المستحسن تجاهل الملفات التي تم إنشاؤها بواسطة Intlayer. هذا يسمح لك بتجنب دفعها إلى مستودع Git الخاص بك.

    للقيام بذلك، يمكنك إضافة التعليمات التالية إلى ملف .gitignore الخاص بك:

    .gitignore
    # تجاهل الملفات التي تم إنشاؤها بواسطة Intlayer.intlayer

    إذا كان لديك فكرة لتحسين هذه الوثيقة، فلا تتردد في المساهمة من خلال تقديم طلب سحب على GitHub.

    رابط GitHub للتوثيق