Переключение языков

Механизм смены языка в i18next строится вокруг динамического изменения активного языка контекста интернационализации и автоматического обновления всех связанных переводов. Система изначально проектируется так, чтобы язык мог изменяться в рантайме без перезагрузки приложения и без повторной инициализации всего i18n-слоя.

Ключевая идея заключается в том, что текущее языковое состояние хранится внутри экземпляра i18next и влияет на результат функции t().


Активный язык и его роль

Активный язык — это значение, которое определяет, какой набор переводов будет использоваться при вызове функций интернационализации.

Внутри i18next он задаётся через параметр lng.

i18next.init({
  lng: 'en',
  resources: {
    en: {
      translation: {
        hello: "Hello"
      }
    },
    ru: {
      translation: {
        hello: "Привет"
      }
    }
  }
});

В этом случае язык en становится активным, и вызов:

i18next.t('hello');

вернёт "Hello".


Переключение языка через changeLanguage

Основной метод смены языка — changeLanguage. Он изменяет активный язык и запускает процесс обновления всех подписчиков.

i18next.changeLanguage('ru');

После выполнения:

i18next.t('hello'); // "Привет"

Метод возвращает Promise, что позволяет обрабатывать момент завершения переключения:

i18next.changeLanguage('ru').then(() => {
  console.log('Язык переключён');
});

Асинхронная природа переключения

Переключение языка в i18next часто связано с загрузкой ресурсов с сервера. Поэтому операция может включать асинхронные шаги:

  • загрузка JSON-файлов переводов
  • обновление кэша ресурсов
  • пересчёт интерполяций и форм множественного числа
  • уведомление подписчиков
i18next.changeLanguage('de').then(() => {
  console.log(i18next.t('hello'));
});

Если используется backend-загрузка переводов, задержка может быть связана именно с сетью.


Получение текущего языка

Текущее состояние языка доступно через метод:

i18next.language;

или:

i18next.resolvedLanguage;

Разница заключается в том, что language отражает установленное значение, а resolvedLanguage — фактически применённый язык после всех fallback-правил.


Fallback-языки и их влияние

Если выбранный язык недоступен, система автоматически использует fallback:

i18next.init({
  lng: 'ru',
  fallbackLng: 'en',
  resources: {
    en: {
      translation: {
        hello: "Hello"
      }
    }
  }
});

В этом случае:

i18next.changeLanguage('fr');
i18next.t('hello'); // "Hello"

Fallback является важной частью архитектуры i18next, так как предотвращает появление «пустых» интерфейсов.


Принудительная установка языка

Помимо changeLanguage, язык можно задать напрямую:

i18next.init({
  lng: 'ru'
});

Однако в отличие от changeLanguage, этот способ не инициирует динамическое обновление интерфейса в уже запущенном приложении.


События смены языка

Система событий позволяет реагировать на переключение языка:

i18next.on('languageChanged', (lng) => {
  console.log('Новый язык:', lng);
});

Это особенно важно для UI-слоёв, которые должны реагировать на изменение переводов без ручного обновления.

Внутри i18next события используются как основной механизм синхронизации состояния.


Принцип реактивного обновления переводов

После смены языка библиотека не просто меняет строку состояния. Она инициирует цепочку обновлений:

  1. Обновление внутреннего состояния lng
  2. Пересборка ключей переводов
  3. Уведомление подписчиков
  4. Перерисовка UI (если интеграция поддерживает binding)

В React-экосистемах это обычно реализуется через обёртки над i18next, но сам механизм заложен на уровне ядра.


Параметр lng в t() и override языка

Язык можно временно переопределить прямо в вызове t:

i18next.t('hello', { lng: 'en' });
i18next.t('hello', { lng: 'ru' });

Это позволяет получать перевод без изменения глобального состояния.

В i18next это используется для:

  • предпросмотра переводов
  • сравнений языков
  • генерации контента в нескольких локалях одновременно

Смена языка и интерполяция

Переключение языка влияет не только на строки, но и на форматирование значений:

i18next.init({
  lng: 'ru',
  resources: {
    ru: {
      translation: {
        price: "Цена: {{value}} ₽"
      }
    },
    en: {
      translation: {
        price: "Price: ${{value}}"
      }
    }
  }
});

После переключения:

i18next.changeLanguage('en');
i18next.t('price', { value: 10 });

Результат изменится автоматически в соответствии с новым языковым контекстом.


Кэширование и оптимизация переключения

В реальных приложениях i18next активно использует кэш ресурсов. Это снижает стоимость повторного переключения языка.

Основные оптимизации:

  • хранение загруженных переводов в памяти
  • ленивая загрузка новых языков
  • предотвращение повторных запросов
  • дедупликация событий смены языка

Динамическая загрузка языков

При использовании backend-модуля переключение языка может инициировать загрузку:

i18next.changeLanguage('es');

Если испанский язык не загружен, происходит запрос ресурсов, после чего язык активируется.

Этот процесс позволяет масштабировать мультиязычность без увеличения размера бандла.


Синхронизация с локальным хранилищем

Типичная практика — сохранение выбранного языка:

i18next.on('languageChanged', (lng) => {
  localStorage.setItem('lang', lng);
});

И восстановление:

i18next.init({
  lng: localStorage.getItem('lang') || 'en'
});

Таким образом, состояние языка становится устойчивым между сессиями.


Особенности поведения при быстрых переключениях

При частых вызовах:

i18next.changeLanguage('ru');
i18next.changeLanguage('en');
i18next.changeLanguage('de');

система:

  • отменяет промежуточные загрузки
  • применяет только последний язык
  • игнорирует устаревшие промисы

Это предотвращает гонки состояний и неконсистентность UI в i18next.


Интеграция переключения языка в архитектуру приложения

Переключение языка обычно становится частью глобального состояния приложения. Оно влияет на:

  • текст интерфейса
  • формат дат и чисел
  • направление текста (LTR/RTL)
  • загрузку локализованных ресурсов

i18next предоставляет единый механизм управления этим состоянием, что позволяет избегать разрозненных решений в разных слоях системы.