Определение языка браузера

В браузерной среде выбор языка интерфейса строится вокруг доступных данных окружения и стратегии приоритетов, заданной конфигурацией интернационализации. В случае i18next ключевая роль отводится механизму определения языка (language detection), который формирует начальное значение текущей локали до загрузки ресурсов переводов.

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

  • navigator.language — основной язык интерфейса браузера
  • navigator.languages — массив предпочтительных языков в порядке приоритета
  • document.documentElement.lang — значение атрибута lang у HTML-документа
  • локальное хранилище (LocalStorage)
  • cookies
  • параметры URL (query string, path, subdomain)

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

В рамках i18next эти источники не используются напрямую «вручную» в коде приложения — вместо этого применяется модуль детекции языка.

Механизм language detector

Для браузера стандартным решением выступает плагин i18next-browser-languagedetector, который интегрируется в систему и автоматизирует выбор языка.

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

  1. Query string (?lng=ru)
  2. Cookie
  3. LocalStorage
  4. Navigator (browser settings)
  5. HTML tag (<html lang="...">)
  6. Path URL
  7. Subdomain

Порядок задаётся явно в конфигурации и является определяющим фактором.

Конфигурация порядка определения языка

Основная настройка выглядит следующим образом:

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

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

Поведение navigator и особенности браузеров

Источник navigator считается базовым, но имеет ограничения:

  • возвращает один основной язык (navigator.language)
  • может содержать региональный код (например, ru-RU, en-US)
  • не всегда отражает реальное предпочтение пользователя внутри приложения

Если доступен navigator.languages, используется первый элемент массива, так как он отражает приоритет языков.

Пример:

navigator.languages = ['ru-RU', 'en-US', 'en'];

В этом случае будет выбран ru-RU, если он поддерживается ресурсами переводов.

Нормализация языковых кодов

После определения язык проходит нормализацию:

  • приведение к единому формату (ru-RUru)
  • проверка доступности ресурса перевода
  • сопоставление с fallback-цепочкой

Если точное совпадение отсутствует, используется стратегия fallback:

fallbackLng: 'en'

или массив:

fallbackLng: ['en', 'de']

Fallback активируется, если:

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

Приоритет источников и конфликт значений

При наличии нескольких источников возможны конфликты. Например:

  • браузер: en-US
  • cookie: ru
  • localStorage: de

В этом случае выбор определяется порядком order. Если первым стоит cookie, итоговым языком будет ru, даже при наличии navigator.language.

Таким образом, детектор реализует строгую систему приоритетов, а не «усреднение» значений.

Сохранение выбранного языка

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

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

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

Типичные варианты:

  • localStorage — для SPA-приложений
  • cookie — для серверной синхронизации

Влияние HTML lang атрибута

Источник htmlTag использует:

<html lang="ru">

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

URL-based определение языка

Два распространённых варианта:

Query string

/home?lng=ru

Path-based

/ru/home

Subdomain

ru.example.com

Каждый вариант требует настройки соответствующего детектора. Они используются в системах с мультиязычной маршрутизацией, где язык является частью URL-структуры.

Пример полной конфигурации детектора

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

i18n
  .use(LanguageDetector)
  .init({
    fallbackLng: 'en',
    detection: {
      order: [
        'querystring',
        'cookie',
        'localStorage',
        'navigator',
        'htmlTag',
        'path',
        'subdomain'
      ],
      caches: ['localStorage']
    }
  });

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

Если детектор возвращает язык, отсутствующий в ресурсах:

  1. проверяется точное совпадение ключа
  2. выполняется попытка усечения региона (fr-CAfr)
  3. применяется fallback

Это позволяет корректно обрабатывать региональные варианты без дублирования переводов.

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

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

  • пользователь переключает язык вручную
  • обновляется localStorage
  • вызывается i18n.changeLanguage()

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


Роль детектора в общей архитектуре i18n

Внутри i18next детектор языка выполняет функцию начального состояния системы. Он определяет контекст до загрузки переводов и влияет на:

  • выбор namespace ресурсов
  • загрузку переводов с сервера
  • форматирование даты и чисел (при интеграциях)
  • маршрутизацию интерфейса

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