複数言語のサイトマップインデックスの作成

SEOのための大規模な多言語サイトの管理

問題

サイトには多くの言語にわたる大量のページがあります。すべての言語のすべてのURLを列挙した単一の巨大なsitemap.xmlファイルは非効率的で、管理が難しく、ファイルサイズの制限を超える可能性があります。これにより、ある言語のURLを更新したり、検索エンジンがすべてのコンテンツを効率的に発見したりすることが困難になります。

解決策

「サイトマップインデックス」として機能するsitemap.xmlファイルを作成し、他の言語固有のサイトマップ(例:sitemap-en.xmlsitemap-es.xml)を指し示します。このアプローチはコンテンツを整理し、管理が容易で、新しい言語やページが追加されても効率的にスケールします。

手順

1. サイトマップインデックスルートを作成する

sitemap.tsファイルの代わりに、標準のルートハンドラーを作成する必要があります。これによりサイトマップインデックスを生成する完全な制御が可能になります。

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',
    },
  });
}

このファイルは検索エンジンに対して、サイトのサイトマップがsitemap-en.xmlsitemap-es.xmlなどの他のファイルを指し示すインデックスであることを伝えます。

2. 言語サイトマップ用の動的ルートを作成する

次に、各言語固有のサイトマップを生成する動的ルートを作成します。

app/sitemap-[lang].xml/route.tsを作成します。

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

// ビルド時にNext.jsが生成するサイトマップを指定
export async function generateStaticParams() {
  return locales.map((lang) => ({
    lang,
  }));
}

// 言語ごとのすべてのページを取得するヘルパー関数
// 実際のアプリでは、CMSやデータベースからフェッチします
async function getPagesForLanguage(lang: string): Promise<string[]> {
  // これらは言語プレフィックスなしの相対パスです
  // 例:'/'、'/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',
    },
  });
}

これで、sitemap.xmlファイルはクリーンなインデックスとなり、各言語のURLはこの動的ルートによって生成される独自のファイル(例:/sitemap-en.xml)に整理されます。