---
title: Next.js 多语言 SEO 实践：hreflang、站点地图与语言回退机制
description: >-
  本文提供了一个实用的指南，介绍如何在多语言 Next.js 网站中设置 hreflang 替代链接、x-default、本地化站点地图、翻译后的 slug
  以及语言回退链。
publishedAt: '2026-07-08'
updatedAt: '2026-07-08'
noindex: false
canonicalPath: /zh-CN/blog/multilingual-seo-hreflang-sitemaps-fallbacks
---
内容翻译只是多语言 SEO 的第一步。你还需要向搜索引擎清晰地传达：哪个 URL 对应哪种语言，哪个是默认版本，以及当某个特定语言暂无翻译时该显示什么。如果设置不当，Google 可能会在英文搜索结果中展示你的法文页面，或者将十种语言的翻译版本视为重复内容。

以下是我们推荐的检查清单。得益于 Scribe 对内容的全面掌握，大部分配置都可以自动生成。

## 为所有页面配置 hreflang 替代链接

每一个本地化页面都应该声明它的所有兄弟版本（包括它自己），并指定一个指向无匹配语言版本的 `x-default`。在 Next.js 中，这是通过页面元数据的 `alternates.languages` 字段来实现的。

最让人头疼的往往是翻译后的 slug。如果英文的 `/docs/getting-started` 在法文中变成了 `/fr/docs/premiers-pas`，你的替代链接就必须使用本地化后的 slug，而不是简单地在英文 slug 前加上语言前缀。Scribe 会将翻译后的 slug 与每条翻译数据一同保存。借助运行时的 `alternates()` 辅助函数，你可以获取每个文档完整的映射表。这样一来，元数据代码就变成了一个简单的循环，再也不用手动维护复杂的查找表了。

以下两个原则能帮你避免常见错误：

- hreflang 必须是双向的。如果法文页面指向了德文版本，德文页面也必须指向法文版本。通过统一的数据源来生成双向链接，就能确保这一点。
- Canonical URL 必须指向各语言版本自身的链接。法文页面的 canonical 链接就是法文的 URL。如果把所有语言的 canonical 链接都指向英文版，就等于是在告诉 Google 从索引中剔除你的翻译内容。

## 支持多语言的站点地图

站点地图中的每个 URL 条目都应包含相同的替代链接以及 `x-default`。Scribe 的 `sitemapEntries()` 为每个文档返回一个包含所有语言 URL 的条目，并根据内置的 `publishedAt` 和 `updatedAt` 字段自动计算 `lastmod`。这意味着站点地图始终保持最新状态，无需手动更新日期。

当你停用某个文档时，它不应该直接消失。Scribe 在每个类型下维护一个 `_redirects.json` 文件，将被停用的 URL 通过 301 重定向到它们在各语言下的替代页面，从而保留你辛苦积攒的链接权重。

## 语言回退取代 404 错误

如果你翻译了法文版页面，但没有专门针对加拿大法语（`fr-CA`）进行翻译，那么当用户访问 `/fr-CA/guide` 时该显示什么？直接返回 404 错误白白浪费了现有的翻译资源，而默默展示英文内容又会让读者感到困惑。

Scribe 能够自动处理回退链：区域性语言在回退到英文之前，会优先回退到它的基础语言。例如，`fr-CA` 会先尝试 `fr`，然后再尝试 `en`。`zh-Hant-TW` 会先尝试 `zh-Hant`，接着是 `zh`，最后才是 `en`。运行时的 `actualLocale` 字段会报告实际显示的语言版本，因此你的布局代码可以如实地标注页面内容。预渲染参数包含了回退 URL，确保这些页面在构建时就已经存在。

## 元数据也是重要内容

标题和 meta 描述直接影响排名，因此它们值得与正文同等的翻译待遇。在 Scribe 中，它们被处理为普通的易译前置数据字段，会像其他内容一样进行哈希处理和验证。我们的翻译提示词专为创译（transcreation）而非逐字直译而设计，这对于只有 60 个字符的标题标签来说尤为关键。

## 总结

其实这些都不算什么黑科技，本质上就是做账：替代链接、规范链接、站点地图、重定向和回退机制，所有这些都源于一个核心问题——“哪个文档在哪个语言的哪个 URL 下存在”。如果一个 CMS 能够将翻译作为一等数据来存储，它就能在一个地方回答这个问题。而如果你要在托管 CMS、翻译平台和路由器之间手动连接这些信息，多语言 SEO 往往就是在这个环节掉链子。

想了解各个组件如何协同工作，请参阅[运行时 API 指南](/docs/runtime-api)，或者从[快速入门](/docs/getting-started)开始你的旅程。
