Comment lier les versions linguistiques alternatives dans TanStack Start v1

Lier les alternatives linguistiques pour les moteurs de recherche

Problème

Lorsqu'un site web propose le même contenu en plusieurs langues, les moteurs de recherche traitent par défaut chaque version linguistique comme une page distincte. Sans signaux explicites reliant ces versions, les moteurs de recherche ne peuvent pas comprendre que /en/about et /fr/about sont des traductions du même contenu plutôt que des doublons concurrents. Cette fragmentation divise l'autorité de classement entre les versions linguistiques et crée des problèmes d'affichage : un utilisateur francophone pourrait voir la version anglaise mieux classée dans les résultats de recherche, même si une traduction française existe. Les moteurs de recherche ont besoin de métadonnées explicites pour comprendre la relation entre les variantes linguistiques et afficher la version appropriée en fonction des préférences linguistiques et de la localisation de l'utilisateur.

Solution

Ajoutez des éléments de lien hreflang dans l'en-tête du document qui déclarent toutes les versions linguistiques disponibles de chaque page. Ces liens indiquent aux moteurs de recherche quelles URL contiennent le même contenu dans différentes langues, leur permettant de consolider les signaux de classement et de présenter la version correcte aux utilisateurs. Chaque page liste toutes ses alternatives linguistiques, y compris une référence à elle-même, créant une relation bidirectionnelle que les moteurs de recherche utilisent pour comprendre la structure de traduction. Ces métadonnées sont ajoutées par route en utilisant le système de gestion des en-têtes du framework, qui a accès aux paramètres de la route actuelle nécessaires pour construire les URL pour toutes les variantes linguistiques.

Étapes

1. Créer un assistant pour construire les URL alternatives de langue

La méthode buildLocation du routeur construit des URL complètes à partir des paramètres de route, que vous utiliserez pour générer des URL pour chaque version linguistique.

import { AnyRouter } from "@tanstack/react-router";

export function buildLanguageAlternates(
  router: AnyRouter,
  currentPath: string,
  currentLang: string,
  availableLanguages: string[],
) {
  return availableLanguages.map((lang) => {
    const location = router.buildLocation({
      to: currentPath,
      params: { lang },
    });
    return {
      lang,
      href: `${location.pathname}${location.search}${location.hash}`,
    };
  });
}

Cette fonction prend le chemin de la route actuelle et génère des URL alternatives en substituant chaque code de langue dans les paramètres de la route.

2. Définissez vos langues disponibles

Créez un fichier de configuration qui liste toutes les langues prises en charge par votre application.

export const AVAILABLE_LANGUAGES = ["en", "fr", "de", "es"];

export const DEFAULT_LANGUAGE = "en";

Cette liste centralisée sera utilisée pour générer des liens hreflang pour chaque page.

3. Ajoutez des liens hreflang dans la fonction head d'une route

La fonction head reçoit un contexte comprenant matches, params et loaderData, qui donne accès au paramètre de langue actuel et à l'instance du routeur.

import { createFileRoute } from "@tanstack/react-router";
import { buildLanguageAlternates, AVAILABLE_LANGUAGES } from "../i18n-config";

export const Route = createFileRoute("/$lang/about")({
  head: ({ params }) => {
    const alternates = buildLanguageAlternates(
      Route.router,
      "/$lang/about",
      params.lang,
      AVAILABLE_LANGUAGES,
    );

    return {
      links: alternates.map((alt) => ({
        rel: "alternate",
        hreflang: alt.lang,
        href: alt.href,
      })),
    };
  },
  component: AboutPage,
});

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

L'attribut hreflang utilise les codes de langue ISO 639-1, et chaque lien pointe vers la même page dans une langue différente.

4. Ajoutez un hreflang x-default pour le comportement par défaut

L'attribut hreflang x-default indique la page par défaut lorsqu'aucune langue ne correspond.

export const Route = createFileRoute("/$lang/about")({
  head: ({ params }) => {
    const alternates = buildLanguageAlternates(
      Route.router,
      "/$lang/about",
      params.lang,
      AVAILABLE_LANGUAGES,
    );

    const defaultUrl = alternates.find((alt) => alt.lang === "en");

    return {
      links: [
        ...alternates.map((alt) => ({
          rel: "alternate",
          hreflang: alt.lang,
          href: alt.href,
        })),
        {
          rel: "alternate",
          hreflang: "x-default",
          href: defaultUrl?.href || alternates[0].href,
        },
      ],
    };
  },
  component: AboutPage,
});

Le lien x-default fournit une URL de repli pour les utilisateurs dont les préférences linguistiques ne correspondent à aucune alternative déclarée.

5. Appliquer aux routes dynamiques avec paramètres

Pour les routes avec des segments dynamiques supplémentaires au-delà de la langue, incluez ces paramètres lors de la construction des alternatives.

export const Route = createFileRoute("/$lang/posts/$postId")({
  head: ({ params }) => {
    const alternates = AVAILABLE_LANGUAGES.map((lang) => {
      const location = Route.router.buildLocation({
        to: "/$lang/posts/$postId",
        params: { lang, postId: params.postId },
      });
      return {
        lang,
        href: `${location.pathname}${location.search}${location.hash}`,
      };
    });

    return {
      links: [
        ...alternates.map((alt) => ({
          rel: "alternate",
          hreflang: alt.lang,
          href: alt.href,
        })),
        {
          rel: "alternate",
          hreflang: "x-default",
          href:
            alternates.find((a) => a.lang === "en")?.href || alternates[0].href,
        },
      ],
    };
  },
});

Chaque page doit référencer toutes ses versions linguistiques, y compris elle-même, garantissant ainsi que les moteurs de recherche comprennent l'ensemble complet des traductions pour ce contenu.

6. Vérifier l'implémentation hreflang

La fonction head renvoie des éléments de lien qui sont rendus par le composant HeadContent. Inspectez le HTML rendu pour confirmer que les liens apparaissent dans l'en-tête du document.

<link rel="alternate" hreflang="en" href="/en/about" />
<link rel="alternate" hreflang="fr" href="/fr/about" />
<link rel="alternate" hreflang="de" href="/de/about" />
<link rel="alternate" hreflang="es" href="/es/about" />
<link rel="alternate" hreflang="x-default" href="/en/about" />

Les liens bidirectionnels entre les pages garantissent que les moteurs de recherche comprennent la relation entre les versions localisées, leur permettant de servir la version la plus appropriée à chaque utilisateur.