استخدم مساعدك المفضل للملخص واستخدم هذه الصفحة والموفر AI الذي تريده
تاريخ الإصدارات
- "النسخة الأولية"v9.5.1026/9/2026
تمت ترجمة محتوى هذه الصفحة باستخدام الذكاء الاصطناعي.
اعرض آخر نسخة المحتوى الأصلي باللغة الإنكليزيةإذا كان لديك فكرة لتحسين هذه الوثيقة، فلا تتردد في المساهمة من خلال تقديم طلب سحب على GitHub.
رابط GitHub للتوثيقنسخ الـ Markdown من المستند إلى الحافظة
كيفية تدويل تطبيق TanStack Start الخاص بك باستخدام Lingui في عام 2026
جدول المحتويات
ما هو Lingui؟
Lingui هي مكتبة تدويل (i18n) مصممة حول وحدات الماكرو (macros) واستخراج الرسائل (message extraction). تكتب النص المصدر مباشرة داخل مكوناتك ( t`Hello` ، <Trans>Hello</Trans>)، ويقوم أمر lingui extract بجمع كل رسالة في كتالوجات (ملفات PO افتراضياً)، ويقوم المترجمون بملئها، ثم يترجمها مكون Vite الإضافي إلى كود JavaScript مدمج ومضغوط. تستخدم الرسائل تنسيق ICU MessageFormat، لذا فإن صيغ الجمع والاختيارات مدعومة بالكامل.
لا يأتي TanStack Start مع طبقة تدويل مدمجة، لذلك يربط هذا الدليل Lingui به من البداية:
- وحدات ماكرو مجمعة بواسطة Babel من خلال
@rolldown/plugin-babel(مطلوب مع@vitejs/plugin-reactv6 و Vite 8). - توجيه اللغات مع مقطع اختياري
{-$locale}(مثل/about،/fr/about). - كتالوج واحد لكل لغة، يتم تحميله عند الطلب، ونسخة
I18nخاصة بكل عملية تصيير حتى لا تتشارك طلبات SSR المتزامنة في نفس اللغة مطلقاً. - تحسين محركات البحث متعدد اللغات بشكل كامل (SEO): وسم
<title>ووصف مترجم، عنوان URL أساسي (canonical URL)، وسومhreflangمعx-default، لغات Open Graph، بيانات JSON-LD، خريطة الموقع (sitemap)، ملفrobots.txt، التصيير المسبق (pre-rendering) وصفحات 404 مخصصة لكل لغة.
هل تبحث عن حزمة تقنية أخرى؟ راجع دليل TanStack Start + use-intl، أو دليل TanStack Start + Paraglide، أو دليل TanStack Start + Intlayer.
هل تستخدم Next.js؟ راجع دليل Next.js + Lingui. هل تقارن بين المكتبات؟ اقرأ Lingui مقابل Intlayer.
ماذا يقول اختبار الأداء المقارن عن Lingui على TanStack Start
يقوم اختبار الأداء المقارن للتدويل (i18n benchmark) بتشغيل نفس تطبيق TanStack Start المكون من 10 صفحات و 10 لغات مع كل مكتبة رئيسية ويقيس ما يقوم المتصفح بتنزيله بالفعل.
تحميل JSON الديناميكي
تحميل الترجمات ببطء في وقت التشغيل
JSON المحدد (أسماء المحيط)
مساحات أسماء الترجمة لكل صفحة
مقياس أداء I18n
ما هو هذا المقياس؟
الحجم الإجمالي المضغوط بتنسيق gzip لحزمة مكتبة التدويل. وهي تتضمن فقط المزود ومنطق استرداد المحتوى بعد تقليل الحجم (tree-shaking) والضغط (minification).
لماذا هو مهم؟
يقلل حجم المكتبة الأصغر من حمولة JavaScript الأولية، مما يؤدي إلى سرعة التنزيل وأوقات التنفيذ على العميل.
عرض كـ
الأرقام الرئيسية لحزمة @lingui/core@6.6.0، المقاسة بتاريخ 2026-09-26 (gzip):
افتح الجدول في نافذة منبثقة لعرض جميع محتويات البيانات بوضوح
| الإعداد | حجم المكتبة | حجم JS لكل صفحة | تسريب اللغات الأخرى | تسريب الصفحات الأخرى |
|---|---|---|---|---|
| بدون تدويل (التطبيق الأساسي) | - | 111.0 KB | 0% | 0% |
| Lingui (إعداد هذا الدليل) | 56.7 KB | 115.2 KB | 9.3% | 0% |
@intlayer/lingui (التوافق) | 9.8 KB | 136.7 KB | 9.9% | 0% |
react-intlayer (Intlayer الأصلي) | 4.5 KB | 126.8 KB | 0% | 0% |
النقاط الأساسية المستفادة:
- قم بتحميل كتالوج واحد لكل لغة، عند الطلب. يحافظ ذلك على حجم الصفحات قريباً من حجم التطبيق الأساسي.
- وقت التشغيل يظل كبيراً وثقيلاً (~57 كيلوبايت gzip). محول التوافق
@intlayer/lingui(الخطوة 16) يحتفظ بوحدات الماكرو الخاصة بك ويقلل حجمه إلى ~10 كيلوبايت.
اطلع على البيانات الكاملة: تقرير اختبار أداء TanStack Start، ومستودع اختبار الأداء.
مقارنة الميزات على TanStack Start
كيف يقارن Lingui بالمكتبات الأخرى شائعة الاستخدام في TanStack Start:
افتح الجدول في نافذة منبثقة لعرض جميع محتويات البيانات بوضوح
| الميزة | react-intlayer (Intlayer) | use-intl | Paraglide JS | Lingui |
|---|---|---|---|---|
| الترجمات بجانب المكونات | ✅ في نفس الموضع (Co-located) | ❌ ملف JSON مركزي | ❌ ملف JSON واحد لكل لغة | ⚠️ النص المصدر داخل المكونات |
| التكامل مع TypeScript | ✅ أنواع منشأة تلقائياً | ✅ عبر AppConfig | ✅ دوال رسائل محددة النوع | ⚠️ وحدات ماكرو فقط |
| اكتشاف الترجمات المفقودة | ✅ أخطاء أثناء فحص الأنواع وتحذيرات بناء | ⚠️ استرجاع احتياطي في وقت التشغيل | ⚠️ الرجوع إلى اللغة الأساسية | ⚠️ الرجوع إلى النص المصدر |
| المحتوى الغني (JSX, Markdown) | ✅ دعم مباشر | ⚠️ وسوم عبر t.rich | ⚠️ نصوص فقط | ✅ JSX داخل <Trans> |
| التوجيه المترجم للغات | ✅ مدمج | ❌ يدوي عبر {-$locale} | ✅ urlPatterns + إعادة كتابة الموجه | ❌ يدوي عبر {-$locale} |
| تبديل اللغة بدون إعادة تحميل | ✅ نعم | ✅ نعم | ❌ إعادة تحميل الصفحة بالكامل | ✅ نعم |
| صيغ الجمع (Pluralization) | ✅ معتمد على التعداد | ✅ ICU | ✅ متغيرات (Variants) | ✅ ICU |
| ICU MessageFormat | ✅ عبر format: "icu" | ✅ أصلي | ⚠️ عبر إضافة inlang | ✅ أصلي |
| تنسيقات المحتوى | ✅ .ts, .json, .md, .yaml... | ⚠️ .json | ⚠️ inlang JSON | ✅ PO, JSON, CSV |
| الترجمة بالذكاء الاصطناعي | ✅ المزود والمفتاح الخاص بك | ❌ لا | ❌ لا | ❌ لا |
| المحرر المرئي / CMS | ✅ محرر محلي + CMS اختياري | ❌ منصات خارجية | ⚠️ تطبيقات منظومة inlang | ❌ منصات خارجية |
| أدوات مساعدة لـ SEO (hreflang, sitemap) | ✅ مدمج | ❌ يدوي | ⚠️ عناوين URL مترجمة، والباقي يدوي | ❌ يدوي |
| حجم وقت التشغيل (gzip, benchmark) | 4.5 KB | 75.9 KB | 1.8 KB | 56.7 KB |
| التسريب، أفضل إعداد (لغة / صفحة) | 0% / 0% | 0% / 0% | 49.7% / 0% | 8.6% / 0% |
| الترجمات المفقودة في CI | ✅ npx intlayer test | ⚠️ غير مدمج | ⚠️ غير مدمج | ✅ lingui compile --strict |
أرقام حجم وقت التشغيل ونسبة التسريب مأخوذة من اختبار أداء TanStack Start. يتم قياس التسريب بناءً على أفضل إعداد لكل مكتبة.
أدلة أخرى لـ TanStack Start: use-intl، وParaglide JS، وIntlayer.
ممارسات يجب عليك اتباعها
- قم بضبط
langوdirفي وسم<html>من لغة المسار، بحيث تكون صحيحة في كود HTML المُنشأ على الخادم. - احتفظ بعنوان URL واحد لكل لغة باستخدام بادئة، بحيث تكون كل نسخة لغوية قابلة للفهرسة.
- أنشئ نسخة
I18nواحدة لكل لغة، ولا تقم أبداً بتعديل نسخة عامة مشتركة أثناء SSR: حيث يمكن لطلبين متزامنين الكتابة فوق لغة بعضهما البعض. - قم بتحميل الكتالوج النشط فقط، ولا تستورد جميع الكتالوجات دفعة واحدة في كود العميل.
- اختر أسلوب ماكرو واحداً (
useLingui+tفي المكونات، وmsgللواصفات الكسولة) والتزم به. خلطtوi18n._وi18n.tو<Trans>يجعل الكود أكثر صعوبة في القراءة للمطورين ومساعدي الذكاء الاصطناعي. - قم بتشغيل
lingui extractفي CI حتى لا يتم شحن رسالة جديدة أبداً دون ترجمة. - ترجم بياناتك الوصفية (Metadata)، وأعلن عن
canonicalوhreflangوx-defaultفي كل صفحة. - أنشئ ملف sitemap و robots.txt متعددي اللغات، وقم بالتصيير المسبق لكل لغة.
- استخدم روابط حقيقية لمبدل اللغات، حتى تتمكن برامج الزحف من اكتشاف كل لغة.
راجع دليلنا حول التدويل وتحسين محركات البحث (SEO) ودليل hreflang.
دليل خطوة بخطوة لإعداد Lingui في تطبيق TanStack Start
إليك هيكل المشروع الذي سنقوم بإنشائه:
نسخ الكود إلى الحافظة
تثبيت التبعيات
bashنسخ الكودنسخ الكود إلى الحافظة
- @lingui/core / @lingui/react: وقت التشغيل،
I18nProviderووحدات الماكرو (@lingui/core/macro،@lingui/react/macro). - @lingui/cli: أمر
lingui extractلجمع الرسائل في كتالوجات. - @lingui/vite-plugin: يقوم بتجميع كتالوجات
.poعند الاستيراد، لذلك لا يلزم تشغيلlingui compile. - @lingui/babel-plugin-lingui-macro + @rolldown/plugin-babel: لتحويل وحدات الماكرو في وقت البناء.
- @lingui/core / @lingui/react: وقت التشغيل،
مركزية إعدادات اللغات
تظل اللغة الافتراضية بدون بادئة (
/about)، بينما تحصل اللغات الأخرى على بادئة (/fr/about).src/i18n/config.tsنسخ الكودنسخ الكود إلى الحافظة
تكوين Lingui
يعيد تكوين Lingui استخدام نفس قائمة اللغات، بحيث لا يحدث أي تعارض بين الكتالوجات والموجه وخريطة الموقع.
lingui.config.tsنسخ الكودنسخ الكود إلى الحافظة
أضف نصوص الاستخراج البرمجية (extraction scripts):
package.jsonنسخ الكودنسخ الكود إلى الحافظة
يفشل أمر
i18n:checkفي CI إذا كان أحد المكونات يحتوي على رسالة لم يتم استخراجها وتضمينها في الـ commit.تكوين Vite
مع
@vitejs/plugin-reactv6، لم يعد Babel مدمجاً بشكل افتراضي. يقوم@rolldown/plugin-babelبتشغيل إضافة ماكرو Lingui، وتعالجlinguiTransformerBabelPresetفقط الملفات التي تستورد وحدات ماكرو، مما يحافظ على سرعة عمليات البناء.vite.config.tsنسخ الكودنسخ الكود إلى الحافظة
تحميل الكتالوجات لكل لغة
تتيح السلسلة النصية القالبية (template literal) داخل
import()لـ Vite إنشاء مقطع برمجي (chunk) منفصل لكل كتالوج، وتقوم إضافة Lingui بتجميع ملف.poبداخله. يقوم الزائر باللغة الفرنسية بتنزيل الكتالوج الفرنسي فقط.الرسائل المجمعة هي بيانات عادية، لذا يمكن إرجاعها بواسطة محمل المسار (route loader)، وتسلسلها داخل كود HTML، وإعادة استخدامها عند الترطيب (hydration).
src/i18n/lingui.tsنسخ الكودنسخ الكود إلى الحافظة
لكي يقبل TypeScript استيراد ملفات
.po، أعلن عن الوحدة مرة واحدة:src/i18n/po.d.tsنسخ الكودنسخ الكود إلى الحافظة
إنشاء المستند الجذري (Root Document)
يقرأ المسار الجذري معلمة اللغة الاختيارية لضبط
langوdirعلى وسم<html>المُصيّر على الخادم.src/routes/__root.tsxنسخ الكودنسخ الكود إلى الحافظة
إنشاء مسار تخطيط اللغة (Locale Layout Route)
يُنشئ المجلد
{-$locale}مقطع مسار اختياري: يتطابق كل من/aboutو/fr/aboutمع/{-$locale}/about. يرفض التخطيط البادئات غير المعروفة، ويحمل كتالوج اللغة الحالية، ويوفر نسخةI18nمخصصة.src/routes/{-$locale}/route.tsxنسخ الكودنسخ الكود إلى الحافظة
استخدام الترجمات في صفحاتك
اكتب النص المصدر داخل المكون. تحوله وحدات الماكرو إلى معرّفات رسائل في وقت البناء، ويلتقطه أمر
lingui extract.<Trans>لمحتوى JSX، بما في ذلك العناصر المتداخلة؛useLingui().tللنصوص العادية (الخصائص والسمات)؛<Plural>لصيغ الجمع بتنسيق ICU.
src/routes/{-$locale}/about.tsxنسخ الكودنسخ الكود إلى الحافظة
يتم تخزين الاستيراد الديناميكي
import()للكتالوج مؤقتاً بواسطة نظام الوحدات، لذلك فإن استدعاءloadI18nفي عدة محملات لا يعيد تنزيل الكتالوج مرتين.استخراج وترجمة رسائلك
قم بتشغيل عملية الاستخراج. يكتب Lingui كل رسالة في كتالوج كل لغة:
bashنسخ الكودنسخ الكود إلى الحافظة
ثم قم بترجمة حقل
msgstrلكل مدخل:src/locales/fr/messages.poنسخ الكودنسخ الكود إلى الحافظة
src/locales/es/messages.poنسخ الكودنسخ الكود إلى الحافظة
افتراضياً، تكون معرّفات الرسائل عبارة عن تجزئة (hash) للنص المصدر: يؤدي تغيير النص الإنجليزي إلى إنشاء رسالة جديدة. استخدم معرّفات صريحة (
<Trans id="about.title">About us</Trans>) للنصوص التي تتغير بشكل متكرر.بناء مكون رابط مترجم (Localized Link)
اختيارييعيش كل مسار تحت
{-$locale}، لذلك يجب أن تحمل الروابط معلمة اللغة الحالية.src/components/LocalizedLink.tsxنسخ الكودنسخ الكود إلى الحافظة
تغيير لغة المحتوى الخاص بك
اختياريقم بإنشاء مبدل اللغة كـ روابط، حتى تجد برامج الزحف جميع الإصدارات اللغوية. يُبقي
to="."على الصفحة الحالية ويستبدل معلمة اللغة. يقوم محمل تخطيط اللغة بعد ذلك بجلب الكتالوج الجديد.src/components/LocaleSwitcher.tsxنسخ الكودنسخ الكود إلى الحافظة
تدويل بياناتك الوصفية (Metadata)
اختيارييمكن لكل إصدار لغوي أن يتصدر نتائج البحث بشكل مستقل، شريطة أن تكشف كل صفحة عن وسم
<title>ووصف مترجمين، ورابط أساسي يشير إلى نفسه (self-referencing canonical)، ورابطhreflangواحد لكل لغة بالإضافة إلىx-default، ولغات Open Graph، وبيانات JSON-LD معinLanguage. تتم ترجمة البيانات الوصفية في المحمل (الخطوة 8)، وتبني هذه الدالة المساعدة بقية العناصر:src/i18n/seo.tsنسخ الكودنسخ الكود إلى الحافظة
تدويل خريطة الموقع (Sitemap) وملف robots.txt
اختياريتسرد خريطة الموقع كل عنوان URL لكل لغة، ويعلن كل مدخل عن جميع بدائله باستخدام
xhtml:link. يحظر ملفrobots.txtالمسارات الخاصة في كل لغة ويشير إلى خريطة الموقع. احذفpublic/robots.txtإذا كان قالب البداية قد أنشأ واحداً.src/routes/sitemap[.]xml.tsنسخ الكودنسخ الكود إلى الحافظة
src/routes/robots[.]txt.tsنسخ الكودنسخ الكود إلى الحافظة
التصيير المسبق لكل لغة (Pre-render Every Locale)
اختياريقم بإدراج كل مسار مترجم حتى يقوم TanStack Start بالتصيير المسبق لجميع الإصدارات اللغوية في وقت البناء:
vite.config.tsنسخ الكودنسخ الكود إلى الحافظة
إعادة توجيه الزوار لأول مرة ومعالجة صفحات 404
اختيارييقوم وسيط الطلبات (request middleware) بتوجيه الزائر الذي يدخل على
/إلى لغته المفضلة (ملف تعريف الارتباط أولاً، ثمAccept-Language). لا تتم إعادة توجيه الروابط العميقة أبداً، بحيث تحصل برامج الزحف وعناوين URL المشتركة دائماً على الصفحة المطلوبة بدقة.src/i18n/negotiateLocale.tsنسخ الكودنسخ الكود إلى الحافظة
src/start.tsنسخ الكودنسخ الكود إلى الحافظة
بالنسبة لصفحات 404، يقوم مسار شامل (catch-all) بتصيير
notFoundComponentالمترجم الخاص بالتخطيط. ضع عليه علامةnoindex: حيث يقوم React 19 برفع وسم<meta>تلقائياً إلى داخل<head>.src/components/NotFound.tsxنسخ الكودنسخ الكود إلى الحافظة
src/routes/{-$locale}/$.tsxنسخ الكودنسخ الكود إلى الحافظة
احتفظ بوحدات الماكرو الخاصة بك وخفف وقت التشغيل باستخدام Intlayer
اختيارييحافظ محول التوافق
@intlayer/linguiعلى الكود المصدري دون أي تعديل: يتم تجميع وحدات الماكرو تماماً كما كانت من قبل، وتتم خدمة استدعاءاتi18n._()وuseLingui()و<Trans>الناتجة عن طريق قواميس Intlayer المجمعة. في اختبار الأداء، ينخفض وقت التشغيل من ~56.7 كيلوبايت إلى ~9.8 كيلوبايت gzip.bashنسخ الكودنسخ الكود إلى الحافظة
أضف الإضافة بعد تحويل الماكرو، بحيث يتم توجيه
@lingui/coreو@lingui/reactبالاسم المستعار (alias) إلى المحول:vite.config.tsنسخ الكودنسخ الكود إلى الحافظة
تتم مزامنة الكتالوجات باستخدام إضافة مزامنة JSON (كتالوجات JSON) أو إضافة مزامنة PO (كتالوجات PO). راجع الإعداد الكامل في دليل توافق Lingui، والمقارنة المفصلة في Lingui مقابل @intlayer/lingui.
أتمتة ترجماتك باستخدام Intlayer
اختيارييقوم Lingui باستخراج الرسائل، ولكن ملء عشرات الكتالوجات يدوياً هو ما يستهلك معظم الوقت. Intlayer مجاني ومفتوح المصدر، وتعمل أدواته جنباً إلى جنب مع Lingui:
- الترجمة باستخدام الذكاء الاصطناعي باستخدام مفتاح API والمزود الخاص بك. راجع الملء التلقائي (auto fill) وواجهة سطر الأوامر (CLI).
- الاحتفاظ بملفات PO كمصدر وحيد للحقيقة باستخدام إضافة مزامنة PO.
- اختبار الترجمات المفقودة في CI. راجع اختبار ترجماتك.
- تدقيق موقعك المنشور للتحقق من عدم وجود
hreflangمفقود أو روابط أساسية غير صحيحة أو تسريب للغات باستخدام أمر scan.
الأسئلة الشائعة
نعم. لا يحتوي Lingui على تكامل مخصص لـ TanStack Start، ولكن إضافة Vite وإضافة ماكرو Babel تعملان كما هما. النقطتان الأساسيتان اللتان يجب ضبطهما هما تشغيل وحدات الماكرو عبر @rolldown/plugin-babel (لم يعد Vite 8 و @vitejs/plugin-react v6 يشتملان على Babel)، وإنشاء نسخة I18n منفصلة لكل لغة بدلاً من تفعيل نسخة عامة واحدة أثناء SSR.
على الخادم، تعالج عملية واحدة العديد من الطلبات في نفس الوقت. يؤدي استدعاء i18n.activate("fr") على كائن مشترك إلى تبديل لغة طلب آخر يتم تصييره باللغة الإنجليزية بالتوازي. ينشئ setupI18n نسخة معزولة لكل لغة، وهو أمر آمن ومضمون.
لا. تقوم إضافة @lingui/vite-plugin بتجميع كتالوجات .po تلقائياً عند استيرادها. تحتاج فقط إلى تشغيل lingui extract لجمع الرسائل الجديدة.
أعلن عنها باستخدام ماكرو msg، وترجمها في محمل المسار (route loader) باستخدام i18n._(msg`...`). يُرجع المحمل نصوصاً عادية، بحيث تظل دالة head() متزامنة ويتم تسلسل القيم للترطيب. توضح الخطوة 8 والخطوة 12 الإعداد الكامل.
يقيس اختبار الأداء حوالي ~56.7 كيلوبايت gzip لوقت التشغيل. مع تحميل كتالوج واحد لكل لغة عند الطلب، تزن الصفحات حوالي ~115 كيلوبايت مقارنة بـ 111 كيلوبايت بدون تدويل. يؤدي استيراد جميع الكتالوجات بشكل ثابت إلى زيادة الحجم إلى حوالي ~152 كيلوبايت.
نعم. يحافظ محول @intlayer/lingui على وحدات الماكرو ويستبدل وقت التشغيل فقط. يمكنك بعد ذلك نقل المكونات إلى useIntlayer واحداً تلو الآخر. راجع محولات التوافق.
التعليقات
لا توجد تعليقات بعد. كن أول من يشارك أفكاره.
