webpack + react-i18nextのi18n.use()するときに行った設定

react-i18nextはi18nextをReactでも使えるようにしてくれるwrapperで、Hooks対応してくれているので今回採用しました。 その際に行った設定を簡単にまとめます。

webpackのentryに初期化moduleを含める

webpack.config.babel.js ファイル名はなんでもいいですが、とにかくwebpackの設定をしているところでentryにi18n.use()するmoduleを入れ込みたい。

import { entries } from './config/entries';
...
module.exports = {
  entry: entries,
  ...
}

/config/entries.js

const srcDir = path.resolve(__dirname, '../src');
const nodeModuleDir = path.resolve(__dirname, '../node_modules');
const entriesDir = path.resolve(srcDir, 'pages');

const entryKey = (p) => path.join(path.dirname(p), path.basename(p, path.extname(p)));
export const entries = glob.sync('**/*.+(tsx|jsx)', { cwd: entriesDir }).reduce((r, p) => {
  const key = entryKey(p);
  return Object.assign(r, {
    [key]: [
      '@babel/polyfill',
      ...
      path.resolve(srcDir, 'localeSetter.ts'), // ここでentryに含める
      ...
    ]
  });
}, {});

src/localeSetter.ts

import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import jaJson from './locales/dictionaries/ja.json';
import enJson from './locales/dictionaries/en.json';

i18n.use(initReactI18next).init({
  resources: {
    en: { translation: enJson },
    ja: { translation: jaJson },
  },
  lng: 'ja',
  fallbackLng: 'ja',
  interpolation: { escapeValue: false },
});

ここら辺は以下の記事を参考にさせていただきました。

suzukalight.com

ただ、このままだと モジュール './locales/dictionaries/ja.json' が見つかりません。'--resolveJsonModule ' を使用して'.json' 拡張子を持つモジュールをインポートすることを検討してくださいts(2732)

となったので、tsconfig.jsonをいじります。

{
  "compilerOptions": {
      ... 
      "resolveJsonModule": true,
   }

"resolveJsonModule": true を追加するとエラーが消えるはず。自分の手元だとvscodeを再起動しないと出続けました...。

以上で、i18n.use()の初期化は完了。ただこの方法だと全てのentryで初期化されるので、一部ではしたくないというようなことは出来ないので要注意...。ただ、他の方法だと結局初期化漏れが発生しそうなので、この方が安全そうだなと判断しました。