Construyendo un selector de idiomas

Permitiendo a los usuarios cambiar de idioma en cualquier página

Problema

Un usuario está en una página específica, como /en/products/123, y quiere ver la misma página en otro idioma. Al hacer clic en un selector de idioma (por ejemplo, 'Français') a menudo lo envía de vuelta a la página de inicio (/fr/) en lugar de a la página de producto correspondiente, interrumpiendo su flujo de trabajo y obligándolo a navegar nuevamente.

Solución

Crear un componente de cliente que lea la ruta actual de la URL. Genera una lista de enlaces para todos los otros idiomas compatibles reemplazando el segmento de idioma actual en la ruta. También establece una cookie de preferencia al hacer clic, asegurando que la elección se recuerde para futuras visitas.

Pasos

1. Define tu configuración de idioma

Asegúrate de que tu archivo i18n.config.ts incluya la lista de locales y el nombre de la cookie que utilizarás.

// i18n.config.ts

export const locales = ['en', 'es', 'fr'];
export const defaultLocale = 'en';
export const localeCookieName = 'NEXT_LOCALE';

2. Crea el componente selector de idioma

Crea un nuevo archivo, por ejemplo, app/components/LanguageSwitcher.tsx. Este debe ser un componente de cliente para usar hooks como usePathname.

// app/components/LanguageSwitcher.tsx
'use client';

import { usePathname } from 'next/navigation';
import Link from 'next/link';
import { locales, localeCookieName } from '@/i18n.config';

export default function LanguageSwitcher() {
  const pathname = usePathname();

  // Esta función establece la cookie
  const setLocaleCookie = (locale: string) => {
    document.cookie = `${localeCookieName}=${locale}; path=/; max-age=31536000; samesite=lax`;
  };

  // Esta función elimina el locale actual de la ruta
  const getRedirectedPath = (locale: string) => {
    if (!pathname) return '/';
    const segments = pathname.split('/');
    segments[1] = locale; // El locale siempre es el primer segmento
    return segments.join('/');
  };

  return (
    <div>
      {locales.map((locale) => (
        <Link
          key={locale}
          href={getRedirectedPath(locale)}
          onClick={() => setLocaleCookie(locale)}
          style={{
            display: 'inline-block',
            padding: '0.5rem',
            textDecoration: 'underline',
          }}
        >
          {locale.toUpperCase()}
        </Link>
      ))}
    </div>
  );
}

3. Añade el selector a tu layout

Importa y coloca tu nuevo componente en el archivo de layout raíz, app/[lang]/layout.tsx. Esto lo hace visible en todas las páginas.

// app/[lang]/layout.tsx
import LanguageSwitcher from '@/app/components/LanguageSwitcher';

export async function generateStaticParams() {
  // Esto le dice a Next.js que pre-renderice 'en', 'es', y 'fr'
  return [{ lang: 'en' }, { lang: 'es' }, { lang: 'fr' }];
}

export default function RootLayout({
  children,
  params,
}: {
  children: React.ReactNode;
  params: { lang: string };
}) {
  return (
    <html lang={params.lang}>
      <body>
        <header>
          {/* Añade el selector a tu encabezado o navegación */}
          <LanguageSwitcher />
        </header>
        <main>{children}</main>
      </body>
    </html>
  );
}

Ahora, cuando un usuario está en /es/products/123 y hace clic en "EN", el componente calcula la nueva ruta como /en/products/123 y establece la cookie NEXT_LOCALE a 'en'.