ひだまりソケットは壊れない

ソフトウェア開発に関する話を書きます。 最近は主に Android アプリ、Windows アプリ (UWP アプリ)、Java 関係です。

まじめなことを書くつもりでやっています。 適当なことは 「一角獣は夜に啼く」 に書いています。

Firefox の JS コンテキストのロケール指定方法

背景・目的

WebDriver 経由で geckodriver + Firefox を操作して JS の自動テストを行いたい。 その時、JS にロケール依存の処理が含まれていれば、テスト実行時にも Firefox の JS コンテキストのロケール指定を行いたい。

本記事では、Firefox 59 以降での、JS コンテキストのロケール指定方法について簡単に書いておく。

3 行まとめ

詳しい話

ECMAScript と国際化

ECMAScript における国際化のための仕様として ECMA-402 (ECMAScript Internationalization API Specification) というものがある。

この仕様により、例えば Date.prototype.toLocaleString メソッドなどが定義される。 このメソッドの呼び出し時にロケールを明示的に指定しなかった場合、使用されるロケールDefaultLocale 抽象操作によって決まる。 DefaultLocale実装依存である。

Firefox での DefaultLocale (JS コンテキストのデフォルトロケール)

Firefox における ECMA-402 の DefaultLocale の実装は、Firefoxロケールを返すようになっている模様。 ちゃんとしたドキュメントは見当たらなかったが、Bugzilla で教えてもらった。

JS context locale is tied to Firefox locale, not requested locale.

1475876 - intl.locale.requested doesn't affect to JS locale unless Language Pack is installed
Firefoxロケールの決まり方

で、Firefoxロケールの決まり方であるが、RFC 5656 をベースに、available locales と requested locales から決まるらしい。

Due to the imperfections in data matching, all operations on locales should always use a language negotiation algorithm to resolve the best available set of locales, based on the list of all available locales and an ordered list of requested locales.

Such algorithms may vary in sophistication and number of strategies. Mozilla’s solution is based on modified logic from RFC 5656.

Locale management — Mozilla Source Tree Docs 63.0a1 documentation

Available locales は、Firefox のパッケージに含まれているロケール (packaged locales) と、拡張機能としてインストールされた言語パックのロケール

In Gecko, available locales come from the Packaged Locales and the installed language packs. Language packs are a variant of web extensions providing just localized resources for one or more languages.

Locale management — Mozilla Source Tree Docs 63.0a1 documentation

デスクトップ版の Firefox では、Packaged locales は普通は 1 つのみ。 Android 版の方は 100 ぐらいのロケールを含むらしい。

When the Gecko application is being packaged it bundles a selection of locale resources to be available within it. At the moment, for example, most Firefox for Android builds come with almost 100 locales packaged into it, while Desktop Firefox comes with usually just one packaged locale.

Locale management — Mozilla Source Tree Docs 63.0a1 documentation

Requested locales は次のとおりで、intl.locale.requested pref に保持される。

After the sanitization, the value will be stored in a pref intl.locale.requested. The pref usually will store a comma separated list of valid BCP47 locale codes, but it can also have two special meanings:

  • If the pref is not set at all, Gecko will use the default locale as the requested one.
  • If the pref is set to an empty string, Gecko will look into OS app locales as the requested.

The former is the current default setting for Firefox Desktop, and the latter is the default setting for Firefox for Android.

Locale management — Mozilla Source Tree Docs 63.0a1 documentation

なので、基本的には使いたいロケールFirefox のパッケージに含まれるロケールか言語パックとしてインストールされたロケールであれば、intl.locale.requested にそのロケールを指定してやれば JS コンテキストのロケールがそのロケールになる。

en-US ロケールは特殊なロケール

日本語ロケールのデスクトップ版 Firefoxintl.locale.requested=en-US とした場合、英語の言語パックをインストールしていないと en-US ロケールにはならなさそう (available locales に含まれてないはずなので) なのだけど、実際には JS コンテキストのロケールは en-US になっているような挙動になった。

なんでだろー、と思ったのだけど、どうやら last fallback locale という特殊な扱いで en-US が使われてるらしい。

Gecko also support a notion of last fallback locale, which is currently hardcoded to “en-US”, and is the very final locale to try in case nothing else (including the default locale) works.

Locale management — Mozilla Source Tree Docs 63.0a1 documentation

悩み

というわけで、複数のロケールを切り替えて JS のテストをしたい場合は、言語パックをインストールすることになるっぽい。 もしくはロケールごとに Firefox のバイナリを用意するか。

言語パックのインストールがコマンドライン上で簡単にできればいいのだけど、ちょっと調べた感じでは大変そうで、どうしたものかなーと思っている。 簡単にできる方法があれば教えてください!

参考

Acknowledgement

この記事の内容は、株式会社 OND の仕事の一環として調べたものです。