Comment traduire les métadonnées de page dans React Router v7

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 en dehors de la page elle-même, dans les onglets du navigateur, les favoris, les résultats de recherche et les aperçus sur les réseaux sociaux. Lorsque ces métadonnées ne correspondent pas à la langue de la page, cela crée une incohérence déconcertante. Une page en espagnol avec un titre en anglais déroute les utilisateurs avant même qu'ils ne voient le contenu. Les moteurs de recherche interprètent cette incohérence comme un signal indiquant que la page est mal localisée ou de faible qualité, ce qui peut réduire son classement dans les résultats spécifiques à une langue. Les utilisateurs peuvent abandonner la page avant son chargement, en supposant qu'elle n'est pas dans leur langue.

Solution

Traduisez les métadonnées de page pour qu'elles correspondent à la langue actuelle en exportant une fonction meta depuis votre module de route. Utilisez l'API formatMessage de react-intl avec des Message Descriptors pour traduire les chaînes de titre et de description, garantissant ainsi que les métadonnées utilisent les mêmes ressources de traduction que le contenu de la page. Cela maintient la cohérence entre ce qui s'affiche dans les onglets du navigateur, les résultats de recherche et la page elle-même.

Étapes

1. Créer un helper pour accéder à intl en dehors des composants

L'objet intl fournit formatMessage et peut être accédé via le hook useIntl dans les composants ou créé directement avec createIntl dans des environnements non-React. Étant donné que la fonction meta s'exécute en dehors de l'arborescence des composants React, créez un helper qui construit une instance intl à partir de vos messages.

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

const cache = createIntlCache();

export function createIntlForLocale(
  locale: string,
  messages: Record<string, string>,
) {
  return createIntl(
    {
      locale,
      messages,
    },
    cache,
  );
}

Ce helper crée une instance intl capable de formater des messages dans n'importe quelle fonction, pas seulement dans les composants React.

2. Charger les messages dans un loader de route parent

Les loaders de route renvoient des données auxquelles les composants accèdent via les props loaderData. Chargez vos messages de traduction dans une route parent afin qu'ils soient disponibles pour les routes enfants.

import type { Route } from "./+types/root";

export async function loader({ request }: Route.LoaderArgs) {
  const url = new URL(request.url);
  const locale = url.pathname.split("/")[1] || "en";

  const messages = await import(`../translations/${locale}.json`);

  return {
    locale,
    messages: messages.default,
  };
}

La fonction meta reçoit un paramètre matches contenant les données du loader de toutes les routes correspondantes, rendant les données du loader parent accessibles aux fonctions meta des routes enfants.

3. Exporter une fonction meta qui traduit les métadonnées

Exportez une fonction meta depuis votre module de route qui retourne un tableau d'objets descripteurs meta. Accédez aux données du loader parent depuis matches et utilisez votre helper intl pour traduire les chaînes.

import type { Route } from "./+types/product";
import { createIntlForLocale } from "~/utils/intl";

export function meta({ matches }: Route.MetaArgs) {
  const rootMatch = matches.find((match) => match.id === "root");
  const { locale, messages } = rootMatch?.data || {
    locale: "en",
    messages: {},
  };

  const intl = createIntlForLocale(locale, messages);

  return [
    {
      title: intl.formatMessage({
        id: "product.meta.title",
        defaultMessage: "Product Details",
      }),
    },
    {
      name: "description",
      content: intl.formatMessage({
        id: "product.meta.description",
        defaultMessage: "View detailed information about this product",
      }),
    },
  ];
}

La fonction formatMessage accepte un Message Descriptor avec un id et un defaultMessage, retournant la chaîne traduite pour la locale actuelle.

4. Ajouter les chaînes de métadonnées traduites à vos fichiers de messages

Ajoutez les clés de traduction des métadonnées au fichier de messages de chaque locale afin que formatMessage puisse les trouver.

{
  "product.meta.title": "Détails du produit",
  "product.meta.description": "Voir les informations détaillées sur ce produit"
}

Lorsque les utilisateurs naviguent vers cette route, le composant Meta dans votre layout racine affiche toutes les balises meta créées par les exports meta des routes, affichant des titres et descriptions traduits qui correspondent à la langue de la page.