# General Translation Knowledge Base: 多言語対応のNext.jsアプリでSEOを設定するには？
URL: https://generaltranslation.com/ja/kb/multilingual-nextjs-seo.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: 言語ごとに専用のURLを用意し、html の lang 属性を設定します。各ページのカノニカルURLは自身を指すようにし、すべての言語の hreflang 代替リンクを追加します。さらに、タイトルと説明文を翻訳し、すべての言語版をサイトマップに掲載します。
Category: 多言語SEO
Last updated: 2026-02-17
Authors: General Translation Team
Published: 2026-02-17

## Video

The video is narrated in English, with English captions.

[How do I set up SEO for a multilingual Next.js app?](https://caxecubb9c64cezv.public.blob.vercel-storage.com/films/kb-multilingual-nextjs-seo.mp4) (50 秒)

General Translation lets you give every language its own URL and tell search engines about them. Move your pages into `app/[locale]` with `gt-next`'s middleware, set the html `lang` attribute with `useLocale`, add canonical and hreflang links with a helper, translate the title with `getGT`, and list every page in every language in a sitemap.

## 多言語SEOに特別な注意が必要な理由

Next.jsアプリにi18nを導入する開発者の多くは、UIを翻訳しただけで作業完了としてしまいます。
しかし、検索エンジンが各言語版を発見・インデックスし、正しく関連付けられなければ、
せっかくの翻訳作業も誰の目にも触れません。

SEOのセットアップが不十分な多言語サイトでは、次のような問題が起こります。

* Googleが1つの言語版だけをインデックスし、他の言語版を無視する可能性がある
* スペイン語で検索したユーザーに英語のページが表示される
* Googleが `/en/about` と `/fr/about` を同じページとみなし、重複コンテンツとしてペナルティを受ける
* 検索結果のスニペットに誤った言語が表示される

**朗報です：** Next.jsで多言語SEOを正しく実装するのは難しくありません。
押さえるべきポイントは6つあり、このガイドでは [`gt-next`](/docs/react/nextjs-quickstart) を使ってそのすべてを解説します。

***

## 1. ロケールに基づくURLルーティング

多言語SEOの基本は、言語ごとに個別のURLを用意することです。
検索エンジンが各言語版を個別にインデックスするには、言語版ごとにクロール可能な別々のURLが必要です。

つまり、**URLにロケールを含める**ということです。クッキーやクエリパラメーターを使ったり、`Accept-Language` による検出だけに頼ったりする方法では不十分です。

```text
✅ generaltranslation.com/en/about
✅ generaltranslation.com/fr/about
✅ generaltranslation.com/es/about

❌ generaltranslation.com/about?lang=fr
❌ generaltranslation.com/about （ロケールをクッキーで保持）
```

### gt-next でロケールルーティングを設定する

まず、ページを `[locale]` 動的セグメント配下に配置します。

```text
app/
└── [locale]/
    ├── layout.tsx
    ├── page.tsx
    └── about/
        └── page.tsx
```

次に、プロジェクトルートにミドルウェアを作成します (Next.js 16以降では `proxy.ts`、Next.js 15以前では `middleware.ts`) 。

```ts title="proxy.ts"
import { createNextMiddleware } from 'gt-next/middleware';

export default createNextMiddleware();

export const config = {
  matcher: ['/((?!api|static|.*\\..*|_next).*)'],
};
```

これにより、ロケールのプレフィックス付きURLが自動的に生成されます。
デフォルトでは、デフォルトロケール (例：英語) にはプレフィックスが付かないため、`/about` はすっきりとしたURLのままです。
一方、スペイン語のユーザーには `/es/about`、フランス語のユーザーには `/fr/about` が表示されます。

***

## 2. HTML の `lang` 属性を設定する

`<html>` タグの `lang` 属性は、ページがどの言語で書かれているかをブラウザや検索エンジンに伝えます。
アクセシビリティと SEO の向上に向けて、最も手軽で効果の大きい施策の一つです。

この属性がないと、スクリーンリーダーは言語を推測するしかなく (しかも誤ることが多く) 、検索エンジンも言語を確信を持って判定しにくくなります。

{/* useLocale はクライアント側とサーバー側のどちらでレンダリングされるコンポーネントでも使えますが、非同期コンポーネントでは使えません */}

gt-next には [`useLocale`](/docs/react/reference/hooks/use-locale) フックが用意されているため、ルートレイアウトで簡単に設定できます：

```tsx title="app/[locale]/layout.tsx"
import { useLocale, GTProvider } from 'gt-next';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  const locale = useLocale();

  return (
    <html lang={locale}>
      <body>
        <GTProvider>
          {children}
        </GTProvider>
      </body>
    </html>
  );
}
```

[`useLocale`](/docs/react/reference/hooks/use-locale) は BCP 47 形式のロケールコード (例：`en-US`、`ar`、`zh-Hans`) を返します。

***

## 3. カノニカルURL

カノニカルタグは、どのURLがページの「正規」バージョンであるかを検索エンジンに伝えるものです。
多言語サイトでは、各言語バージョンがそれぞれ自分自身をカノニカルとして指定する必要があります：

```html
<!-- /fr/about ページの場合 -->
<link rel="canonical" href="https://example.com/fr/about" />
```

これにより、検索エンジンがフランス語のページを英語のページの重複コンテンツとして扱うのを防げます。

Next.js では、[メタデータ API](https://nextjs.org/docs/app/api-reference/functions/generate-metadata) を使ってカノニカル URL を設定します。
gt-next の [`getLocale`](/docs/react/nextjs/reference/functions/get-locale) と組み合わせれば、ロケールごとに正しいカノニカル URL を生成できます：

```tsx title="app/[locale]/about/page.tsx"
import { getLocale } from 'gt-next/server';

const BASE_URL = 'https://example.com';

export async function generateMetadata() {
  const locale = await getLocale();

  return {
    alternates: {
      canonical: `${BASE_URL}/${locale}/about`,
    },
  };
}

export default function AboutPage() {
  return <h1>About Us</h1>;
}
```

デフォルトロケールにプレフィックスを付けない場合は、次のように調整します:

```tsx
import { getDefaultLocale } from 'gt-next';
import { getLocale } from 'gt-next/server';

export async function generateMetadata() {
  const locale = await getLocale();
  const defaultLocale = getDefaultLocale();
  const path = '/about';

  const prefix = locale === defaultLocale ? '' : `/${locale}`;

  return {
    alternates: {
      canonical: `${BASE_URL}${prefix}${path}`,
    },
  };
}
```

***

## 4. hreflang タグ

hreflang タグは、多言語 SEO において最も重要なシグナルです。
hreflang タグは検索エンジンに対して、「このページには他の言語版もあり、それぞれの URL はこちらです」と伝える役割を果たします。

hreflang がないと、Google は検索結果にどの言語版を表示すべきかを推測するしかなく、しばしば誤った言語版を表示してしまいます。

```html
<link rel="alternate" hreflang="en" href="https://example.com/about" />
<link rel="alternate" hreflang="fr" href="https://example.com/fr/about" />
<link rel="alternate" hreflang="es" href="https://example.com/es/about" />
<link rel="alternate" hreflang="x-default" href="https://example.com/about" />
```

`x-default` タグは、指定したどの言語もユーザーに該当しない場合に表示する URL を検索エンジンに伝えます。

Next.js では、メタデータ API の `alternates.languages` プロパティを使って hreflang を追加できます。
以下は、gt-next と組み合わせて使える再利用可能なヘルパーです：

```tsx title="lib/i18n-metadata.ts"
import { getDefaultLocale } from 'gt-next';
import { getLocale } from 'gt-next/server';

const BASE_URL = 'https://example.com';
const SUPPORTED_LOCALES = ['en', 'fr', 'es'];

export async function getI18NMetadata(path: string) {
  const locale = await getLocale();
  const defaultLocale = getDefaultLocale();

  const getUrl = (loc: string) => {
    const prefix = loc === defaultLocale ? '' : `/${loc}`;
    return `${BASE_URL}${prefix}${path}`;
  };

  const languages: Record<string, string> = {};
  for (const loc of SUPPORTED_LOCALES) {
    languages[loc] = getUrl(loc);
  }
  languages['x-default'] = getUrl(defaultLocale);

  return {
    alternates: {
      canonical: getUrl(locale),
      languages,
    },
  };
}
```

あとは、任意のページで次のように使用します：

```tsx title="app/[locale]/about/page.tsx"
import { getI18NMetadata } from '@/lib/i18n-metadata';

export async function generateMetadata() {
  return await getI18NMetadata('/about');
}
```

これにより、カノニカルタグとすべての hreflang タグを 1 回の呼び出しでまとめて生成できます。

***

## 5. 翻訳済みメタデータ

検索エンジンは、ページのタイトルと説明文を検索結果に表示します。
フランス語のページなのにこれらが英語のままだと、ユーザーにクリックされにくくなるうえ、Google が検索順位を下げることもあります。

メタデータの文字列を翻訳するには、gt-next の [`getGT`](/docs/react/nextjs/reference/functions/get-gt) 関数を使用します：

```tsx title="app/[locale]/about/page.tsx"
import { getGT } from 'gt-next/server';
import { getI18NMetadata } from '@/lib/i18n-metadata';

export async function generateMetadata() {
  const t = await getGT();
  const i18nMeta = await getI18NMetadata('/about');

  return {
    title: t('About Us'),
    description: t('Learn about our mission and team.'),
    ...i18nMeta,
  };
}
```

これにより、検索結果にローカライズされたタイトルとディスクリプションが表示され、
英語以外の検索クエリでのクリック率が大幅に向上します。

***

## 6. 多言語サイトマップ

サイトマップを用意すると、検索エンジンが各言語版を含むすべてのページを見つけやすくなります。
多言語サイトでは、サイトマップにも hreflang 注釈を含めるようにしましょう。

Next.js では、`sitemap.ts` ファイルを使って[サイトマップをプログラムで生成](https://nextjs.org/docs/app/api-reference/file-conventions/metadata/sitemap)できます。

```ts title="app/sitemap.ts"
import { MetadataRoute } from 'next';

const BASE_URL = 'https://example.com';
const LOCALES = ['en', 'fr', 'es'];
const DEFAULT_LOCALE = 'en';
const PAGES = ['/', '/about', '/blog', '/contact'];

export default function sitemap(): MetadataRoute.Sitemap {
  return PAGES.flatMap((path) => {
    const getUrl = (locale: string) => {
      const prefix = locale === DEFAULT_LOCALE ? '' : `/${locale}`;
      return `${BASE_URL}${prefix}${path === '/' ? '' : path}`;
    };

    const languages: Record<string, string> = {};
    for (const locale of LOCALES) {
      languages[locale] = getUrl(locale);
    }

    return LOCALES.map((locale) => ({
      url: getUrl(locale),
      lastModified: new Date(),
      alternates: { languages },
    }));
  });
}
```

これにより、ページとロケールの組み合わせごとに1つのエントリを持つサイトマップが生成されます。
各エントリには、すべての言語版を指す hreflang 注釈が含まれます。

***

## チェックリスト

ここまでの内容を簡単にまとめます。

| SEO 要件           | 実装方法                                                                                                              |
| ---------------- | ----------------------------------------------------------------------------------------------------------------- |
| URL 内のロケール       | `[locale]` 動的セグメントと [`createNextMiddleware()`](/docs/react/nextjs/reference/functions/create-next-middleware) を併用 |
| HTML の `lang` 属性 | ルートレイアウトで [`useLocale()`](/docs/react/reference/hooks/use-locale) を使用                                             |
| カノニカル URL        | [`getLocale()`](/docs/react/nextjs/reference/functions/get-locale) と Next.js メタデータ API の `alternates.canonical`   |
| Hreflang タグ      | Next.js メタデータ API の `alternates.languages` にすべてのサポート対象のロケールを指定                                                    |
| 翻訳済みメタデータ        | ページのタイトルと説明に [`getGT()`](/docs/react/nextjs/reference/functions/get-gt) を使用                                       |
| 多言語サイトマップ        | ロケールごとのエントリと hreflang 代替リンクを含む `sitemap.ts`                                                                       |

***

まずは [`gt-next` クイックスタート](/docs/react/nextjs-quickstart)で国際化のスタック全体をセットアップしましょう。続いて、[ミドルウェアガイド](/docs/react/nextjs/app-router-middleware)を参考にルーティングを設定し、[静的サイト生成](/docs/react/nextjs/app-router-static-site-generation)で多言語ページを生成したうえで、[右から左に書く言語への対応](/docs/react/guides/managing-locales)を追加してください。

## Related questions

- [翻訳ファイルなしで i18n はできますか？](https://generaltranslation.com/ja/kb/i18n-without-translation-files.mdx): はい。gt-react または gt-next を使えば、コンテンツは `<T>` コンポーネントで囲んだままコンポーネント内にインラインで記述でき、翻訳はビルド時に出力として生成されます。そのため、キーやロケールごとの JSON ファイルを作成したり、同期を保ったりする必要はありません。
- [開発者にとって最適なローカライゼーションソフトウェアとは？](https://generaltranslation.com/ja/kb/best-localization-software.mdx): ライブラリ、翻訳管理システム、翻訳ベンダーを個別に組み合わせるのではなく、コード内のi18nライブラリから翻訳、配信まで、パイプライン全体を1つでカバーできるシステムを選びましょう。
- [多言語アプリをローンチする前に何を確認すべきか？](https://generaltranslation.com/ja/kb/multilingual-app-launch-checklist.mdx): 多言語アプリをローンチする前に、サポート対象のすべてのロケールで次の9項目をテストしてください：エラー時を含むユーザージャーニー全体、言語検出と言語の切り替え、変数と複数形、通貨とタイムゾーン、テキストの伸長、右から左のレイアウト、アクセシビリティ、本番環境での翻訳の配信、SEOのためのクロール可能な言語別URL。各項目には明確な合格条件が必要です。

## Previous and next questions

- Previous question: [JSX 内の条件付きテキストはどう翻訳すればよいですか？](https://generaltranslation.com/ja/kb/translate-conditional-jsx.mdx)
- Next question: [開発者にとって最適なローカライゼーションソフトウェアとは？](https://generaltranslation.com/ja/kb/best-localization-software.mdx)

## Sitemap

See the [Knowledge Base sitemap](https://generaltranslation.com/ja/kb/sitemap.md) for every article.
