Next.jsのexport(SSG)してi18n(国際化)実装を行いたい時のススメ
方針
Next.jsには、標準でi18n設定ができる機能がついています。next.configで設定すれば、ささっとi18n実装ができます
しかし、上の機能Next.jsをサーバーとして利用している時しか使えないです。
Next.jsでbuild & exportしたものを他のWebサーバーなどに渡すときはNext.js標準の機能が使えないです
e.g. Next.jsでexportしたファイルをNestJSを使って配信したい
そこでフロントエンドのみでi18nを実装する必要があります。
今回はreact-i18next i18next
のライブラリを用いて実装します。
初回レンダリング時にブラウザの言語情報(Navigator)を取得して、localStorageで言語情報を持つ方法で実装します。
別の方法で
-
ダイナミックルートセグメントを使う方法
https://dev.to/adrai/static-html-export-with-i18n-compatibility-in-nextjs-8cd -
next exoprtに対応したライブラリを使う
https://dev.to/martinkr/next-js-i18n-with-static-sites-2644
があるが、ディレクトリの構造を変えたり、URLにクエリを生やして言語切り替えを行なっています。今回実装する方がシンプルな気がするのですが、知見者の方メリットデメリット教えてください。
実装
成果物
今回作成したリポジトリとサイトのURLを貼っておきます。
作ったサイト(初回レンダリング時にブラウザの情報を読み込んでlocalStorageを見て言語の切り替えを行なっている)
実装手順
- まず、ライブラリをインストールします。
npm install react-i18next i18next --save
or
yarn add react-i18next i18next
ブラウザの言語情報を取ってきてくれるライブラリも入れます。
npm install i18next-browser-languagedetector
- Next.jsのrootにi18n用のフォルダを作成します。(pageディレクトリ以外だと任意のディレクトリでも可)
- 下記ファイルを作成します。
import type { InitOptions } from "i18next";
import i18next from "i18next";
import { initReactI18next } from "react-i18next";
import LanguageDetector from "i18next-browser-languagedetector";
import enCommon from "../public/locales/en/common.json";
import jaCommon from "../public/locales/ja/common.json";
import enTest from "../public/locales/en/test.json";
import jaTest from "../public/locales/ja/test.json";
const detector = new LanguageDetector(null, {
order : ['navigator', 'localStorage']
})
const option: InitOptions = {
resources: {
en: {
Common: enCommon,
Test: enTest,
},
ja: {
Common: jaCommon,
Test: jaTest,
},
},
};
i18next.use(detector).use(initReactI18next).init(option);
export default i18next;
detectorを設定することで、ブラウザの言語設定を読み取ってlocalStorageに言語情報を入れてくれています。
import type { AppProps } from "next/app";
import "../i18n/i18n";
export default function App({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />;
}
import { useTranslation } from "react-i18next";
import i18n from "i18next";
import Link from "next/link";
export default function Home() {
const { t } = useTranslation("Common");
return (
<>
<h1>{t("test1")}</h1>
<button onClick={() => i18n.changeLanguage("ja")}>日本語</button>
<button onClick={() => i18n.changeLanguage("en")}>英語</button>
<Link href={'/test'}>テストページへ</Link>
</>
);
}
Next.jsの_app.tsxで初回レンダリング時にi18n.tsをインポートしています。
しi18n.tsをインポートすることによって言語情報を設定し、翻訳済みのjsonファイルを読み込んでいます。
そうすることで、index.tsxでuseTranslationが使えます。
もっと改善の余地ありそうですが、最小限で実装を行いました。i18n.init(option)の設定でもっとカスタマイズできそうです。
所感
jsonファイルが増えてくると初回レンダリング時に重くなりそうです。(知見のある方教えてください)
今回のi18n実装を行うとNext.jsを使うメリットが見出せ内容な気がします。
Next.jsを使うときはVercelにデプロイしてアプリケーションサーバーとして使う方が使える機能もありますしオススメです。
折角標準で用意してあるものは使いたいですね。。。。
FYI
Discussion