多言語対応の react-i18next でリンクや html タグを使う

## やりたいこと
react-i18next を使うと、React.js を簡単に多言語対応することができる。インストールや基本的な使い方は、ググればいくらでも出てくるので、そちらに任せるとして、多言語対応のサイトを構築していると、例えば、

- [利用規約](#)に同意する
- Agree with [the terms of use](#)

といった文章で、日本語では「利用規約」に、英語では、「the terms of use」に、リンクを貼りたいみたいなことがある。言語によって言葉の並び順が違ったり、文章の長さが異なるので、スマホで英語の場合は、改行したい。みたいなこともある。

key を分割してうまいことやる、元の文章を工夫する。というのも手だが、ダサい。
できるだけ複雑にせず、うまいことやりたい。

## ```Trans``` コンポーネント

そこで、```Trans``` というコンポーネントを使う。

https://react.i18next.com/latest/trans-component

ドキュメントを開くと、いきなり、あんまり使ってくれるな的なことが書いてある。

> Important note
>While \<Trans\> gives you a lot of power by letting you interpolate or translate complex React elements, the truth is: in most cases you don't even need it.
As long you have no React/HTML nodes integrated into a cohesive sentence (text formatting like strong, em, link components, maybe others), you won't need it - most of the times you will be using the good old t function.

重要
```Trans``` を使うと、複雑なことができるようになりますが、ほとんどの場合、必要ありません。
文章が strong, em, リンクなどを含まない限り、普通に ```t``` 関数を使いましょう。

というわけで、いくつかオプションで設定したりできるようだが、素のまま使うことにする。


## 検証環境

- react: v18.2.0
- i18next: v21.10.0
- react-i18next: v11.18.6

それぞれの言語の設定は、```src/locale/ja.json```, ```src/locale/en.json``` などにまとめる。

## 改行する

```br```, ```strong```, ```i```, ```p``` は、デフォルトでそのまま使える設定になっているようなので、普通に使う。


```json:en.json
{
    "text": "Lorem ipsum dolor sit,<br /> amet consectetur adipisicing elit."
}
```

この br 入りのテキストは、

```typescript
import { Trans } from 'react-i18next';
...

<Trans i18nKey="text" />
...
```

これだけ。
デフォルトのまま使うと言ったけど、例えば、どうしても ```span``` タグも普通に使いたい！という場合は、init する際に、追加すれば良い。

```typescript
i18n
  .use(initReactI18next)
  .init({
    ...
    react: {
      transKeepBasicHtmlNodesFor: ['br', 'strong', 'i', 'p', 'span'],
    },
  });
```

こうすると、

```json:ja.json
{
    "text": "どうしても<span>span</span>タグが使いたい！"
}
```
span タグが span タグとして出力される。

## 文章中にリンクを入れる

```json:ja.json
{
    "termsText": "<l>利用規約</l>に同意する"
}
```

```json:en.json
{
    "termsText": "Agree with <l>the terms of use</l>"
}
```

```typescript
<Trans
  i18nKey="termsText"
  components={{ l: <a href="/terms">利用規約</a> }}
/>
```

こんな感じで、```components``` オプションに指定することで、リンクを変換することができる。
```link, img, media``` などのキーワードは使えない。```link_terms``` などは使える。
components の中の「利用規約」という文字は、lint で怒られるので入れたが、どこにも出てこないので、分かりやすさのためくらいで入れておくと良いかも知れない。

私は、リンクは言語によってパスが変わったり、装飾したりしたいので、別途コンポーネント化し、それを入れているので、こういう使わないテキストは入れてない。

```components``` オプションは、複数指定することもできる。

```json:ja.json
    "termsText": "<link_terms>利用規約</link_terms>と<link_privacy>プライバシーポリシー</link_privacy>に同意する
```

```typescript
<Trans
  i18nKey="termsText"
  components={{
     link_terms: <a href="/terms">利用規約</a>,
     link_privacy: <a href="/privacy">プライバシーポリシー</a>,
   }}
/>
```

```components``` オプションは、配列で指定することもできる。

```typescript
<Trans
  i18nKey="termsText"
  components={[
     <a href="/terms">利用規約</a>,
     <a href="/privacy">プライバシーポリシー</a>,
   ]}
/>
```

設定の方は、添字で指定する。

```json:ja.json
{
    "termsText": "<0>利用規約</0>と<1>プライバシーポリシー</1>に同意する"
}
```

すっきりするけど、分かりづらいので、key を指定する方が良さそう。

## ```&gt;``` とか ```&amp;``` とか ```&copy;``` とか

```shouldUnescape``` オプションを ```true``` にする。

```json:ja.json
{
    "copyright": "&copy; 2022 TAKT R&amp;D Co.,Ltd."
}
```

```typescript
<Trans i18nKey="copyright" shouldUnescape={true} />
```

## 変数を代入する

```values``` を使う。```components``` と使い方はだいたい一緒。

```json:ja.json
{
    "version": "バージョン: {{ version }}"
}
```

```typescript
<Trans i18nKey="version" values={{ version: "11.18.6" }} />

// とか、

const version = process.env.REACT_APP_VERSION;
<Trans i18nKey="version" values={{ version }} />
```

## おしまい

というわけで、やりたいことはできました。
なんかいちいち面倒なので、良い感じにコンポーネント化できないかなとも一瞬思いましたが、

```typescript
{t('text_key')}
```

このお手軽さが良いので、余計なことはしないでおきました。


今回紹介したもの以外にも、あんまり推奨してない割にはたくさんのオプションがあるので、どうしてもやりたいことがあるという場合は、調べてみてください。

https://react.i18next.com/latest/trans-component#trans-props