المؤلف:
    إنشاء:2026-09-13آخر تحديث:2026-09-13

    i18next مقابل Intlayer | اختبار أداء تدويل (i18n) تطبيقات React و Next.js

    يُعد i18next إطار عمل التدويل (i18n) الأكثر استخداما في بيئة عمل JavaScript. فمن خلال react-i18next و next-i18next، يدعم شريحة ضخمة من تطبيقات React و Next.js. في المقابل، يمثل Intlayer بديلا حديثا قائما على المترجم (Compiler) ونطاق المكونات (Component-scoped).

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

    ملخص سريع (tl;dr): يُعد i18next أثقل بيئة تشغيل (runtime) في اختبار الأداء: يضيف +77 كيلوبايت gzip لكل صفحة في Next.js في الإعداد الأولي البسيط، و +22 كيلوبايت حتى بعد التحسين الكامل لنطاقات الأسماء والتحميل الكسول (Lazy-loading). بينما يضيف Intlayer ما مقداره +0.3 كيلوبايت فقط. جميع إعدادات i18next باستثناء الإعداد المعزول تماما (scoped) تقوم بإرسال نحو 90% من نصوص الصفحات غير المعروضة؛ بينما يرسل Intlayer نسبة 0% بشكل افتراضي. استغرق تبديل اللغة مع خلفية محملة كسولا 123-185 مللي ثانية مع react-i18next مقابل 3-4 مللي ثانية مع Intlayer. محول التوافق @intlayer/next-i18next يحتفظ بنفس واجهة برمجة تطبيقات i18next وخفض الحجم إلى 150.7 كيلوبايت لكل صفحة مقارنة بـ 218.5 كيلوبايت للأصل.

    باختصار

    • i18next / react-i18next / next-i18next - ناضج، غني بالإضافات، ومستقل عن أطر العمل. يوفر مساحات الأسماء (Namespaces)، مكتشفات اللغة، الخلفيات، دعم ICU عبر الإضافات، ومكون <Trans> للمحتوى المنسق. يتم تجميع المحتوى مركزيا في locales/{lng}/{ns}.json. إنه قوي للغاية، لكن كل تحسين (تقسيم مساحات الأسماء، التحميل لكل صفحة، أمان الأنواع) هو إعداد يقع عبء كتابته وصيانته عليك.
    • Intlayer - نموذج محتوى يتمحور حول المكونات. توضع قواميس .content.ts بجوار المكون الذي تخدمه مباشرة، ويقوم المترجم في وقت البناء بتطبيق تقنية Tree-shaking والتحميل الكسول لكل مكون ولكل لغة، مع توليد أنواع TypeScript صارمة تلقائيا من محتواك، وفشل عملية البناء عند وجود ترجمات مفقودة. يوفر وسائط برمجية (middleware)، ومساعدات SEO، ومحررا مرئيا / CMS، وترجمة مدعومة بالذكاء الاصطناعي.
    المكتبةنجوم GitHubإجمالي الالتزامات (Commits)آخر التزامأول إصدارإصدار NPMتنزيلات NPM الشهرية
    aymericzip/intlayerGitHub Repo starsGitHub commit activityLast Commitأبريل 2024npmnpm downloads
    i18next/i18nextGitHub Repo starsGitHub commit activityLast Commitيناير 2012npmnpm downloads
    i18next/react-i18nextGitHub Repo starsGitHub commit activityLast Commitديسمبر 2015npmnpm downloads
    i18next/next-i18nextGitHub Repo starsGitHub commit activityLast Commitنوفمبر 2018npmnpm downloads
    يتم تحديث الشارات تلقائيا. قد تختلف الأرقام بمرور الوقت.

    مقارنة الميزات جنبا إلى جنب

    الميزةIntlayer (react-intlayer / next-intlayer)i18next (react-i18next / next-i18next)
    وضع الترجمات بجوار المكونات✅ نعم، ملف .content.ts مجاور لكل مكون❌ لا، تجميع مركزي في locales/{lng}/{ns}.json
    التكامل مع TypeScript✅ توليد تلقائي لأنواع صارمة استنادا إلى المحتوى⚠️ أساسي؛ تتطلب المفاتيح الصارمة توسيع CustomTypeOptions وتحديد الأنواع يدويا
    اكتشاف الترجمات المفقودة✅ خطأ TypeScript + خطأ/تحذير أثناء البناء⚠️ احتياطي وقت التشغيل (saveMissing، إرجاع المفتاح نفسه)
    المحتوى المنسق (JSX / Markdown / مكونات)✅ دعم مباشر أصيل⚠️ عبر مكون <Trans> مع عناصر نائبة مفهرسة
    دعم صيغ ICU⚠️ قيد التطوير⚠️ عبر إضافة (i18next-icu)
    الجموع (Pluralization)✅ أنماط معتمدة على التعداد (Enumeration)✅ لواحق _one / _other (باستخدام Intl.PluralRules)
    التنسيق (التواريخ، الأرقام، العملات)useNumber، useDate، إلخ (تعتمد على Intl داخليا)⚠️ منسقات الاستيفاء (Interpolation) أو استدعاء Intl.* يدويا
    التوجيه المترجم والوسائط البرمجية✅ وكيل ووسيط برمجي مدمج، مع دالة getMultilingualUrls⚠️ غير مدمج؛ يتطلب وسيطا برمجيا مخصصا أو حزما خارجية
    مساعدات SEO (hreflang، sitemap، robots)✅ مساعدات مدمجة وجاهزة❌ إعداد يدوي بالكامل
    مكونات الخادم المتزامنة (Server Components)✅ تعمل useIntlayer من next-intlayer/server في أي مكون خادم فرعي مباشرة⚠️ استدعاء getFixedT في الصفحة ثم تمرير t عبر Props
    Tree-shaking (شحن المحتوى المستخدم فقط)✅ لكل مكون ولكل لغة تلقائيا بواسطة المترجم⚠️ يدوي: مساحات أسماء + قائمة ns لكل صفحة + خلفية برمجية
    التحميل الكسول (Lazy loading)importMode: 'dynamic' (سطر إعداد واحد)✅ عبر إضافات الخلفيات البرمجية (i18next-resources-to-backend وغيرها)
    تنظيف المحتوى غير المستخدم (Purge)✅ حذف القواميس المهملة تلقائيا أثناء البناء❌ غير مدعوم افتراضيا
    اختبار الترجمات المفقودة (CLI / CI)npx intlayer content test⚠️ عبر أداة i18next-parser أو أدوات خارجية
    الترجمة بالذكاء الاصطناعي✅ مدمجة، وتستخدم مفاتيح مزود الخدمة الخاصة بك❌ لا (Locize هي خدمة مدفوعة منفصلة)
    محرر مرئي / CMS✅ محرر مرئي مجاني + نظام إدارة محتوى (CMS) اختياري❌ لا (تتطلب Locize أو منصات خارجية)
    خادم MCP ومهارات الوكلاء (Agent Skills)✅ متوفر❌ غير متوفر
    النظام البيئي والمجتمع⚠️ أحدث ولكنه ينمو بسرعة فائقة✅ الأكبر والأكثر نضجا وتجربة

    اختبار الأداء (Benchmark)

    ما تم قياسه

    تقوم حزمة Benchmark Bloom ببناء نفس التطبيق تماما باستخدام كل مكتبة: 10 صفحات (الرئيسية، عن الموقع، المدونة، الوظائف، التواصل، الأسئلة الشائعة، الأسعار، المنتجات، الإعدادات، الفريق)، 10 لغات (en, fr, es, de, it, pt, zh, ja, ko, ru)، ومكونات ومحتوى متطابق تماما. يتم قياس الصفحات باللغتين الإنجليزية والفرنسية. تم اختبار كل مكتبة عبر أربع استراتيجيات تحميل:

    الاستراتيجيةالوصفمن يستخدمها عادة
    staticتجميع كل اللغات والصفحات معا في حزمة واحدة (تضمين resources مباشرة في init())النماذج الأولية السريعة، الأكواد المولدة بالـ AI
    dynamicتحميل اللغة النشطة فقط عبر خلفية برمجية، مع تحميل جميع مساحات الأسماء دفعة واحدةأغلب المشاريع العامة
    scoped-staticمساحة أسماء واحدة لكل مسار، مع تضمين الكل مسبقا في الحزمةحالات نادرة
    scoped-dynamicمساحة أسماء لكل مسار + تحميل كسول عبر خلفية برمجية. الصفحة الحالية واللغة الحالية فقطالتطبيقات ذات الميزانيات الصارمة في الأداء

    لا يمتلك Intlayer خيارا باسم "scoped": لأن المترجم يحدد نطاق المحتوى لكل مكون على حدة تلقائيا، وبالتالي فإن سطري static و dynamic معزولان ومحسنان بالفعل.

    تسجل حزمة الاختبارات لكل عملية بناء المقاييس التالية:

    • Lib size: حجم gzip لمكون فارغ يستورد مكتبة التدويل فقط، وهو ما يمثل التكلفة الثابتة لبيئة التشغيل.
    • Page JS: حجم JavaScript بصيغة gzip الذي يتم تنزيله لكل صفحة، كمتوسط عبر جميع الصفحات واللغات.
    • Locale leak %: نسبة النصوص المترجمة في كود JS التي تنتمي إلى لغة لا يعرضها المستخدم حاليا.
    • Page leak %: نسبة النصوص المترجمة في كود JS التي تنتمي إلى صفحة لا يتواجد فيها المستخدم.
    • Component avg: متوسط حجم gzip لكل مكون عند تجميعه بشكل معزول.
    • E2E reactivity: الوقت الفعلي المستغرق بين اختيار لغة جديدة وتحديث html[lang] في DOM (باستخدام Playwright عبر 5 تكرارات).
    • Hydration: مدة مرحلة إماهة (Hydration) مكونات React.
    الأرقام الواردة أدناه تعود لتشغيل الاختبار بتاريخ 2026-09-12 باستخدام next-i18next 16.3.0، react-i18next 17.0.13، و intlayer 9.5.1. التطبيق التجريبي صغير عمدا، لذا فإن نسب التسرب تعبر عن نمط هيكلي: فهي تكبر طرديا مع تزايد المحتوى بينما تظل تكلفة بيئة التشغيل ثابتة.

    النتائج على Next.js (next-i18next)

    المكتبةالاستراتيجيةحجم المكتبة (gz)متوسط JS للصفحة (gz)تسرب اللغاتتسرب الصفحاتمتوسط حجم المكون (gz)سرعة الاستجابة E2Eمدة الإماهة (Hydration)
    base (بدون i18n)-0.0 KB141.0 KB0.0%0.0%0.9 KB13.4 ms11.8 ms
    next-i18nextstatic19.7 KB218.5 KB0.0%89.8%78.5 KB16.4 ms15.6 ms
    next-i18nextdynamic19.7 KB169.5 KB50.0%89.8%26.1 KB15.4 ms27.7 ms
    next-i18nextscoped-static19.7 KB220.1 KB0.0%89.8%78.9 KB16.4 ms14.7 ms
    next-i18nextscoped-dynamic19.7 KB163.4 KB0.0%0.0%27.1 KB15.9 ms15.1 ms
    next-intlayerstatic5.5 KB141.3 KB0.0%0.0%8.5 KB15.5 ms16.9 ms
    next-intlayerdynamic5.5 KB141.3 KB0.0%0.0%6.9 KB15.3 ms15.9 ms
    @intlayer/next-i18next (توافقي)static9.4 KB150.7 KB0.0%0.0%9.7 KB10.7 ms11.3 ms
    @intlayer/next-i18next (توافقي)dynamic9.4 KB150.7 KB0.0%0.0%9.7 KB11.9 ms10.6 ms

    قراءة النتائج وتحليلها

    • تكلفة بيئة التشغيل: يُعد نواة i18next مع react-i18next أثقل بيئة تشغيل تم قياسها: 19.7 كيلوبايت gzip لمكون فارغ، مقارنة بـ 5.5 كيلوبايت لـ next-intlayer.
    • الإعداد البسيط عالي التكلفة: تضمين resources مباشرة داخل init() يولد 218.5 كيلوبايت لكل صفحة، أي زيادة قدرها +77.5 كيلوبايت مقارنة بالتطبيق الأساسي. حيث تحمل كل صفحة كل مساحات الأسماء بلا استثناء.
    • التحسين اليدوي عملية معقدة: التحول إلى خلفية برمجية (dynamic) يوفر 49 كيلوبايت لكنه لا يزال يسرب 90% من نصوص الصفحات الأخرى، ونصف النصوص المحملة تخص لغة أخرى. بينما يؤدي تقسيم مساحات الأسماء لكل مسار (scoped-dynamic) إلى إيقاف التسرب والوصول إلى 163.4 كيلوبايت، لكنه يظل أكبر بمقدار +22.4 كيلوبايت لكل صفحة مقارنة بـ Intlayer الذي سجل 141.3 كيلوبايت دون الحاجة لأي إعدادات يدوية معقدة.
    • حجم المكون الفردي: المكون الذي يستدعي useTranslation() يتراوح حجمه بين 26 و 79 كيلوبايت؛ بينما يبلغ حجم نفس المكون مع useIntlayer() ما يعادل 6.9 كيلوبايت فقط.
    • تباطؤ الإماهة: يقفز زمن الإماهة إلى 27.7 مللي ثانية في إعداد dynamic، نظرا لأن نسخة i18next تبدأ العمل وتعالج طلبات الخلفية على العميل قبل أن يتمكن React من إتمام عملية الإماهة.

    النتائج على TanStack Start (react-i18next)

    نفس التطبيق التجريبي على TanStack Start مع استخدام react-i18next الصافي لإبعاد التأثيرات الخاصة بـ Next.js.

    المكتبةالاستراتيجيةحجم المكتبة (gz)متوسط JS للصفحة (gz)تسرب اللغاتتسرب الصفحاتمتوسط حجم المكون (gz)سرعة الاستجابة E2Eمدة الإماهة (Hydration)
    base (بدون i18n)-0.0 KB111.0 KB0.0%0.0%0.7 KB8.1 ms21.6 ms
    react-i18nextstatic18.4 KB180.3 KB50.0%89.8%24.3 KB12.9 ms85.1 ms
    react-i18nextdynamic18.4 KB136.4 KB23.1%89.8%24.8 KB123.1 ms32.9 ms
    react-i18nextscoped-static18.4 KB184.2 KB50.7%89.8%25.3 KB185.1 ms25.2 ms
    react-i18nextscoped-dynamic18.4 KB127.2 KB0.0%0.0%26.7 KB17.6 ms11.3 ms
    intlayerstatic5.0 KB125.8 KB50.0%0.0%8.1 KB3.2 ms11.5 ms
    intlayerdynamic5.0 KB118.6 KB0.0%0.0%6.3 KB3.6 ms14.1 ms

    قراءة النتائج وتحليلها

    • يشحن تطبيق react-i18next غير المحسن زيادة قدرها +69 كيلوبايت لكل صفحة مقارنة بالتطبيق الأساسي، وتستغرق الإماهة 85 مللي ثانية (أربعة أضعاف الأساس) لأن شجرة الموارد الكاملة يتم فحصها وتسجيلها على العميل قبل العرض الأولي.
    • تأخر التحميل الكسول عند تبديل اللغة: عند تحميل الموارد عند الطلب عبر خلفية برمجية، يتطلب تبديل اللغة رحلة شبكة كاملة قبل أن يتم تحديث html[lang]: 123 مللي ثانية في dynamic، و 185 مللي ثانية في scoped-static. في المقابل، يقوم Intlayer بتحديث شجرة DOM في غضون 3-4 مللي ثانية في كلا الوضعين وبشكل فوري دون التعطل في انتظار استجابة الشبكة.
    • التكوين عالي التحسين scoped-dynamic يصل إلى 0% تسرب عند 127.2 كيلوبايت، ولكنه لا يزال أكبر بمقدار +8.6 كيلوبايت مقارنة بـ Intlayer في وضع dynamic، وتطلب لتحقيق ذلك خريطة مسارات وخلفيات موارد وحدود Suspense خاصة.
    • يسجل وضع static في Intlayer نسبة 0% تسرب للصفحات افتراضيا لأن القواميس التي تستوردها مكونات الصفحة فقط هي التي تُحزم في الكود. وتفعيل importMode: 'dynamic' يزيل تسرب اللغات أيضا.
    • حجم المكونات: 24-27 كيلوبايت مع react-i18next مقابل 6-8 كيلوبايت مع Intlayer. حيث يربط useTranslation() كل مكون بالنسخة العالمية لـ i18next.

    ما سبب هذا الفارق؟ النسخة العالمية مقابل القواميس المترجمة

    صُمم i18next في عام 2012 كبيئة تشغيل (runtime): تحتفظ نسخة عالمية واحدة بمخزن الموارد، وتتولى الإضافات توسيعها، بينما تبحث دالة t() عن المفاتيح أثناء العرض. هذه البنية تمنحه مرونة واسعة ولكنها تفرض تكلفة باهظة في الحجم:

    bash
    .
    ├── i18n.ts                      # createInstance().use(...).use(...).init({...})
    └── src
        ├── locales
       ├── en
       ├── common.json
       ├── home.json
       └── about.json
       └── fr
           ├── common.json
           ├── home.json
           └── about.json
        ├── components
       └── Counter.tsx          # useTranslation("about") + t("counter.label")
        └── app
            └── [locale]
                └── about
                    └── page.tsx     # يجب أن تعرف مسبقا أنها تحتاج ["common", "about"]
    

    لا يمكن للنسخة العالمية التنبؤ بالمفاتيح التي سيطلبها المكون، لذا تضطر لتحميل جميع مساحات الأسماء التي تحددها لها. والتحسين يفرض عليك أنت تقسيم الملفات، وأنت تحديد مساحات الأسماء لكل صفحة، وأنت الحفاظ على دقة هذه القائمة كلما تم نقل المكونات. وكما توضح ملاحظات الاختبار: "الحفاظ على أمان الأنواع ومعرفة أي مساحة أسماء يجب تضمينها في كل صفحة يعد كابوسا حقيقيا".

    يتخلص Intlayer من النسخة العالمية تماما. يُعلن المحتوى بجوار المكون مباشرة، ويقوم المترجم بحل مخطط الاعتماديات في وقت البناء:

    bash
    .
    ├── intlayer.config.ts
    └── src
        ├── components
       └── Counter
           ├── index.tsx        # useIntlayer("counter")
           └── index.content.ts
        └── app
            └── [locale]
                └── about
                    ├── page.tsx
                    └── page.content.ts
    

    يتعرف @intlayer/swc / @intlayer/babel على المكون والقاموس الذي يستورده، فيحزم هذين فقط، وللغة النشطة فقط، ويتخلص من أي محتوى لا تتم الإشارة إليه. يصبح نمط "scoped-dynamic" نتاجا تلقائيا لعملية البناء بدلا من كونه عبئا تنظيميا يديره الفريق يدويا.

    للحصول على أرقام سطر dynamic، اضبط dictionary.importMode: 'dynamic' في intlayer.config.ts. راجع دليل تحسين الحزمة.

    تجربة المطور (DX)

    الإعداد

    next-i18next (App Router)

    src/app/i18n/server.ts
    import { createInstance } from "i18next";
    import { initReactI18next } from "react-i18next/initReactI18next";
    import resourcesToBackend from "i18next-resources-to-backend";
    import { defaultLocale } from "@/i18n.config";
    
    const backend = resourcesToBackend(
      (locale: string, namespace: string) =>
        import(`../../locales/${locale}/${namespace}.json`)
    );
    
    export const initI18next = async (
      locale: string,
      namespaces: string[] = ["common"]
    ) => {
      const i18n = createInstance();
      await i18n
        .use(initReactI18next)
        .use(backend)
        .init({
          lng: locale,
          fallbackLng: defaultLocale,
          ns: namespaces,
          defaultNS: "common",
          interpolation: { escapeValue: false },
          react: { useSuspense: false },
        });
      return i18n;
    };
    

    بالإضافة إلى كتابة I18nProvider لجانب العميل يعيد بناء نفس النسخة، مع إعداد generateStaticParams وتحديد مصفوفة namespaces في كل صفحة.

    Intlayer

    intlayer.config.ts
    import { type IntlayerConfig, Locales } from "intlayer";
    
    const config: IntlayerConfig = {
      internationalization: {
        locales: [Locales.ENGLISH, Locales.FRENCH],
        defaultLocale: Locales.ENGLISH,
      },
    };
    
    export default config;
    
    src/app/[locale]/layout.tsx
    import { getHTMLTextDir } from "intlayer";
    import { IntlayerClientProvider, type NextLayoutIntlayer } from "next-intlayer";
    
    const LocaleLayout: NextLayoutIntlayer = async ({ children, params }) => {
      const { locale } = await params;
    
      return (
        <html lang={locale} dir={getHTMLTextDir(locale)}>
          <body>
            <IntlayerClientProvider locale={locale}>
              {children}
            </IntlayerClientProvider>
          </body>
        </html>
      );
    };
    
    export default LocaleLayout;
    

    مكون العميل

    react-i18next

    src/locales/en/about.json
    {
      "counter": {
        "label": "Counter",
        "increment": "Increment"
      }
    }
    
    src/components/Counter.tsx
    "use client";
    
    import { useState } from "react";
    import { useTranslation } from "react-i18next";
    
    export const Counter = () => {
      const { t, i18n } = useTranslation("about");
      const [count, setCount] = useState(0);
      const numberFormat = new Intl.NumberFormat(i18n.language);
    
      return (
        <div>
          <p>{numberFormat.format(count)}</p>
          <button
            aria-label={t("counter.label")}
            onClick={() => setCount((c) => c + 1)}
          >
            {t("counter.increment")}
          </button>
        </div>
      );
    };
    
    الصفحة التي تعرض هذا المكون ملزمة بتحميل مساحة أسماء about، ودالة t("counter.label") تبقى نصا عاديا مجردا من أنواع التحقق ما لم تقم بتوسيع CustomTypeOptions.

    Intlayer

    src/components/Counter/index.content.ts
    import { t, type Dictionary } from "intlayer";
    
    const counterContent = {
      key: "counter",
      content: {
        label: t({ en: "Counter", fr: "Compteur" }),
        increment: t({ en: "Increment", fr: "Incrémenter" }),
      },
    } satisfies Dictionary;
    
    export default counterContent;
    
    src/components/Counter/index.tsx
    "use client";
    
    import { useState } from "react";
    import { useIntlayer } from "next-intlayer";
    import { useNumber } from "next-intlayer/format";
    
    export const Counter = () => {
      const { label, increment } = useIntlayer("counter");
      const number = useNumber();
      const [count, setCount] = useState(0);
    
      return (
        <div>
          <p>{number(count)}</p>
          <button aria-label={label} onClick={() => setCount((c) => c + 1)}>
            {increment}
          </button>
        </div>
      );
    };
    

    يتمتع كل من label و increment بأنواع TypeScript صارمة ودقيقة؛ أي خطأ كتابي يظهر فورا كخطأ برمجي، والترجمة المفقودة تتسبب في إيقاف عملية البناء وتنبيهك فوريا.

    مكون الخادم المتزامن

    next-i18next

    src/components/ServerCounter.tsx
    type ServerCounterProps = {
      t: (key: string) => string;
      locale: string;
      count: number;
    };
    
    export const ServerCounter = ({ t, locale, count }: ServerCounterProps) => (
      <div>
        <p>{new Intl.NumberFormat(locale).format(count)}</p>
        <button aria-label={t("counter.label")}>{t("counter.increment")}</button>
      </div>
    );
    

    يجب أن تستدعي الصفحة دالة i18n.getFixedT(locale, "about") وتقوم بتمرير t و locale عبر الخصائص (Props).

    Intlayer

    src/components/ServerCounter.tsx
    import { useIntlayer } from "next-intlayer/server";
    import { useNumber } from "next-intlayer/server/format";
    
    export const ServerCounter = ({ count }: { count: number }) => {
      const { label, increment } = useIntlayer("counter");
      const number = useNumber();
    
      return (
        <div>
          <p>{number(count)}</p>
          <button aria-label={label}>{increment}</button>
        </div>
      );
    };
    

    احتفظ بواجهة i18next، واحصل على أداء Intlayer العالي

    لست بحاجة إلى إعادة كتابة مكوناتك للحصول على نتائج الأداء المذكورة أعلاه. محولات التوافق @intlayer/i18next، @intlayer/react-i18next، و @intlayer/next-i18next جاهزة للعمل كبديل فوري: useTranslation، t()، <Trans>، صيغ الجمع، ولواحق السياق تواصل العمل بسلاسة، بينما يقدم المترجم قواميس Intlayer المحسنة في الخلفية.

    next.config.ts
    import type { NextConfig } from "next";
    import { createNextI18nPlugin } from "@intlayer/next-i18next/plugin";
    
    const withIntlayer = createNextI18nPlugin();
    
    const nextConfig: NextConfig = {};
    
    export default withIntlayer(nextConfig);
    
    vite.config.ts
    import { defineConfig } from "vite";
    import { reactI18nextVitePlugin } from "@intlayer/react-i18next/plugin";
    
    export default defineConfig({
      plugins: [reactI18nextVitePlugin()],
    });
    

    في اختبار الأداء، انخفض بناء التوافق لنفس تطبيق Next.js من 218.5 كيلوبايت إلى 150.7 كيلوبايت لكل صفحة، ومن 78.5 كيلوبايت إلى 9.7 كيلوبايت لكل مكون، ومن ~90% تسرب للصفحات إلى 0%، مع تحسن وقت الإماهة من 15.6 مللي ثانية إلى 11.3 مللي ثانية، دون أي تعديل في كود المكونات. ويمكن لملفات locales/{lng}/{ns}.json الحالية أن تظل المصدر الرئيسي للبيانات عبر إضافة مزامنة JSON.

    راجع أدلة الترحيل: i18next، react-i18next، next-i18next.

    متى تختار كل منهما؟

    • اختر i18next: إذا كنت بحاجة حتمية إلى نظامه البيئي من الإضافات (مكتشفات محددة، خلفيات خاصة، ICU، Locize)، أو تقوم بالتدويل خارج بيئة React أيضا (خدمات Node، جافاسكريبت نقية، أطر عمل أخرى)، أو كان فريقك يتقنه بالفعل، أو كانت منصة الترجمة تتطلب ملفات locales/{lng}/{ns}.json. ولكن خصص وقتا كافيا لإدارة مساحات الأسماء والخلفيات البرمجية ومطابقة المسارات إذا كان الأداء يهمك.
    • اختر Intlayer: إذا كنت تريد محتوى مرتبطا بالمكونات، وأنواع TypeScript صارمة، واكتشاف الأخطاء والترجمات الناقصة وقت البناء، وتحسينا تلقائيا للحزم والتحميل الكسول دون تعقيدات، مع تبديل لغات فوري، ومكونات خادم متزامنة، وأدوات تحرير مدمجة (محرر مرئي، CMS، ترجمة بالذكاء الاصطناعي، خادم MCP). وهو ملائم بامتياز لقواعد الأكواد المعيارية وأنظمة التصميم (Design Systems).
    • اختر محولات @intlayer/*-i18next: إذا كان لديك تطبيق يعمل بالفعل على i18next وتريد جني فوائد تقليص الحجم وسرعة الاستجابة دون إعادة كتابة الأكواد.

    مقارنات ذات صلة

    نجوم GitHub

    تعد نجوم GitHub مؤشرا بارزا على شعبية المشروع، وثقة المطورين به، واستمراريته على المدى الطويل. ورغم أنها لا تقيس الجودة التقنية وحدها، إلا أنها توضح اهتمام المجتمع ورغبته في الاعتماد عليه في الإنتاج.

    مخطط تاريخ النجوم

    الخاتمة

    اكتسب i18next مكانته الريادية بفضل تشغيله في كل مكان، وتوفيره إضافات لكل استخدام، ودعمه المستمر لأكثر من عقد. ولكن اختبار الأداء يوضح تكلفة هذا التصميم القائم على وقت التشغيل. الإعداد الشائع يضيف +70-77 كيلوبايت gzip لكل صفحة، ويسرب ~90% من محتوى الصفحات الأخرى، ويستغرق تبديل اللغة عبر التحميل الكسول أكثر من 100 مللي ثانية. والوصول إلى 0% تسرب ممكن لكنه يتطلب خلفيات ومساحات أسماء يدوية، ومع ذلك يظل أكبر بمقدار +9-22 كيلوبايت من Intlayer.

    ينقل Intlayer هذا العبء بالكامل إلى المترجم. فالقواميس لكل مكون، والتحميل الكسول لكل لغة، وحذف النصوص المهملة هي نواتج بناء تلقائية وليست قيودا يدوية. على نفس التطبيق: +0.3 كيلوبايت لكل صفحة، 0% تسرب، مكونات أصغر بـ 3 إلى 10 مرات، وتبديل لغة خلال 3-4 مللي ثانية.

    جميع البيانات الخام، والتطبيقات التجريبية، ونصوص الاختبار متاحة في مستودع Benchmark Bloom. يمكنك تشغيلها والتحقق منها بنفسك.

    راجع توثيق 'لماذا Intlayer؟' لمزيد من التفاصيل.

    التعليقات

    لا توجد تعليقات بعد. كن أول من يشارك أفكاره.

    مقالات ذات صلة

    آخر المقالات