Как определить языковые предпочтения пользователя в Next.js (Pages Router) v16
Автоматическое перенаправление на основе настроек браузера
Проблема
Каждый браузер отправляет заголовок Accept-Language с каждым HTTP-запросом, указывая предпочитаемые пользователем языки в порядке приоритета. Большинство приложений игнорируют этот ценный сигнал и показывают язык по умолчанию всем посетителям, заставляя их вручную искать переключатель языка, даже если приложение уже знает их предпочтения. Это создает лишние трудности при первом посещении и может привести к тому, что пользователь покинет сайт, так и не найдя контент на своем языке.
Когда пользователь попадает на корневой путь приложения, появляется возможность определить его языковые предпочтения и сразу направить к контенту на понятном ему языке. Без такой проверки международные пользователи сталкиваются с интерфейсом на английском языке, независимо от настроек браузера, и теряется шанс произвести дружелюбное, локализованное первое впечатление.
Решение
Создайте корневую страницу, которая выполняет серверную логику при каждом запросе к корню сайта. Прочитайте HTTP-заголовок Accept-Language из входящего запроса и проанализируйте его, чтобы определить наиболее предпочтительный язык пользователя. Сравните этот язык со списком поддерживаемых языков вашего приложения. Если совпадение найдено, перенаправьте пользователя на корневой путь этого языка. Если ни один из поддерживаемых языков не совпадает, перенаправьте на путь языка по умолчанию.
Этот подход использует функцию getServerSideProps в Next.js, которая выполняется на сервере для каждого запроса и может возвращать ответ с перенаправлением. Обрабатывая определение языка на корневом пути, приложение предлагает умный вариант по умолчанию, при этом пользователь всегда может вручную выбрать другой язык позже, если захочет.
Шаги
1. Установите библиотеку для парсинга заголовка Accept-Language
Заголовок Accept-Language содержит список языковых кодов, разделённых запятыми, с необязательными значениями качества, которые нужно распарсить. Установите библиотеку-парсер для работы с этим форматом.
npm install accept-language-parser
Эта библиотека извлекает языковые коды и показатели качества из строки заголовка и возвращает их в порядке приоритета.
2. Создайте корневую страницу с логикой серверного редиректа
Создайте файл pages/index.tsx, который будет автоматически маршрутизироваться в корневую директорию. Используйте getServerSideProps, чтобы вернуть объект редиректа с указанием назначения и флага постоянности.
import { GetServerSideProps } from "next";
import parser from "accept-language-parser";
const SUPPORTED_LOCALES = ["en", "fr", "es", "de"];
const DEFAULT_LOCALE = "en";
export default function RootPage() {
return null;
}
export const getServerSideProps: GetServerSideProps = async (context) => {
const acceptLanguageHeader = context.req.headers["accept-language"];
let targetLocale = DEFAULT_LOCALE;
if (acceptLanguageHeader) {
const languages = parser.parse(acceptLanguageHeader);
const matchedLanguage = languages.find((lang) =>
SUPPORTED_LOCALES.includes(lang.code),
);
if (matchedLanguage) {
targetLocale = matchedLanguage.code;
}
}
return {
redirect: {
destination: `/${targetLocale}`,
permanent: false,
},
};
};
Функция getServerSideProps выполняется при каждом запросе, читает заголовок Accept-Language и перенаправляет на соответствующий путь локали до рендеринга содержимого страницы.
3. Определите поддерживаемые локали
Обновите массив SUPPORTED_LOCALES в соответствии с языками, которые поддерживает ваше приложение. Парсер вернёт языки в порядке качества, а код выберет первое совпадение.
const SUPPORTED_LOCALES = ["en", "fr", "es", "de", "ja", "zh"];
const DEFAULT_LOCALE = "en";
Парсер возвращает языки, отсортированные по качеству от наивысшего к низшему, поэтому первый найденный поддерживаемый язык — это наивысший приоритет пользователя, который ваше приложение может удовлетворить.
4. Обработка случаев без заголовка Accept-Language
Некоторые запросы могут не содержать заголовок Accept-Language. Код проверяет наличие заголовка и использует локаль по умолчанию, если он отсутствует.
if (acceptLanguageHeader) {
const languages = parser.parse(acceptLanguageHeader);
const matchedLanguage = languages.find((lang) =>
SUPPORTED_LOCALES.includes(lang.code),
);
if (matchedLanguage) {
targetLocale = matchedLanguage.code;
}
}
Это гарантирует, что приложение всегда перенаправляет на корректный путь локали, даже если информация о языке браузера недоступна.