見出し画像

Remixとreact-i18nextで多言語対応

remix-i18nextを使う紹介もあったりしましたが、あまり依存を増やしたくなかったのでreact-i18nextのみ(i18nextは使う)で多言語対応してみたメモです。

ChatGPTでサンプルコード生成

まずはChatGPTでサンプルコードを作成してもらいました(笑

Remixのセットアップ

こちらを参考に以下のコマンドでセットアップします。表示される選択肢を選びながら進めば完了です。

npx create-remix@latest

react-i18nextの導入

こちらを参考にパッケージを追加します。

npm install react-i18next i18next --save

構成ファイルの作成

procject/app/i18n.ts を作成します(ChatGPTのサンプルのコピペ)

import i18n from "i18next";
import { initReactI18next } from "react-i18next";

const resources = {
  en: {
    translation: {
      "welcome": "Welcome",
      // 他の翻訳キーと値を追加
    },
  },
  ja: {
    translation: {
      "welcome": "ようこそ",
      // 他の翻訳キーと値を追加
    },
  },
};

i18n.use(initReactI18next).init({
  resources,
  lng: "en",
  fallbackLng: "en",
  interpolation: {
    escapeValue: false,
  },
});

export default i18n;

i18nのインスタンスを使えるようにする

ここが少しポイントでした。
ChatGPTやQuickStartは通常のReactを想定しているため、index.js(HTMLDocumentにReactをレンダリングする指定が含まれるファイル)に、上記構成ファイルをインポートするようになっています。
しかし、Remixではそのようなファイルがありません(通常見えるプロジェクトファイル内には)ので、react-i18next の I18nextProvider を利用しました。

project/app/root.tsx に追記します。
import i18n の追加と <Outlet /> を I18nextProvider で囲みます。

import type { MetaFunction } from "@remix-run/node";
import {
  Links,
  LiveReload,
  Meta,
  Outlet,
  Scripts,
  ScrollRestoration,
} from "@remix-run/react";
import { I18nextProvider } from "react-i18next";
import i18n from "./i18n";

export const meta: MetaFunction = () => ({
  charset: "utf-8",
  title: "New Remix App",
  viewport: "width=device-width,initial-scale=1",
});

export default function App() {
  return (
    <html lang="en">
      <head>
        <Meta />
        <Links />
      </head>
      <body>
        <I18nextProvider i18n={i18n}>
          <Outlet />
        </I18nextProvider>
        <ScrollRestoration />
        <Scripts />
        <LiveReload />
      </body>
    </html>
  );
}

ページ内で利用

多言語対応したいページで以下のように利用します。
project/app/routes/index.tsx (元々生成されたファイルに追記)

import { useTranslation } from "react-i18next";

export default function Index() {
  const { t, i18n } = useTranslation();

  const change = (language: string) => {
    console.log(language);
    i18n.changeLanguage(language);
  };

  return (
    <div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.4" }}>
      <h1>{t("welcome")}</h1>
      <button onClick={() => change("en")}>English</button>
      <button onClick={() => change("ja")}>日本語</button>
      <ul>
        <li>
          <a
            target="_blank"
            href="https://remix.run/tutorials/blog"
            rel="noreferrer"
          >
            15m Quickstart Blog Tutorial
          </a>
        </li>
        <li>
          <a
            target="_blank"
            href="https://remix.run/tutorials/jokes"
            rel="noreferrer"
          >
            Deep Dive Jokes App Tutorial
          </a>
        </li>
        <li>
          <a target="_blank" href="https://remix.run/docs" rel="noreferrer">
            Remix Docs
          </a>
        </li>
      </ul>
    </div>
  );
}

i18n.changeLanguage(language) で言語を変更して表示します。

この記事が気に入ったらサポートをしてみませんか?