В HTTP-запросах клиент передаёт информацию о предпочтительных языках
через заголовок Accept-Language. Этот заголовок формируется
браузером или мобильным приложением на основе системных настроек
пользователя и содержит упорядоченный список языков с коэффициентами
приоритета (quality values).
Пример структуры заголовка:
Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7
Каждый язык сопровождается параметром q, определяющим
степень предпочтения. Значение 1.0 означает максимальный
приоритет, отсутствие параметра интерпретируется как
1.0.
На стороне сервера этот заголовок становится основным источником для автоматического выбора языка интерфейса.
В экосистеме i18next обработка языка из HTTP-заголовков реализуется
через модуль промежуточного уровня i18next-http-middleware.
Он интегрируется с серверными фреймворками (Express, Koa, Fastify через
адаптеры) и выполняет определение языка до обработки маршрута.
Основная логика заключается в последовательном применении стратегий определения языка:
Для серверной среды приоритетным источником обычно выступает именно
header.
Конфигурация i18next задаёт порядок источников:
import i18next from 'i18next';
import middleware from 'i18next-http-middleware';
i18next.use(middleware.LanguageDetector).init({
detection: {
order: ['header', 'querystring', 'cookie'],
caches: ['cookie']
},
fallbackLng: 'en',
supportedLngs: ['en', 'ru', 'de']
});
Ключевой параметр order определяет приоритет источников.
При наличии header система анализирует
Accept-Language раньше других механизмов.
Внутренняя логика обработки заголовка включает несколько этапов:
Упрощённая схема:
Accept-Language
↓
разбиение на языковые токены
↓
учёт параметра q
↓
сортировка по приоритету
↓
поиск первого совпадения в supportedLngs
Заголовок может содержать как региональные, так и базовые языковые коды:
ru-RUruen-USen-GBi18next выполняет нормализацию:
ru-RU → ruen-US → enПоведение зависит от параметра:
load: 'languageOnly'
или
load: 'currentOnly'
При наличии нескольких языков в заголовке происходит последовательная проверка:
ru-RU → ru → en-US → en
Если поддерживаемые языки ограничены:
supportedLngs: ['ru', 'en']
алгоритм выберет первый совпадающий вариант.
Если совпадения отсутствуют, активируется fallback:
fallbackLng: 'en'
В серверных приложениях Express обработка заголовков происходит через middleware:
import express from 'express';
import i18next from 'i18next';
import middleware from 'i18next-http-middleware';
const app = express();
app.use(middleware.handle(i18next));
app.get('/', (req, res) => {
const lng = req.language;
res.send(i18next.t('welcome', { lng }));
});
Поле req.language заполняется автоматически после
анализа Accept-Language.
Для снижения нагрузки система может сохранять результат определения языка:
i18next)lng)Приоритет кэширования ниже, чем у HTTP-заголовков, если явно не изменена конфигурация.
В реальных сценариях возможны конфликты между источниками:
| Источник | Пример | Приоритет |
|---|---|---|
| header | Accept-Language: ru | высокий |
| querystring | ?lng=en | средний |
| cookie | lng=de | средний |
При стандартной конфигурации порядок разрешения следующий:
Это означает, что значение из Accept-Language может
переопределять явно заданный язык в cookie или URL.
В некоторых системах требуется игнорирование
Accept-Language, например при строгом управлении локалью со
стороны приложения.
Конфигурация:
detection: {
order: ['querystring', 'cookie'],
lookupHeader: undefined
}
Или через фильтрацию:
detection: {
lookupHeader: () => undefined
}
В таком режиме заголовок перестаёт участвовать в выборе языка.
i18next допускает замену стандартного поведения через кастомную функцию:
detection: {
order: ['header'],
lookupHeader: (req) => {
const lang = req.headers['accept-language'];
return lang ? lang.split(',')[0].split(';')[0] : undefined;
}
}
Такой подход позволяет:
qПри использовании reverse proxy (Nginx, Cloudflare, API Gateway) заголовок может:
Типичный случай — передача оригинального заголовка через:
X-Forwarded-For
Accept-Language
Некоторые инфраструктуры требуют явного проброса:
proxy_set_header Accept-Language $http_accept_language;
При отсутствии корректной передачи язык может определяться некорректно или переходить в fallback.
На клиенте i18next использует navigator.language и
navigator.languages, но при серверном рендеринге эти
значения отсутствуют, и источником становится исключительно
HTTP-заголовок.
Сопоставление:
Accept-LanguageAccept-LanguageВозможные случаи:
Поведение i18next:
headerorderfallbackLng, если все источники не дали
результатаПри большом количестве запросов обработка заголовка может стать значимой частью middleware-цепочки. Оптимизации включают:
qТипичная стратегия:
supportedLngs: ['en', 'ru']
detection: {
order: ['header'],
caches: []
}
При использовании i18next в API-сервисах заголовок становится контрактом между клиентом и сервером. Он позволяет:
Результат определения языка через заголовок напрямую влияет на: