🌏

Next.js を next-i18next で i18n 対応させる手順

2021/02/17に公開

Next.js を next-i18next で i18n 対応させる手順をまとめます。

最終的なコードは GitHub 参照

0. 事前準備

Next.js でアプリを作成し、必要に応じて TypeScript の設定をおこないます。

1. next-i18next のインストール

yarn add next-i18next

2. 翻訳ファイルの作成

public/static/locales/[locale] フォルダを作成し、翻訳ファイル(JSON 形式)を格納します。

.
└── public
    └── static
        └── locales
            ├── en
            |   └── common.json
            └── de
                └── common.json

翻訳ファイルの例:

common.json
{
  "hello": "Hello from English!",
  "nested": {
    "greeting": "How are you, {{name}}?"
  }
}
  • オブジェクトでネストできます
  • {{ }} で動的な値が使えます

3. アプリのセットアップ

i18n.js

ルート層に i18n.js を追加します。

i18n.js
const NextI18Next = require('next-i18next').default;
const { localeSubpaths } = require('next/config').default().publicRuntimeConfig;
const path = require('path');

module.exports = new NextI18Next({
  otherLanguages: ['de'],
  localeSubpaths,
  localePath: path.resolve('./public/static/locales'),
});

(公式 README よりコピペ)

next.config.js

ルート層に next.config.js を追加します。

next.config
const { nextI18NextRewrites } = require('next-i18next/rewrites');

const localeSubpaths = {};

module.exports = {
  rewrites: async () => nextI18NextRewrites(localeSubpaths),
  publicRuntimeConfig: {
    localeSubpaths,
  },
};

(公式 examples/simple/next.config.js よりコピペ)

_app.tsx

_app.tsx コンポーネントを HOC appWithTranslation でラップします。以下のコードは、言語切り替えボタンを含んでいます。

_app.tsx
import type { AppProps } from 'next/app';
import { useEffect, useState } from 'react';

import { appWithTranslation, useTranslation } from '../i18n';

const MyApp = ({ Component, pageProps }: AppProps) => {
  const { i18n } = useTranslation();
  const [currentLanguage, setCurrentLanguage] = useState(i18n.language || 'en');

  useEffect(() => {
    i18n.changeLanguage(currentLanguage);
  }, [currentLanguage]);

  return (
    <>
      <button
        onClick={() => {
          setCurrentLanguage('en');
        }}
      >
        EN
      </button>{' '}
      <button
        onClick={() => {
          setCurrentLanguage('de');
        }}
      >
        DE
      </button>
      <Component {...pageProps} />
    </>
  );
};

export default appWithTranslation(MyApp);
  • HOC appWithTranslation でラップします
  • i18n.changeLanguage(currentLanguage) 言語設定を切り替えれます

index.tsx

ページレベルのコンポーネントを HOC withTranslation でラップします。

index.tsx
import { NextPage } from 'next';

import { withTranslation } from '../i18n';
import { TFunction } from 'next-i18next';

interface HomeProps {
  readonly t: TFunction;
}

const Home: NextPage<HomeProps> = ({ t }) => {
  return (
    <div>
      <h2>{t('hello')}</h2>
      <p>{t('nested.greeting', { name: 'Kei' })}</p>
    </div>
  );
};

export default withTranslation('common')(Home);

  • HOC withTranslation でラップします
  • t() で翻訳テキストを呼びます
  • t() の第2引数に動的な値(オブジェクト)を渡せます

必要な設定は以上です。

References

Discussion