この記事では、i18next パッケージの基本的な使い方と React アプリケーションを多言語対応にするための、関連パッケージの導入方法を紹介します。参考動画
アプリ作成とファイル構成
React アプリを作成します。
npx create-react-app
or
npm create vite@latest
パッケージをインストール
i18next と関連するパッケージをインストールします。
npm i i18next react-i18next i18next-browser-languagedetector i18next-http-backend
i18next | JavaScript 環境向けのアプリを多言語対応させます。 |
react-i18next | React コンポーネントで i18next を使用する際に使用します。 |
i18next-browser-languagedetector | ブラウザに言語設定を保存、読み込み、適用します。この記事では、localStorage を使用します。 |
i18next-http-backend | バックエンドサーバーからリソースを読み込みます。 |
ファイル構成
※ 変更する箇所のみ記載しています。
|-- public//
| `-- languages//
| |-- en//
| | |-- main.json
| | `-- validation.json
| `-- ja//
| |-- main.json
| `-- validation.json
|
|-- src//
| |-- components//
| | `-- LngButton.jsx
| |-- App.jsx
| `-- main.jsx
`-- i18next.js
多言語対応にする
import i18next from "i18next";
import { initReactI18next } from "react-i18next";
import LanguageDetector from "i18next-browser-languagedetector";
import Backend from "i18next-http-backend";
i18next
.use(initReactI18next)
.use(LanguageDetector)
.use(Backend)
.init({
fallbackLng: "ja",
// debug: true,
ns: ["main", "validation"],
fallbackNS: "main",
detection: {
order: ["localStorage", "navigator"],
},
backend: {
loadPath: "/languages/{{lng}}/{{ns}}.json",
}
});
11: デフォルト言語
13, 14 : ネームスペースとデフォルト
15~17: i18next-browser-languagedetector の設定、優先順位を localStorage、 ブラウザの言語設定の順にしています。初回はブラウザの言語設定に従い、アプリ内ボタンで言語を変更した場合、変更した言語を優先するようになります。cookie や path を使用することもできるようです。
18~20: i18next-http-backend の設定、上記のネームスペースを使用して、json 形式の言語ファイルの配置場所を指定します。例 public/languages/ja/main.json、 public/languages/en/validation.json
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import './index.css'
import '../i18next'
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<App />
</React.StrictMode>,
)
5: i18next.js を読み込みます。
翻訳言語の基本的な使い方
import "./App.css";
import LngButton from "./components/LngButton";
import { useTranslation } from "react-i18next";
function App() {
const { t } = useTranslation();
return (
<div className="App">
<LngButton />
<p>{t("hello")}</p>
<p>{t("hello", {lng: 'ja'})}</p>
<p>{t("auth.login")}</p>
{/* 代入 */}
<p>{t("name", {fn: 'Tanaka', ln: 'Taro'})}</p>
{/* 複数 */}
<p>{t("comment", {count: 0})}</p>
<p>{t("comment", {count: 1})}</p>
<p>{t("comment", {count: 100})}</p>
{/* context */}
<p>{t("comment", {context: 'good', count: 20})}</p>
{/* namespace */}
<p>{t("validation:error")}</p>
<p>{t("error", {ns: 'validation'})}</p>
</div>
);
}
export default App;
10: 言語切替ボタンのコンポーネント LngButton を読み込みます。
3, 6, 11~24: public 配下に保存されてある、言語を使用しています。
en
{
"hello": "hello world",
"name": "hello {{fn}} {{ln}}",
"auth": {
"login": "login"
},
"comment_zero": "zero comment",
"comment_one": "a comment",
"comment_other": "{{count}} comments",
"comment_good_other": "{{count}} good comments"
}
{
"error": "is error"
}
ja
{
"hello": "こんにちは",
"name": "こんにちは {{fn}} {{ln}}",
"auth": {
"login": "ログイン"
},
"comment_zero": "ゼロコメ",
"comment_one": "イチコメ",
"comment_other": "{{count}} コメンツ",
"comment_good_other": "{{count}} グッド コメンツ"
}
日本語の comment_one が反映されないのは、必要じゃないからですかね。
{
"error": "エラーがあります。"
}
言語切替ボタン
import { useTranslation } from "react-i18next";
export default function LngButton() {
const { t, i18n } = useTranslation();
const lngs = {
ja: "日本語",
en: "English",
};
const lngChange = (lng) => {
i18n.changeLanguage(lng);
};
return (
<>
{Object.keys(lngs).map((lng) => (
<button
key={lng}
onClick={() => lngChange(lng)}
disabled={i18n.resolvedLanguage === lng}
>
{lngs[lng]}
</button>
))}
</>
);
}
11: i18n.changeLanguage() 言語の変更
20: i18n.resolvedLanguage 現在の言語
i18next-browser-languagedetector パッケージが、言語決定時などに localStorage に保存、ページを読み込み時に反映を行うので、そのへんの処理は必要ないようです。
以上多言語にする方法でした。