Haz tu pregunta y obtén un resumen del documento referenciando esta página y el proveedor AI de tu elección
Al integrar el servidor MCP Intlayer a tu asistente de IA, puedes recuperar todos los documentos directamente desde ChatGPT, DeepSeek, Cursor, VSCode, etc.
Ver la documentación del servidor MCPHistorial de versiones
- Introduce validatePrefix y añade el paso 14: Cómo gestionar páginas 404 con rutas localizadas.v7.4.011/12/2025
- Añade el paso 13: Obtener la configuración regional en tus server actions (Opcional)v7.3.95/12/2025
- Añadido para Tanstack Startv5.8.19/9/2025
El contenido de esta página ha sido traducido con una IA.
Ver la última versión del contenido original en inglésSi tienes una idea para mejorar esta documentación, no dudes en contribuir enviando una pull request en GitHub.
Enlace de GitHub a la documentaciónCopiar el Markdown del documento a la portapapeles
Traduce tu Tanstack Start con Intlayer | Internacionalización (i18n)
Tabla de contenido
Esta guía demuestra cómo integrar Intlayer para una internacionalización fluida en proyectos Tanstack Start con enrutamiento consciente de la configuración regional, soporte para TypeScript y prácticas modernas de desarrollo.
¿Qué es Intlayer?
Intlayer es una biblioteca innovadora y de código abierto para internacionalización (i18n) diseñada para simplificar el soporte multilingüe en aplicaciones web modernas.
Con Intlayer, puedes:
- Gestionar traducciones fácilmente usando diccionarios declarativos a nivel de componente.
- Localizar dinámicamente metadatos, rutas y contenido.
- Garantizar soporte para TypeScript con tipos autogenerados, mejorando la autocompletación y la detección de errores.
- Beneficiarte de características avanzadas, como la detección y el cambio dinámico de configuración regional.
- Habilitar enrutamiento consciente de la configuración regional con el sistema de enrutamiento basado en archivos de Tanstack Start.
Guía paso a paso para configurar Intlayer en una aplicación Tanstack Start
Ver la Plantilla de aplicación en GitHub.
Paso 1: Crear proyecto
Comienza creando un nuevo proyecto TanStack Start siguiendo la guía Start new project en el sitio web de TanStack Start.
Paso 2: Instalar paquetes de Intlayer
Instala los paquetes necesarios usando tu gestor de paquetes preferido:
npm install intlayer react-intlayernpm install vite-intlayer --save-devintlayer
intlayer
El paquete principal que proporciona herramientas de internacionalización para la gestión de configuración, traducción, declaración de contenido, transpileación y comandos CLI.
react-intlayer El paquete que integra Intlayer con aplicaciones React. Proporciona proveedores de contexto y hooks para la internacionalización en React.
vite-intlayer Incluye el plugin de Vite para integrar Intlayer con el empaquetador Vite, así como middleware para detectar la configuración regional preferida del usuario, gestionar cookies y manejar redirecciones de URL.
Paso 3: Configuración de tu proyecto
Cree un archivo de configuración para configurar los idiomas de su aplicación:
Copiar el código al portapapeles
import type { IntlayerConfig } from "intlayer";import { Locales } from "intlayer";const config: IntlayerConfig = { internationalization: { defaultLocale: Locales.ENGLISH, locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH], },};export default config;A través de este archivo de configuración, puede configurar URLs localizadas, redirección mediante middleware, nombres de cookies, la ubicación y extensión de sus declaraciones de contenido, desactivar los registros de Intlayer en la consola y más. Para una lista completa de los parámetros disponibles, consulte la documentación de configuración.
Paso 4: Integra Intlayer en tu configuración de Vite
Agrega el plugin intlayer en tu configuración:
Copiar el código al portapapeles
import { tanstackStart } from "@tanstack/react-start/plugin/vite";import viteReact from "@vitejs/plugin-react";import { nitro } from "nitro/vite";import { defineConfig } from "vite";import { intlayer } from "vite-intlayer";import viteTsConfigPaths from "vite-tsconfig-paths";const config = defineConfig({ plugins: [ nitro(), viteTsConfigPaths({ projects: ["./tsconfig.json"], }), tanstackStart(), viteReact(), intlayer(), // To add ],});export default config;El plugin intlayer() para Vite se utiliza para integrar Intlayer con Vite. Asegura la construcción de los archivos de declaración de contenido y los monitorea en modo desarrollo. Define variables de entorno de Intlayer dentro de la aplicación Vite. Además, proporciona alias para optimizar el rendimiento.
Paso 5: Crear Componentes de Diseño
Configura tu diseño raíz y los diseños específicos por localización:
Diseño Raíz
Copiar el código al portapapeles
import { createFileRoute, Outlet } from "@tanstack/react-router";import { IntlayerProvider, useLocale } from "react-intlayer";import { useI18nHTMLAttributes } from "@/hooks/useI18nHTMLAttributes";export const Route = createFileRoute("/{-$locale}")({ component: LayoutComponent,});function LayoutComponent() { const { defaultLocale } = useLocale(); const { locale } = Route.useParams(); return ( <IntlayerProvider locale={locale ?? defaultLocale}> <Outlet /> </IntlayerProvider> );}Paso 6: Declara Tu Contenido
Crea y administra tus declaraciones de contenido para almacenar traducciones:
Copiar el código al portapapeles
import type { Dictionary } from "intlayer";import { t } from "intlayer";const appContent = { content: { links: { about: t({ en: "About", es: "Acerca de", fr: "À propos", }), home: t({ en: "Home", es: "Inicio", fr: "Accueil", }), }, meta: { description: t({ en: "This is an example of using Intlayer with TanStack Router", es: "Este es un ejemplo de uso de Intlayer con TanStack Router", fr: "Ceci est un exemple d'utilisation d'Intlayer avec TanStack Router", }), }, title: t({ en: "Welcome to Intlayer + TanStack Router", es: "Bienvenido a Intlayer + TanStack Router", fr: "Bienvenue à Intlayer + TanStack Router", }), }, key: "app",} satisfies Dictionary;export default appContent; fr: "Bienvenue à Intlayer + TanStack Router", }), }, key: "app",} satisfies Dictionary;export default appContent;Tus declaraciones de contenido pueden definirse en cualquier parte de tu aplicación tan pronto como se incluyan en el directorio contentDir (por defecto, ./app). Y deben coincidir con la extensión de archivo de declaración de contenido (por defecto, .content.{json,ts,tsx,js,jsx,mjs,mjx,cjs,cjx}).
Para más detalles, consulta la documentación de declaración de contenido.
Paso 7: Crear Componentes y Hooks Sensibles al Idioma
Crea un componente LocalizedLink para la navegación sensible al idioma:
Copiar el código al portapapeles
import type { FC } from "react";import { Link, type LinkComponentProps } from "@tanstack/react-router";import { useLocale } from "react.intlayer";export const LOCALE_ROUTE = "{-$locale}" as const;// Utilidad principalexport type RemoveLocaleParam<T> = T extends string ? RemoveLocaleFromString<T> : T;export type To = RemoveLocaleParam<LinkComponentProps["to"]>;type CollapseDoubleSlashes<S extends string> = S extends `${infer H}//${infer T}` ? CollapseDoubleSlashes<`${H}/${T}`> : S;type LocalizedLinkProps = { to?: To;} & Omit<LinkComponentProps, "to">;// Ayudantestype RemoveAll< S extends string, Sub extends string,> = S extends `${infer H}${Sub}${infer T}` ? RemoveAll<`${H}${T}`, Sub> : S;type RemoveLocaleFromString<S extends string> = CollapseDoubleSlashes< RemoveAll<S, typeof LOCALE_ROUTE>>;export const LocalizedLink: FC<LocalizedLinkProps> = (props) => { const { locale } = useLocale(); const { localePrefix } = getPrefix(locale); return ( <Link {...props} params={{ locale: localePrefix, ...(typeof props?.params === "object" ? props?.params : {}), }} to={`/${LOCALE_ROUTE}${props.to}` as LinkComponentProps["to"]} /> );};Este componente tiene dos objetivos:
- Eliminar el prefijo {-$locale} innecesario de la URL.
- Inyectar el parámetro de localización en la URL para asegurar que el usuario sea redirigido directamente a la ruta localizada.
Luego podemos crear un hook useLocalizedNavigate para la navegación programática:
Copiar el código al portapapeles
import { useLocale } from "react.intlayer";import { useNavigate } from "@tanstack/react-router";import { LOCALE_ROUTE } from "@/components/localized-link";import type { FileRouteTypes } from "@/routeTree.gen";export const useLocalizedNavigate = () => { const navigate = useNavigate(); const { locale } = useLocale(); type StripLocalePrefix<T extends string> = T extends | `/${typeof LOCALE_ROUTE}` | `/${typeof LOCALE_ROUTE}/` ? "/" : T extends `/${typeof LOCALE_ROUTE}/${infer Rest}` ? `/${Rest}` : never; type LocalizedTo = StripLocalePrefix<FileRouteTypes["to"]>; interface LocalizedNavigate { (to: LocalizedTo): ReturnType<typeof navigate>; ( opts: { to: LocalizedTo } & Record<string, unknown> ): ReturnType<typeof navigate>; } const localizedNavigate: LocalizedNavigate = (args: any) => { if (typeof args === "string") { return navigate({ to: `/${LOCALE_ROUTE}${args}`, params: { locale } }); } const { to, ...rest } = args; const localedTo = `/${LOCALE_ROUTE}${to}` as any; return navigate({ to: localedTo, params: { locale, ...rest } as any }); }; return localizedNavigate;};Paso 8: Utiliza Intlayer en Tus Páginas
Accede a tus diccionarios de contenido a lo largo de toda tu aplicación:
Página de Inicio Localizada
Copiar el código al portapapeles
import { createFileRoute } from "@tanstack/react-router";import { getIntlayer } from "intlayer";import { useIntlayer } from "react.intlayer";import LocaleSwitcher from "@/components/locale-switcher";import { LocalizedLink } from "@/components/localized-link";import { useLocalizedNavigate } from "@/hooks/useLocalizedNavigate";export const Route = createFileRoute("/{-$locale}/")({ component: RouteComponent, head: ({ params }) => { const { locale } = params; const metaContent = getIntlayer("app", locale); return { meta: [ { title: metaContent.title }, { content: metaContent.meta.description, name: "description" }, ], }; },});function RouteComponent() { const content = useIntlayer("app"); const navigate = useLocalizedNavigate(); return ( <div> <div> {content.title} <LocaleSwitcher /> <div> <LocalizedLink to="/">{content.links.home}</LocalizedLink> <LocalizedLink to="/about">{content.links.about}</LocalizedLink> </div> <div> <button onClick={() => navigate({ to: "/" })}> {content.links.home} </button> <button onClick={() => navigate({ to: "/about" })}> {content.links.about} </button> </div> </div> </div> );}Para aprender más sobre el hook useIntlayer, consulta la documentación.
Paso 9: Crear un Componente Selector de Idioma
Crea un componente para permitir a los usuarios cambiar de idioma:
Copiar el código al portapapeles
import type { FC } from "react";import { useLocation } from "@tanstack/react-router";import { getHTMLTextDir, getLocaleName, getPathWithoutLocale, getPrefix, Locales,} from "intlayer";import { useLocale } from "react-intlayer";import { LocalizedLink, To } from "./localized-link";export const LocaleSwitcher: FC = () => { const { pathname } = useLocation(); const { availableLocales, locale, setLocale } = useLocale(); const pathWithoutLocale = getPathWithoutLocale(pathname); return ( <ol> {availableLocales.map((localeEl) => ( <li key={localeEl}> <LocalizedLink aria-current={localeEl === locale ? "page" : undefined} onClick={() => setLocale(localeEl)} params={{ locale: getPrefix(localeEl).localePrefix }} > <span> {/* Localización - por ejemplo FR */} {localeEl} </span> <span> {/* Idioma en su propia localización - por ejemplo Français */} {getLocaleName(localeEl, locale)} </span> <span dir={getHTMLTextDir(localeEl)} lang={localeEl}> {/* Idioma en la localización actual - por ejemplo Francés con la localización actual configurada en Locales.SPANISH */} {getLocaleName(localeEl)} </span> <span dir="ltr" lang={Locales.ENGLISH}> {/* Idioma en inglés - por ejemplo French */} {getLocaleName(localeEl, Locales.ENGLISH)} </span> </LocalizedLink> </li> ))} </ol> );};Para aprender más sobre el hook useLocale, consulta la documentación.
Paso 10: Añadir gestión de atributos HTML (Opcional)
Crea un hook para gestionar los atributos lang y dir del HTML:
Copiar el código al portapapeles
// src/hooks/useI18nHTMLAttributes.tsximport { getHTMLTextDir } from "intlayer";import { useEffect } from "react";import { useLocale } from "react-intlayer";export const useI18nHTMLAttributes = () => { const { locale } = useLocale(); useEffect(() => { document.documentElement.lang = locale; document.documentElement.dir = getHTMLTextDir(locale); }, [locale]);};Luego úsalo en tu componente raíz:
Copiar el código al portapapeles
import { createFileRoute, Outlet } from "@tanstack/react-router";import { IntlayerProvider, useLocale } from "react-intlayer";import { useI18nHTMLAttributes } from "@/hooks/useI18nHTMLAttributes"; // importar el hookexport const Route = createFileRoute("/{-$locale}")({ component: LayoutComponent,});function LayoutComponent() { useI18nHTMLAttributes(); // agregar esta línea const { defaultLocale } = useLocale(); const { locale } = Route.useParams(); return ( <IntlayerProvider locale={locale ?? defaultLocale}> <Outlet /> </IntlayerProvider> );}Paso 11: Añadir middleware (Opcional)
También puedes usar el intlayerProxy para agregar enrutamiento del lado del servidor a tu aplicación. Este plugin detectará automáticamente la configuración regional actual basada en la URL y establecerá la cookie de configuración regional apropiada. Si no se especifica ninguna configuración regional, el plugin determinará la configuración regional más adecuada según las preferencias de idioma del navegador del usuario. Si no se detecta ninguna configuración regional, redirigirá a la configuración regional predeterminada.
Ten en cuenta que para usar el intlayerProxy en producción, necesitas cambiar el paquete vite-intlayer de devDependencies a dependencies.
Copiar el código al portapapeles
import { reactRouter } from "@react-router/dev/vite";import tailwindcss from "@tailwindcss/vite";import { defineConfig } from "vite";import { intlayer, intlayerProxy } from "vite-intlayer";import tsconfigPaths from "vite-tsconfig-paths";export default defineConfig({ plugins: [ intlayerProxy(), // El proxy debe colocarse antes del servidor si usas Nitro tailwindcss(), reactRouter(), tsconfigPaths(), intlayer(), ],});Paso 12: Internacionalizar tus Metadatos (Opcional)
También puedes usar el hook getIntlayer para acceder a tus diccionarios de contenido en toda tu aplicación:
Copiar el código al portapapeles
import { createFileRoute } from "@tanstack/react-router";import { getIntlayer } from "intlayer";export const Route = createFileRoute("/{-$locale}/")({ component: RouteComponent, head: ({ params }) => { const { locale } = params; const metaContent = getIntlayer("page-metadata", locale); return { meta: [ { title: metaContent.title }, { content: metaContent.description, name: "description" }, ], }; },});Paso 13: Recuperar la configuración regional en sus acciones del servidor (Opcional)
Es posible que desee acceder a la configuración regional actual desde dentro de sus acciones del servidor o endpoints de API. Puede hacerlo utilizando el asistente getLocale de intlayer.
Aquí hay un ejemplo usando las funciones del servidor de TanStack Start:
Copiar el código al portapapeles
import { createServerFn } from "@tanstack/react-start";import { getRequestHeader, getRequestHeaders,} from "@tanstack/react-start/server";import { getCookie, getIntlayer, getLocale } from "intlayer";export const getLocaleServer = createServerFn().handler(async () => { const locale = await getLocale({ // Obtener la cookie de la solicitud (por defecto: 'INTLAYER_LOCALE') getCookie: (name) => { const cookieString = getRequestHeader("cookie"); return getCookie(name, cookieString); }, // Obtener el encabezado de la solicitud (por defecto: 'x-intlayer-locale') getHeader: (name) => getRequestHeader(name), // Respaldo usando negociación Accept-Language getAllHeaders: async () => { const headers = getRequestHeaders(); const result: Record<string, string> = {}; // Convertir TypedHeaders en un simple Record<string, string> for (const [key, value] of headers.entries()) { result[key] = value; } return result; }, }); // Recuperar algún contenido usando getIntlayer() const content = getIntlayer("app", locale); return { locale, content };});Paso 14: Gestionar páginas no encontradas (Opcional)
Cuando un usuario visita una página que no existe, puedes mostrar una página personalizada de no encontrada y el prefijo de configuración regional puede afectar la forma en que se activa la página de no encontrada.
Entender el manejo de 404 de TanStack Router con prefijos de configuración regional
En TanStack Router, manejar páginas 404 con rutas localizadas requiere un enfoque de múltiples capas:
- Ruta 404 dedicada: Una ruta específica para mostrar la UI de 404
- Validación a nivel de ruta: Valida los prefijos de configuración regional y redirige los inválidos a 404
- Ruta catch-all: Captura cualquier ruta no coincidente dentro del segmento de configuración regional
Copiar el código al portapapeles
import { createFileRoute } from "@tanstack/react-router";// Esto crea una ruta dedicada /[locale]/404// Se usa tanto como una ruta directa como importada como componente en otros archivosexport const Route = createFileRoute("/{-$locale}/404")({ component: NotFoundComponent,});// Exportado por separado para que pueda reutilizarse en notFoundComponent y rutas catch-allexport function NotFoundComponent() { return ( <div> <h1>404</h1> </div> );}Copiar el código al portapapeles
import { createFileRoute, Outlet, redirect } from "@tanstack/react-router";import { validatePrefix } from "intlayer";import { IntlayerProvider, useLocale } from "react-intlayer";import { LocaleSwitcher } from "@/components/locale-switcher";import { NotFoundComponent } from "./404";export const Route = createFileRoute("/{-$locale}")({ // beforeLoad se ejecuta antes de que la ruta se renderice (tanto en el servidor como en el cliente) // Es el lugar ideal para validar el prefijo de configuración regional beforeLoad: ({ params }) => { // Obtener la configuración regional de los parámetros de la ruta (no de los encabezados del servidor, ya que beforeLoad se ejecuta tanto en el cliente como en el servidor) const localeParam = params.locale; // validatePrefix verifica si la configuración regional es válida según tu configuración de intlayer // Retorna: { isValid: boolean, localePrefix: string } // - isValid: true si el prefijo coincide con una configuración regional configurada (o está vacío cuando el prefijo es opcional) // - localePrefix: el prefijo validado o el prefijo de configuración regional predeterminado para redirecciones const { isValid, localePrefix } = validatePrefix(localeParam); if (isValid) { // La configuración regional es válida, permitir que la ruta se renderice normalmente return; } // Prefijo de configuración regional inválido (p. ej., /xyz/about donde "xyz" no es una configuración regional válida) // Redirigir a la página 404 con un prefijo de configuración regional válido // Esto asegura que la página 404 siga estando correctamente localizada throw redirect({ to: "/{-$locale}/404", params: { locale: localePrefix }, }); }, component: RouteComponent, // notFoundComponent se llama cuando una ruta hija no existe // p. ej., /en/pagina-inexistente activa esto dentro del diseño /en notFoundComponent: NotFoundLayout,});function RouteComponent() { const { defaultLocale } = useLocale(); const { locale } = Route.useParams(); return ( // Envuelve todo el segmento de configuración regional con IntlayerProvider // Vuelve a defaultLocale cuando el parámetro locale es undefined (modo de prefijo opcional) <IntlayerProvider locale={locale ?? defaultLocale}> <Outlet /> </IntlayerProvider> );}// NotFoundLayout envuelve el componente 404 con IntlayerProvider// Esto asegura que las traducciones sigan funcionando en la página 404function NotFoundLayout() { const { defaultLocale } = useLocale(); const { locale } = Route.useParams(); return ( <IntlayerProvider locale={locale ?? defaultLocale}> <NotFoundComponent /> {/* Incluir LocaleSwitcher para que los usuarios puedan cambiar el idioma incluso en 404 */} <LocaleSwitcher /> </IntlayerProvider> );}Copiar el código al portapapeles
import { createFileRoute } from "@tanstack/react-router";import { NotFoundComponent } from "./404";// La ruta $ (splat/catch-all) coincide con cualquier ruta que no coincida con otras rutas// p. ej., /en/algun/ruta/profunda/anidada/invalida// Esto asegura que TODAS las rutas no coincidentes dentro de una configuración regional muestren la página 404// Sin esto, las rutas profundas no coincidentes podrían mostrar una página en blanco o un errorexport const Route = createFileRoute("/{-$locale}/$")({ component: NotFoundComponent,});Paso 15: Configurar TypeScript (Opcional)
Intlayer utiliza la ampliación de módulos para aprovechar las ventajas de TypeScript y fortalecer tu base de código.
Asegúrate de que tu configuración de TypeScript incluya los tipos autogenerados:
Copiar el código al portapapeles
{ // ... tus configuraciones existentes include: [ // ... tus inclusiones existentes ".intlayer/**/*.ts", // Incluir los tipos autogenerados ],}Configuración de Git
Se recomienda ignorar los archivos generados por Intlayer. Esto te permite evitar comprometerlos en tu repositorio Git.
Para hacer esto, puedes agregar las siguientes instrucciones a tu archivo .gitignore:
Copiar el código al portapapeles
# Ignorar los archivos generados por Intlayer.intlayerExtensión de VS Code
Para mejorar tu experiencia de desarrollo con Intlayer, puedes instalar la Extensión oficial de Intlayer para VS Code.
Instalar desde el Marketplace de VS Code
Esta extensión proporciona:
- Autocompletado para las claves de traducción.
- Detección de errores en tiempo real para traducciones faltantes.
- Vistas previas en línea del contenido traducido.
- Acciones rápidas para crear y actualizar traducciones fácilmente.
Para más detalles sobre cómo usar la extensión, consulta la documentación de la extensión Intlayer para VS Code.
Ir Más Allá
Para ir más allá, puedes implementar el editor visual o externalizar tu contenido usando el CMS.
Referencias de la Documentación
- Documentación de Intlayer
- Documentación de Tanstack Start
- Hook useIntlayer
- Hook useLocale
- Declaración de Contenido
- Configuración
Esta guía completa proporciona todo lo que necesitas para integrar Intlayer con Tanstack Start para una aplicación completamente internacionalizada con enrutamiento consciente de la configuración regional y soporte para TypeScript.