Ответ
Для локализации с динамическими данными с бекенда можно использовать библиотеку i18next вместе с react-i18next.
- Настройка i18next:
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
i18n.use(initReactI18next).init({
resources: {
en: { translations: {} },
ru: { translations: {} },
},
lng: 'en',
fallbackLng: 'en',
interpolation: { escapeValue: false },
});
- Загрузка переводов с бекенда:
const loadTranslations = async (lang) => {
const response = await fetch(`/api/translations?lang=${lang}`);
const data = await response.json();
i18n.addResourceBundle(lang, 'translations', data);
i18n.changeLanguage(lang);
};
- Использование в компоненте:
import { useTranslation } from 'react-i18next';
const Component = () => {
const { t } = useTranslation();
return <div>{t('key_from_backend')}</div>;
};
Нюансы:
- Кешируйте переводы, чтобы избежать лишних запросов.
- Учитывайте асинхронность загрузки (можно добавить лоадер).
- Для SSR (Next.js) используйте
getServerSidePropsдля предзагрузки.
Ответ 18+ 🔞
А, ну это же про локализацию, когда переводы с бекенда прилетают! Классика, блядь. Сейчас разжуем, как это с i18next запилить, чтобы не вышло пиздеца.
Смотри, первым делом надо эту библиотеку инициализировать, как полагается. Заводишь себе файлик i18n.js и пишешь там стандартную хуйню:
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
i18n.use(initReactI18next).init({
resources: {
en: { translations: {} },
ru: { translations: {} },
},
lng: 'en',
fallbackLng: 'en',
interpolation: { escapeValue: false },
});
Видишь? Сначала ресурсы пустые, как твои карманы после зарплаты. Потому что мы их будем тянуть с сервака, а не хранить статично, как дурачки.
Дальше — самое интересное, ёпта. Надо эти переводы загрузить. Пишем функцию, которая дергает бекенд и суёт ответ прямо в i18next. Смотри, не обосрись:
const loadTranslations = async (lang) => {
const response = await fetch(`/api/translations?lang=${lang}`);
const data = await response.json();
i18n.addResourceBundle(lang, 'translations', data);
i18n.changeLanguage(lang);
};
Вот это уже дело! Прилетел JSON с ключами-переводами — и бац, добавляем его в ресурсы. Главное, не забудь это вызвать где надо, например, при смене языка юзером или при первоначальной загрузке приложения.
Ну и финальный аккорд — использование в компонентах. Тут всё просто, как три копейки:
import { useTranslation } from 'react-i18next';
const Component = () => {
const { t } = useTranslation();
return <div>{t('key_from_backend')}</div>;
};
Вызываешь t('some_key'), а библиотека уже сама находит нужный перевод в тех данных, что мы с бекенда притащили. Красота, в рот меня чих-пых!
А теперь, блядь, нюансы, на которых все погорают:
- Кеширование, ёбаный насос! Не гоняй запросы на бекенд каждый раз, когда юзер ткнул в переключатель языка. Сохрани переводы куда-нибудь, хоть в
localStorage, хоть в стейт-менеджер. А то сервер тебе ебальник отломает. - Асинхронность, сука! Пока переводы грузятся, покажи какой-нибудь лоадер или заглушку. Не оставляй пользователя смотреть на пустые ключи типа
common.loading.... Выглядит пиздецово. - Если на SSR (типа Next.js) сидишь — там свои пляски с бубном. Переводы надо грузить в
getServerSidePropsилиgetStaticProps, чтобы на сервере уже всё было готово и в браузер прилетала готовая, локализованная страница, а не кусок говна.
Вот, в принципе, и вся магия. Ничего сложного, главное — не накосячить с асинхронной загрузкой и всё протестить, а то будет не "Hello World", а "хуюло ворлд", понимаешь?