i18nについて - React Ariaの実装読むぞ
こんにちは、フロントエンドエンジニアの mehm8128 です。
今日は i18n について書いていきます。
React Aria の i18n
React Aria の i18n についてはこのページにまとめられています。
React Aria では主に、文字列の翻訳、日付と数値のフォーマット、RTL がサポートされています。
そしてこれらはブラウザに組み込まれている Intl オブジェクトの各 API を利用して実装されています。
Intl については saji さんの 1 人アドベントカレンダーでまとめられているので、適宜参照しながら解説していきます。
Intl の全体像についてはこちらの記事をご覧ください。
文字列の翻訳
useLocalizedStringFormatterを用いて現在の locale に基づいて翻訳されたテキストを取得できます。ここでは Intl は使われていません多分。
例えばuseNumberFieldだと、+/-ボタンに振られているラベルが翻訳されています。
en-US.jsonとja-JP.jsonを見てみます。IncreaseとDecreaseをそれぞれ「拡大」と「縮小」と訳すのはかなり微妙な気もするのですが、こんな感じに翻訳されています。
useLocalizedStringFormatter関数内ではuseLocaleで現在の locale を取得し、その locale のテキストに翻訳するためのformatメソッドを含むLocalizedStringFormatterオブジェクトを返しています。
useColorPickerでも、同じく翻訳用のパッケージが利用されていました。
数値のフォーマット
再びuseNumberFieldの話です。useNumberFieldでは様々な数値のフィーマットに対応していて、ブログ記事にまとめられています。
Intl.NumberFormatを用いて小数点や%や通貨、単位などのフォーマットをいい感じにしています。
Intl.NumberFormatについてはここらへんの記事を読みましょう。
RTL
アラビア語など、右から左に文字を書く言語圏の locale の場合、画面内の要素もミラーリングする必要があります。
ただし、React Aria はスタイリングにまでは責任を持っていないので、React Aria は主にキーボード操作などのインタラクション部分で RTL サポートをしています。
useLocaleからdirectionというltr | rtlの union 型の値を取得し、その値に応じてインタラクションの方向を変化させます。
例えばuseTabListの場合、directionをTabsKeyboardDelegateというオブジェクトのコンストラクタに渡しています。
TabsKeyboardDelegateはこれを受け取り、flipDirectionを定義するのに使います。flipDirectionはtrueのときにキーボード操作を反転させます。
getKeyLeftOfという関数では引数のkeyの 1 つ左のkeyを取得しますが、通常時(direction = ltrのとき)は 1 つ左というのは 1 つ前のkeyですが、flipDirection時には 1 つ左は 1 つ次のkeyになるので(見た目がミラーリングされても ← キーを押したときには左に移動する、みたいになっています)、getNextKey関数を使用しています。
Typeahead
useListBoxやuseGridList、useMenuでは Typeahead が実装されています。
useListBoxの記事で軽く言及していました。が、Typeahead についての説明が抜けていたので説明すると、リストにフォーカスしているときに頭文字を入力するとその文字から始まるリストアイテムにフォーカスを移動できるというものです。
これはuseCollatorを用いて実装されていて、内部でIntl.Collatorを使っています。
Intl.Collatorについてはこちらの記事をご覧ください。
上記の 3 つの hooks で共通で使われているuseSelectableListでは、ここでuseCollatorを用いてcollatorを取得し、ListKeyboardDelegateオブジェクトのコンストラクタに渡しています。
ListKeyboardDelegateはこれを受け取り、getKeyForSearchでリストアイテムの検索に用いてます。
日付のフォーマット
日付も地域によって様々なフォーマットがあるので、フォーマットされています。詳しくは明日の記事で書いたり書かなかったりするのですが、useDateFormatterという hook が提供されていて、その中でIntl.DateTimeFormatを利用しています。
useDateSegmentではここらへんで使われています。
日付についての公式ブログ記事はこちらです。
Intl.DateTimeFormatについてはここらへんの記事を読むといいです。
まとめ
明日の担当は @mehm8128 さんで、DateField についての記事です。お楽しみにー
Discussion