Reactで最初に驚いたことの1つは、すべてがコンポーネントであるということです。 表面的には単純に聞こえるかもしれませんが、機能的なもの(フォーム管理、i18n(国際化)、ルーティング、状態など)については、私にはあまり自然に感じられず、 -ビジュアル機能のみのコンポーネント。

通常、他のUIライブラリ/フレームワークには、ルーターAPI、フォームAPIなどの機能ロジックを処理するためのAPIベースの方法があります。 それらは、それらの場合のために独自のAPIまたはインスタンスを拡張する方法を提供します。

Reactのi18nソリューションを調べたところ、ほとんどのソリューションが翻訳コンポーネントを使用していることがわかりました。 特に、より多くの機能が必要な大規模なプロジェクトには最適ですが、私のユースケースは非常に単純だったので、自分で行うことにしました。 この投稿では、私がそれをどのように行ったかについて説明します。

React用のi18nライブラリの1つを試すことに興味がある場合は、i18nextとreact-i18nextをカバーするこの投稿をチェックしてください。

リテラルレデューサー

ここで紹介するソリューションは、 Redux を使用しています。これは、すでに優れた状態のコンテナーであるためですが、必要に応じて、リテラル用のコンテナーを自分で作成することもできます。メカニズムは似ています。

まず、リテラルを格納するためのReduxの状態として store/literals.jsを作成しましょう。

store /literals.js
const defaultState = {};

const LOAD_LITERALS = "LOAD_LITERALS";

export default (state = defaultState, { type, payload }) => {
  switch (type) {
    case LOAD_LITERALS:
      return payload;
    default:
      return state;
  }
};

export const loadLiterals = literals => ({
  type: LOAD_LITERALS,
  payload: literals,
});

すでにReduxに精通している場合は、ここで特別なことは何もありません。 リテラルの状態全体を置き換えるレデューサーと、それらを設定するためのloadLiteralsアクションクリエーターがあります。


React / Reduxアプリでは、セットアップは通常、ReactReduxのProviderコンポーネントを使用するindex.jsファイルから始まります。

index.js
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";

import App from "./App";
import store from "./store";

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById("root")
);

ここで、storeは、Reduxストアを作成するファイルから取得され、ルートレデューサーをcombineReducersのような関数に渡します。

store / index.js
import { createStore, combineReducers } from "redux";
import literals from "./literals.js";

const rootReducer = combineReducers({
  literals,
  // other reducers...
});

export createStore(rootReducer);

まだ特別なことは何もありません。Reduxストアを作成するための通常の手順だけです。

リテラルのロード

i18nロジックを整理するために、次の構造のフォルダーを作成しましょう。

+ i18n
  - index.js
  - en.json
  - es.json
  ....

JSONファイルには、言語リテラルを含むKey-Valueデータが含まれています。

i18n / en.json
{
  "app_greet": "Hey Joe!"
}

index.js ファイルに関しては、特定の言語のリテラルを返す関数を公開できます。

i18n / index.js
import en from "./en.json";
import es from "./es.json";

const langs = {
  en,
  es
};

export default function (lang = "en") {
  return langs[lang];
};

アイデアは、アプリの早い段階でリテラルをロードすることです。 おそらく、他のものも同時に初期化して構成する必要があります。 そのためにinit.jsファイルを作成することもありますが、必要に応じて作成してください。

ただし、ストアがすでに作成されていることを確認する必要があります。 ストアを作成した直後に、index.jsでそれを実行しましょう。

index.js
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";

import App from "./App";
import { loadLiterals } from "store/literals";
import store from "./store";
import loadLang from "./i18n";

const lang = loadLang();
store.dispatch(loadLiterals(lang))

ReactDOM.render(
  
    <App />
  ,
  document.getElementById("root")
);

ご覧のとおり、loadLiterals関数を呼び出してロードしています。 store.dispatchインスタンスメソッドを使用して、コンポーネントの外部からReduxアクションを呼び出すことができます。

リテラルをロードするには、これで十分です。 次に、どのコンポーネントでも、接続機能を使用してストアの一部を取得できます。 基本的な例は次のとおりです。

index.js
import React from "react";
import { connect } from "react-redux";

const App = ({ literals }) => (
  <div>
    {literals.app_greet}
  </div>
);

const mapStateToProps = ({ literals }) => ({
  literals
});

export default connect(mapStateToProps)(App);

遅延読み込みリテラル

さらに一歩進めたい場合は、JavaScript 動的インポート機能を使用して、i18n/index.jsのデフォルトのエクスポートを変更し、リテラルを遅延ロードすることができます。

i18n / index.js
export default function (lang = "en") {
  return import(`./${lang}.json`);
};

関数が単純になるだけでなく、リテラルはオンデマンドで遅延読み込みされるため、バンドルサイズが小さくなり、アプリの読み込みが速くなります。

動的インポートはpromiseを返すため、ストアでリテラルをロードする方法を次のように更新する必要があります。

index.js
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";

import App from "./App";
import { loadLiterals } from "store/literals";
import store from "./store";
import loadLang from "./i18n";

loadLang().then(lang => store.dispatch(loadLiterals(lang)));

ReactDOM.render(
  
    <App />
  ,
  document.getElementById("root")
);

まとめ

いくつかの単純なi18n機能をReact/Reduxアプリに最初から追加する方法を見てきました。 そのようにする必要はありません。同じことを達成するためのさまざまな方法が確かにありますが、自分でそれを行うのは簡単で楽しいことがあり、これで簡単にできることを理解していただければ幸いです。ユースケース。