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

    إضافة ESLint x OXLint

    تلتقط eslint-plugin-intlayer أنواع أخطاء التدويل (i18n) التي لا يستطيع TypeScript اكتشافها:

    1. النصوص المكتوبة يدويًا (Hardcoded text) التي لم يتم نقلها إلى القاموس مطلقًا.
    2. الاستدعاءات الديناميكية التي تجتاز فحص الأنواع وتعمل، لكن مترجم Intlayer لا يمكنه تحسينها.
    3. المحتوى غير المستخدم (Dead content) — القواميس والحقول التي لا يقرأها أي شيء في المشروع (اختياري بالطلب).

    المفاتيح غير المعروفة ومسارات الحقول غير المعروفة واللغات المفقودة هي بالفعل أخطاء تجميع، لذا لا تعيد الإضافة تكرارها.

    التثبيت

    bash
    npm install --save-dev eslint-plugin-intlayer

    تتطلب الإصدار 9 من ESLint أو أحدث (flat config). ESLint 10 مدعوم.

    الاستخدام

    تعمل الإضافة في كل من ESLint و oxlint — بنفس القواعد ونفس الخيارات.

    أو انشر أحد الإعدادات وحدّد مستويات الخطورة بنفسك:

    الإعدادات المسبقة (Configs)

    الإعداد no-raw-text static-dictionary-key no-dynamic-field-access enforce-adapter-import no-unused-content
    recommended warn error error off off
    strict error (+ نصوص خارج JSX) error error error off
    contract-only off error error off off

    يحتفظ recommended بـ no-raw-text عند مستوى warn عمدًا: توجيهه إلى قاعدة تعليمات برمجية حالية يُظهر جميع النصوص غير المترجمة دفعة واحدة، وهو ما لا ينبغي أن يعطل عملية البناء من اليوم الأول.

    enforce-adapter-import معطلة افتراضيًا — قم بتمكينها بشكل صريح إذا أردت ذلك.

    no-unused-content معطلة في كل الإعدادات، بما في ذلك strict. إنها القاعدة الوحيدة التي تقرأ إعدادات Intlayer وتفحص ملفات المصدر من القرص، لذا يجب أن يكون تفعيلها خيارًا مقصودًا بدلاً من شيء يتم تفعيله تلقائيًا.

    القواعد

    no-raw-text

    تبلغ عن النصوص الموجهة للمستخدم غير المصرح بها في القاموس. تستخدم نفس آلية الكشف مثل intlayer extract، لذلك يتم تجاهل أسماء العلامات التجارية وفئات CSS والمعرفات التقنية.

    jsx
    // ✗ تم الإبلاغ عنه<h1>Welcome to our documentation</h1><input placeholder="Enter your email address" />// ✓ سليمconst { title } = useIntlayer("home");<h1>{title}</h1>

    يتم تخطي ملفات الإعلان عن المحتوى (*.content.ts, …).

    لإصلاح ملف بالكامل مرة واحدة، قم بتشغيل npx intlayer extract ودع المترجم ينقل النصوص إلى قاموس نيابة عنك.

    الخيارات

    static-dictionary-key

    تتطلب أن يكون مفتاح القاموس سلسلة نصية صريحة (string literal).

    لا يمكن للمترجم تحميل القاموس مسبقًا إلا عندما يتمكن من قراءة المفتاح مباشرة في موقع الاستدعاء. عند استخدام مفتاح محسوب، يتخطى التحسين بصمت ويقوم بحزم جميع القواميس بدلاً من ذلك.

    typescript
    // ✗ تم الإبلاغ عنهuseIntlayer(dictionaryKey);useIntlayer(`home-${suffix}`);getTranslations({ namespace: page });// ✗ المتغير لا يزال ليس قيمة صريحةconst key = "home";useIntlayer(key);// ✓ سليمuseIntlayer("home");getTranslations({ namespace: "home" });

    ينطبق هذا على useIntlayer و getIntlayer وجميع محولات التوافق (useTranslation, useTranslations, formatMessage, <FormattedMessage id>, <Trans i18nKey>, …).

    no-dynamic-field-access

    تتطلب أن يكون الحقل الذي تقرأه من القاموس معروفًا بشكل ثابت.

    يقوم المترجم بإزالة الحقول التي لا يرى أنها مستخدمة. الوصول الديناميكي غير مرئي بالنسبة له، وبالتالي قد تُرجع القراءة undefined أثناء التشغيل.

    typescript
    // ✗ تم الإبلاغ عنهconst content = useIntlayer("home");content[fieldName];const t = useTranslations("home");t(messageKey);// ✓ سليمcontent.title;content["title"];content.items[0];t("hero.title");

    enforce-adapter-import

    تفضل استخدام محول التوافق @intlayer/* على الحزمة الأصلية. لا يتم حل الحزمة الأصلية إلى Intlayer إلا عند تكوين الاسم المستعار في أداة التجميع؛ بينما يعمل المحول دائمًا. قابلة للإصلاح التلقائي باستخدام --fix.

    typescript
    // ✗ تم الإبلاغ عنهimport { useTranslation } from "react-i18next";import { getTranslations } from "next-intl/server";// ✓ سليمimport { useTranslation } from "@intlayer/react-i18next";import { getTranslations } from "@intlayer/next-intl/server";

    no-unused-content

    معطلة افتراضيًا. تبلغ عن المحتوى الذي لا يقرأه أي شيء في مشروعك، بالإضافة إلى مفاتيح القاموس المصرح بها في أكثر من مكان.

    src/home.content.ts
    export default {  key: "home", // ✗ يتم الإبلاغ عنه إذا لم يطلب أي مستدعي "home" في المشروع  content: {    title: t({ ar: "العنوان", en: "Title" }),    // ✗ يتم الإبلاغ عنه عندما لا يقرأ أي شيء `hero`    hero: {      subtitle: t({ ar: "العنوان الفرعي", en: "Subtitle" }),    },  },};

    على عكس القواعد الأخرى، لا يمكن لهذه القاعدة الإجابة من الملف الحالي فقط — فالحقل يعتبر غير مستخدم بالنسبة للمشروع بأكمله فقط. عند أول إعلان محتوى في فحص الفاحص، تقوم بتحميل تكوين Intlayer الخاص بك، وفحص ملفات المصدر التي يعلن عنها التكوين (build.traversePattern, compiler.transformPattern)، وتشغيل نفس محلل الاستخدام الذي يشغل @intlayer/lsp والخط المشطوب "غير مستخدم" في إضافة VS Code. يتم تخزين النتيجة مؤقتًا لمدى cacheTtl مللي ثانية، بحيث يتم الفحص مرة واحدة لكل تشغيل بدلاً من مرة واحدة لكل ملف.

    الخيارات

    قم بتقليل cacheTtl عند الفحص من خادم محرر طويل الأمد وتريد أن تظهر تعديلاتك بشكل أسرع؛ قم بتعيين baseDir عندما يمتد فحص واحد عبر عدة مشاريع Intlayer في مستودع موحد (monorepo).

    تميل إلى التزام الصمت. الإيجابية الخاطئة هنا تحذف ترجمة، لذا لا يتم الإبلاغ عن أي شيء عند استهلاك القاموس بطريقة لا يمكن للتحليل تتبعها: تمرير كائن المحتوى ككل، دالة ترجمة مرتبطة به (const t = useTranslations("home"))، إعلان تم الوصول إليه من خلال استيراد مباشر (useDictionary(myDictionary))، استخدام nest() من قاموس آخر، أو قائمة حقول غير شاملة بسبب استخدام عامل النشر (spread). يتم احتساب مكونات الملف الواحد (.vue, .svelte, .astro) على أنها تستخدم كل حقل من القواميس المذكورة لأن كتل البرمجة النصية الخاصة بها لا يتم تحليلها هنا.

    تقرأ reportDuplicateKeys القواميس غير المدمجة التي يكتبها البناء تحت .intlayer/، لذا تظل هادئة حتى يتم بناء المشروع مرة واحدة على الأقل. يتم دمج إعلانين يشتركان في نفس المفتاح وهو نمط مشروع — يوجد التقرير لأن حقلاً محددًا على كلا الجانبين يحتفظ بصمت بقيمة واحدة فقط من القيمتين.

    يتم تحميل المحلل من @intlayer/lsp، والذي يتم توزيعه كـ ESM. وبالتالي تتطلب القاعدة إصدار Node قادرًا على تنفيذ require() لوحدة ES — مثل Node 20.19+ أو 22.12+. في أي إصدار أقدم، لا تبلغ عن شيء بدلاً من التسبب في فشل الفحص.

    أطر العمل (Frameworks)

    تعمل كل قاعدة عبر جميع تكاملات Intlayer، بما في ذلك داخل قوالب Vue و Svelte و Angular. ما عليك سوى إخبار ESLint بالمحلل الذي يقرأ كل نوع ملف.

    إطار العمل الملفات المحلل (Parser)
    React, Preact, Solid, Lit .jsx .tsx typescript-eslint
    Next.js .jsx .tsx typescript-eslint
    Vue, Nuxt .vue vue-eslint-parser
    Svelte, SvelteKit .svelte svelte-eslint-parser
    Angular .ts typescript-eslint
    قوالب Angular .component.html @angular-eslint/template-parser
    Astro .astro astro-eslint-parser

    قم بتثبيت المحللات التي يحتاجها مشروعك فقط.

    قيد معروف. في قوالب Vue و Angular، التعبير مثل {{ content[key] }} لا يتم فحصه بواسطة no-dynamic-field-access. يتم التقاط القراءات الديناميكية المكتوبة داخل كتلة البرمجة النصية كالمعتاد.