Dynamic HTML lang property in statically generated Next.js pages

拈花ヽ惹草 提交于 2021-02-19 05:39:46

问题


I'm working on a multilange static landing page in a Next.Js project. My goal is to have the following structure:

  • / -> English Home page
  • /de -> German Home page
  • /it -> Italian Home page

I'm building it in the following way:

pages/index.js

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

pages/de.js

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

In order to make the website accessible, I would like to set html lang accordingly.

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>
    )
  }
}

How can I specify the language per page? I tried with getInitialProps, but that forces my website to be SSR.


回答1:


You are indeed right about using getInitialProps. Unlike getInitialProps in normal pages that will disable Automatic Static Optimization, getInitialProps in _document.js has no such effect.

It is because Document is only rendered in the server. Document's getInitialProps function is not called during client-side transitions, nor when a page is statically optimized. More about its technical details

That's why you can use it to inject a lang prop into pages and still get the benefits of static optimization.

// _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 };
}
...

To have the lang attribute also updated during client-transitions, you have to also set up an useRouter hook in _app.js to watch the route change:

// _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} />;
}

I have created this CodeSandbox for you as a demo.

Download it to your local machine and inspect the code. After npm install, run npm run build. You will see from the Build Logs that both "/" and "de" are static. Run npm start and view the page source, you will see the lang attribute is set properly in the HTML.




回答2:


Hey maybe not the best solution, but should work, you can use dangerousAsPath prop on _document.jsx page and decide the lang based on the path.

render() {
  return (
   <Html lang={this.props.dangerousAsPath === '/de' ? 'de' : 'en'}>
     {/* ... */}
   </Html>
  )
}

Again there probably should be a better solution for this. Cheers.

Edit: There might be a chance that dangerousAsPath will be removed, if so you can use this.props.__NEXT_DATA__.page until you find a better option.




回答3:


For your example, if you assume your urls will always follow this pattern https://somedomain.com/{lang}/everything-else,

then you could extract the lang from the url like:

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>
    )
  }
}

As a side-note, I'd suggest exploring next-i18next package, for a more standard way of implementing localization in next.js



来源:https://stackoverflow.com/questions/62297280/dynamic-html-lang-property-in-statically-generated-next-js-pages

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!