Créer un index de sitemap pour plusieurs langues

Gérer de grands sites multilingues pour le SEO

Problème

Un site possède un grand nombre de pages dans plusieurs langues. Un seul fichier sitemap.xml massif listant toutes les URL pour chaque langue est inefficace, difficile à gérer et peut dépasser les limites de taille de fichier. Cela rend difficile la mise à jour des URL d'une langue ou la découverte efficace de tout le contenu par les moteurs de recherche.

Solution

Créer un fichier sitemap.xml qui agit comme un « index de sitemap », pointant vers d'autres sitemaps spécifiques à chaque langue (par exemple, sitemap-en.xml, sitemap-es.xml). Cette approche organise le contenu, est plus facile à gérer et évolue efficacement à mesure que de nouvelles langues ou pages sont ajoutées.

Étapes

1. Créer la route d'index de sitemap

Au lieu du fichier sitemap.ts, vous devez créer un gestionnaire de route standard. Cela vous donne un contrôle total pour générer un index de sitemap.

Créer app/sitemap.xml/route.ts.

// app/sitemap.xml/route.ts
import { locales, siteBaseUrl } from '@/i18n-config';

export async function GET() {
  const sitemapIndex = `<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="[http://www.sitemaps.org/schemas/sitemap/0.9](http://www.sitemaps.org/schemas/sitemap/0.9)">
  ${locales
    .map((locale) => {
      return `
    <sitemap>
      <loc>${siteBaseUrl}/sitemap-${locale}.xml</loc>
      <lastmod>${new Date().toISOString()}</lastmod>
    </sitemap>`;
    })
    .join('')}
</sitemapindex>
`;

  return new Response(sitemapIndex, {
    headers: {
      'Content-Type': 'application/xml',
    },
  });
}

Ce fichier indique aux moteurs de recherche que le sitemap de votre site est un index qui pointe vers d'autres fichiers, comme sitemap-en.xml, sitemap-es.xml, etc.

2. Créer la route dynamique pour les sitemaps par langue

Ensuite, créer la route dynamique qui générera chaque sitemap spécifique à une langue.

Créer app/sitemap-[lang].xml/route.ts.

// app/sitemap-[lang].xml/route.ts
import { locales, siteBaseUrl } from '@/i18n-config';

// This tells Next.js which sitemaps to build at build time
export async function generateStaticParams() {
  return locales.map((lang) => ({
    lang,
  }));
}

// A helper function to get all pages for a language
// In a real app, this would fetch from a CMS or database
async function getPagesForLanguage(lang: string): Promise<string[]> {
  // These are relative paths, *without* the lang prefix
  // e.g., '/', '/about', '/blog/my-post'
  return ['/', '/about', '/contact'];
}

export async function GET(
  request: Request,
  { params }: { params: { lang: string } }
) {
  const { lang } = params;

  if (!locales.includes(lang)) {
    return new Response('Not Found', { status: 404 });
  }

  const pages = await getPagesForLanguage(lang);

  const sitemap = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="[http://www.sitemaps.org/schemas/sitemap/0.9](http://www.sitemaps.org/schemas/sitemap/0.9)">
  ${pages
    .map((page) => {
      const path = page === '/' ? '' : page;
      return `
    <url>
      <loc>${siteBaseUrl}/${lang}${path}</loc>
      <lastmod>${new Date().toISOString()}</lastmod>
    </url>`;
    })
    .join('')}
</urlset>
`;

  return new Response(sitemap, {
    headers: {
      'Content-Type': 'application/xml',
    },
  });
}

Maintenant, votre fichier sitemap.xml est un index clair, et les URL de chaque langue sont soigneusement organisées dans leurs propres fichiers (par exemple, /sitemap-en.xml), qui sont générés par cette route dynamique.