Cómo construir un componente de cambio de idioma en TanStack Start v1
Cambia de idioma sin salir de la misma página
Problema
Cuando los usuarios cambian de idioma en una aplicación multilingüe, esperan permanecer en la misma página viendo el mismo contenido en el nuevo idioma. Un selector de idioma mal implementado trata la selección de idioma como una navegación a un destino diferente, a menudo redirigiendo a los usuarios a la página de inicio y perdiendo completamente su ubicación. Esto interrumpe el flujo del usuario y crea frustración, especialmente cuando los usuarios están inmersos en un flujo de trabajo o visualizando contenido específico. El desafío es construir un selector que cambie solo el segmento de idioma de la URL mientras preserva el resto de la ruta, los parámetros de búsqueda y el hash.
Solución
Construir un componente selector de idioma que lea la ruta actual de la URL y construya enlaces para cada idioma disponible reemplazando el segmento de localización en la ruta. Extraer la localización actual de la estructura de la URL, luego generar nuevas rutas para otros idiomas soportados sustituyendo la porción de localización mientras se mantienen intactos todos los demás segmentos de la URL. Usar estas rutas para renderizar enlaces que permitan a los usuarios cambiar de idioma sin perder el contexto de su página actual.
Pasos
1. Definir las localizaciones soportadas
Crear un archivo de configuración que enumere todos los idiomas que tu aplicación soporta e identifique la localización predeterminada.
export const locales = ["en", "fr", "es", "de"] as const;
export type Locale = (typeof locales)[number];
export const defaultLocale: Locale = "en";
Esta configuración sirve como única fuente de verdad para los idiomas disponibles y se utilizará para generar enlaces del selector.
2. Crear un helper para extraer la localización actual de la ruta
Escribe una función de utilidad que analice el pathname y extraiga el segmento de localización si está presente.
import { defaultLocale, locales, type Locale } from "./locales";
export function getLocaleFromPathname(pathname: string): Locale {
const segments = pathname.split("/").filter(Boolean);
const firstSegment = segments[0];
if (firstSegment && locales.includes(firstSegment as Locale)) {
return firstSegment as Locale;
}
return defaultLocale;
}
Esta función inspecciona el primer segmento de la ruta y lo devuelve si coincide con una localización soportada, de lo contrario, recurre a la localización predeterminada.
3. Crear un helper para construir rutas localizadas
Escribe una función que tome el pathname actual y una localización objetivo, luego construya una nueva ruta con el segmento de localización reemplazado.
import { defaultLocale, locales, type Locale } from "./locales";
export function getLocalizedPath(
pathname: string,
targetLocale: Locale,
): string {
const segments = pathname.split("/").filter(Boolean);
const firstSegment = segments[0];
const hasLocalePrefix =
firstSegment && locales.includes(firstSegment as Locale);
if (hasLocalePrefix) {
segments[0] = targetLocale;
} else {
segments.unshift(targetLocale);
}
return "/" + segments.join("/");
}
Esta función reemplaza un segmento de localización existente o antepone la localización objetivo a la ruta, asegurando que la nueva URL apunte a la misma página en un idioma diferente.
4. Construir el componente de selector de idioma
Crea un componente que utilice la ubicación actual para generar enlaces para todos los idiomas soportados.
import { Link } from "@tanstack/react-router";
import { useLocation } from "@tanstack/react-router";
import { locales, type Locale } from "./locales";
import { getLocaleFromPathname, getLocalizedPath } from "./locale-helpers";
export function LanguageSwitcher() {
const location = useLocation();
const currentLocale = getLocaleFromPathname(location.pathname);
return (
<nav>
<ul>
{locales.map((locale) => {
const isActive = locale === currentLocale;
const localizedPath = getLocalizedPath(location.pathname, locale);
return (
<li key={locale}>
<Link
to={localizedPath}
search={location.search}
hash={location.hash}
aria-current={isActive ? "page" : undefined}
>
{locale.toUpperCase()}
</Link>
</li>
);
})}
</ul>
</nav>
);
}
El componente lee el pathname actual, determina la localización activa y renderiza un enlace para cada idioma soportado que preserva la estructura de la página actual, los parámetros de búsqueda y el fragmento hash. Los usuarios pueden cambiar de idioma mientras permanecen en la misma página lógica.