多言語 Next.js の HTML タグに動的に lang を設定する

imatomix
2021年8月17日 10:37

概要

Next.js単体で多言語対応できるようになってるので、試してみました。(ちなみに、以前まではNext.jsの多言語対応には next-i18-next を使っていました。)

設定は公式の通りとても簡単で、各コンポーネント内でのlocale情報はuseRouterから取得できるようになっています。
1点、HTMLタグに lang を設定するのをどうやろうか少し考えた結果、無駄骨だったのでメモを残しておきます。

余談

htmlのlangをみて、日本語のときだけ、一部テキストにtext-align: justify;をかけたりします。
html[lang=ja] .text-justify { text-align: justify; }

結論

_document.tsrender()__NEXT_DATA__からlocaleを取得できる。
pages/_document.tsx
import Document, { Html, Head, Main, NextScript, DocumentContext, DocumentInitialProps, } from 'next/document' class imDocument extends Document { static async getInitialProps( ctx: DocumentContext ): Promise<DocumentInitialProps> { const initialProps = await Document.getInitialProps(ctx) return initialProps } render(): JSX.Element { const { locale } = this.props.__NEXT_DATA__ // localeを取得 return ( <Html lang={locale} dir="ltr"> { // langに設定 } <Head /> <body> <Main /> <NextScript /> </body> </Html> ) } } export default MyDocument
今まで__NEXT_DATA__をちゃんと理解してなかった。
サーバーサイドからのデータがここに入るらしく、ページのソースから見えちゃうので、逆に出ちゃ駄目なデータが入らないように気を付けないと。

おまけ、最初にやったこと

ctxからlocaleを取得して render に渡そうと考えた結果
  • getInitialProps内で locale を取得しての返り値に足す
  • render()this.propsからlocaleを取得する
でうまくいったけど、完全に骨折り損です。
pages/_document.tsx
import Document, { Html, Head, Main, NextScript, DocumentContext, DocumentInitialProps, } from 'next/document' // 型にlocaleを足す type Props = DocumentInitialProps & { locale: string } class MyDocument extends Document { static async getInitialProps( ctx: DocumentContext ): Promise<Props> { const initialProps = await Document.getInitialProps(ctx) return {...initialProps, locale: ctx?.locale || 'ja' } // locale を取得 } render(): JSX.Element { return ( <Html lang={this.props.locale} dir="ltr"> { // langに設定 } <Head /> <body> <Main /> <NextScript /> </body> </Html> ) } } export default MyDocument