Reactの多言語対応


## 前書き
現在、reactの多言語対応の実装は`i18next`使うことが主流のため、手順を記録します。:writing_hand_tone1:

:point_up_tone1:ちなみに、`i18n`の意味は国際語化（Internationalization）の略。 ... I18Nとは、ある特定の１カ国語しか扱うことができないプログラムなどを、それ以外の言語圏でも利用できるように改造、変更することをします。

### 公式ドキュメント
https://react.i18next.com/guides/quick-start

### リポジトリ
https://github.com/i18next/react-i18next

## インストール

```
npm install react-i18next i18next --save 
```
or

```
yarn add react-i18next i18next
```

:point_up_2_tone1:i18nextはTypescript対応してるため、別途typeファイルインストールする必要はありません。

## 実装
:writing_hand_tone1:`i18n`使って、言語切替機能の実装をやってみます。
あくまで参考ですが、フォルダ構成は以下になります。
`src`フォルダの配下に`i18n`フォルダを作ります、命名何でもいいですが、わかりやすくするために`i18n`にします。


```
|-- react-project
...
|-- src
|-- |-- i18n
|-- |-- components(任意)
|-- |-- pages(任意)
|-- index.tsx
...
```
:point_up_tone1:`i18n`フォルダ内に、`i18next`必要な設定ファイルと言語ファイルを置く必要があります。
仮に日本語と英語の切り替えを対応したい場合、`ja.json`と`en.json`の二つの言語ファイルを用意する必要があります。


```
...
|-- i18n
|-- |-- configs.ts
|-- |-- ja.json
|-- |-- en.json
...
```
`ja.json`ファイルの中身は以下になります。:point_down_tone1:
構成は特に決まりはないですが、コンポネートに合わせるとよいかもしれません。:point_up_tone1:

```ja.json
{
 "header": {
    "signin": "ログイン"
  }
}
```
`en.json`ファイルの中身は以下になります。:point_down_tone1:

```en.json
{
  "header": {
    "signin": "Signin"
  }
}
```

`configs.ts`ファイルの中身は以下になります。:point_down_tone1:

```typescript:configs.ts
import i18n from "i18next";
import { initReactI18next } from "react-i18next";

// 言語jsonファイルのimport
import translation_en from "./en.json";
import translation_ja from "./ja.json";

const resources = {
    ja: {
      translation: translation_ja
    },
    en: {
      translation: translation_en
    }
  };

  i18n
  .use(initReactI18next) // passes i18n down to react-i18next
  .init({
    resources,
    lng: "ja", 
    interpolation: {
      escapeValue: false // react already safes from xss
    }
  });

  export default i18n;
```
`index.tsx`に`i18next`の設定をimportします。

```typescript:index.tsx
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import "./i18n/configs"; //i18

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);
```
以上でi18の設定は終わりました。

## 使用

### クラスコンポネートで使用する場合

```typescript:任意のクラスコンポネート.tsx
...
import { withTranslation, WithTranslation } from "react-i18next";

class FooBarPageComponent extends React.Component<WithTranslation> {
 render() {
  const { t } = this.props;
  return (
    <>
     {t("header.signin")}
    </>
  )
 }
}
export const FooBarPage = withTranslation()(FooBarPageComponent);
```

### 関数コンポネートで使用する場合

```typescript:任意の関数コンポネート.tsx
...
import { useTranslation } from "react-i18next";

export const FooBarPage: React.FC = () => {
  const { t } = useTranslation();
  return (
    <>
     {t("header.signin")}
    </>
  )
}
```

### 言語切替関数の呼び出し

言語切替用の関数は`i18next`に用意されてます、
実装箇所は決まりないですが、大概それを呼び出すのはReducer内になると思います。

```typescript:言語用のReducer.ts
import i18n from "i18next";

...
export default (state, action) => {
    switch(action.type) {
        case CHANGE_LANGUAGE:
            i18n.changeLanguage("ja"); //呼び出し     
            return {...state, language: action.payload}
        default:
            return state;   
    }
}
```
`changeLanguage()`の引数は`configs.ts`に定義されてる`resources`の対応言語から選べます。