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 una cabecera Accept-Language con cada solicitud HTTP, indicando los idiomas preferidos del usuario en orden de prioridad. Esta cabecera proporciona información valiosa sobre qué idioma le resulta más cómodo al usuario, sin embargo, muchas aplicaciones la ignoran por completo. En su lugar, muestran un idioma predeterminado —típicamente inglés— a todos los visitantes, independientemente de sus preferencias reales. Los usuarios deben entonces buscar manualmente un selector de idioma, creando una fricción innecesaria cuando la aplicación ya tiene la información necesaria para hacer una mejor elección inicial.

Esta oportunidad perdida de personalización es particularmente frustrante para los hablantes no anglófonos 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 la cabecera Accept-Language para determinar el idioma preferido del usuario. Analiza la cabecera para extraer el idioma de mayor prioridad que tu aplicación soporte. Si se encuentra una coincidencia, redirige al usuario a la ruta localizada apropiada. Si no se encuentra ningún idioma soportado en la cabecera, redirige a un idioma predeterminado como 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 la página se renderice, asegurando que los usuarios lleguen directamente al contenido en su idioma preferido sin ver un destello del idioma incorrecto.

Pasos

1. Crear un helper para analizar la cabecera Accept-Language

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

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 la cabecera por comas, extrae los valores de calidad, ordena por preferencia y verifica tanto coincidencias exactas como coincidencias de idioma base contra tus locales soportados.

2. Define tus locales soportados

Crea una configuración que enumere todos los idiomas que tu aplicación soporta y especifica 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 idiomas y facilitan añadir o eliminar idiomas soportados a medida que tu aplicación crece.

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

Añade un manejador GET del lado del servidor a tu ruta de índice que lea el encabezado Accept-Language, determine el mejor locale y redirija al usuario a la ruta específica del idioma apropiado.

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 manejador se ejecuta en el servidor cuando un usuario visita la ruta raíz, examina sus preferencias de idioma y los redirecciona inmediatamente a la ruta de locale 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 la función auxiliar de análisis esté disponible en tu archivo de ruta importándola en la parte superior junto con tu configuración de locale.

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 locale en un módulo compartido para que puedan ser reutilizadas en toda tu aplicación si es necesario.