如何在 NextJs Document 上动态设置 HTML lang 属性?

Posted

技术标签:

【中文标题】如何在 NextJs Document 上动态设置 HTML lang 属性?【英文标题】:How to set HTML lang attribute dynamically on NextJs Document? 【发布时间】:2020-08-02 06:28:48 【问题描述】:

我有一个多语言网站,需要根据每个页面的语言设置 html lang 属性。

我尝试在上下文中传递值,但在页面更改时不更新。

这里是当前代码:

import Document,  Html, Head, Main, NextScript  from 'next/document'
import GlobalContext , eLanguage from '../components/GlobalContext' //my global context 

export default class MyDocument extends Document 

static async getInitialProps(ctx) 

  const initialProps = await Document.getInitialProps(ctx)
  return  ...initialProps 

static contextType = GlobalContext;
render() 

  console.debug('Started')
  console.debug('language:'+ this.context.language) 

  return (
    <Html lang=eLanguage[this.context.language]> //if the first page loaded as lang 'en' it sets 'en' and apply to all other pages.
      <Head>
      </Head>
      <body>       
        <Main />
        <NextScript />
      </body>
    </Html>
  )

更新: 从页面路由可以推断出每个页面的语言

【问题讨论】:

【参考方案1】:

Next 10 支持Internationalized Routing 并将动态添加lang,为您留下:

<Html>
  <Head />
  <body>       
    <Main />
    <NextScript />
  </body>
</Html>

【讨论】:

【参考方案2】:

如果您使用next/head,您可以将语言设置为html标签。您传递给 Head 组件的任何内容都将放置在 或 中。

Next Head 的工作方式类似于 React Helmet,因此对于您的情况,您可以按照以下方式进行操作:

创建一个组件并从“next/head”导入Head 在 Head 标记内,您将 添加到组件中。

然后您可以将所需的语言传递给该组件,然后在所需的页面上导入该组件。

import React from "react"
import Head from "next/head"

const Language = (title, lang) => (
  <Head>
    <html lang=lang />
    <title>title</title>
  </Head>
)

export default Language

该 html 位将被注入到标签内。

请注意,即使我们像这样注入它,控制台也会记录以下错误:TypeError: n is null

【讨论】:

我在控制台上收到此错误:head-manager.js?0ea4:2 警告:缺少下一个头数。 err.sh/next.js/next-head-count-missing。在任何一种情况下,该组织都不是可行的方法。 还要注意 Html 标签是 Head 标签的父标签。我不认为 Head 组件意味着以这种方式使用。 谢谢,这是正确的答案。与 nextjs 文档中提供的相同。 @GabrielLinassi,这与docs 中的不完全相同,它说您应该在_document 中执行此操作。在其他地方做技术上是可行的,但也许你不能依靠它来继续工作,并且它会让控制台减弱 Warning: next-head-count is missing 如上所述。 @ArneHugo 没错。感谢您的指正。我在这里检查了我的代码,它也在 _document 上定义。【参考方案3】:

我认为这里最好的解决方案是使用自定义 ./pages/_document.js 文件并覆盖文档本身。

import Document,  Html, Head, Main, NextScript  from 'next/document'

class MyDocument extends Document 
  static async getInitialProps(ctx) 
    const initialProps = await Document.getInitialProps(ctx)
    return  ...initialProps 
  

  render() 
    return (
      <Html lang="en">
        <Head />
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    )
  


export default MyDocument

更多解释可以在这里找到:https://nextjs.org/docs/advanced-features/custom-document

【讨论】:

【参考方案4】:

使用文档对象的 lang 属性可以这样设置:

var language= ...
switch (language) 
    case en:  document.documentElement.lang = 'en-us'; break;
    ...

这个 lang 属性不会在初始 html 上设置,在页面水合之前,但仍会通过 chrome "hreflang" 审计检查。

【讨论】:

【参考方案5】:

我通过将它添加到 next.config.js 文件来实现这一点:

i18n: 
// These are all the locales you want to support in
// your application
locales: ['en-US'],
// This is the default locale you want to be used when visiting
// a non-locale prefixed path e.g. `/hello`
defaultLocale: 'en-US' 

我不需要创建自定义 _document.js

【讨论】:

【参考方案6】:

您可以使用 React useEffect 挂钩来设置文档的语言,而无需更改 Next.js 自身生成 HTML 标记的方式。

在您的页面组件或其他适当的组件中,包含 useEffect 挂钩:

import useEffect from "react";

然后加上钩子:

const MyPage = () => 
  useEffect(() => 
    document.documentElement.lang = "en-us";
  );
  // The rest of your component

这通过了 Lighthouse 对“hreflang”的检查,如果您的网站有多种语言,您可以使用它来设置每个页面的页面语言。

【讨论】:

【参考方案7】:

要覆盖默认的 nextjs 设置,请创建文件 ./pages/_document.js 并扩展 Document 类,如下所示:

import Document,  Html, Head, Main, NextScript  from 'next/document'

class MyDocument extends Document 
  static async getInitialProps(ctx) 
    const initialProps = await Document.getInitialProps(ctx)
    return  ...initialProps 
  

  render() 
    return (
      <Html>
        <Head />
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    )
  


export default MyDocument

允许自定义属性作为 props,例如 lang:

<Html lang="en">

您可以在此处阅读有关自定义文档的更多信息:https://nextjs.org/docs/advanced-features/custom-document

【讨论】:

以上是关于如何在 NextJs Document 上动态设置 HTML lang 属性?的主要内容,如果未能解决你的问题,请参考以下文章

NextJS - Google 字体未加载或显示在网站上

NEXTJS - 公共图像未显示在动态路线上

NextJS:如何在根处理多个动态路由

使用 Nextjs 和 GSAP 悬停在标题上动态显示图像

如何在 NextJS+React 中使用 api 生成的内容创建用户可自定义的动态 url?

无法使用样式组件的 Nextjs 组件(链接)