كيف تتوقف عن الخوف وتبدأ في الترجمة: تدويل تطبيقات TypeScript
هل تساءلت يومًا لماذا تصل بعض المشاريع إلى المستوى الدولي بينما تظل مشاريع أخرى "شركات ناشئة بلغة واحدة"؟ في أغلب الأحيان، الإجابة بسيطة: الترجمة. نعم، هذا الاختصار المخيف i18n الذي يسبب تشنجًا عصبيًا للعديد من المطورين. لكن لنكن صادقين: جعل تطبيق TypeScript مدوَّلاً ليس علمًا من علوم الصواريخ. إنها مجرد مجموعة من الأساليب والأدوات الصحيحة. اليوم سنقوم بتحليل هذا عمليًا، مع أمثلة كود حية، بدون حشو، وبدون نظريات غامضة.
لماذا TypeScript هو المرشح المثالي لـ i18n؟
يمنحنا TypeScript ما يفتقر إليه JavaScript العادي: الكتابة الثابتة. عندما يتعلق الأمر بالترجمات، تصبح هذه قوة خارقة. تخيل: تقوم بتغيير مفتاح ترجمة، ويصرخ TypeScript قبل أن يعمل التطبيق: "مرحبًا، لقد نسيت تحديث الترجمة في الإعدادات المحلية الإسبانية!". اتفق معي، هذا أفضل من اكتشاف الأخطاء في بيئة الإنتاج.
علاوة على ذلك، تتيح المكتبات الحديثة لـ i18n في TypeScript إنشاء أنواع مباشرة من ملفات الترجمة. هذا يعني أن الإكمال التلقائي في IDE سيعمل بدقة الساعة. لا سلاسل سحرية، ولا أخطاء إملائية. فقط كود نظيف وآمن.
اختيار مكتبة: i18next مقابل react-intl
هناك لاعبان رئيسيان في السوق: i18next و react-intl (جزء من FormatJS). كلاهما يعمل بشكل رائع مع TypeScript، لكن نهجهما يختلف.
- i18next — سكين الجيش السويسري للتدويل. يدعم صيغ الجمع، والاستيفاء، والسياقات، والتحميل البطيء. رائع للمشاريع الكبيرة.
- react-intl — أكثر خفة، مصمم خصيصًا لـ React. يستخدم نهجًا قائمًا على المكونات (
<FormattedMessage>) ونظام ICU MessageFormat القوي.
في هذه المقالة، سنستخدم i18next مع المحول الرسمي لـ React react-i18next. لماذا؟ لأنه الأكثر شيوعًا ويمنحك أقصى درجات التحكم.
الإعداد خطوة بخطوة: من الصفر إلى أول ترجمة
دعنا نصل إلى صلب الموضوع مباشرة. قم بتثبيت التبعيات:
npm install i18next react-i18next i18next-browser-languagedetectorالآن لنقم بإنشاء ملف إعدادات. هذا هو قلب تدويل تطبيق TypeScript الخاص بنا.
// i18n.tsimport i18n from 'i18next';import { initReactI18next } from 'react-i18next';import LanguageDetector from 'i18next-browser-languagedetector';
import enTranslation from './locales/en/translation.json';import ruTranslation from './locales/ru/translation.json';
i18n .use(LanguageDetector) // automatic browser language detection .use(initReactI18next) // integration with React .init({ resources: { en: { translation: enTranslation }, ru: { translation: ruTranslation }, }, fallbackLng: 'en', // if translation is not found interpolation: { escapeValue: false, // React already escapes }, });
export default i18n;لاحظ fallbackLng. هذا مهم جدًا لتجربة المستخدم: إذا جاء مستخدم بمتصفح مضبوط على لغة السواحيلية، فسنظهر له النسخة الإنجليزية، وليس شاشة فارغة.
هيكل ملف الترجمة
دعنا ننشئ مجلد locales وداخله مجلدات فرعية لكل لغة. إليك مثال لملف en/translation.json:
{ "welcome": "Welcome to our application!", "description": "This is a {{framework}} app with i18n support.", "items": { "zero": "No items", "one": "One item", "other": "{{count}} items" }}وإليك نظيره الروسي:
{ "welcome": "Добро пожаловать в наше приложение!", "description": "Это приложение на {{framework}} с поддержкой i18n.", "items": { "zero": "Нет элементов",