10
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

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

Posted at

やりたいこと

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

といった文章で、日本語では「利用規約」に、英語では、「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 は、デフォルトでそのまま使える設定になっているようなので、普通に使う。

en.json
{
    "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'],
    },
  });

こうすると、

ja.json
{
    "text": "どうしても<span>span</span>タグが使いたい!"
}

span タグが span タグとして出力される。

文章中にリンクを入れる

ja.json
{
    "termsText": "<l>利用規約</l>に同意する"
}
en.json
{
    "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 オプションは、複数指定することもできる。

ja.json
    "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>,
   ]}
/>

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

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

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

&gt; とか &amp; とか &copy; とか

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

ja.json
{
    "copyright": "&copy; 2022 TAKT R&amp;D Co.,Ltd."
}
<Trans i18nKey="copyright" shouldUnescape={true} />

変数を代入する

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

ja.json
{
    "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')}

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

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

10
4
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?