Browserify環境でMoment.jsの国際化を利用しようとしたときのメモ
ちょっとした日時計算をするだけのペライチなWebページを作ろうとしていました。
日時情報を取り扱う処理を実装するので、定番の Moment.js を組み込んでいたのですが。
UI部分は最近取り組んでいるReactを使うことにして、JSXの変換も済ませた形で組み込むのが良いと思ったので、開発環境としてはBrowserify + Babelify (+ Watchify)としつつ、Moment.jsも含めて、npmで諸々導入していました。
そのついでに、特に必須というわけではなかったのですが、日付や時刻の表記をMoment.js使えば国際化するの簡単なんじゃじゃない?と思ってやってみたところハマってしまったので、そのメモです。
ハマったこと
ハマった点は、以下の3つ。
クライアント(ブラウザ)のタイムゾーンが取れない
国際化をするにあたり、まずは結果表示時にタイムゾーン名を表示しようと思ったのですが、Moment.jsにタイムゾーンを取得するAPIがありませんでした。
Moment.jsの拡張ライブラリのような Moment Timezone というものがあるのですが、こちらを見ても、 タイムゾーンを指定して 処理をするAPIはあるのですが、肝心の取得をするものが見当たりません。
そこで調べていると、以下の記事を発見しました。
JavaScript でタイムゾーン名を取得する方法 - Qiita
これによると、そもそもJavaScriptのDateには、タイムゾーン名を取得するためのインターフェイスが用意されていないから、ということでした。
紹介されている jsTimezoneDetect というライブラリを使うことで、ある程度判定してくれるようですが、あくまで予測であって正確なものではないということです。
ちなみに、jsTimezoneDetectもnpmから導入できます。
$ npm install jstimezonedetect
Moment.jsをrequireで読み込んだ場合、ロケールデータが読み込まれない
次に、Moment.jsの format()
で得られる結果を国際化しようとして、ハマりました。
以前にもWebサイトの制作でMoment.js自体は使ったことがあり、そのときはロケール設定さえすれば問題なく日本語フォーマットにできた覚えがあったので、特につまずくことはないと思っていたのですが。
Node.jsでロケールデータを読み込む場合、公式のドキュメントによると、 moment.locale('ja')
を最初に呼び出したのタイミングで読み込まれるようです。
ところが、Browserifyを使って変換・結合されたJavaScriptを確認すると、ロケールデータが含まれていませんでした。
おそらく、 moment.locale()
で指定する言語が明確に指定されていないため、読み込まれないのだと推測しました。
調べていたところ、別のライブラリのIssueで対応策を発見。
How to use different locales with browserify/npm build? · Issue #10 · zippyui/react-date-picker
これによると、以下のように require
で個別にロケールデータを読み込むというもの。
require('moment/locale/ja');
しかし、ユーザーの環境に応じてロケールデータを切り替えたい場合は、この方法だと全部の require
を書く必要があります。
少し面倒だったので、以下のようにて指定したみたところ、一括で全ロケールデータを読み込んでくれました。
require('moment/min/locales');
注意点は、その後 moment.locale()
でロケールを設定しないと、最後に読み込んでいる zh-tw
が使われてしまう模様。
アプリの最初にデフォルトのロケールを設定してあげるのが良さそうです。
ブラウザの言語設定の取り方は複数ある
クライアント(ブラウザ)に合ったロケールを指定するために、今度は言語設定を参照したいわけですが、そのAPIがブラウザによって若干違うらしいということもわかりました。
ブラウザの言語をJavascriptから調べる。 – @masuidrive blog
上記のサイトでは先頭2文字を切り出していましたが、Moment.jsではハイフン区切りのものと一致しない場合は自動的にハイフン前の部分で探してくれるらしい( en-NZ
がなければ en
を探す、など)ので、 .substr(0,2)
の部分は省いた形で利用させていただくことにしました。
function browserLanguage() { try { return (navigator.browserLanguage || navigator.language || navigator.userLanguage); } catch(e) { return undefined; } }
感想
ふだん国際化を意識することがあまりなかったこともあり、ブラウザ周りの言語関係は迂闊に手を出すとハマるということがわかりました。
参考
- Moment.js
- Moment Timezone
- jsTimezoneDetect
- JavaScript でタイムゾーン名を取得する方法 - Qiita
- ブラウザの言語をJavascriptから調べる。 – @masuidrive blog
- 作者: 佐藤鉄平,小林明大,石村真吾,坂上卓史,上原誠,鳥居英,佐藤歩,泉水翔吾,うさみけんた,伊藤直也,高橋侑久,佐藤太一,hayajo,橋本翔,西尾泰和,中島聡,はまちや2,WEB+DB PRESS編集部
- 出版社/メーカー: 技術評論社
- 発売日: 2015/06/24
- メディア: 大型本
- この商品を含むブログを見る