静态生成的Next.js页面中的动态HTML lang属性

时间:2020-06-10 06:37:28

标签: reactjs next.js

我正在Next.Js项目中的多语言静态着陆页上工作。 我的目标是具有以下结构:

  • /->英文主页
  • / de->德语主页
  • / it->意大利语主页

我通过以下方式构建它:

pages / index.js

export default function Home() {
  return <div>English Homepage</div>
}

pages / de.js

export default function Home() {
  return <div>German page</div>
}

为了使网站易于访问,我想相应地设置html lang。

pages / _document.js

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

  render() {
    return (
      <Html lang={???}>
        <Head />
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    )
  }
}

如何指定每页的语言? 我尝试使用getInitialProps,但是这迫使我的网站成为SSR。

3 个答案:

答案 0 :(得分:0)

嘿,也许不是最好的解决方案,但是应该可以,您可以在from django.contrib.auth import get_user_model from graphene_django.utils import GraphQLTestCase from graphql_jwt.shortcuts import get_token class ExampleTests(GraphQLTestCase): def test_create_member_mutation(self): token = get_token(get_user_model().objects.get(pk=1)) headers = {"HTTP_AUTHORIZATION": f"JWT {token}"} graphql = ''' mutation createMember($firstName: String) { createMember(firstName: $firstName) { member { id } } } ''' respsone = self.query( graphql, op_name='createMember', variables={'firstName': 'Foo'}, headers=headers, ) self.assertResponseNoErrors(response) 页面上使用dangerousAsPath属性,并根据路径确定_document.jsx

lang

同样,应该为此提供更好的解决方案。干杯。

编辑: render() { return ( <Html lang={this.props.dangerousAsPath === '/de' ? 'de' : 'en'}> {/* ... */} </Html> ) } 可能会是removed,如果这样的话,您可以使用dangerousAsPath直到找到更好的选择为止。

答案 1 :(得分:0)

使用getInitialProps确实是正确的。与正常页面中的getInitialProps会禁用自动静态优化不同,getInitialProps中的_document.js具有没有这种效果。

这是因为Document仅在服务器中呈现。在客户端转换期间或静态优化页面时,不会调用Document的{​​{1}}函数。 More about its technical details

这就是为什么您可以使用它向页面中插入getInitialProps道具并仍然获得静态优化的好处的原因。

lang

要在客户端转换期间也更新// _document.js ... static async getInitialProps(ctx) { const initialProps = await Document.getInitialProps(ctx); const { pathname } = ctx; const lang = pathname.startsWith("/de") ? "de" : "en"; return { ...initialProps, lang }; } ... 属性,还必须在lang中设置一个useRouter钩子以观察路由更改:

_app.js

我已经为您创建了此CodeSandbox作为演示。

Edit dynamic-html-lang-property-in-statically-generated-next-js-pages

将其下载到本地计算机并检查代码。在// _app.js import React, { useEffect } from "react"; import { useRouter } from "next/router"; export default function MyApp({ Component, pageProps }) { const { pathname } = useRouter(); const lang = pathname.startsWith("/de") ? "de" : "en"; useEffect(() => { document.documentElement.lang = lang; }, [lang]); return <Component {...pageProps} />; } 之后,运行npm install。您将从构建日志中看到“ /”和“ de”都是静态的。运行npm run build并查看页面源,您将看到npm start属性已在HTML中正确设置。

答案 2 :(得分:0)

以您的示例为例,如果您假设自己的网址将始终遵循此格式 https://somedomain.com/{lang}/everything-else

然后您可以像这样从网址中提取lang

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

    // `ctx.req.path` would be of pattern: `/{lang}/everything-else`
    // ctx.req.path.split('/') --> ['', 'lang', 'everything-else']
    const locale = ctx.req.path.split('/')[1]

    return { ...initialProps, locale }
  }

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

作为一个旁注,我建议探索next-i18next包,以获取在next.js中实现本地化的更标准方法