كيفية إضافة الترجمة وتعدد اللغات إلى تطبيق React باستخدام react-i18next
مقدمة: لماذا تحتاج إلى تعدد اللغات في تطبيق React؟
إضافة الترجمة أو ما يُعرف بـ localization إلى موقعك تعني إتاحة المحتوى للمستخدمين بأكثر من لغة، وهو ما يحسن تجربة الاستخدام، ويوسّع نطاق الوصول، ويرفع قابلية التطبيق للانتشار في أسواق متعددة. في هذا الدليل العملي، سنتعرف على طريقة احترافية لإضافة دعم اللغتين الإنجليزية والإسبانية إلى تطبيق React صغير باستخدام المكتبتين react-i18next وi18next.
الفكرة الأساسية بسيطة: بدلاً من كتابة النصوص مباشرة داخل المكوّنات، يتم تخزينها في ملفات JSON، ثم استدعاؤها داخل التطبيق عبر مفاتيح محددة. وعند تغيير اللغة، يعرض التطبيق القيم المناسبة من ملف الترجمة الموافق.

نظرة سريعة على آلية العمل
تعتمد مكتبة react-i18next على فصل المحتوى النصي عن منطق الواجهة. وبهذا الأسلوب يصبح من السهل:
- إدارة النصوص من مكان مركزي.
- إضافة لغات جديدة دون تعديل جذري في المكوّنات.
- الحفاظ على قابلية التوسع في التطبيقات الكبيرة.
- تحسين تجربة المستخدم للمواقع متعددة اللغات.
في هذا المثال، سيكون الهدف هو جعل التطبيق يعمل باللغتين:
enللغة الإنجليزية.esللغة الإسبانية.

