Reactで簡単に多言語対応する方法は?react-i18nextの使い方

はじめに

こんにちは。フロントエンドエンジニアのKimuraです。

アトラスが展開する大会事業サービスConfitは、国内大会のみではなく、国際大会でも数多くご利用いただいています。このため、各種画面は日本語のみでなく英語表示にも対応しています。

React上の多言語対応ライブラリとしては、react-i18nextがよく取り上げられるかと思います。アトラスでも、react-i18nextを利用して多言語対応を実装しています。 本記事では、react-i18nextの基本的な利用方法と、Jestによるテスト実装をご紹介いたします。
なおテストについては、公式がJest + Enzymeを利用したサンプルコードを公開しています。本記事ではそちらを参考に、React Testing Libraryを使用していきます。

利用技術

React

Create React Appを利用したTypeScriptプロジェクト上で実装を進めていきます。プロジェクトは下記のコマンドを利用して生成しています。

npx create-react-app react-i18next-sample --template typescript

react-i18next

i18nextのReact用ライブラリです。
i18nextは多言語対応ライブラリであり、react-i18nextではAPIとしてReact Hooksが提供されています。

Jest

Create React Appにデフォルトとして採用されているテスティングライブラリです。

React Testing Library

Testing Libraryが提供するReactコンポーネント用テスティングライブラリです。こちらもCreate React Appにデフォルトとして採用されています。
類似ライブラリにEnzymeがあります。

react-i18nextの利用方法

今回は、useTranslationを利用してメッセージを取得する方法を扱います。

インストール

まずは、関連するnpmパッケージをインストールします。

npm install react-i18next i18next i18next-http-backend i18next-browser-languagedetector

メッセージjson作成

言語ごとに、メッセージを定義したjsonファイルを作成します。今回は例として、日本語と英語の定義を用意します。

{
  "test": {
    "message": "テストメッセージ"
  }
}
{
  "test": {
    "message": "test message"
  }
}

初期化

メッセージ取得を利用する前に、初期化を実装したi18n.tsを作成します。

import i18n from 'i18next';
import Backend from 'i18next-http-backend';
import LanguageDetector from 'i18next-browser-languagedetector';
import { initReactI18next } from 'react-i18next';

i18n
  .use(Backend)
  .use(LanguageDetector)
  .use(initReactI18next)
  .init({
    fallbackLng: 'ja',
    ns: ['translations'],
    defaultNS: 'translations',
    debug: true,
    interpolation: {
      escapeValue: false,
    }
  });

export default i18n;

本記事は、React Suspenseを利用する前提の実装となります。利用しない場合は、初期化時に追加設定が必要となります。

i18n
  // (中略)
  .init({
    // (中略)
    react: { 
      useSuspense: false
    }
});

作成したi18n.tsindex.tsx内に読み込みます。これにより初期化が実行され、コンポーネント内でuseTranslationを利用可能となります。

import './i18n';

コンポーネント作成

実際にメッセージを取得するコンポーネントを作成します。

import React from 'react';
import { useTranslation } from 'react-i18next';

export const TestComponent = () => {
  const { t } = useTranslation();
  return 
{t('test.message')}
; }

上記のコンポーネントは、<div>内にreact-i18next経由で取得した文字列を表示します。
メッセージキーをtに渡すことで、jsonファイルに定義されたメッセージが返却されます。json上の階層は.で表現されています。

App.tsx内に<TestComponent>を配置して、表示を確認してみます。

import React, { Suspense } from 'react';
import { TestComponent } from './components/TestComponent';

function App() {
  return (
    Loading...

}>
); }

この状態で開発サーバを立ち上げると、<TestComponent>が画面表示されます。

npm start

コンポーネントキャプチャ

言語切替実装

デフォルトの日本語表示から、英語表示に切り替えるボタンを実装していきます。

import { useTranslation } from 'react-i18next';

const AppPage = () => {
  const { i18n } = useTranslation();

  const changeLanguage = (lng: string) => {
    i18n.changeLanguage(lng);
  };

  return (
    
); } function App() { return ( Loading...

}>
); }

画面を確認すると、jaenのボタンが追加されています。これらを押下することにより、<TestComponent>の表示言語が切り替わります。

言語切替ボタンキャプチャ

テスト

最後に、JestとReact Testing Libraryを利用してテストを実装します。

import { render } from "@testing-library/react";
import { TestComponent } from './TestComponent';

jest.mock('react-i18next', () => ({
  useTranslation: () => {
    return {
      t: (str: string) => str,
      i18n: {
        changeLanguage: () => new Promise(() => {}),
      },
    };
  },
}));

it('test render', () => {
  const { getByText } = render();
  expect(getByText('test.message'));
});

モック実装が存在しない場合、実行時に警告が表示されます。react-i18nextの初期化処理が行われていないため、useTranslation()などAPIのインスタンスが取得できないことが原因です。
なお、上記のモックはtの引数をそのまま返却しています。json定義したメッセージは、コンポーネント上に表示されません。
メッセージが表示されているかを確認するため、getByTextにメッセージキー(test.messageなど)を引き渡します。これにより、任意のメッセージが出力対象となっているか検証可能となります。

下記のコマンドで、テストを実行します。

npm test src/components

最後に

react-i18next + Jest による多言語対応の実装方法、いかがでしたでしょうか。

グローバル化が進む昨今、多言語対応サービスも数多く存在しております。アトラスでも引き続き、国内外のお客様にご利用いただけるサービスを目指していきたいと思います。

新卒・中途エンジニア募集中!

100%自社内開発!学術に特化した自社サービスで設計からリリースまでフルスタックなスキルを身につけませんか?
テレワーク主体ですがコミュニケーションも活発でチームのつながりも大切にしている環境です。

カジュアル面談からお気軽にお越しください!

採用情報はこちら

アトラス採用情報。新卒・中途エンジニア募集中!