
الدليل الكامل لتدويل React
من الصفر إلى تعدد اللغات: أعد إعداد i18n في تطبيق React، ثم أتمت الترجمات بالذكاء الاصطناعي.
تثبيت الحِزم
تحتاج إلى ثلاث حِزم: react-i18next (روابط React)، و i18next (المكتبة الأساسية)، وبشكل اختياري i18next-browser-languagedetector لاكتشاف المحلية تلقائياً.
npm install react-i18next i18next i18next-browser-languagedetector i18next-http-backendتهيئة مثيل i18n
أنشئ ملف تهيئة i18n يهيّئ i18next بلغتك الافتراضية، وموارد الترجمة، وسلسلة الإضافات. يجب استيراد هذا الملف في نقطة دخول تطبيقك قبل أن يُعرَض أي مكوّن.
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import Backend from 'i18next-http-backend';
i18n
.use(Backend)
.use(LanguageDetector)
.use(initReactI18next) // Must come before .init()
.init({
fallbackLng: 'en',
debug: process.env.NODE_ENV === 'development',
interpolation: {
escapeValue: false, // React already escapes
},
backend: {
loadPath: '/locales/{{lng}}/{{ns}}.json',
},
});
export default i18n;لفّ تطبيقك بـ I18nextProvider
استورد ملف تهيئة i18n في جذر التطبيق ولفّ شجرة المكوّنات بـ I18nextProvider. بدون ذلك، تُرجِع useTranslation() مفاتيح خاماً بدلاً من النص المترجم.
import React, { Suspense } from 'react';
import ReactDOM from 'react-dom/client';
import { I18nextProvider } from 'react-i18next';
import i18n from './i18n'; // Import your config
import App from './App';
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<Suspense fallback={<div>Loading...</div>}>
<I18nextProvider i18n={i18n}>
<App />
</I18nextProvider>
</Suspense>
</React.StrictMode>
);إنشاء ملفات الترجمة
أنشئ ملف JSON واحداً لكل لغة. استخدم مفاتيح متداخلة لتنظيم السلاسل حسب الميزة أو الصفحة. احتفِظ بلغة المصدر (عادةً الإنجليزية) باعتبارها المصدر الوحيد للحقيقة.
// public/locales/en/translation.json
{
"nav": {
"home": "Home",
"about": "About",
"settings": "Settings"
},
"greeting": "Hello, {{name}}!",
"cart": {
"itemCount_one": "{{count}} item",
"itemCount_other": "{{count}} items"
}
}
// public/locales/de/translation.json
{
"nav": {
"home": "Startseite",
"about": "Über uns",
"settings": "Einstellungen"
},
"greeting": "Hallo, {{name}}!",
"cart": {
"itemCount_one": "{{count}} Artikel",
"itemCount_other": "{{count}} Artikel"
}
}استخدام الترجمات في المكوّنات
استدعِ useTranslation() في أي مكوّن للحصول على الدالة t(). استخدمها للسلاسل البسيطة، والمتغيرات المُستوفاة، والترجمات المُضمّنة في JSX باستخدام المكوّن Trans.
import { useTranslation } from 'react-i18next';
function Greeting({ userName }: { userName: string }) {
const { t } = useTranslation();
return (
<div>
<h1>{t('greeting', { name: userName })}</h1>
<nav>
<a href="/">{t('nav.home')}</a>
<a href="/about">{t('nav.about')}</a>
</nav>
</div>
);
}import { Trans, useTranslation } from 'react-i18next';
// For JSX inside translations:
// "terms": "By signing up, you agree to our <link>Terms</link>."
function SignUp() {
const { t } = useTranslation();
return (
<Trans i18nKey="terms" components={{
link: <a href="/terms" className="underline" />
}} />
);
}التعامل مع صيغ الجمع والمتغيرات
يتعامل i18next مع صيغ الجمع باستخدام قواعد CLDR، وليس فقط مفرداً وجمعاً. للعربية 6 صيغ (zero و one و two و few و many و other). ولليابانية صيغة واحدة (other). عرّف جميع الصيغ المطلوبة في ملفات الترجمة، وسيختار i18next الصيغة الصحيحة تلقائياً.
// English: 2 forms (one, other)
{
"itemCount_one": "{{count}} item",
"itemCount_other": "{{count}} items"
}
// Arabic: 6 forms (zero, one, two, few, many, other)
{
"itemCount_zero": "لا عناصر",
"itemCount_one": "عنصر واحد",
"itemCount_two": "عنصران",
"itemCount_few": "{{count}} عناصر",
"itemCount_many": "{{count}} عنصرًا",
"itemCount_other": "{{count}} عنصر"
}
// Japanese: 1 form (other)
{
"itemCount_other": "{{count}}個のアイテム"
}إضافة تبديل اللغة والاكتشاف
ابنِ محدِّد لغة يستدعي i18n.changeLanguage(). واجمعه مع كاشف لغة المتصفح لاكتشاف لغة المستخدم المفضلة تلقائياً عند الزيارة الأولى، ثم ثبّت اختياره الصريح.
import { useTranslation } from 'react-i18next';
const LANGUAGES = [
{ code: 'en', label: 'English' },
{ code: 'de', label: 'Deutsch' },
{ code: 'ja', label: '日本語' },
{ code: 'es', label: 'Español' },
];
function LanguageSwitcher() {
const { i18n } = useTranslation();
return (
<select
value={i18n.language}
onChange={(e) => i18n.changeLanguage(e.target.value)}
>
{LANGUAGES.map(({ code, label }) => (
<option key={code} value={code}>{label}</option>
))}
</select>
);
}أتمتة الترجمات
بعد اكتمال إعداد i18n، ترجم ملفات المحلية باستخدام الذكاء الاصطناعي. في IDE، اطلب من مساعدك بالذكاء الاصطناعي ترجمة ملف المصدر، أو استخدم i18n Agent CLI ضمن مسار CI/CD.
# In your IDE, ask your AI assistant:
> Translate public/locales/en/translation.json to German, Japanese, and Spanish
✓ de/translation.json created (1.2s)
✓ ja/translation.json created (1.5s)
✓ es/translation.json created (1.1s)
# Or use the CLI in CI/CD:
npx i18n-agent translate public/locales/en/translation.json --lang de,ja,esأتمتة جودة الترجمة
الأخطاء الشائعة
تُعرَض مفاتيح خام بدلاً من الترجمات
خطأ Suspense بدون Fallback
عدم تطابق hydration في SSR
لا يوجد إكمال تلقائي لمفاتيح الترجمة
بنية الملفات الموصى بها
my-react-app/
├── public/
│ └── locales/
│ ├── en/
│ │ ├── translation.json # Default namespace
│ │ ├── common.json # Shared strings
│ │ └── dashboard.json # Feature namespace
│ ├── de/
│ │ ├── translation.json
│ │ ├── common.json
│ │ └── dashboard.json
│ └── ja/
│ └── ...
├── src/
│ ├── i18n.ts # i18n configuration
│ ├── main.tsx # App entry with Provider
│ ├── App.tsx
│ └── components/
│ └── LanguageSwitcher.tsx
└── package.jsonجرّب i18n Agent الآن
أفلت ملف الترجمة هنا
JSON, YAML, PO, XML, CSV, Markdown, Properties
أو انقر للاستعراض
اللغات المستهدفة