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 dans plusieurs langues, les moteurs de recherche traitent chaque version linguistique comme une page distincte par défaut. 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 de diffusion : 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 diffuser 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 à 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 diffuser la version correcte aux utilisateurs. Chaque page répertorie 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 d'en-tête du framework, qui a accès aux paramètres de route actuels nécessaires pour construire les URL de toutes les variantes linguistiques.

Étapes

1. Créer une fonction utilitaire pour construire les URL alternatives linguistiques

La méthode buildLocation du routeur construit des URL complètes à partir des paramètres de route, que vous utiliserez pour générer les URL de 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 route.

2. Définir 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 les liens hreflang pour chaque page.

3. Ajouter les liens hreflang dans la fonction head d'une route

La fonction head reçoit le contexte incluant matches, params et loaderData, qui fournit l'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. Ajouter un hreflang x-default pour le comportement de repli

L'attribut hreflang x-default signale 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 que les moteurs de recherche comprennent l'ensemble complet des traductions pour ce contenu.

6. Vérifier l'implémentation hreflang

La fonction head retourne des éléments link 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.