Language detector плагины

В экосистеме i18next механизм определения языка строится на концепции language detector plugins, которые отвечают за извлечение предпочтительного языка пользователя из различных источников окружения. Эти плагины формируют цепочку проверки, где каждый источник данных рассматривается в заданном порядке приоритета, а первый найденный валидный язык становится активным.

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

Каждый language detector реализует набор стандартных методов:

  • detect() — возвращает язык или массив языков
  • cacheUserLanguage() — сохраняет выбранный язык в хранилище (если поддерживается)

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

Принцип работы цепочки детекторов

Механизм определения языка основан на последовательной проверке источников:

  1. Query string (параметры URL)
  2. Cookie
  3. LocalStorage
  4. SessionStorage
  5. Navigator (браузерный язык)
  6. HTML tag (<html lang="">)
  7. Path или subdomain
  8. HTTP headers (в серверной среде)

Каждый источник проверяется в заданном порядке. Как только обнаруживается валидное значение, цепочка прерывается.

Ключевой параметр конфигурации:

detection: {
  order: ['querystring', 'cookie', 'localStorage', 'navigator', 'htmlTag']
}

i18next-browser-languagedetector

Наиболее распространённый детектор в клиентской среде — i18next-browser-languagedetector. Он объединяет несколько стратегий извлечения языка из браузера и обеспечивает гибкую конфигурацию источников.

Подключение плагина

import i18next from 'i18next';
import LanguageDetector from 'i18next-browser-languagedetector';

i18next
  .use(LanguageDetector)
  .init({
    detection: {
      order: ['querystring', 'cookie', 'localStorage', 'navigator', 'htmlTag'],
      caches: ['localStorage', 'cookie']
    }
  });

Основные источники данных

Querystring

Извлечение языка из URL-параметра:

https://example.com?lng=ru

Настройка ключа параметра:

detection: {
  lookupQuerystring: 'lng'
}

Язык сохраняется и читается из cookie-хранилища:

detection: {
  lookupCookie: 'i18next'
}

Дополнительно задаются параметры cookie:

detection: {
  cookieMinutes: 10080,
  cookieDomain: 'example.com'
}

LocalStorage и SessionStorage

Использование браузерных хранилищ:

detection: {
  lookupLocalStorage: 'i18nextLng',
  lookupSessionStorage: 'i18nextLng'
}

Кэширование языка позволяет сохранять выбор пользователя между сессиями.

Использование системного языка браузера:

detection: {
  order: ['navigator']
}

Данные берутся из:

  • navigator.language
  • navigator.languages

HTML tag

Извлечение языка из атрибута документа:

<html lang="ru">
detection: {
  lookupFromPathIndex: 0
}

Кэширование выбранного языка

После определения языка система может сохранить его в один или несколько persistence-слоёв. Это управляется параметром caches.

detection: {
  caches: ['localStorage', 'cookie']
}

Поддерживаемые стратегии:

  • cookie
  • localStorage
  • sessionStorage

Механизм кэширования активируется через cacheUserLanguage() в детекторе.

Пользовательская реализация detector plugin

Детекторы могут быть реализованы вручную при необходимости нестандартной логики.

Интерфейс кастомного детектора

const customDetector = {
  name: 'customDetector',

  lookup(options) {
    return window.customLang || null;
  },

  cacheUserLanguage(lng, options) {
    window.customLang = lng;
  }
};

Подключение:

i18next
  .use(customDetector)
  .init({
    detection: {
      order: ['customDetector']
    }
  });

Серверная детекция языка

В серверной среде используется i18next-http-middleware, где источником данных выступают HTTP-заголовки.

Accept-Language header

Основной механизм — заголовок:

Accept-Language: ru-RU,ru;q=0.9,en;q=0.8

Конфигурация:

middleware.handle(i18next, {
  order: ['header', 'querystring', 'cookie'],
  lookupHeader: 'accept-language'
});

Алгоритм учитывает приоритеты языков, заданные клиентом через q-values.

Приоритеты и разрешение конфликтов

Если несколько источников возвращают разные значения, применяется стратегия первого совпадения согласно order.

Пример:

order: ['querystring', 'cookie', 'localStorage']

При наличии:

  • ?lng=en
  • cookie = ru
  • localStorage = kz

Результатом будет en.

Нормализация языковых тегов

Детекторы возвращают языки в различных форматах:

  • en
  • en-US
  • ru-RU

i18next выполняет нормализацию:

  • приведение к нижнему регистру
  • сопоставление с доступными ресурсами
  • fallback на базовый язык (en-US → en)

Fallback стратегия

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

i18next.init({
  fallbackLng: 'en'
});

Fallback активируется после завершения цепочки detection и проверки доступных ресурсов.

Отключение и переопределение детекции

Механизм детекции может быть полностью отключён:

i18next.init({
  detection: false
});

В таком случае язык задаётся явно через lng:

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

Поведение при множественных языках

Некоторые источники возвращают массив языков, например navigator.languages:

['ru-RU', 'ru', 'en-US']

В этом случае используется первый поддерживаемый язык из списка.

Расширенные сценарии детекции

Path-based routing

Язык извлекается из URL:

/ru/home
/en/home
detection: {
  lookupFromPathIndex: 0
}

Subdomain-based detection

ru.example.com
en.example.com
detection: {
  lookupFromSubdomainIndex: 0
}

Взаимодействие с ресурсами i18next

Результат детекции напрямую влияет на выбор ресурса перевода:

resources: {
  en: { translation: {} },
  ru: { translation: {} }
}

Определённый язык связывается с соответствующим namespace, после чего происходит загрузка переводов.

Особенности работы в SPA

В одностраничных приложениях детекция выполняется один раз при инициализации, однако изменение URL или состояния приложения может требовать ручного обновления языка:

i18next.changeLanguage('ru');

При этом детекторы могут быть повторно вызваны только при явной переинициализации.

Влияние middleware и плагинов

Language detector plugins являются частью более широкой системы middleware i18next. Они могут взаимодействовать с:

  • backend-плагинами загрузки переводов
  • cache-бэкендами
  • framework-обёртками (React, Vue, Angular)

Порядок выполнения критичен: детекция происходит до загрузки ресурсов переводов.

Ограничения и поведение в нестандартных окружениях

В средах без браузерных API:

  • navigator недоступен
  • localStorage может отсутствовать
  • cookie могут быть ограничены

В таких случаях детекторы автоматически пропускаются, переходя к следующим источникам в цепочке.