# gt-next: General Translation Next.js SDK: ロケールエイリアスとSEO
URL: https://generaltranslation.com/ja/docs/next/guides/locale-aliases.mdx
---
title: ロケールエイリアスとSEO
description: 検索エンジン向けの BCP 47 準拠を維持しつつ、URLルーティングにカスタムのロケールエイリアスを使用します
---
ロケールエイリアスを使うと、URL でカスタムのロケールコード (例: `/zh/` の代わりに `/cn/`) を使用しながら、検索エンジンが求める [BCP 47 標準](https://www.w3.org/International/articles/language-tags/) に準拠した SEO メタデータを維持できます。
## なぜエイリアスが必要なのか?
`zh` (中国語) や `zh-Hant` (繁体字中国語) のような BCP 47 ロケールコードは、Web上で言語を識別するための標準です。
ただし、ブランディング、わかりやすさ、または地域上の理由から、URL パスでは別のコードを使いたいことがあります。たとえば、中国語圏の利用者向けに `/zh/` ではなく `/cn/` を使うケースです。
GT では、`gt.config.json` の **カスタムマッピング** によってこれをサポートしています。エイリアスはルーティングと URL パスに使用され、正規の BCP 47 コードは検索エンジンが参照する箇所で使用されます。
**SEO 要件:** 検索エンジンが認識するのは [BCP 47 ロケールコード](https://www.w3.org/International/articles/language-tags/) のみです。
`hreflang` 属性や `` に `cn` のような標準外コードを使うと、検索エンジンはロケール指定を無視します。
## セットアップ
### ステップ1: カスタムマッピングを設定する
各エイリアスごとに、`gt.config.json` に `customMapping` 項目を追加します:
```json title="gt.config.json"
{
"defaultLocale": "en-US",
"locales": ["en-US", "cn", "ja", "zh-Hant"],
"customMapping": {
"cn": {
"code": "zh",
"name": "Mandarin"
}
}
}
```
ここで、`cn` は URL とミドルウェアルーティングで使うエイリアスで、`zh` は正規の BCP 47 コードです。
### ステップ 2: middleware を通常どおり使用する
[middleware](/docs/next/guides/middleware) と `[locale]` ダイナミックルートは、エイリアスコードでもそのまま動作します。`/cn/about` にアクセスしたユーザーには中国語のコンテンツが配信されるため、ルーティング用の特別な処理は不要です。
## SEO における BCP 47 準拠
エイリアスはルーティングでは問題なく機能しますが、次の 3 か所では、エイリアスではなく正規の BCP 47 コードを**必ず**使用する必要があります。
1. `` タグの `lang` 属性
2. ページのメタデータ内の代替リンクタグ
3. サイトマップ内の代替エントリ
GT には、エイリアスを対応する BCP 47 コードに変換する `resolveCanonicalLocale()` メソッドがあります。これは `gt-next/server` の `getGTClass` 経由で利用できます。
```ts
import { getGTClass } from 'gt-next/server';
const gtInstance = getGTClass();
const canonicalLocale = gtInstance.resolveCanonicalLocale('cn');
// 戻り値: "zh"
```
エイリアスでないロケールでは、`resolveCanonicalLocale()` は入力をそのまま返します。
```ts
gtInstance.resolveCanonicalLocale('ja'); // "ja"
gtInstance.resolveCanonicalLocale('en-US'); // "en-US"
```
### 1. HTML `lang` 属性
`` 属性は、そのページの言語をブラウザや検索エンジンに伝えます。有効な BCP 47 コードである必要があります。
root layout では、`` タグに渡す前にロケールを特定します:
```tsx title="app/[locale]/layout.tsx"
import { getGTClass } from 'gt-next/server';
export default function RootLayout({
children,
params,
}: {
children: React.ReactNode;
params: { locale: string };
}) {
const gtInstance = getGTClass();
const canonicalLocale = gtInstance.resolveCanonicalLocale(params.locale);
return (
{children}
);
}
```
これがないと、`/cn/about` のページが誤って `` としてレンダリングされてしまい、検索エンジンに認識されません。
### 2. メタデータの代替リンク
代替リンクは、そのページの他言語版が存在することを検索エンジンに伝えます。`hreflang` 属性には BCP 47 コードを使用する必要があります。
```tsx title="app/[locale]/layout.tsx"
import type { Metadata } from 'next';
import { getGTClass } from 'gt-next/server';
export async function generateMetadata({
params,
}: {
params: { locale: string };
}): Promise {
const gtInstance = getGTClass();
const locales = ['en-US', 'cn', 'ja', 'zh-Hant'];
// 正規のBCP 47コードをキーとしてalternatesを構築する
const languages: Record = {};
for (const locale of locales) {
const canonical = gtInstance.resolveCanonicalLocale(locale);
languages[canonical] = `https://example.com/${locale}`;
}
// デフォルトロケール用にx-defaultを追加する
languages['x-default'] = 'https://example.com';
return {
alternates: {
canonical: `https://example.com/${params.locale}`,
languages,
},
};
}
```
これにより、ページのheadに正しい``タグが出力されます。
```html
```
`hreflang` の値には正規コード (`cn` ではなく `zh`) が使われますが、`href` の URL では引き続きエイリアスのパス (`/cn/`) が使われる点に注意してください。
### 3. サイトマップの代替リンク
[動的サイトマップ](https://nextjs.org/docs/app/api-reference/file-conventions/metadata/sitemap)を使用している場合も、同じパターンを適用してください:
```ts title="app/sitemap.ts"
import type { MetadataRoute } from 'next';
import { getGTClass } from 'gt-next/server';
export default function sitemap(): MetadataRoute.Sitemap {
const gtInstance = getGTClass();
const locales = ['en-US', 'cn', 'ja', 'zh-Hant'];
const baseUrl = 'https://example.com';
const pages = ['', '/about', '/pricing'];
return pages.map((page) => {
// 正規コードで言語の代替URLを構築する
const languages: Record = {};
for (const locale of locales) {
const canonical = gtInstance.resolveCanonicalLocale(locale);
languages[canonical] = `${baseUrl}/${locale}${page}`;
}
return {
url: `${baseUrl}${page}`,
lastModified: new Date(),
alternates: {
languages,
},
};
});
}
```
これにより、適切な`hreflang`属性を持つサイトマップXMLが生成されます。
```xml
https://example.com
```
## よくある間違い
| 間違い | 影響 | 修正方法 |
| ----------------------------- | ---------------------- | ------------------------------------------------- |
| `` でエイリアスコードを使う | 検索エンジンがページの言語を判別できない | `lang` 属性には `resolveCanonicalLocale()` を使用します |
| `hreflang` でエイリアスコードを使う | 検索エンジンに代替リンクが無視される | `hreflang` の値には `resolveCanonicalLocale()` を使用します |
| `x-default` の代替リンクがない | 一覧にない言語のユーザー向けの案内先がない | デフォルトロケールの URL を指す `x-default` を追加します |
| HTML とサイトマップで代替リンクの内容が一致していない | 矛盾したシグナルによってクローラーが混乱する | 両方で `resolveCanonicalLocale()` を使用します |
## 次のステップ
* ロケールに基づく URL ルーティングについては [middleware](/docs/next/guides/middleware) を参照してください
* [`resolveCanonicalLocale`](/docs/core/class/methods/locales/resolve-canonical-locale) の API リファレンスを参照してください
* `gt.config.json` で [`customMapping`](/docs/cli/reference/config) を設定してください