i18n — react-i18next bilan ko'p tilli ilova
Muammodan boshlaylik
Internet do'kon o'zbek tilida tayyor. Endi rus va ingliz tillari ham kerak. Birinchi fikr:
<button>
{til === 'uz' ? "Savatga qo'shish" : til === 'ru' ? 'В корзину' : 'Add to cart'}
</button>
300 ta matn uchun shunday — kod o'qib bo'lmaydigan bo'ladi. Va yana muammolar:
- Ko'plik: "1 ta mahsulot", "5 ta mahsulot" — o'zbekchada oddiy, rus tilida esa uch xil shakl: "1 товар", "3 товара", "5 товаров"
- O'zgaruvchilar: "Salom, Ali!" — ism jumlaning o'rtasida, har tilda boshqa joyda
- Sana va son:
07.11.2026yoki11/7/2026;1 500 000yoki1,500,000 - Tarjimon kod ichiga kirmasligi kerak
i18n (internationalization — "i", 18 ta harf, "n") — ilovani ko'p tillilikka tayyorlash. React da eng mashhur vosita — react-i18next.
O'rnatish
npm install i18next react-i18next i18next-browser-languagedetector
Tarjima fayllari
src/locales/
├── uz/translation.json
├── ru/translation.json
└── en/translation.json
// src/locales/uz/translation.json
{
"header": {
"katalog": "Katalog",
"savat": "Savat"
},
"mahsulot": {
"savatga": "Savatga qo'shish",
"narx": "Narxi: {{narx}} so'm"
},
"salom": "Salom, {{ism}}!"
}
// src/locales/ru/translation.json
{
"header": {
"katalog": "Каталог",
"savat": "Корзина"
},
"mahsulot": {
"savatga": "В корзину",
"narx": "Цена: {{narx}} сум"
},
"salom": "Здравствуйте, {{ism}}!"
}
Matnlar koddan ajratilgan. Tarjimon faqat JSON fayllar bilan ishlaydi.
Sozlash
// src/i18n.js
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import uz from './locales/uz/translation.json';
import ru from './locales/ru/translation.json';
import en from './locales/en/translation.json';
i18n
.use(LanguageDetector) // brauzer tili, localStorage
.use(initReactI18next)
.init({
resources: {
uz: { translation: uz },
ru: { translation: ru },
en: { translation: en },
},
fallbackLng: 'uz', // tarjima topilmasa
supportedLngs: ['uz', 'ru', 'en'],
interpolation: {
escapeValue: false, // React o'zi XSS dan himoya qiladi
},
});
export default i18n;
// main.jsx
import './i18n'; // App dan oldin
useTranslation
import { useTranslation } from 'react-i18next';
function MahsulotKartochka({ mahsulot }) {
const { t } = useTranslation();
return (
<article>
<h3>{mahsulot.nomi}</h3>
<p>{t('mahsulot.narx', { narx: mahsulot.narx.toLocaleString() })}</p>
<button>{t('mahsulot.savatga')}</button>
</article>
);
}
t('kalit')— joriy tildagi matn- Ichma-ich kalitlar — nuqta bilan:
'header.savat' {{narx}}— o'zgaruvchi;tning ikkinchi argumenti orqali
Til o'zgarganda useTranslation ishlatadigan barcha komponentlar avtomatik qayta render bo'ladi.
Tilni almashtirish
function TilTanlash() {
const { i18n } = useTranslation();
return (
<select
value={i18n.resolvedLanguage}
onChange={(e) => i18n.changeLanguage(e.target.value)}
aria-label="Til"
>
<option value="uz">O'zbekcha</option>
<option value="ru">Русский</option>
<option value="en">English</option>
</select>
);
}
LanguageDetector tanlangan tilni localStorage ga saqlaydi — keyingi tashrifda o'sha til. <html lang> ni ham yangilang (HTML kursi, 2 va 20-darslar):
i18n.on('languageChanged', (til) => {
document.documentElement.lang = til;
});
Ko'plik shakllari
// uz
{
"savatda_one": "Savatda {{count}} ta mahsulot",
"savatda_other": "Savatda {{count}} ta mahsulot"
}
// ru
{
"savatda_one": "В корзине {{count}} товар",
"savatda_few": "В корзине {{count}} товара",
"savatda_many": "В корзине {{count}} товаров",
"savatda_other": "В корзине {{count}} товара"
}
// en
{
"savatda_one": "{{count}} item in cart",
"savatda_other": "{{count}} items in cart"
}
t('savatda', { count: 5 });
// uz: "Savatda 5 ta mahsulot"
// ru: "В корзине 5 товаров"
// en: "5 items in cart"
- O'zgaruvchi nomi aynan
countbo'lishi kerak - Qo'shimchalar (
_one,_few,_many,_other) — har bir til qoidalari brauzerningIntl.PluralRulesdan olinadi - Qaysi tilda qaysi shakllar borligini bilish shart emas — i18next to'g'risini tanlaydi
Matn ichida komponentlar — Trans
{
"shartlar": "Davom etish orqali <link>foydalanish shartlariga</link> rozilik bildirasiz"
}
import { Trans } from 'react-i18next';
<Trans
i18nKey="shartlar"
components={{ link: <a href="/shartlar" /> }}
/>
Havola matnning o'rtasida — va har tilda boshqa joyda bo'lishi mumkin. Jumlani t('qism1') + <a> + t('qism2') ga bo'lmang — tarjimon butun jumlani ko'rishi kerak.
Sana va son — Intl
const { i18n } = useTranslation();
const til = i18n.resolvedLanguage;
new Intl.NumberFormat(til).format(1500000);
// uz: "1 500 000", en: "1,500,000"
new Intl.NumberFormat(til, { style: 'currency', currency: 'UZS', maximumFractionDigits: 0 }).format(1500000);
new Intl.DateTimeFormat(til, { dateStyle: 'long' }).format(new Date());
// ru: "7 ноября 2026 г.", en: "November 7, 2026"
new Intl.RelativeTimeFormat(til, { numeric: 'auto' }).format(-1, 'day');
// ru: "вчера", en: "yesterday"
Brauzerning o'rnatilgan Intl API si — qo'shimcha kutubxonasiz (72-dars).
[!INFO] Brauzerlarning o'zbek tili uchun ma'lumotlari (oy nomlari, formatlar) boshqa tillarga qaraganda to'liq bo'lmasligi va brauzerdan brauzerga farq qilishi mumkin. Muhim joylarda natijani tekshiring va kerak bo'lsa o'z formatlash funksiyangizni yozing.
Katta ilovalar uchun
Namespace lar — bo'lish
locales/uz/
├── common.json // tugmalar, umumiy so'zlar
├── katalog.json
├── savat.json
└── admin.json
const { t } = useTranslation('savat');
t('jami'); // savat.json dan
t('common:saqlash'); // boshqa namespace dan
Kerak bo'lganda yuklash
Barcha tillarning barcha tarjimalarini bundle ga qo'shish — ortiqcha hajm. i18next-http-backend bilan tarjimalar public/locales/ dan kerak bo'lganda yuklanadi:
import HttpBackend from 'i18next-http-backend';
i18n.use(HttpBackend).init({
backend: { loadPath: '/locales/{{lng}}/{{ns}}.json' },
// ...
});
Yuklanayotganda — Suspense (81-dars).
[!TIP] TypeScript bilan kalitlarni tekshirish mumkin:
t('mahsulot.savtga')(xato yozilgan) — kompilyatsiya xatosi beradi. Shuningdeki18next-parserkabi vositalar koddagi barchat()chaqiruvlarini topib, tarjima fayllarida yetishmayotgan kalitlarni ko'rsatadi.
Nima uchun shunday?
Nima uchun tarjima uchun maxsus kutubxona kerak — oddiy { uz: {...}, ru: {...} } obyekti yetmaydimi?
Oddiy matnlar uchun yetadi. Lekin tillar bir-biridan juda farq qiladi, va bu farqlar kutilmagan joylarda chiqadi. O'zbek tilida ko'plik shakli bitta ("5 ta mahsulot"), ingliz tilida ikkita, rus tilida uchta, arab tilida oltita. So'zlar tartibi har xil: o'zgaruvchi jumlaning boshida, o'rtasida yoki oxirida bo'lishi mumkin. Sanalar, sonlar va valyutalar har bir mintaqada boshqacha yoziladi. i18next kabi kutubxonalar bu qoidalarni — o'nlab yillik lingvistik tajribani — tayyor holda beradi va sizga faqat "nima demoqchi ekanimni" yozish imkonini qoldiradi. "Qanday yozilishi" esa har bir tilning o'z qoidalariga topshiriladi.
Xulosa
Eslab qoling:
- i18n — matnlarni koddan ajratish:
locales/{til}/translation.json i18next+react-i18next+LanguageDetector;fallbackLng,escapeValue: falseconst { t, i18n } = useTranslation();t('kalit', { o'zgaruvchi })i18n.changeLanguage('ru');<html lang>ni yangilang- Ko'plik:
kalit_one,kalit_few,kalit_many,kalit_other+{ count } - Matn ichida komponent —
<Trans components={{ link: <a /> }}>; jumlalarni bo'lmang - Sana va son —
Intl.NumberFormat,Intl.DateTimeFormat - Katta ilova: namespace lar,
i18next-http-backendbilan kerak bo'lganda yuklash
Keyingi dars
87-dars: PWA — React da Progressive Web App