Traduction des métadonnées de page

Définition des balises <title> et <description> localisées

Problème

Un utilisateur consulte une page en espagnol, et tout le contenu visible est correctement traduit. Cependant, l'onglet du navigateur et l'extrait de résultat du moteur de recherche affichent toujours le titre et la description en anglais. Cette incohérence des métadonnées crée une expérience utilisateur confuse et nuit au référencement en présentant des informations non pertinentes dans les résultats de recherche.

Solution

Utilisez la fonction generateMetadata de Next.js dans vos pages et layouts. Cette fonction côté serveur peut charger les traductions correctes en fonction du paramètre lang (en utilisant la même logique de chargement de dictionnaire que vos composants) et renvoyer un objet metadata dynamique avec le titre et la description localisés.

Étapes

1. Créer une fonction pour charger les dictionnaires

Vous avez besoin d'un moyen de charger vos fichiers de traduction plats côté serveur. Créez une fonction d'aide pour cela.

// app/get-dictionary.ts
import 'server-only';

type Messages = Record<string, string>;

const dictionaries: { [key: string]: () => Promise<Messages> } = {
  en: () => import('@/dictionaries/en.json').then((module) => module.default),
  es: () => import('@/dictionaries/es.json').then((module) => module.default),
};

export const getDictionary = async (lang: string) => {
  const load = dictionaries[lang];
  if (load) {
    return load();
  }
  return dictionaries.en();
};

2. Définir les métadonnées sur une page

Dans votre fichier de page (par exemple, app/[lang]/about/page.tsx), exportez une fonction async appelée generateMetadata. Next.js appellera automatiquement cette fonction lors du rendu de la page.

// app/[lang]/about/page.tsx
import { getDictionary } from '@/app/get-dictionary';
import type { Metadata } from 'next';

type Props = {
  params: { lang: string };
};

// This function generates metadata
export async function generateMetadata({ params }: Props): Promise<Metadata> {
  // Load the dictionary for this page
  const dict = await getDictionary(params.lang);

  return {
    title: dict['about.title'], // e.g., "About Us" or "Sobre Nosotros"
    description: dict['about.description'],
  };
}

// The rest of your page component
export default function AboutPage() {
  return (
    <div>
      {/* Page content */}
      <h1>...</h1>
    </div>
  );
}

3. Définir un modèle de titre dans le layout racine

Pour éviter de répéter le nom de votre site dans chaque titre, vous pouvez définir un modèle dans votre layout racine.

// app/[lang]/layout.tsx
import { getDictionary } from '@/app/get-dictionary';
import type { Metadata } from 'next';

type Props = {
  params: { lang: string };
  children: React.ReactNode;
};

// You can generate metadata in layouts too
export async function generateMetadata({ params }: Props): Promise<Metadata> {
  const dict = await getDictionary(params.lang);

  return {
    // This provides a base title and a template
    title: {
      default: dict['site.name'], // e.g., "My Awesome Site"
      template: `%s | ${dict['site.name']}`, // e.g., "About Us | My Awesome Site"
    },
    description: dict['site.description'],
  };
}

export default async function RootLayout({ children, params }: Props) {
  // ... rest of your layout (loading providers, etc.)
  return (
    <html lang={params.lang}>
      <body>{children}</body>
    </html>
  );
}