استخدم مساعدك المفضل للملخص واستخدم هذه الصفحة والموفر AI الذي تريده
تمت ترجمة محتوى هذه الصفحة باستخدام الذكاء الاصطناعي.
اعرض آخر نسخة المحتوى الأصلي باللغة الإنكليزيةإذا كان لديك فكرة لتحسين هذه الوثيقة، فلا تتردد في المساهمة من خلال تقديم طلب سحب على GitHub.
رابط GitHub للتوثيقنسخ الـ Markdown من المستند إلى الحافظة
Vite i18n: الأجزاء المتعلقة بـ Vite نفسه، وليس بإطار عملك
معظم الشروحات المعنونة بـ "Vite i18n" هي في الواقع شروحات لـ React أو Vue تصادف أنها تستخدم Vite. يتناول هذا المقال الطبقة الأساسية أدناها: كيف يتم استيراد الكتالوجات، ماذا يفعل Rollup بها، ولماذا التحميل الكسول (lazy loading) الذي كتبته ربما لا يكون كسولاً في الواقع.
جدول المحتويات
الاستيراد الثابت هو الافتراضي، وهو متزامن وفوري
أبسط إعداد يستورد كل كتالوج في الجزء العلوي من الوحدة البرمجية (Module):
نسخ الكود إلى الحافظة
هذا يعني تضمين ثلاثة كتالوجات في حزمة الإدخال الأساسية (Entry chunk)، في كل صفحة، ولكل زائر. هذا محتمل للغتين ومائة نص. لكن عند الوصول إلى عشر لغات، يصبح هذا أكبر تكلفة يمكن تفاديها في الحزمة بأكملها.
import.meta.glob والمعامل الذي يخطئ فيه الجميع
خاصية استيراد glob في Vite هي الحل المعتاد:
نسخ الكود إلى الحافظة
التحميل الكسول هو السلوك الافتراضي: كل عنصر هو دالة تُرجع استيراداً ديناميكياً، ويقوم Rollup بإنشاء حزمة منفصلة لكل ملف. أما إضافة { eager: true } فتدمج جميع الملفات مباشرة داخل الوحدة المستوردة، وهو بالضبط ما كنت تحاول تجنبه:
نسخ الكود إلى الحافظة
الفخ يكمن في أن كلا الخيارين يعملان بشكل جيد في بيئة التطوير، لأن Vite يقدم الوحدات دون تجميعها في حزم. الفرق الحقيقي لا يظهر إلا داخل مجلد dist. اختبر ذلك عبر npx vite build && npx vite preview وافحص محتويات حزمة الدخول فعلياً.
التقسيم حسب المسار نادراً ما يقسم الملفات فعلياً
هذا هو السلوك الذي يفاجئ الكثيرين. تقوم بتقسيم الكتالوجات حسب الصفحات:
نسخ الكود إلى الحافظة
ثم يقوم مساران مختلفان باستيراد checkout.json، فيقوم Rollup برفع هذا الملف إلى حزمة مشتركة يتم تنزيلها في كلتا الصفحتين. يعتمد تقسيم الحزم في Rollup على مخطط علاقات الوحدات (Module graph) وليس على أسماء المجلدات: أي وحدة يمكن الوصول إليها من أكثر من نقطة دخول تصبح تابعة لحزمة مشتركة. إضافة مسار ثالث لا يغير شيئاً، وإضافة مسار رابع قد تعيد توزيع الحزم بشكل غير متوقع.
بالتالي، لا يصمد التقسيم حسب المسار إلا إذا كان مخطط الاستيراد منفصلاً تماماً. وإذا كان حجم الحزمة يهمك، فتحقق بالأدوات بدلاً من التخمين:
نسخ الكود إلى الحافظة
إذا كنت مضطراً لفرض حدود تقسيم معينة، فإن build.rollupOptions.output.manualChunks هو المهرب الوحيد، ولكن على حساب الصيانة اليدوية المستمرة.
الكتالوجات لا تدعم التحديث الحي (HMR) تلقائياً
عدل على أي مكون، وسيقوم Vite بتحديثه على الفور. لكن عدل على locales/fr.json، وبحسب طريقة الاستيراد، قد لا يحدث أي شيء. فالـ JSON المستورد ديناميكياً يفتقر لحدود HMR الأصلية، مما يجعل مخطط الوحدات عاجزاً عن معرفة كيفية إبطال المكونات المستهلكة له.
يلجأ المطورون عادة إلى إعادة تشغيل خادم التطوير مع كل تعديل على النصوص، دون إدراك أن هذا الأمر يمكن تفاديه عبر إضافات i18n المتخصصة، حيث يجب على الإضافة استقبال تحديث HMR ودفع الرسائل المحدثة مباشرة للتطبيق المشغل.
define يثبت اللغة بشكل دائم داخل الكود المترجم
من المغري تحديد اللغة الافتراضية أثناء وقت البناء:
نسخ الكود إلى الحافظة
خاصية define تقوم باستبدال نصي بحت في وقت التجميع. القيمة الموجودة أثناء البناء هي التي يتم شحنها في الكود النهائي، مما يلزمك بعمل بناء منفصل لكل لغة. هذه استراتيجية معتمدة في حلول مثل نظام i18n المدمج في Angular، لكنها لا تناسبك إذا كنت تريد لعملية نشر واحدة خدمة جميع اللغات.
القيم التي تتغير حسب طلب المستخدم يجب إبقاؤها بعيدة عن define وتحديدها وقت التشغيل.
نقل معالجة النصوص إلى وقت البناء
تتجه جميع الخيارات الناضجة في هذا المجال نحو مسار واحد: التوقف عن معالجة وتفسير النصوص داخل متصفح المستخدم.
افتح الجدول في نافذة منبثقة لعرض جميع محتويات البيانات بوضوح
| الإضافة | ما تنقله إلى وقت البناء |
|---|---|
@intlify/unplugin-vue-i18n | تجميع نصوص vue-i18n إلى دوال تصيير (شحن حزمة وقت التشغيل الخفيفة فقط) |
| Lingui (ماكرو + إضافة) | استخراج وتجميع الكتالوجات واستبدال الماكرو بمعرفات نصوص مختصرة |
| Paraglide (inlang) | تجميع كل رسالة في دالة مستقلة قابلة للـ tree-shaking |
vite-intlayer | بناء قواميس لكل مكون على حدة، وتفريغ وضغط الحقول غير المستخدمة |
المكسب مزدوج: التخلص من مترجم النصوص الثقيل في الحزمة النهائية للمتصفح، والقدرة على حذف النصوص غير المستخدمة برمجياً. التكلفة المقابلة: خادم التطوير ونظام CI يحتاجان كلاهما للإضافة، كما يتطلب تشغيل tsc المجرد خارج Vite ضبطاً إضافياً.
SSR: إياك والاحتفاظ باللغة على مستوى الوحدة البرمجية
عند استخدام التصيير من جهة الخادم (SSR)، سواء عبر إطار عمل أو عبر vite-plugin-ssr، تنص القاعدة الذهبية على: المتغير الموجود على مستوى الوحدة والذي يحمل اللغة الحالية تتم مشاركته بين كافة الطلبات المتزامنة المعالجة في نفس خادم Node.js.
نسخ الكود إلى الحافظة
إذا طلب مستخدمان الخادم في نفس اللحظة، ستحدث حالة تسابق برمجية، وسيرى أحدهما لغة الآخر. هذا لا يحدث في التطوير المحلي لأنك المستخدم الوحيد. حدد اللغة لكل طلب بمفرده ومررها صراحة عبر السياق (Context) أو تخزين الطلب الخاص بإطار العمل.
إضافة Vite الخاصة بـ Intlayer
توفر Intlayer إضافة واحدة موحدة تدير بناء القواميس، ومراقبة الملفات أثناء التطوير، ومسار التحسين:
نسخ الكود إلى الحافظة
إعادة كتابة الاستيرادات، والتفريغ (purge)، والضغط (minify) مفعلة بشكل افتراضي. يتم ضبط الإعدادات الرئيسية في ملف intlayer.config.ts:
نسخ الكود إلى الحافظة
نظراً لأن المحتوى يُصرح به لكل مكون على حدة بدلاً من حفظه في ملفات لغات عالمية ضخمة، فإن مرحلة التفريغ تعتمد على مخطط ارتباط الوحدات الحقيقي، مما يجعل حذف الأكواد غير المستغلة آمناً للغاية. التفاصيل في توثيق تحسين الحزم.
أخطاء شائعة
- وضع
{ eager: true }على استيراد كان الهدف منه أن يكون كسولاً. يعمل محلياً، ولكنه يشحن كل اللغات في الإنتاج. - الظن بأن أسماء المجلدات تقسم الحزم تلقائياً. يتبع Rollup مسار الاستيراد وليس المجلدات.
- إعادة تشغيل خادم التطوير لرؤية تعديلات النصوص. دليل على غياب معالج HMR مناسب.
- تثبيت اللغة في
define. يلزمك بعمل بناء منفصل لكل لغة. - حفظ حالة اللغة على مستوى الوحدة في SSR. يسبب تسريب وتضارب اللغات بين المستخدمين المتزامنين.
- قياس الأداء على خادم التطوير. الملفات غير المجمعة محلياً لا تمثل بأي شكل حزمة الإنتاج.
للمزيد من القراءة
التعليقات
لا توجد تعليقات بعد. كن أول من يشارك أفكاره.
