📝

【React】i18nライブラリーを導入しプロジェクトを多言語対応する手順

2024/11/02に公開

はじめに

1時間の音声を15秒で文字起こしし、かつ、自然な会話形式に自動変換する「インタビューAI」を開発中。

https://www.interview-ai.site/

現在、日本語で日本国内向けに提供開始しているが、海外展開も進めていきたいので、サービスを多言語対応したいと思う。今回は、Reactプロジェクトを多言語対応する手順を記載。

フロントエンドの英語対応を進めるために、次のように進める。

i18nライブラリーの導入

Reactのプロジェクトでの多言語対応には、react-i18nextのような国際化ライブラリが便利。まず、以下のコマンドでreact-i18nexti18nextをfrontend/ディレクトリにインストールする。

また、今回は、ユーザーのブラウザの表示言語に基づいて、自動的に言語を切り替えたいので、i18nextで提供されている、ブラウザの設定を検出して言語を自動的に設定するためのプラグインであるi18next-browser-languagedetectorもインストールする

npm install react-i18next i18next i18next-browser-languagedetector

多言語化対応のディレクトリ構造(フロントエンド)

src/locales/配下に多言語対応のための翻訳ファイル(例えばen.jsonja.json)を格納し、アプリ全体で使えるようにする

project-root/
  └── src/
      ├── components/
      ├── locales/        <-- ここに言語ファイルを格納
      │     ├── en.json   <-- 英語の翻訳ファイル
      │     └── ja.json   <-- 日本語の翻訳ファイル
      ├── App.tsx
      ├── i18n.js         <-- i18nの設定ファイル
      └── index.tsx

i18nの設定ファイルの作成

次に、i18n設定ファイルを作成し、プロジェクト全体で使用できるように設定する。例えば、src/i18n.jsに以下のように記述する。

import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import en from './locales/en.json';
import ja from './locales/ja.json';

i18n
  .use(LanguageDetector) // 言語検出機能を使用
  .use(initReactI18next)
  .init({
    resources: {
      en: { translation: en },
      ja: { translation: ja },
    },
    fallbackLng: 'en', // 言語が検出されない場合のフォールバック
    interpolation: { escapeValue: false },
    detection: {
      order: ['querystring', 'cookie', 'localStorage', 'navigator', 'htmlTag'], // 言語の検出順序
      caches: ['localStorage', 'cookie'], // 言語を保存する場所
    },
  });

export default i18n;

この設定で、ユーザーのブラウザの表示言語を自動的に検出し、それに基づいて初期の言語を設定することができる。例えば、日本語環境でブラウザを使用している場合は自動的にjaに設定される。

次にlocales/en.jsonlocales/ja.jsonに言語ごとのテキストを記述する。

言語ファイルの作成

次に、各言語のテキストをlocalesフォルダに作成する。例えばen.jsonファイルを以下のように作成する。

en.json:

{
  "welcome": "Welcome",
  "logout": "Logout",
  "delete_account": "Delete Account",
  "transcription": "Transcription",
  "summary": "Summary",
  "title_header": "Title & Headings"
}

ja.json:

{
  "welcome": "ようこそ",
  "logout": "ログアウト",
  "delete_account": "退会",
  "transcription": "文字起こし",
  "summary": "要約",
  "title_header": "タイトル・小見出し"
}

アプリ全体にi18nを適用

src/index.jsまたはsrc/index.tsxでi18nをインポートし、アプリ全体に適用する。

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import './i18n';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

既存のコンポーネントを翻訳対応に変更

次に、各ファイルの翻訳対応を行う。試しに、まず、App.tsxの「文字起こし」「要約」「タイトル・小見出しのボタン」を英語対応する。

スクリーンショット 2024-11-02 10.10.27.png

App.tsxにおいて、以下の変更を加える。

  1. react-i18nextをインポートして、useTranslationフックを使う。
  2. 各テキストをt()を使用して翻訳対応する。
import React from 'react';
import { useTranslation } from 'react-i18next';
// その他のインポートは省略

const App: React.FC = () => {
  const { t } = useTranslation();

  // 他のコードはそのまま
  return (
    <Elements stripe={stripePromise}>
      <div className="app-container">
        <Navbar
          currentUser={currentUser}
          onLogout={handleLogout}
          onDeleteAccount={handleDeleteAccount}
        />

        <div className="container mx-auto mt-20 pt-5 px-4">
          {!location.pathname.includes("/login") &&
            !location.pathname.includes("/upgrade-plan") && (
              <div className="flex justify-center mb-12 mt-4">
                <div className="flex space-x-4">
                  <Link to="/transcription">
                    <Button
                      variant={
                        activeService === "transcription"
                          ? "primary"
                          : "outline"
                      }
                      className="w-auto"
                      onClick={() => setActiveService("transcription")}
                    >
                      {t('transcription')}
                    </Button>
                  </Link>

                  <Link to="/summary">
                    <Button
                      variant={
                        activeService === "summary" ? "primary" : "outline"
                      }
                      className="w-auto"
                      onClick={() => setActiveService("summary")}
                    >
                      {t('summary')}
                    </Button>
                  </Link>

                  <Link to="/title-header-generator">
                    <Button
                      variant={
                        activeService === "title-header-generator"
                          ? "primary"
                          : "outline"
                      }
                      className="w-auto"
                      onClick={() => setActiveService("title-header-generator")}
                    >
                      {t('title_header')}
                    </Button>
                  </Link>
                </div>
              </div>
            )}
        {/* その他のコード */}
        </div>
      </div>
    </Elements>
  );
};

このようにして、各コンポーネントでuseTranslationを使用し、テキストを言語ファイルから取得するようにする。

ブラウザの言語を自動的に設定した後でも、ユーザーが手動で言語を切り替えたい場合には、Navbarに言語選択のドロップダウンメニューを追加する。以下のように、手動で言語を切り替えるボタンを追加。

<select>タグのvalue属性にi18n.languageを設定することで、ユーザーがページをロードした際に、ブラウザで検出された言語がドロップダウンで自動的に選択されるようにする。例えば、ブラウザが英語設定であれば、ドロップダウンのデフォルトの選択肢も「English」になる。

ついでに、ナビゲーションのボタン(プラン・使い方・お問い合わせ・ログイン・ログアウト・退会)も多言語対応しておく。

続きは、こちらで記載しています。
https://kazulog.fun/dev/react-i18n-multiple-language/

Discussion