# gt-next: General Translation Next.js SDK: 区域设置别名与 SEO
URL: https://generaltranslation.com/zh/docs/next/guides/locale-aliases.mdx
---
title: 区域设置别名与 SEO
description: 使用自定义区域设置别名进行 URL 路由,同时保持搜索引擎要求的 BCP 47 合规性
---
区域设置别名允许你在 URL 中使用自定义区域设置代码 (例如用 `/cn/` 代替 `/zh/`) ,同时让 SEO 元数据继续符合搜索引擎要求的 [BCP 47 标准](https://www.w3.org/International/articles/language-tags/)。
## 为什么要使用别名?
像 `zh` (中文) 或 `zh-Hant` (繁体中文) 这样的 BCP 47 区域设置代码,是 Web 上标识语言的标准。
不过,出于品牌、可读性或区域方面的考虑,你可能希望在 URL 路径中使用不同的代码——例如,面向中文用户时使用 `/cn/` 而不是 `/zh/`。
GT 通过 `gt.config.json` 中的**自定义映射**支持这一点。别名用于路由和 URL 路径,而标准区域设置 BCP 47 代码则用于所有搜索引擎需要识别的地方。
**SEO 要求:**搜索引擎只识别 [BCP 47 区域设置代码](https://www.w3.org/International/articles/language-tags/)。
在 `hreflang` 属性或 `` 中使用像 `cn` 这样的非标准代码,会导致搜索引擎忽略你的区域设置信号。
## Setup
### 第 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` 的用户会直接看到中文内容——无需对 routing 做任何特殊处理。
## SEO 所需的 BCP 47 合规性
虽然别名在路由中可以无缝使用,但有三个地方你**必须**使用标准区域设置对应的 BCP 47 代码,而不能使用别名:
1. `` 标签上的 `lang` 属性
2. 页面元数据中的备用链接标签
3. 站点地图中的备用条目
GT 提供了 `resolveCanonicalLocale()` 方法,用于将别名转换回其对应的 BCP 47 代码。你可以通过 `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 布局中,先确定区域设置,再将其传递给 `` 标签:
```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 代码作为键构建替代项
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,
},
};
}
```
这会在页面头部生成正确的 `` 标签:
```html
```
请注意,`hreflang` 的值使用的是标准区域设置代码 (`zh`,不是 `cn`) ,而 `href` URL 仍使用别名路径 (`/cn/`) 。
### 3. Sitemap 替代项
如果你使用[动态 sitemap](https://nextjs.org/docs/app/api-reference/file-conventions/metadata/sitemap),请套用相同的 pattern:
```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) => {
// 使用标准区域设置代码构建语言替代项
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)