# 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)