تثبيت الحزم المطلوبة
بما أن react-i18next مبنية فوق i18next، فأنت بحاجة إلى تثبيت المكتبتين معاً داخل المشروع.
npm install --save react-i18next i18next
بعد التثبيت، شغّل التطبيق باستخدام الأمر التالي:
npm start
من الأفضل قبل البدء أن تراجع الملفات الأساسية داخل مجلد src، خصوصاً المكوّنات Nav وHome وPage2، لأنها تحتوي على النصوص التي سنترجمها.
إنشاء هيكل ملفات الترجمة
داخل مجلد src، أنشئ مجلداً جديداً باسم i18n ليضم كل ما يتعلق بإعدادات الترجمة وملفات اللغات.
src
+-- i18n
+-- locales
| +-- en
| | +-- translations.json
| +-- es
| +-- translations.json
+-- config.js
وظيفة الملفات ستكون كالتالي:
- ملف
config.jsيحتوي على إعدادات كائنi18n. - ملف
translations.jsonداخلenيحتوي النصوص الإنجليزية. - ملف
translations.jsonداخلesيحتوي النصوص الإسبانية.
إعداد كائن i18n داخل config.js
كائن i18n هو المسؤول عن إدارة الترجمات، واللغة الحالية، وآليات التبديل بين اللغات. يمكن إعداد الملف بالشكل التالي:
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
i18n.use(initReactI18next).init({
fallbackLng: 'en',
lng: 'en',
resources: {
en: {
translations: require('./locales/en/translations.json')
},
es: {
translations: require('./locales/es/translations.json')
}
},
ns: ['translations'],
defaultNS: 'translations'
});
i18n.languages = ['en', 'es'];
export default i18n;
شرح أهم الإعدادات
fallbackLng: اللغة الاحتياطية عند غياب ترجمة معينة.lng: اللغة الافتراضية عند تشغيل التطبيق.resources: مصدر ملفات الترجمة لكل لغة.ns: مساحة الأسماء الخاصة بملفات الترجمة.defaultNS: مساحة الأسماء الافتراضية المستخدمة داخل التطبيق.
إذا كان التطبيق كبيراً، يمكنك تقسيم النصوص إلى أكثر من ملف ترجمة باستخدام أكثر من namespace. أما في التطبيقات الصغيرة، فغالباً يكفي ملف واحد فقط.
ربط إعدادات الترجمة بالتطبيق
حتى يتعرف التطبيق على إعدادات الترجمة، استورد ملف config.js داخل ملف index.js:
import './i18n/config';
بعد ذلك، ضع كائناً فارغاً مؤقتاً داخل ملفي translations.json لتفادي الأخطاء أثناء التطوير:
{}
ترجمة المكوّن الوظيفي باستخدام useTranslation
لنبدأ بملف Nav.js. بما أنه مكوّن وظيفي Functional Component، فيمكن استخدام الخطاف useTranslation.
أضف الاستيراد التالي:
import { useTranslation } from 'react-i18next';
ثم عدّل المكوّن ليصبح بالشكل التالي:
import { useTranslation } from 'react-i18next';
const Nav = () => {
const { t } = useTranslation();
return (
...
);
}
الآن أضف المفاتيح المطلوبة داخل ملف الترجمة الإنجليزي:
{
"home": "Home",
"page2": "Page 2"
}
ثم استخدم الدالة t() داخل المكوّن:
<Link to="/">{t('home')}</Link>
<Link to="/page2">{t('page2')}</Link>
إضافة الترجمة الإسبانية للتجربة
داخل ملف الترجمة الإسباني، أضف:
{
"home": "Casa",
"page2": "Página 2"
}
بعدها غيّر قيمة lng في ملف config.js إلى es ثم أعد تحميل الصفحة لمعاينة الواجهة بالإسبانية. وعند الانتهاء، يمكنك إرجاعها إلى en.
ترجمة مكوّن صنفي باستخدام withTranslation
في ملف Home.js ستجد مكوّناً من نوع Class Component. هنا لا نستخدم useTranslation، بل نعتمد على withTranslation.
أضف الاستيراد التالي:
import { withTranslation } from 'react-i18next';
ثم صدّر المكوّن بهذه الطريقة:
export default withTranslation()(Home);
وداخل الدالة render()، استخرج الدالة t من props:
import { withTranslation } from 'react-i18next';
class Home extends Component {
...
render() {
const { t } = this.props;
...
}
}
export default withTranslation()(Home);
ترجمة نص يحتوي على متغير
إذا كان النص يتضمن متغيراً مثل اسم المستخدم، فيمكن تمريره إلى الدالة t() ككائن:
<p>{t('welcome', { username: username })}</p>
ثم أضف المفتاح داخل ملف الإنجليزية:
"welcome": "Welcome, {{username}}"
وفي ملف الإسبانية:
"welcome": "Bienvenido {{username}}"
ترجمة باقي عناصر النموذج
أضف المفاتيح التالية إلى ملف الإنجليزية:
"change-username": "Change your username:",
"submit": "Submit"
وفي ملف الإسبانية:
"change-username": "Cambia tu nombre de usuario:",
"submit": "Enviar"
بعدها استخدم t() في ترجمة label وزر الإرسال. سيبدو الجزء الخاص بـ render() على النحو التالي:
render() {
const { username } = this.state;
const { t } = this.props;
return (
<div className='body'>
<p>{t('welcome', { username: username })}</p>
<div>
<label>{t('change-username')}</label>
<input type='text' onChange={this.updateUsername.bind(this)} />
<button onClick={this.setUsername.bind(this)}>{t('submit')}</button>
</div>
<p>Click <Link to='/page2'>here</Link> to go to page 2, {username}</p>
</div>
);
}
استخدام المكوّن Trans مع العناصر المتداخلة
عندما يحتوي النص على عناصر HTML أو مكوّنات مثل Link داخل الجملة، تصبح الدالة t() وحدها غير كافية. هنا يأتي دور المكوّن Trans.
ترجمة عناصر بسيطة مثل <strong>
في ملف Page2.js، استورد:
import { Trans, withTranslation } from 'react-i18next';
ثم صدّر المكوّن هكذا:
const Page2 = () => ( ... );
export default withTranslation()(Page2);
إذا كان النص يحتوي على وسم بسيط مثل strong، فاستخدم Trans مباشرة:
<p>
<Trans>this-is-page2</Trans>
</p>
وفي ملف الإنجليزية:
"this-is-page2": "This is <strong>page 2</strong>"
وفي الإسبانية:
"this-is-page2": "Esta es la <strong>página 2</strong>"
تدعم هذه الطريقة افتراضياً بعض الوسوم الأساسية مثل br وstrong وi وp.
ترجمة عناصر أكثر تعقيداً مثل Link
عندما يحتوي النص على مكوّن متداخل مثل Link، مرّر المفتاح عبر الخاصية i18nKey، واترك العنصر المتداخل داخل Trans:
<Trans i18nKey='go-to-home'>
<Link to='/'></Link>
</Trans>
ثم أضف النصوص التالية:
في الإنجليزية:
"go-to-home": "Go to <0>the home page</0>"
في الإسبانية:
"go-to-home": "Ir a la <0>pagina principal</0>"
الوسم <0> يشير إلى أول عنصر متداخل داخل Trans. وإذا وُجد عنصر ثانٍ فسيشار إليه بالوسم <1>.
ترجمة نص يجمع بين عنصر متداخل ومتغير
السطر الأخير في ملف Home.js يحتوي على رابط ومتغير username معاً، لذلك يجب استخدام Trans.
<Trans i18nKey='go-to-page2'>
<Link to='/page2'></Link>
{{username}}
</Trans>
ثم أضف القيمة المناسبة في ملف الإنجليزية:
"go-to-page2": "Click <0>here</0> to go to page 2, {{username}}"
وفي ملف الإسبانية:
"go-to-page2": "Haga clic <0>aquí</0> para ir a la página 2, {{username}}"
بهذه الطريقة يحصل التطبيق على مرونة عالية في ترجمة النصوص المركبة دون كسر بنية الواجهة.
إتاحة التبديل بين اللغات للمستخدم
بعد تجهيز النصوص، تبقى خطوة مهمة وهي منح المستخدم القدرة على تغيير اللغة يدوياً. في ملف Footer.js، استخدم الخطاف useTranslation للحصول على الكائن i18n.
import { useTranslation } from 'react-i18next';
const Footer = () => {
const { i18n } = useTranslation();
function changeLanguage(e) {
i18n.changeLanguage(e.target.value);
}
return (
<div className='footer'>
<button onClick={changeLanguage} value='en'>English</button>
<button onClick={changeLanguage} value='es'>Español</button>
</div>
);
}
الآن يمكن للمستخدم التنقل بين الإنجليزية والإسبانية عبر الأزرار، دون الحاجة إلى إعادة بناء التطبيق أو إنشاء صفحات مستقلة لكل لغة.
كيفية إضافة لغات جديدة مستقبلاً
إحدى أقوى مزايا هذا الأسلوب أنه قابل للتوسع بسهولة. لإضافة لغة جديدة، كل ما عليك فعله هو:
- إنشاء مجلد جديد داخل
localesيحمل رمز اللغة الجديدة. - إضافة ملف
translations.jsonخاص بها. - تعريف اللغة الجديدة داخل
resourcesفي ملفconfig.js. - إضافة زر أو آلية اختيار لغة للمستخدم إذا لزم الأمر.
هذا يجعل بنية المشروع أكثر تنظيماً وملاءمة للتطبيقات التي تستهدف جمهوراً دولياً.
أفضل ممارسات SEO وتهيئة المحتوى متعدد اللغات
إذا كنت تطور تطبيقاً أو موقعاً متعدد اللغات بهدف تحسين الظهور في محركات البحث، فاحرص على النقاط التالية:
- استخدم ترجمات بشرية دقيقة بدلاً من الترجمة الحرفية الآلية.
- خصص المحتوى لكل سوق، ولا تكتفِ باستبدال الكلمات فقط.
- حافظ على تناسق المفاتيح داخل ملفات
JSONلتسهيل الصيانة. - اختبر اتجاه النصوص جيداً، خاصة عند الدمج بين العربية والإنجليزية.
- راقب تجربة المستخدم عند تغيير اللغة، وتأكد من وضوح أزرار التبديل.
الخلاصة التقنية
استخدام react-i18next مع i18next يعد من أفضل الحلول لإدارة الترجمة داخل تطبيقات React، لأنه يجمع بين المرونة والتنظيم وسهولة التوسع. الدالة t() مناسبة للنصوص البسيطة، بينما يوفر المكوّن Trans حلاً ممتازاً للنصوص التي تحتوي على عناصر متداخلة أو متغيرات. وإذا كنت تبني تطبيقاً قابلاً للنمو أو يستهدف أكثر من سوق، فإن اعتماد هذا النهج مبكراً سيوفر عليك كثيراً من الوقت والجهد لاحقاً.