Библиотека i18next строится вокруг идеи полной изоляции пользовательского текста от логики приложения. Интернационализация рассматривается не как дополнительный слой поверх интерфейса, а как часть архитектуры системы.
Ключевая философия библиотеки основана на нескольких принципах:
В отличие от примитивных словарей вида:
const messages = {
hello: "Привет"
}
архитектура I18next ориентирована на крупные приложения с десятками языков, сложными правилами склонений, lazy-loading переводов и разделением контента по модулям.
Внутренняя архитектура библиотеки строится вокруг нескольких базовых сущностей:
| Сущность | Назначение |
|---|---|
resource store |
Хранилище переводов |
language detector |
Определение языка |
backend |
Загрузка переводов |
namespace |
Логическое разделение переводов |
translator |
Механизм поиска и обработки ключей |
interpolator |
Подстановка переменных |
plural resolver |
Обработка множественных форм |
Главная идея — разделение ответственности между независимыми подсистемами.
Одно из фундаментальных решений I18next — отсутствие привязки к конкретной платформе.
Библиотека может использоваться с:
Ядро библиотеки остаётся одинаковым:
import i18next from "i18next"
i18next.init({
lng: "ru",
resources: {
ru: {
translation: {
hello: "Привет"
}
}
}
})
UI-интеграции существуют как отдельные адаптеры:
react-i18nextnext-i18nextvue-i18nextТакой подход соответствует архитектурному принципу loose coupling — слабой связанности компонентов.
I18next использует декларативную модель локализации.
Вместо ручного выбора строк:
if (lang === "ru") {
text = "Привет"
}
используются ключи:
t("greeting.hello")
Ключ становится стабильным идентификатором текста.
Это создаёт несколько преимуществ:
Код приложения не зависит от языка.
Текст можно изменять без изменения бизнес-логики.
Все локализационные данные находятся в одном месте.
В основе I18next лежит resource store — объект,
содержащий переводы.
Типичная структура:
{
en: {
translation: {
common: {
save: "Save"
}
}
},
ru: {
translation: {
common: {
save: "Сохранить"
}
}
}
}
Архитектурно это дерево:
language
└── namespace
└── key
Каждый уровень имеет собственную ответственность:
| Уровень | Назначение |
|---|---|
| Язык | Изоляция локали |
| Namespace | Модульность |
| Ключ | Конкретный перевод |
Namespace — один из важнейших элементов архитектуры.
Без namespaces крупное приложение быстро превращается в огромный файл:
{
"save": "Save",
"cancel": "Cancel",
"profile_edit_button": "Edit profile",
"dashboard_sidebar_menu": "Menu"
}
I18next предлагает разделение:
locales/
en/
common.json
auth.json
dashboard.json
Инициализация:
i18next.init({
ns: ["common", "auth", "dashboard"],
defaultNS: "common"
})
Использование:
t("login", { ns: "auth" })
Каждый модуль хранит собственные переводы.
Загрузка только нужных переводов:
i18next.loadNamespaces("dashboard")
Особенно важно для SPA-приложений.
Разные команды работают с разными namespaces.
I18next не навязывает способ хранения переводов.
Поддерживаются:
Это достигается через backend abstraction layer.
Пример подключения backend:
import Backend from "i18next-http-backend"
i18next
.use(Backend)
.init({
backend: {
loadPath: "/locales/{{lng}}/{{ns}}.json"
}
})
Backend представляет собой реализацию стратегии получения данных.
Библиотека не знает:
Она лишь вызывает backend API.
Это соответствует принципу Dependency Inversion из SOLID.
I18next изначально проектировался как асинхронная система.
Причины:
Инициализация:
await i18next.init({
lng: "en"
})
Смена языка:
await i18next.changeLanguage("de")
Внутри библиотеки активно используется событийная архитектура.
Например:
i18next.on("languageChanged", (lng) => {
console.log("Новый язык:", lng)
})
Другие события:
| Событие | Назначение |
|---|---|
initialized |
Завершение инициализации |
loaded |
Загрузка ресурсов |
failedLoading |
Ошибка загрузки |
missingKey |
Отсутствующий перевод |
Такой подход делает библиотеку расширяемой и хорошо интегрируемой.
Один из центральных принципов I18next — отказоустойчивость локализации.
Если перевод отсутствует:
t("unknown.key")
система пытается:
Настройка:
i18next.init({
fallbackLng: "en"
})
Механизм fallback образует цепочку разрешения:
fr-CA
↓
fr
↓
en
Это особенно важно для региональных локалей:
en-USen-GBpt-BRzh-HansI18next отделяет хранение текста от динамических данных.
Пример:
{
"welcome": "Добро пожаловать, {{name}}"
}
Использование:
t("welcome", {
name: "Алексей"
})
Архитектурно это реализовано через отдельный interpolator module.
По умолчанию интерполяция экранирует HTML:
{
interpolation: {
escapeValue: true
}
}
Это защищает от XSS-атак.
Пример опасного значения:
{
name: "<script>alert(1)</script>"
}
После экранирования вредоносный код не выполнится.
Разные языки имеют разные формы множественного числа.
Например:
| Язык | Форм |
|---|---|
| Английский | 2 |
| Русский | 3 |
| Арабский | 6 |
I18next содержит отдельный plural resolver.
Пример:
{
"item_one": "{{count}} предмет",
"item_few": "{{count}} предмета",
"item_many": "{{count}} предметов"
}
Использование:
t("item", { count: 5 })
Хотя ядро I18next использует собственную модель pluralization, архитектура допускает ICU-формат через плагины.
Это важно для:
I18next построен как plugin-oriented architecture.
Подключение:
i18next
.use(Backend)
.use(LanguageDetector)
.use(initReactI18next)
Каждый плагин расширяет pipeline библиотеки.
| Тип | Назначение |
|---|---|
| Backend | Загрузка переводов |
| Detector | Определение языка |
| Formatter | Форматирование |
| Post Processor | Постобработка |
| Framework Adapter | Интеграция с UI |
Определение языка реализовано как цепочка стратегий.
Пример:
detection: {
order: [
"querystring",
"cookie",
"localStorage",
"navigator"
]
}
Каждый detector проверяется последовательно.
Архитектурная идея состоит в том, что пользовательский выбор важнее системных настроек.
Типичный приоритет:
URL
↓
Cookie
↓
LocalStorage
↓
Browser Language
I18next поддерживает несколько уровней кэширования:
Это особенно важно для:
Существует два подхода к именованию ключей.
{
"button.save": "Сохранить"
}
{
"Save changes": "Сохранить изменения"
}
Философия I18next ближе к semantic keys, поскольку они:
I18next поддерживает вложенные структуры:
{
"auth": {
"login": {
"title": "Вход"
}
}
}
Доступ:
t("auth.login.title")
Это позволяет организовывать переводы как полноценную доменную модель.
Архитектура I18next чётко разделяет:
| Ответственность | Подсистема |
|---|---|
| Хранение переводов | Resource Store |
| Получение переводов | Backend |
| Выбор языка | Detector |
| Разрешение ключей | Translator |
| Форматирование | Formatter |
| Интерполяция | Interpolator |
Такое разделение делает систему гибкой и тестируемой.
I18next ориентирован на runtime localization.
Язык можно менять без перезагрузки приложения:
i18next.changeLanguage("fr")
Это критически важно для:
Во фреймворках вроде React библиотека использует реактивную модель обновления интерфейса.
После изменения языка:
i18next.changeLanguage("de")
компоненты автоматически перерисовываются.
Это достигается через подписку на события I18next.
Ядро библиотеки относительно небольшое.
Дополнительные возможности подключаются отдельно:
Такой подход уменьшает:
Архитектура I18next учитывает серверный рендеринг.
Основные задачи SSR:
Поэтому библиотека поддерживает:
Каждый экземпляр I18next хранит собственное состояние:
const instance = i18next.createInstance()
Это важно для:
Глобальный singleton удобен для небольших проектов:
import i18next from "i18next"
Но в enterprise-архитектуре предпочтительнее изолированные экземпляры.
Причины:
I18next позволяет начинать с минимальной конфигурации:
i18next.init({
resources,
lng: "ru"
})
А затем постепенно добавлять:
Это делает библиотеку пригодной как для небольших проектов, так и для enterprise-систем.
I18next рассматривает missing translations как часть рабочего процесса локализации.
Настройки:
saveMissing: true
Событие:
missingKey
Архитектурно это позволяет:
После получения перевода текст может проходить через цепочку post-processors.
Пример:
i18next.use({
type: "postProcessor",
name: "uppercase",
process(value) {
return value.toUpperCase()
}
})
Это создаёт pipeline обработки:
translation
↓
interpolation
↓
pluralization
↓
post-processing
I18next стремится скрыть сложность локализации за простым API:
t("welcome")
При этом внутри могут выполняться:
Такой подход соответствует принципу abstraction over complexity.
Основные идеи, лежащие в основе I18next:
| Принцип | Реализация |
|---|---|
| Модульность | Plugins, namespaces |
| Масштабируемость | Lazy loading, backend abstraction |
| Независимость | Отсутствие привязки к UI |
| Расширяемость | Plugin architecture |
| Отказоустойчивость | Fallback chain |
| Изоляция ответственности | Separate subsystems |
| Runtime-динамика | Смена языка без reload |
| Enterprise-ready | SSR, caching, async loading |
Именно сочетание этих принципов делает I18next не просто библиотекой переводов, а полноценной инфраструктурой интернационализации для крупных JavaScript-приложений.