Next.js 多语言 SEO 实践:hreflang、站点地图与语言回退机制
本文提供了一个实用的指南,介绍如何在多语言 Next.js 网站中设置 hreflang 替代链接、x-default、本地化站点地图、翻译后的 slug 以及语言回退链。
View as Markdown内容翻译只是多语言 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 指南,或者从快速入门开始你的旅程。