# General Translation React SDKs (gt-react, gt-next, gt-react-native): ロケールのエイリアスに関する SEO の管理
URL: https://generaltranslation.com/ja/docs/react/nextjs/locale-alias-seo.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: 検索エンジン向けに正規の言語メタデータを公開しながら、Next.js の URL でカスタムロケールエイリアスを使用する方法。

ロケールのエイリアスを使用すると、翻訳では正規の BCP 47 コード `zh` を使用しつつ、ルートには `/cn` のようなカスタムセグメントを使用できます。`gt-next` は翻訳とルーティングのマッピングを解決しますが、`<html lang>`、正規 URL、言語の代替リンク、サイトマップのエントリについては、引き続きアプリ側で対応する必要があります。

## エイリアス を設定する [#configure]

[`customMapping`](/docs/react/reference/config#custom-mapping) を使用して、URL のロケールを対応する正規コードにマッピングします。

```json title="gt.config.json"
{
  "defaultLocale": "en-US",
  "locales": ["en-US", "cn", "ja"],
  "customMapping": {
    "cn": {
      "code": "zh",
      "name": "Mandarin"
    }
  }
}
```

ミドルウェアは `/cn` をローカライズされたルートとして受け入れます。General Translation は正規ロケールが必要な場合、`cn` を `zh` に解決します。

SEO コードでは、これら 2 つの値を区別して使用してください。

* `/cn/about` のようなルート URL では、**エイリアス**を使用します。
* `lang` と `hreflang` では、`zh` のように**正規 BCP 47 コード**を使用します。

## ドキュメントの言語を設定する [#document-language]

`<html lang>` 属性を設定する前に、ルートのロケールを解決します。

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

export default async function LocaleLayout({
  children,
  params,
}: {
  children: React.ReactNode;
  params: Promise<{ locale: string }>;
}) {
  const { locale } = await params;
  const canonicalLocale = resolveCanonicalLocale(locale);

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

この変換を行わないと、`/cn` ルートでは `lang="cn"` がレンダリングされますが、これは有効な中国語の言語タグではありません。

## ページの代替リンクを公開 [#page-alternates]

Next.js は `metadata.alternates.languages` から `hreflang` リンクを出力します。オブジェクトのキーには 正規 コードを、値には alias ベースのルートを使用します。

このホームページの例は、ローカライズされたページに記述します。ネストされた各ページの metadata で、ルート固有の URL を構築します。

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

const locales = ['en-US', 'cn', 'ja'];
const baseUrl = 'https://example.com';

export async function generateMetadata({
  params,
}: {
  params: Promise<{ locale: string }>;
}): Promise<Metadata> {
  const { locale } = await params;
  const languages = Object.fromEntries(
    locales.map((urlLocale) => [
      resolveCanonicalLocale(urlLocale),
      `${baseUrl}/${urlLocale}`,
    ])
  );

  return {
    alternates: {
      canonical: `${baseUrl}/${locale}`,
      languages: {
        ...languages,
        'x-default': `${baseUrl}/en-US`,
      },
    },
  };
}
```

これにより、言語が `zh` で URL は `/cn` のままの代替ページが生成されます。正規言語キーごとに追加する URL は 1 つだけにしてください。そうしないと、後のエントリによって先のエントリが上書きされます。

`/cn` と `/zh` の両方で同じページをレンダリングできる場合は、優先する URL を 1 つ選び、両方のページの `canonical` 値をその URL に設定してください。これにより、同じローカライズ済みコンテンツに対するインデックス可能な重複 URL の公開を防げます。

## サイトマップに代替リンクを追加 [#sitemap]

`app/sitemap.ts` にも同じマッピングを適用します：

```ts title="app/sitemap.ts"
import type { MetadataRoute } from 'next';
import { resolveCanonicalLocale } from 'gt-next/server';

const locales = ['en-US', 'cn', 'ja'];
const pages = ['', '/about', '/pricing'];
const baseUrl = 'https://example.com';

export default function sitemap(): MetadataRoute.Sitemap {
  return pages.map((page) => ({
    url: `${baseUrl}/en-US${page}`,
    alternates: {
      languages: {
        ...Object.fromEntries(
          locales.map((urlLocale) => [
            resolveCanonicalLocale(urlLocale),
            `${baseUrl}/${urlLocale}${page}`,
          ])
        ),
        'x-default': `${baseUrl}/en-US${page}`,
      },
    },
  }));
}
```

ページメタデータとサイトマップで、言語と URL の対応を統一してください。ローカライズされたページが存在する場合にのみ、代替ページを含めます。

## Next steps

- /docs/react/nextjs/app-router-middleware
- /docs/react/nextjs/app-router-static-site-generation
- /docs/react/nextjs/registering-request-locales
- /docs/react/nextjs/cache-components

## Sitemap

See the full [sitemap](https://generaltranslation.com/sitemap.md) for all pages.
