サクッとi18n対応を行うためのReact hooksライブラリ、use-mini18nを作った。

現在、私はいくつかのアプリを個人で開発しています。
それらのほとんどはReactを用いたWebアプリです。アプリはどれも小さなものですが、世界中の人に使ってもらいたいと考えているため、i18n対応はなるべく行うようにしています。
(といっても、なかなか時間が確保できず、英語と日本語だけしか対応できていないケースばかりですが...)

一例を挙げると、ランダムな音楽を勧めてくれる、下記のようなシンプルなWebアプリを作っています。
[Dig Music - Dig Musicはレコメンドエンジンを使用せず、完全にランダムな形でユーザに新しい音楽を紹介するWebアプリです。](https://dig-music.shinshin86.com/ja)

Reactでi18n対応をする場合、[react-i18next](https://github.com/i18next/react-i18next)や[react-intl (FormatJSと呼ばれるモノレポに含まれる形に変わったようですね)](https://github.com/formatjs/formatjs)を使うことが多いと思います。
私もこれらを使用したことがありますが、どちらも素晴らしいライブラリだと感じています。

ですが、私が作成するアプリは非常に小規模なものが多いため、これらのライブラリがオーバースペックに感じることもあります。
**設定された言語設定に応じて、適切な言語ファイルを読み込み、表示できればそれでいい**んだよな...と思いましたが、少し調べてみたところ、そのようなライブラリはなさそうに思えたので、自分で作ることにしました。
TypeScriptを用いてReact hooksライブラリを作成してみたかったという別の理由もあります。

## シンプルでこじんまりとしたi18nライブラリ、use-mini18n
こちらが作ったものになります。

[use-mini18n - A simple and minimalistic React hook library for i18n](https://github.com/shinshin86/use-mini18n)

ロゴも思い切って作りました。勢い大事。

![use-mini18n-logo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205976/46992151-53ad-73a9-a13c-5fb45d2bbd85.png)

こちらのライブラリでやれることはシンプルです。
以下のコードサンプルは、このライブラリがやれることをすべて表しています。
[(実際に動作しているところをCodeSandbox上で確認できます)](https://codesandbox.io/s/use-mini18n-minimal-basic-example-qsug1?file=/src/index.js)

```javascript
import React from "react";
import ReactDOM from "react-dom";
import { TransProvider, useI18n } from "use-mini18n";
import "./styles.css";

const i18n = {
  en: {
    Hello: "Hello {name}",
    "Start editing to see some magic happen!":
      "Start editing to see some magic happen!"
  },
  ja: {
    Hello: "こんにちは {name}",
    "Start editing to see some magic happen!":
      "いくつかの魔法を目にするために編集を開始します！"
  }
};

const App = () => {
  const { t, lang, langs, changeLang, getText } = useI18n();

  return (
    <div className="App">
      <h1>{getText("Hello", { name: "CodeSandbox" })}</h1>
      <h2>{t["Start editing to see some magic happen!"]}</h2>
      <hr />
      <p>Selected lang: {lang}</p>
      <select
        name="lang"
        onChange={({ target }) => changeLang(target.value)}
        value={lang}
      >
        {langs.map((l, i) => (
          <option value={l} key={i}>
            {l}
          </option>
        ))}
      </select>
    </div>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(
  <React.StrictMode>
    <TransProvider i18n={i18n}>
      <App />
    </TransProvider>
  </React.StrictMode>,
  rootElement
);
```

開発者が `use-mini18n` でやれることは、このサンプルコードに記載されていることだけです。
いくつかの細かなオプションも用意してあるので、そちらについては[リポジトリ内のREADME](https://github.com/shinshin86/use-mini18n/blob/master/README.md)、もしくは[examples](https://github.com/shinshin86/use-mini18n/tree/master/examples)を参照してください。

また、`use-mini18n`はデフォルトで、ユーザの希望した言語設定をブラウザの `localStorage` に保存します。
私がこのような設計にしたのは、開発者として言語設定の管理に一切時間を割きたくなかったからです。
もしそのような動作を望まない場合は、`localStorage`を利用しないオプションも存在しています。

```javascript
<TransProvider i18n={i18n} enableLocalStorage={false}>
  <App />
</TransProvider>
```

これで`use-mini18n`に関する話は終わりとなります。

`use-mini18n`のミニマムな世界観には満足しています。このライブラリはi18n関連のすべてをカバーしているわけではありませんが、それはそれで良いと考えています。
もし`use-mini18n`が力不足だと感じるときがあれば、そのときは他の素晴らしいi18nライブラリに切り替えるときだと考えています。

もしバグや疑問点などありましたら、上に貼ったGitHubリポジトリか、こちらのポストに直接コメントを頂けたらと思います。

というわけで、サクッとi18n対応を行うためのReact hooksライブラリを作ってみた、という内容でした。
最後まで読んでいただき、ありがとうございます！