如何在 Next.js(Pages Router)v16 中设置文档语言

为浏览器和屏幕阅读器声明页面语言

问题

网页需要向浏览器、搜索引擎和辅助技术声明其主要语言。如果没有明确声明语言,这些工具只能猜测内容的语言。屏幕阅读器会默认使用用户系统的语言,这会导致当内容语言不一致时发音错误。浏览器由于缺乏源语言信息,无法准确地提供翻译功能。搜索引擎在为正确的语言受众建立索引时会遇到困难,降低了使用该语言搜索的用户的可发现性。

解决方案

在根 lang 属性的 <html> 元素上设置页面的主要语言。在 Next.js Pages Router 中,可以通过创建自定义 Document 组件来包裹应用的 HTML 结构来实现。lang 属性接受标准语言代码,告知浏览器、辅助技术和搜索引擎内容所用的语言,从而实现正确发音、合适的翻译提示和准确的索引。

步骤

1. 创建自定义 document 文件

pages 目录下创建名为 _document.js(或 TypeScript 版本为 _document.tsx)的文件。该文件允许你自定义包裹应用每个页面的 HTML 文档结构。

import { Html, Head, Main, NextScript } from "next/document";

export default function Document() {
  return (
    <Html lang="en">
      <Head />
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  );
}

来自 next/documentHtml 组件接受 lang 属性,用于设置根 HTML 元素的语言属性。请将 "en" 替换为你的内容语言代码。

2. 使用合适的语言代码

语言代码遵循 UTS Locale Identifiers 标准格式:language-region-script,其中地区和书写系统为可选项。大多数情况下,请使用两个字母的 ISO 639-1 语言代码。

import { Html, Head, Main, NextScript } from "next/document";

export default function Document() {
  return (
    <Html lang="fr">
      <Head />
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  );
}

常见示例包括英语的 "en",西班牙语的 "es",法语的 "fr",德语的 "de",以及日语的 "ja"。如有需要,也可以包含区域变体,例如 "en-US""en-GB"

3. 根据 locale 动态设置语言

如果你的应用通过 Next.js i18n 路由支持多语言环境,可以从路由上下文中获取当前 locale,以动态设置语言。

import Document, {
  Html,
  Head,
  Main,
  NextScript,
  DocumentContext,
  DocumentInitialProps,
} from "next/document";

export default class MyDocument extends Document {
  static async getInitialProps(
    ctx: DocumentContext,
  ): Promise<DocumentInitialProps> {
    const initialProps = await Document.getInitialProps(ctx);
    return initialProps;
  }

  render() {
    return (
      <Html lang={this.props.locale}>
        <Head />
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

使用 Next.js 内置的 i18n 配置时,框架会自动提供 locale 并更新 lang 属性。当在 next.config.js 中配置了 i18n 后,Document 组件上会有 locale 属性可用。