やりたいこと
react-i18next を使うと、React.js を簡単に多言語対応することができる。インストールや基本的な使い方は、ググればいくらでも出てくるので、そちらに任せるとして、多言語対応のサイトを構築していると、例えば、
- 利用規約に同意する
- Agree with the terms of use
といった文章で、日本語では「利用規約」に、英語では、「the terms of use」に、リンクを貼りたいみたいなことがある。言語によって言葉の並び順が違ったり、文章の長さが異なるので、スマホで英語の場合は、改行したい。みたいなこともある。
key を分割してうまいことやる、元の文章を工夫する。というのも手だが、ダサい。
できるだけ複雑にせず、うまいことやりたい。
Trans
コンポーネント
そこで、Trans
というコンポーネントを使う。
ドキュメントを開くと、いきなり、あんまり使ってくれるな的なことが書いてある。
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
は、デフォルトでそのまま使える設定になっているようなので、普通に使う。
{
"text": "Lorem ipsum dolor sit,<br /> amet consectetur adipisicing elit."
}
この br 入りのテキストは、
import { Trans } from 'react-i18next';
...
<Trans i18nKey="text" />
...
これだけ。
デフォルトのまま使うと言ったけど、例えば、どうしても span
タグも普通に使いたい!という場合は、init する際に、追加すれば良い。
i18n
.use(initReactI18next)
.init({
...
react: {
transKeepBasicHtmlNodesFor: ['br', 'strong', 'i', 'p', 'span'],
},
});
こうすると、
{
"text": "どうしても<span>span</span>タグが使いたい!"
}
span タグが span タグとして出力される。
文章中にリンクを入れる
{
"termsText": "<l>利用規約</l>に同意する"
}
{
"termsText": "Agree with <l>the terms of use</l>"
}
<Trans
i18nKey="termsText"
components={{ l: <a href="/terms">利用規約</a> }}
/>
こんな感じで、components
オプションに指定することで、リンクを変換することができる。
link, img, media
などのキーワードは使えない。link_terms
などは使える。
components の中の「利用規約」という文字は、lint で怒られるので入れたが、どこにも出てこないので、分かりやすさのためくらいで入れておくと良いかも知れない。
私は、リンクは言語によってパスが変わったり、装飾したりしたいので、別途コンポーネント化し、それを入れているので、こういう使わないテキストは入れてない。
components
オプションは、複数指定することもできる。
"termsText": "<link_terms>利用規約</link_terms>と<link_privacy>プライバシーポリシー</link_privacy>に同意する
<Trans
i18nKey="termsText"
components={{
link_terms: <a href="/terms">利用規約</a>,
link_privacy: <a href="/privacy">プライバシーポリシー</a>,
}}
/>
components
オプションは、配列で指定することもできる。
<Trans
i18nKey="termsText"
components={[
<a href="/terms">利用規約</a>,
<a href="/privacy">プライバシーポリシー</a>,
]}
/>
設定の方は、添字で指定する。
{
"termsText": "<0>利用規約</0>と<1>プライバシーポリシー</1>に同意する"
}
すっきりするけど、分かりづらいので、key を指定する方が良さそう。
>
とか &
とか ©
とか
shouldUnescape
オプションを true
にする。
{
"copyright": "© 2022 TAKT R&D Co.,Ltd."
}
<Trans i18nKey="copyright" shouldUnescape={true} />
変数を代入する
values
を使う。components
と使い方はだいたい一緒。
{
"version": "バージョン: {{ version }}"
}
<Trans i18nKey="version" values={{ version: "11.18.6" }} />
// とか、
const version = process.env.REACT_APP_VERSION;
<Trans i18nKey="version" values={{ version }} />
おしまい
というわけで、やりたいことはできました。
なんかいちいち面倒なので、良い感じにコンポーネント化できないかなとも一瞬思いましたが、
{t('text_key')}
このお手軽さが良いので、余計なことはしないでおきました。
今回紹介したもの以外にも、あんまり推奨してない割にはたくさんのオプションがあるので、どうしてもやりたいことがあるという場合は、調べてみてください。