Как определить языковые предпочтения пользователя в TanStack Start v1
Автоматическое перенаправление на основе настроек браузера
Проблема
Веб-браузеры отправляют заголовок Accept-Language с каждым HTTP-запросом, указывая предпочитаемые пользователем языки в порядке приоритета. Этот заголовок содержит ценную информацию о том, на каком языке пользователю удобнее всего работать, но многие приложения полностью игнорируют его. Вместо этого всем посетителям показывается язык по умолчанию — обычно английский — независимо от их реальных предпочтений. В итоге пользователю приходится вручную искать переключатель языка, хотя приложение уже располагает всей необходимой информацией для более удобного выбора.
Упущенная возможность персонализации особенно раздражает неанглоязычных пользователей, которые явно настроили языковые предпочтения в браузере. Это приводит к плохому первому впечатлению и лишним действиям, прежде чем пользователь сможет перейти к контенту на нужном языке.
Решение
Перехватывайте запросы к корневому пути и анализируйте заголовок Accept-Language, чтобы определить предпочтительный язык пользователя. Разберите этот заголовок, чтобы выделить язык с наивысшим приоритетом, который поддерживает ваше приложение. Если совпадение найдено, перенаправьте пользователя на соответствующий локализованный маршрут. Если ни один из поддерживаемых языков не найден в заголовке, выполните редирект на язык по умолчанию.
Такой подход автоматически учитывает предпочтения пользователя и сохраняет понятную структуру URL, где для каждого языка используется свой префикс пути. Перенаправление происходит на стороне сервера до рендеринга страницы, поэтому пользователь сразу попадает на контент на нужном языке, не видя "мигания" неправильного языка.
Шаги
1. Создайте вспомогательную функцию для разбора заголовка Accept-Language
Заголовок Accept-Language содержит языковые коды с необязательными значениями качества, которые указывают порядок предпочтения. Напишите парсер, который извлекает эти языки, сортирует их по приоритету и находит первое совпадение из списка поддерживаемых языков.
export function parseAcceptLanguage(
header: string | null,
supportedLocales: string[],
): string | null {
if (!header) {
return null;
}
const languages = header
.split(",")
.map((lang) => {
const [code, qValue] = lang.trim().split(";q=");
const quality = qValue ? parseFloat(qValue) : 1.0;
return { code: code.toLowerCase(), quality };
})
.sort((a, b) => b.quality - a.quality);
for (const { code } of languages) {
const exactMatch = supportedLocales.find(
(locale) => locale.toLowerCase() === code,
);
if (exactMatch) {
return exactMatch;
}
const baseCode = code.split("-")[0];
const baseMatch = supportedLocales.find((locale) =>
locale.toLowerCase().startsWith(baseCode),
);
if (baseMatch) {
return baseMatch;
}
}
return null;
}
Эта функция разделяет заголовок по запятым, извлекает значения качества, сортирует по приоритету и проверяет как точные совпадения, так и совпадения по базовому языку с вашими поддерживаемыми локалями.
2. Определите поддерживаемые локали
Создайте конфигурацию, в которой перечислены все языки, поддерживаемые вашим приложением, и указывается, какой из них использовать по умолчанию.
export const SUPPORTED_LOCALES = ["en", "fr", "de", "es", "ja"];
export const DEFAULT_LOCALE = "en";
Эти константы централизуют языковую конфигурацию и позволяют легко добавлять или удалять поддерживаемые языки по мере роста вашего приложения.
3. Создайте обработчик маршрута сервера для корневого пути
Добавьте серверный обработчик GET для вашего корневого маршрута, который читает заголовок Accept-Language, определяет лучшую локаль и перенаправляет пользователя на соответствующий языковой путь.
import { createFileRoute, redirect } from "@tanstack/react-router";
import { getRequestHeaders } from "@tanstack/react-start/server";
export const Route = createFileRoute("/")({
server: {
handlers: {
GET: async () => {
const headers = getRequestHeaders();
const acceptLanguage = headers.get("accept-language");
const preferredLocale = parseAcceptLanguage(
acceptLanguage,
SUPPORTED_LOCALES,
);
const targetLocale = preferredLocale || DEFAULT_LOCALE;
throw redirect({
to: `/${targetLocale}`,
statusCode: 302,
});
},
},
},
});
Этот обработчик запускается на сервере, когда пользователь заходит на корневой путь, анализирует его языковые предпочтения и сразу перенаправляет на маршрут с подходящей локалью до выполнения любого клиентского кода.
4. Импортируйте вспомогательную функцию
Убедитесь, что парсер доступен в вашем файле маршрута, импортировав его в начале вместе с конфигурацией локалей.
import { createFileRoute, redirect } from "@tanstack/react-router";
import { getRequestHeaders } from "@tanstack/react-start/server";
import {
parseAcceptLanguage,
SUPPORTED_LOCALES,
DEFAULT_LOCALE,
} from "../lib/locale";
Разместите функцию parseAcceptLanguage и константы локалей в общем модуле, чтобы их можно было использовать повторно в разных частях приложения, если потребуется.