FrontEnd

react-intl (Format.js) を使ってi18n対応

投稿日:2021年12月6日 更新日:

はじめに

最近、Reactを勉強しているので、しばらくはReactの記事を書いていきたいと思います! 今回は、Reactでi18n対応する方法について紹介します。

react-intlとは?

ReactやVue.jsなどで、i18n対応ができるパッケージです。総称してFormat.jsと呼ばれていますが、実際に使用するパッケージは react-intl になります。GithubのStart数も多く、人気のパッケージです。
https://formatjs.io/

react-intlの導入

まずは、create-react-appします。

次に、Format.jsを追加します。また、今回はCSSフレームワークとしてMUIを使用するので、併せて追加します。

使い方

IntlProviderの実装

react-intlは、Reactコンテキストとして実装されており、i18n対応したい箇所を <IntlProvider> コンポーネントで囲う必要があります。IntlProviderは、ロケールや翻訳メッセージなどを持ち、配下の <Formatted*> コンポーネントで使用されます。
一般的には、Reactコンポーネントのルートに近い位置に <IntlProvider> コンポーネントを置き、アプリケーション全体で使えるようにした方が良いそうなので、そのように実装してみます。

index.tsxを編集します。

IntlProviderに渡しているPropsについて説明します。

  • locale
    ja、enなどのロケールが入ります。今回は、 navigator.language から取得しているため、ブラウザの言語設定が入ります。後ほど説明する日時フォーマットは、ここのlocaleによって適切にフォーマットされます。
  • messages
    翻訳メッセージを渡します。今回は selectMessages() で、 navigator.language によってメッセージを切り替えています。メッセージ自体は、JSONファイルに定義して、importしています。

メッセージ定義

今回は、JSONファイルにメッセージを定義していきます。構造はフラットにする必要があるため、構造を示す場合には . などで区切ります。

src/lang/en.json

src/lang/ja.json

<Foramatted*>コンポーネントの使用

IntlProviderの配下で、実際にi18nしていくには、 <Formatted*> コンポーネントを使います。

メッセージ

先ほど定義したメッセージを表示させるには、 <FormattedMessage> を使用します。

「こんにちは、太郎さん!」と表示されました。
この他にも、様々なMessage Syntaxに対応しているので、よく使いそうなものを紹介します。

複数形対応

複数形を表現するには、 plural フォーマットを使用します。

翻訳メッセージ内に {key, plural, matches} という形式で表します。

  • key
    複数化を判断するための数値を受け取ります。
  • plural
    複数形フォーマットを指定するため、 plural を指定します。
  • mathces
    keyの値によって表示させたいメッセージを指定します。書式は 条件 {文言} です。条件には、次のようなものがあります。

    • one: 単数
    • other: 複数
    • =value: 特定の数値

英語や日本語以外では、上記以外の条件を使うこともあるようです。詳しくはこちらの公式リファレンスが参考になります。
https://formatjs.io/docs/core-concepts/icu-syntax/#plural-format

日時

まず、日付を表示させてみます。

これで、「2021年11月30日(火)」と表示されました。プロパティを渡さなくすれば、表示させないようにすることもできます。
また、 year , weekday , month , day などのプロパティを全て渡さなければ、デフォルトである「2021/12/1」と表示されるようになります。

次に、時間を表示させてみます。

こちらは、「19:21:54」と表示されました。もし秒数が不要であれば、 second= を削除すれば表示されなくなります。(その場合、デフォルト設定と同じになるため、hour, minute, secondを全て削除しても構いません。)

<FormattedDate><FormattedTime> は、使用箇所でいちいち定義するより、いずれもラップしたコンポーネントを作り、アプリケーション全体で共通化した方が良いと思いました。日時のフォーマットは、アプリケーション全体で統一感を持たせた方が良いと思うためです。

タイムゾーンについて

<FormattedDate><FormattedTime> は、valueに渡されたDateオブジェクトをもとにフォーマットを行います。そのため、ISO8606形式の日付を Date.parse() でパースすれば、ブラウザのタイムゾーンに変換して表示させることができます。

UTC時間で0時を指定していますが、ブラウザで表示してみると「2021年1月1日(金) 9:00:00」と表示され、ブラウザのタイムゾーンに変換されていることが分かります。

ちなみに、Chromeでタイムゾーンを変更するには、Developer Toolsを開き、「…」からSensorsを開きます。Locationを変更してからリロードすると、タイムゾーンによって時刻の表示が変わることが確認できます。

