Comment traduire les métadonnées de page dans TanStack Start v1

Traduire les métadonnées pour la recherche et les réseaux sociaux

Problème

Les métadonnées de page — titres et descriptions — apparaissent dans les onglets du navigateur, les favoris, les résultats de recherche et les aperçus sur les réseaux sociaux. Lorsque la langue des métadonnées ne correspond pas à celle du contenu de la page, les utilisateurs vivent une incohérence déconcertante avant même de consulter la page. Une page en espagnol avec un titre en anglais dans les résultats de recherche signale une localisation de mauvaise qualité. Les moteurs de recherche peuvent interpréter cette incohérence comme un signal de classement, réduisant potentiellement la visibilité dans les résultats de recherche spécifiques à une langue.

Cette déconnexion nuit à l'expérience utilisateur dès l'étape de découverte. Les utilisateurs qui effectuent des recherches dans leur langue préférée s'attendent à ce que les métadonnées correspondent, et l'incohérence érode la confiance avant même le premier clic.

Solution

Traduisez les métadonnées de page en utilisant les mêmes ressources de traduction que le contenu de la page. Définissez une fonction head dans votre configuration de route qui accède aux chaînes traduites et renvoie des métadonnées de titre et de description localisées. Cela garantit la cohérence entre ce qui apparaît dans l'interface du navigateur, les résultats de recherche et la page rendue.

En utilisant le formatage de messages de react-intl au sein de la fonction head, les métadonnées restent synchronisées avec votre flux de traduction et se mettent à jour automatiquement lors du changement de locale.

Étapes

1. Créer un utilitaire pour formater les messages en dehors des composants React

La fonction head s'exécute en dehors de l'arborescence des composants React où les hooks ne sont pas disponibles. Créez un utilitaire qui formate les messages en utilisant createIntl de react-intl.

import { createIntl, createIntlCache } from "react-intl";

const cache = createIntlCache();

export function formatMetadataMessage(
  locale: string,
  messages: Record<string, string>,
  id: string,
  values?: Record<string, string | number>,
): string {
  const intl = createIntl({ locale, messages }, cache);
  return intl.formatMessage({ id }, values);
}

Cet utilitaire crée une instance intl à la demande pour une utilisation dans des contextes non-React comme la fonction head.

2. Définir les clés de traduction des métadonnées

Ajoutez des clés de titre et de description à vos fichiers de traduction pour chaque page nécessitant des métadonnées localisées.

export const enMessages = {
  "page.home.title": "Welcome to Our Site",
  "page.home.description": "Discover amazing content in your language",
  "page.about.title": "About Us",
  "page.about.description": "Learn more about our mission and team",
};

export const esMessages = {
  "page.home.title": "Bienvenido a Nuestro Sitio",
  "page.home.description": "Descubre contenido increíble en tu idioma",
  "page.about.title": "Acerca de Nosotros",
  "page.about.description": "Conoce más sobre nuestra misión y equipo",
};

Ces clés suivent le même modèle que vos traductions de composants, en conservant tout le contenu localisé au même endroit.

3. Ajouter une fonction head à votre route

Utilisez l'option head dans createFileRoute pour retourner des métadonnées traduites. Accédez à la locale actuelle depuis les paramètres de route ou les données du loader, puis formatez les messages en utilisant votre helper.

import { createFileRoute } from "@tanstack/react-router";
import { formatMetadataMessage } from "../utils/formatMetadataMessage";
import { enMessages, esMessages } from "../i18n/messages";

const messagesByLocale = {
  en: enMessages,
  es: esMessages,
};

export const Route = createFileRoute("/$locale/about")({
  head: ({ params }) => {
    const locale = params.locale || "en";
    const messages = messagesByLocale[locale] || messagesByLocale.en;

    return {
      meta: [
        {
          title: formatMetadataMessage(locale, messages, "page.about.title"),
        },
        {
          name: "description",
          content: formatMetadataMessage(
            locale,
            messages,
            "page.about.description",
          ),
        },
      ],
    };
  },
  component: AboutPage,
});

function AboutPage() {
  return <div>About content</div>;
}

La fonction head s'exécute pendant la correspondance de route et retourne des objets de métadonnées que TanStack Start rend dans l'en-tête du document.

4. Utiliser les données du loader pour les métadonnées dynamiques

Lorsque les métadonnées dépendent de données récupérées, accédez à loaderData dans la fonction head pour combiner le contenu dynamique avec les modèles traduits.

import { createFileRoute } from "@tanstack/react-router";
import { formatMetadataMessage } from "../utils/formatMetadataMessage";
import { enMessages, esMessages } from "../i18n/messages";

const messagesByLocale = {
  en: enMessages,
  es: esMessages,
};

export const Route = createFileRoute("/$locale/posts/$postId")({
  loader: async ({ params }) => {
    const post = await fetchPost(params.postId);
    return { post };
  },
  head: ({ params, loaderData }) => {
    const locale = params.locale || "en";
    const messages = messagesByLocale[locale] || messagesByLocale.en;
    const { post } = loaderData;

    return {
      meta: [
        {
          title: formatMetadataMessage(locale, messages, "page.post.title", {
            title: post.title,
          }),
        },
        {
          name: "description",
          content: post.excerpt,
        },
      ],
    };
  },
  component: PostPage,
});

function PostPage() {
  const { post } = Route.useLoaderData();
  return <article>{post.content}</article>;
}

Le loader récupère les données avant l'exécution de la fonction head, vous permettant d'interpoler des valeurs dynamiques dans les modèles de métadonnées traduits.