私が歌川です

@utgwkk が書いている

Next.js Static HTML Export 国際化 最速 無料

はじめに

みなさまはNext.jsで静的に生成するHTMLファイルを国際化したくありませんか? Next.jsに組み込みのi18n routingStatic HTML Exportに対応していないので、別の手を考える必要があります。

結論から言うと、以下の記事にやり方が書いてあります。

dev.to

この記事では、Next.jsでStatic HTML Exportで言語ごとのHTMLファイルを生成する方法と、ハマったところを簡単にまとめます。

手順

翻訳データを用意する

public/locales/(言語)/common.json に翻訳データを用意します。ラベル→文言というJSONを置けばよいです。

{
  "hello": "こんにちは"
}

next-i18nextをインストールする

Next.jsでi18next (react-i18next) を使えるようにするライブラリです。i18next, react-i18nextのインストールは不要でnext-i18nextだけ入れれば動きます。useTranslation 関数もnext-i18nextからimportします。

$ yarn add next-i18next

next-i18nextの設定を書く

リポジトリルートに next-i18next.config.js というファイルを書きます。設定ファイルの書き方はREADMEを参照してください。ここでは、デフォルトで日本語を使う・対応言語は日本語とアメリカ英語、という設定をしています。

module.exports = {
  i18n: {
    defaultLocale: 'ja-JP',
    locales: [
      'ja-JP',
      'en-US',
    ],
  },
}

言語ごとのページを生成できるようなファイル構成にする

pages ディレクトリを以下のように、[lang] ディレクトリにページを突っ込むような構成にします。簡単のため index.tsx だけ用意します。

pages
├── [lang]
│   └── index.tsx
└── _app.tsx

getStaticProps で言語ごとの情報を読み込む

react-i18nextの serverSideTranslations 関数で翻訳データを読み込んで、それを getStaticProps で呼び出して、propsとして渡します。

import nextI18nextConfig from '../../next-i18next.config';
import {serverSideTranslations} from 'next-i18next/serverSideTranslations';

const getI18nProps = async (ctx) => {
  let locale = ctx.params?.lang ?? nextI18nextConfig.i18n.defaultLocale;
  if (locale instanceof Array) {
    locale = locale[0];
  }

  const props = await serverSideTranslations(locale);
  return props;
};

export const getStaticProps = async (ctx) => ({
  props: await getI18nProps(ctx),
});

getStaticPaths で生成対象の言語を指定する

next-i18next.config.js に対応言語の一覧があるので、それを使ってHTMLを生成する対象の言語を指定します。

const getI18nPaths = () =>
  nextI18nextConfig.i18n.locales.map(lang => ({
    params: {
      lang,
    },
  }));

export const getStaticPaths = () => ({
  fallback: false,
  paths: getI18nPaths(),
});

翻訳する

ここまでできたら useTranslation フックを使って翻訳していけばよいです。

const { t } = useTranslation();
t('hello');

next build して next export したら、言語ごとにHTMLファイルが生成されていることが確認できます。

注意点

生成されたHTMLに翻訳データが埋め込まれる

生成されたHTMLに翻訳データが埋め込まれることに注意しましょう。文言が多いとそれだけファイルサイズも大きくなるし、公開したくない文言がある場合は含めてはいけません。翻訳データの名前空間を絞っておくのが安全です。

クライアントサイドのJavaScriptで翻訳文言を表示する必要がない場合は更に最適化する余地があるかもしれません。

next dev で起動する際にも正しく翻訳させる

defaultNS (デフォルトで使う翻訳データの名前空間) をいじっている場合などでは、 serverSideTranslations 関数の第3引数に next-i18next.config.js の内容を渡す必要があります。

const props = await serverSideTranslations(locale, undefined, nextI18nextConfig);

こうした上で next dev で開発用サーバーを起動して、 /ja-JP などのパスにアクセスすると動作確認できます。

next export で生成した静的ファイルに対して動作確認するには

out ディレクトリ以下で適当なHTTPサーバーを立ち上げればよいです。Pythonなどで適当なワンライナーを書いてもよいし、http-serverなどのライブラリを使うとNode.js上で完結できてよさそうです。

おわりに

Next.jsで国際化しつつStatic HTML Exportできましたね。ファイルパスに [] といった記号を使うのは初見だとギョッとするけど思ったよりも簡単に実現できたのでよかったです。こうして生成したファイルを何らかの方法で言語ごとに出し分ければよさそうですね。