Enlazar entre páginas localizadas

Mantener a los usuarios en su idioma seleccionado

Problema

Cuando los códigos de idioma forman parte de la URL, crear enlaces internos se vuelve complejo. Un enlace simple como <a href="/about"> es incorrecto, ya que rompe la ruta localizada, enviando a un usuario de /fr/contact a /about en lugar de /fr/about. Esto saca al usuario de su idioma seleccionado.

Solución

Crear un componente personalizado envolvente alrededor del componente Link de Next.js. Este nuevo componente utilizará el hook useParams para obtener el idioma actual de la URL y anteponerlo automáticamente a cualquier href que reciba, asegurando que todos los enlaces internos estén correctamente localizados.

Pasos

Crear un nuevo archivo app/components/LocalizedLink.tsx. Este debe ser un componente cliente para usar el hook useParams.

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

import Link from 'next/link';
import { useParams } from 'next/navigation';
import type { ComponentProps } from 'react';

type LinkProps = ComponentProps<typeof Link>;

export default function LocalizedLink({ href, ...rest }: LinkProps) {
  const params = useParams();
  const lang = params.lang as string;

  let localizedHref = href;

  // Check if href is a string and needs prefixing
  if (typeof href === 'string' && href.startsWith('/')) {
    localizedHref = `/${lang}${href}`;
  } else if (
    typeof href === 'object' &&
    href !== null &&
    href.pathname?.startsWith('/')
  ) {
    // Re-create the object with a prefixed pathname
    localizedHref = {
      ...href,
      pathname: `/${lang}${href.pathname}`,
    };
  }
  // Absolute URLs or other cases are passed through

  return <Link href={localizedHref} {...rest} />;
}

Este componente importa las props estándar de Link. Verifica si href es una cadena (como /about) o un objeto (como { pathname: '/about' }) y antepone inteligentemente el lang actual (por ejemplo, es) a él.

2. Usar el componente en tus páginas

Ahora, en tus páginas, importa LocalizedLink en lugar del next/link estándar. Puedes usarlo tal como usarías el componente Link normal, pero sin preocuparte por el prefijo de idioma.

// app/[lang]/page.tsx
import LocalizedLink from '@/app/components/LocalizedLink';

export default function Home({ params }: { params: { lang: string } }) {
  return (
    <div>
      <h1>Home page</h1>
      <p>Current language: {params.lang}</p>
      
      <nav>
        <ul>
          <li>
            {/* This will render as /en/about or /es/about, etc. */}
            <LocalizedLink href="/about">About page</LocalizedLink>
          </li>
          <li>
            {/* This also works */}
            <LocalizedLink href={{ pathname: '/contact' }}>
              Contact page
            </LocalizedLink>
          </li>
        </ul>
      </nav>
    </div>
  );
}

Usar <LocalizedLink href="/about"> ahora renderiza correctamente un enlace a /{current_lang}/about, manteniendo al usuario dentro de su idioma seleccionado mientras navega por tu sitio.