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

    Intlayer v9 الجديد - ما الجديد؟

    مرحبًا بكم في Intlayer v9! يمثل هذا الإصدار الرئيسي علامة فارقة ضخمة في تبسيط مسار الترحيل إلى Intlayer من خلال حزم محولات التوافق (Compat Adapter Packages) لمكتبات i18n الرئيسية (react-i18next, next-intl, vue-i18n, إلخ) ويضيف دعمًا لهياكل المحتوى الغنية: المجموعات (Collections) والمتغيرات (Variants).

    جدول المحتويات


    حزم محولات التوافق (Compat Adapter Packages)

    أصبح الترحيل إلى Intlayer من مكتبات i18n الشهيرة أسهل من أي وقت مضى. لقد أنشأنا خمس حزم توافق تعرض نفس واجهات برمجة التطبيقات العامة (public APIs) تمامًا مثل مكتبات i18n القياسية ولكنها تفوض جميع أعمال الترجمة إلى Intlayer في وقت التشغيل (runtime).

    عرض نفس واجهة برمجة التطبيقات العامة (Public API) مع كتابة صارمة (Strict Typing)

    باستبدال عمليات الاستيراد (imports)، تحصل على جميع مزايا Intlayer (بما في ذلك أمان النوع في وقت التجميع (compile-time type safety) مقابل قواميسك الفعلية) بأقل تغييرات في الكود:

    • @intlayer/i18next
    • @intlayer/react-i18next
    • @intlayer/next-intl
    • @intlayer/react-intl
    • @intlayer/next-i18next
    • @intlayer/vue-i18n
    • @intlayer/lingui

    على سبيل المثال، قم ببساطة بتغيير:

    ts
    import { useTranslation } from "react-i18next";

    إلى:

    ts
    import { useTranslation } from "@intlayer/react-i18next";

    ستكون مفاتيحك الآن مكتوبة بشكل صارم (strictly typed) مقابل قواميس Intlayer الخاصة بك، مما يوفر إكمالًا تلقائيًا كاملاً للمسار النقطي (dot-path auto-completion) في بيئة التطوير المتكاملة (IDE) الخاصة بك!

    إضافات اسم مستعار للمجمّع (Bundler Alias Plugins) (Vite, Next.js, Turbopack)

    للسماح بالترحيل دون إعادة كتابة جميع عبارات الاستيراد (import statements) يدويًا، تتضمن كل حزمة محول توافق (compat adapter package) إضافة مجمّع مخصصة (custom bundler plugin) (Vite أو Next.js) ضمن المسار الفرعي /plugin.

    تعيد هذه الإضافات تلقائيًا كتابة عمليات الاستيراد الموجودة (مثل react-i18next أو next-intl) إلى مكافئاتها @intlayer/* في وقت البناء (build time).

    مثال Next.js (Webpack / Turbopack)

    بدلاً من withIntlayer، قم بتغليف إعدادات Next.js الخاصة بك باستخدام إضافة التوافق (compat plugin):

    next.config.ts
    import { createNextI18nPlugin } from "@intlayer/next-i18next/plugin";import type { NextConfig } from "next";const withIntlayer = createNextI18nPlugin();const nextConfig: NextConfig = {};export default withIntlayer(nextConfig);

    مثال Vite (React, Vue, Solid, Svelte)

    vite.config.ts
    import vueI18nVitePlugin from "@intlayer/vue-i18n/plugin";export default defineConfig({  plugins: [vueI18nVitePlugin()],});

    محلل وقت التشغيل المشترك (Mutualized Runtime Resolver)

    توجه جميع محولات التوافق (compat adapters) الآن حل الترجمة من خلال محلل وقت تشغيل واحد ومحسن للغاية: @intlayer/core/messageFormat.

    • رسالة الاستيفاء (Interpolate Message): تحل {{var}} القياسية (مسافات بيضاء ومسارات نقطية)، وسيطات ICU المنسقة ({v, number, percent} إلخ)، وقوالب {var} المجردة.
    • محلل عقدة الرسالة (Message Node Resolver): يحل العقد المتداخلة: insert()، plural() (قواعد الجمع CLDR)، enu() (التعداد)، gender()، علامات HTML، المصفوفات، وعقد الوظائف القابلة للاستدعاء.
    • محلل العلامات المرمزة (Tokenized Tag Parser): يدعم علامات XML/HTML المضمنة والعلامات المرقمة (مثل <1>children</1>) لتشغيل عرض النص الغني (rich-text rendering) بشكل جاهز.

    مواصفات الميزة: المجموعات (Collections) والمتغيرات (Variants)

    يتوسع Intlayer v9 إلى ما هو أبعد من كائنات المفتاح-القيمة الثابتة، مما يسمح للقواميس بالإعلان عن هياكل تخطيط ديناميكية مكتوبة بالكامل من البداية إلى النهاية.

    1. المجموعات (Collections)

    حدد قائمة من العناصر المرتبة التي يديرها نظام إدارة المحتوى (CMS) (مثل الأسئلة الشائعة، المنتجات، أو قوائم المدونات):

    faq.1.content.ts
    import { t, type Dictionary } from "intlayer";export default {  key: "faq",  item: 1,  content: {    question: t({ en: "What is Intlayer?", fr: "Qu'est-ce qu'Intlayer ?" }),    answer: t({ en: "An i18n toolkit.", fr: "Une boîte à outils i18n." }),  },} satisfies Dictionary;
    faq.2.content.ts
    import { t, type Dictionary } from "intlayer";export default {  key: "faq",  item: 2,  content: {    question: t({ en: "Is it free?", fr: "Est-ce gratuit ?" }),    answer: t({ en: "Yes, open-source.", fr: "Oui, open-source." }),  },} satisfies Dictionary;

    الاستخدام:

    ts
    // Fetch all items as an arrayconst allFaqs = useIntlayer("faq"); // -> { question: string, answer: string }[]// Fetch a single item by indexconst faq = useIntlayer("faq", { item: 2 }); // -> { question: string, answer: string }

    2. المتغيرات (Variants)

    قدم اختبارات A/B، رؤوس صفحات موسمية، علامات ميزات (feature flags)، أو صفحات هبوط مخصصة:

    متغيرات النصوص (مثل اختبارات A/B)

    hero.content.ts
    import { t, type Dictionary } from "intlayer";export default {  key: "hero-banner",  variant: "default",  content: {    control: t({ ar: "مرحباً", en: "Welcome", fr: "Bienvenue" }),    black_friday: t({      ar: "تسوق الآن",      en: "Shop now",      fr: "Acheter maintenant",    }),  },} satisfies Dictionary;

    الاستخدام:

    ts
    const banner = useIntlayer("hero-banner", { variant: "black_friday" });

    متغيرات الكائنات (مثل السجلات الديناميكية)

    product.content.ts
    import { t, type Dictionary } from "intlayer";export default {  key: "product-copy",  variant: {    id: "prod_123",    category: "books",  },  content: {    title: t({ ar: "كود نظيف", en: "Clean Code", fr: "Code Propre" }),  },} satisfies Dictionary;

    الاستخدام:

    ts
    // يجلب العنصر المطلوب فقط ديناميكيًا (يتطلب Suspense)const product = useIntlayer("product-copy", {  variant: { id: "prod_123", category: "books" },});

    Vite Plugin: Bundled Compiler & Proxy

    يجمع plugin intlayer() Vite الآن المترجم وبروكسي التوجيه حسب اللغة مباشرة، لذا تحتاج معظم المشاريع إلى plugin واحد فقط في vite.config.ts:

    vite.config.ts
    import { defineConfig } from "vite";import { intlayer } from "vite-intlayer";export default defineConfig({  plugins: [intlayer()],});
    • Compiler: يتم التفعيل تلقائياً عندما يتم ضبط compiler.enabled على true وتكوين مسار compiler.output. لا تحتاج إلى تسجيل intlayerCompiler() بشكل منفصل بعد الآن.
    • Proxy: يتم التفعيل تلقائياً بناءً على خيار routing.enableProxy الجديد (true افتراضياً). يوصل middleware الكشف عن اللغة / إعادة التوجيه / إعادة الكتابة في التطوير والمعاينة وإنتاج SSR. لا تحتاج إلى تسجيل intlayerProxy() بشكل منفصل بعد الآن.

    خيار routing.enableProxy

    خيار routing.enableProxy جديد يتحكم في ما إذا كان proxy التوجيه الخاص باللغة متصلاً. القيمة الافتراضية هي true. قم بتعطيله عندما تريد التعامل مع توجيه اللغة بنفسك:

    intlayer.config.ts
    import type { IntlayerConfig } from "intlayer";const config: IntlayerConfig = {  routing: {    enableProxy: false, // الافتراضي: true  },};export default config;

    تبقى plugins intlayerCompiler() و intlayerProxy() المستقلة مُصدَّرة للإعدادات المتقدمة. تسجيلها جنباً إلى جنب مع intlayer() آمن — كل plugin يزيل التكرار عن نفسه ويعمل مرة واحدة فقط.


    تعطيل المُجمِّع افتراضياً

    اعتباراً من Intlayer v9، المُجمِّع مُعطَّل افتراضياً (أصبحت القيمة الافتراضية لـ compiler.enabled الآن false). لتفعيل استخراج ملفات .content.ts في وقت البناء، اضبط compiler.enabled: true في إعداداتك:

    intlayer.config.ts
    import type { IntlayerConfig } from "intlayer";const config: IntlayerConfig = {  compiler: {    enabled: true, // الافتراضي: false — مطلوب لتفعيل المُجمِّع منذ الإصدار 9    output: ({ fileName }) => `./${fileName}.content.ts`,  },};export default config;

    عندما يكون المُجمِّع مُعطَّلاً، يتخطى Intlayer خطوة الاستخراج في وقت البناء ويعتمد على القواميس التي أعلنت عنها بالفعل. فعِّله فقط عندما تريد أن يقوم plugin المُجمِّع للحزم (@intlayer/swc أو @intlayer/babel أو plugin الـ Vite intlayer()) باستخراج المحتوى تلقائياً.


    React Native: استيرادات من حزمة واحدة

    في تطبيق React Native أو Expo، لم تعد بحاجة إلى التعامل مع كل من react-intlayer وreact-native-intlayer معًا. تقوم حزمة react-native-intlayer الآن بإعادة تصدير واجهة برمجة التطبيقات الكاملة لـ react-intlayer (الخطافات، والأدوات المساعدة، والمسارات الفرعية /format و/html و/markdown)، كما يطبق IntlayerProvider الخاص بها حزم polyfill الخاصة بـ React Native تلقائيًا.

    استورد كل شيء من حزمة react-native-intlayer الواحدة:

    tsx
    import {  IntlayerProvider,  useIntlayer,  useLocale,} from "react-native-intlayer";
    bash
    npm install intlayer react-native-intlayer
    الاستيراد من react-intlayer لا يزال يعمل، لكن react-native-intlayer أصبح الآن نقطة الدخول الواحدة الموصى بها لـ React Native — يشحن موفره حزم polyfill التي لا يتضمنها موفر react-intlayer الموجه للويب.

    React Native: استيراد من حزمة واحدة

    في تطبيق React Native أو Expo، لم تعد بحاجة إلى التوفيق بين react-intlayer و react-native-intlayer. تقوم حزمة react-native-intlayer الآن بإعادة تصدير واجهة برمجة تطبيقات react-intlayer بالكامل (الخطافات "hooks"، والأدوات، والمسارات الفرعية /format و /html و /markdown)، ويقوم IntlayerProvider الخاص بها بتطبيق polyfills الخاصة بـ React Native تلقائيًا.

    قم باستيراد كل شيء من حزمة react-native-intlayer الفردية:

    tsx
    import {  IntlayerProvider,  useIntlayer,  useLocale,} from "react-native-intlayer";
    bash
    npm install intlayer react-native-intlayer
    الاستيراد من react-intlayer يظل يعمل، ولكن react-native-intlayer هي الآن نقطة الدخول الفردية الموصى بها لـ React Native — حيث يوفر المزود الخاص بها polyfills التي لا يوفرها المزود الموجه للويب react-intlayer.

    CMS SDK: استخدم Intlayer كقاعدة بيانات محتوى headless

    يأتي Intlayer v9 مع SDK نظيف وذاتي المصادقة في @intlayer/api للتفاعل مع نظام إدارة المحتوى (CMS) برمجيًا — جلب المشاريع، وجلب القواميس، ودفعها أو تحديثها من خادمك أو سكربتاتك أو CI الخاص بك. تتم المصادقة (OAuth2 client_credentials) وتجديدها نيابةً عنك.

    تم تقسيم SDK إلى عمليتي استيراد منفصلتين بحيث تتضمن حزمتك فقط النطاقات التي تستخدمها فعليًا:

    1. createIntlayerCMSمُصادِق خفيف يحتفظ ببيانات الاعتماد والرمز المُدار (دون تضمين أي عميل نطاق).
    2. dictionaryEndpoint، projectEndpoint، … — روابط نقاط نهاية لكل نطاق، يُستورد كل منها من مساره الفرعي الخاص.
    cms.ts
    import { createIntlayerCMS } from "@intlayer/api";import { dictionaryEndpoint } from "@intlayer/api/dictionary";// الإعداد اختياري: تعود بيانات الاعتماد إلى INTLAYER_CLIENT_ID /// INTLAYER_CLIENT_SECRET المُحلَّلة بواسطة `@intlayer/config/built`.const cms = createIntlayerCMS();// قراءةconst { data: dictionaries } = await dictionaryEndpoint(cms).getDictionaries();// كتابة — استخدم نظام إدارة المحتوى مثل قاعدة بياناتawait dictionaryEndpoint(cms).pushDictionaries([myDictionary]);
    الأمان: تمنح بيانات اعتماد نظام إدارة المحتوى صلاحية الكتابة على محتواك. أنشئ المُصادِق دائمًا على الخادم فقط — لا ترسل أبدًا clientId / clientSecret إلى المتصفح.

    الاستضافة الذاتية (Self-Hosting)

    يدعم Intlayer v9 دعمًا أصليًا لتشغيل نسختك الخاصة من Intlayer بأمر واحد — دون الحاجة إلى حساب Intlayer Cloud.

    sh
    curl -fsSL https://intlayer.org/install.sh | sh

    يقوم المثبّت بتنزيل ملف docker-compose.yml وملف .env، ويولّد الأسرار المطلوبة تلقائياً، ويشغّل docker compose up -d. كل شيء — لوحة التحكم، وواجهة برمجة التطبيقات، وقاعدة البيانات، وتخزين الكائنات، والبريد الإلكتروني التفاعلي — يعمل محلياً داخل حاويات.

    الخدمات المتضمنة

    الخدمة الغرض
    app (TanStack Start) واجهة لوحة التحكم على المنفذ 3000
    backend (Fastify/Bun) واجهة برمجة تطبيقات REST على المنفذ 3100
    MongoDB 7 (مجموعة نسخ متماثلة أحادية العقدة) قاعدة البيانات الرئيسية
    Redis 7 قوائم انتظار المهام والتخزين المؤقت
    MinIO تخزين كائنات متوافق مع S3 (الصور الرمزية، لقطات الشاشة)
    Mailpit خادم SMTP محلي + واجهة ويب للبريد الإلكتروني التفاعلي على المنفذ 8025

    يتم تضمين Chromium (المستخدم لتوليد لقطات الشاشة عبر Puppeteer) داخل صورة الخادم الخلفي — دون الحاجة إلى حاوية إضافية.


    ملاحظات الترحيل من الإصدار 8

    إذا كنت تقوم بالترقية من الإصدار 8، لاحظ أن الإصدار 9 لا يتضمن تغييرات جذرية (breaking changes). ولكن إليك التغييرات الرئيسية:

    • تعطيل المُجمِّع افتراضياً: أصبحت القيمة الافتراضية لـ compiler.enabled الآن false. إذا كنت تعتمد على استخراج ملفات .content.ts في وقت البناء، فاضبط compiler.enabled: true في ملف intlayer.config.ts.
    • اللغات واللهجات (Locales & Dialects): إذا كنت تستخدم تبعيات i18n خارجية، أضف إضافات محول التوافق (compat adapter plugins) الخاصة بها في إعداداتك أو إعداد المجمّع (bundler setup) لإعادة كتابة عمليات الاستيراد (imports) تلقائيًا.
    • المحددات المخصصة (Custom Selectors): عند استدعاء useIntlayer، تم حجز المعامل الثاني الآن لكائن خيارات يحتوي على { locale, item, variant }. إذا كنت قد مررت سابقًا سلسلة لغة (locale string) مباشرة، فلا يزال بإمكانك القيام بذلك، ولكن يوصى باستخدام كائن الخيارات للاختيارات المتقدمة.

    روابط مفيدة