Cómo detectar las preferencias de idioma del usuario en TanStack Start v1

Redirección automática basada en las preferencias del navegador

Problema

Los navegadores web envían un encabezado Accept-Language con cada solicitud HTTP, indicando los idiomas preferidos del usuario en orden de prioridad. Este encabezado proporciona información valiosa sobre el idioma con el que el usuario se siente más cómodo, sin embargo, muchas aplicaciones lo ignoran por completo. En su lugar, muestran un idioma predeterminado (normalmente inglés) a todos los visitantes, independientemente de sus preferencias reales. Los usuarios deben entonces buscar manualmente un selector de idioma, creando fricción innecesaria cuando la aplicación ya tiene la información necesaria para tomar una mejor decisión inicial.

Esta oportunidad perdida de personalización es particularmente frustrante para los hablantes no nativos de inglés que han configurado explícitamente las preferencias de idioma de su navegador. El resultado es una primera impresión degradada y pasos adicionales antes de que los usuarios puedan interactuar con el contenido en su idioma preferido.

Solución

Intercepta las solicitudes a la ruta raíz y examina el encabezado Accept-Language para determinar el idioma preferido del usuario. Analiza el encabezado para extraer el idioma de mayor prioridad que tu aplicación admite. Si se encuentra una coincidencia, redirige al usuario a la ruta localizada apropiada. Si no se encuentra ningún idioma compatible en el encabezado, redirige a un idioma predeterminado de respaldo.

Este enfoque respeta automáticamente las preferencias del usuario mientras mantiene una estructura de URL clara donde cada idioma tiene su propio prefijo de ruta. La redirección ocurre del lado del servidor antes de que se renderice la página, asegurando que los usuarios lleguen directamente al contenido en su idioma preferido sin ver un destello del idioma incorrecto.

Pasos

1. Crea una función auxiliar para analizar el encabezado Accept-Language

El encabezado Accept-Language contiene códigos de idioma con valores de calidad opcionales que indican el orden de preferencia. Crea un analizador que extraiga estos idiomas, los ordene por prioridad y encuentre la primera coincidencia de tu lista de idiomas compatibles.

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;
}

Esta función divide el encabezado por comas, extrae los valores de calidad, ordena por preferencia y verifica tanto coincidencias exactas como coincidencias de idioma base contra tus configuraciones regionales compatibles.

2. Define tus configuraciones regionales compatibles

Crea una configuración que enumere todos los idiomas que tu aplicación admite y especifique cuál usar como respaldo predeterminado.

export const SUPPORTED_LOCALES = ["en", "fr", "de", "es", "ja"];
export const DEFAULT_LOCALE = "en";

Estas constantes centralizan la configuración de idioma y facilitan agregar o eliminar idiomas compatibles a medida que tu aplicación crece.

3. Crea un controlador de ruta del servidor para la ruta raíz

Agrega un controlador GET del lado del servidor a tu ruta de índice que lea el encabezado Accept-Language, determine la mejor configuración regional y redirija al usuario a la ruta específica del idioma apropiada.

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,
        });
      },
    },
  },
});

Este controlador se ejecuta en el servidor cuando un usuario visita la ruta raíz, examina sus preferencias de idioma y los redirige inmediatamente a la ruta de configuración regional que mejor coincida antes de que se ejecute cualquier código del lado del cliente.

4. Importa la función auxiliar

Asegúrate de que el auxiliar de análisis esté disponible en tu archivo de ruta importándolo en la parte superior junto con tu configuración regional.

import { createFileRoute, redirect } from "@tanstack/react-router";
import { getRequestHeaders } from "@tanstack/react-start/server";
import {
  parseAcceptLanguage,
  SUPPORTED_LOCALES,
  DEFAULT_LOCALE,
} from "../lib/locale";

Coloca la función parseAcceptLanguage y las constantes de configuración regional en un módulo compartido para que puedan reutilizarse en toda tu aplicación si es necesario.