数値(通貨など)

数値のフォーマットを行うには、 <FormattedNumber> を使います。
まず、通貨の表示をやってみます。

USDは「$ 10.00」、JPYは「\ 1,000」と表示されました。このように、通貨に合わせてフォーマットされます。

その他にも、 style="unit" とすることで、様々な単位の数値を出力するこどがてきます。

たとえば、上記の場合は「10 MB」と表示されます。その他にも様々な単位が用意されています。詳しくは下記のを参照してください。
https://formatjs.io/docs/polyfills/intl-numberformat#SupportedUnits

命令型APIの呼び出し

ここまでに紹介した、 Formatted** は Reactコンポーネントとして描画するほかに、命令型APIとしても同じ機能が用意されています。 useIntl フックが用意されているので、これを使います。

例えば、MUIのSnackbarでは、表示するメッセージをstringで渡す必要があります。そこで、 intl.formatMessage() を使うと、 <FormattedMessage> と同じ結果を得られます。
基本的には、 format** という関数名で、先ほど紹介したReactコンポーネントと同じ結果を得ることができます。

言語の変更

ここまでのサンプルでは、 navigator.language でブラウザの言語を取得していましたが、今度は言語をアプリケーション内で変更できるようにしたいと思います。
今回は、 IntlProvider をラップしたReact コンテキストを実装することで、localeやmessagesを切り替えできるようにしたいと思います。

まずは、React コンテキストから実装していきます。

まず、 const langs に言語を定義していきます。ここで定義したプロパティは、そのまま IntlProvider に渡すため、 IntlProvider のプロパティのインターフェイスに合わせておきます。
また、 switchLang 関数を公開することで、子コンポーネントから言語を切り替えることができるようになっています。 switchLang 関数では、指定されたlocaleを探し、 setLang しています。
そして、 <IntlProvider {...lang}> とすることで、選択された言語情報を渡し、変更があったときに再描画されるようにしています。

最後に、index.tsxを修正します。

先ほど作成した <IntlProviderWrapper> で、 <App /> を囲います。これで、アプリケーション全体で、どこからでも言語を変更できるようになりました。
それでは、さっそく言語を変更してみましょう。

先ほど公開した switchLang 関数を呼び出し、言語を変更することができました。

さいごに

react-intlを使うと、i18nだけでなく、日時や単位のフォーマットもできることが分かりました。

おすすめ書籍

Reactハンズオンラーニング 第2版 ―Webアプリケーション開発のベストプラクティス プログラミングTypeScript ―スケールするJavaScriptアプリケーション開発

blog-page_footer_336




blog-page_footer_336




-FrontEnd
-

執筆者:


comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA


関連記事

ウチのMaterialize事情

1 はじめに2 ボタン3 フォーム3.1 ラベルについて3.2 セレクトボックスについて3.3 ラジオボタンについて4 アラート5 フォント6 さいごに はじめに うちのチームでは現在、CSSフレーム ...

js

今さらChart.jsでグラフ描画

1 はじめに2 準備3 折れ線グラフと棒グラフ3.1 コード全体3.2 html3.3 JS4 円グラフ4.1 html4.2 JS5 さいごに6 おすすめ書籍 はじめに JSのチャートライブラリは色 ...

react-icon

React Konvaで状態管理されたCanvasを描画してみた

1 はじめに2 Canvasとは?3 React Konvaとは4 着せ替えアプリっぽいサンプルを作成4.1 React Konvaの導入4.2 画像の描画4.3 stateによるCanvas描画4. ...

react-icon

React Big Calendarの複数タイムゾーン対応

1 はじめに2 端末のタイムゾーンのみに対応する場合3 複数のタイムゾーンに対応する。3.1 日時を指定のタイムゾーンに変換する3.2 イベントの開始日時・終了日時を動的に設定する3.3 ラップクラス ...

Vue.js入門その2〜Vueインスタンスってなんぞ?〜

1 はじめに2 Vueインスタンス3 プロパティとメソッド4 インスタンスライフサイクルフック5 フィルター6 算出プロパティ6.1 例文6.2 算出プロパティを使用した書き換え6.2.1 HTML6 ...

フォロー

blog-page_side_responsive

2021年12月
 1234
567891011
12131415161718
19202122232425
262728293031  

アプリ情報

私たちは無料アプリもリリースしています、ぜひご覧ください。 下記のアイコンから無料でダウンロードできます。