ウェブサイトをグローバル化するために便利なIntl APIの話

この記事は[トレタ Advent Calendar 2016](http://qiita.com/advent-calendar/2016/toreta)の13日目の記事になります。
トレタでは飲食店の予約アプリを作成しています。
今流行のウェブ予約も飲食店向けに開放していますので、見たことある人もいるかと思います。

# インターナショナル対応について
まず、インターナショナル対応の定義を考えてみましょう。
## i18n
 internationalization（国際化）の略で始めのiから終わりのnまでの間に18文字入っているのでi18nと呼ばれています。
 いわゆる言語変換で、日本語を英語に置き換えたりします。

## l10n
 localization(地域化)の略でlとnの間が10文字入っているのでl10nといいます。
 こちらは言語に加え、地域も考慮に入ってきます。
 公用語が英語の国は多々あれど、文化がちがい、英語の代表的な国のイギリスとアメリカでも結構違っています。

さて、ウェブアプリを作成するときには、日本固有のサービスならいいのですが、とくに国は関係ない場合などはその国の言語やフォーマットに合わせたほうが使ってくれる人が増えるというものです。
でも、国のフォーマットなどを用意するのは大変です。

そこで、ブラウザの機能で用意してあるIntl APIを紹介します。

# Intl API

> Intl オブジェクトは、ECMAScriptの国際化APIの名前空間です。それは、言語に依存した文字列の比較、数値フォーマット、日付フォーマットを提供します。

引用: [Intl - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Intl)

# Intl.Collator

## Intl.Collator.prototype.compare
これは、比較する文字の順番を返してくれるメソッドになります。

```JavaScript
console.log(new Intl.Collator().compare('a', 'c'));
//  -> -1
console.log(new Intl.Collator().compare('c', 'a'));
//  -> 1
console.log(new Intl.Collator().compare('a', 'a'));
//  -> 0
```

さて、言語を気にすることで面倒くさいものの一つに日本語や英語ではあまり見ない文字 `ä` などがあります。
aに似ているから親戚かなと思いきや全く違う文字となります。
そして厄介なことに言語によって順番が違っているのです。
しかし、国や地域を指定することで順番を取得することができます。

```JavaScript
// ドイツ語
console.log(new Intl.Collator('de').compare('ä', 'z'));
//  -> -1

// スウェーデン語
console.log(new Intl.Collator('sv').compare('ä', 'z'));
//  -> 1
```



# Intl.DateTimeFormat

## Intl.DateTimeFormat.prototype.format

国際化でよく出てきて大変なのは日付のフォーマットです。
日が先か年が先かなど、国によって様々です。
しかし、このメソッドを大多数をよしなに揃えてくれます。

```JavaScript
var date = new Date(Date.UTC(2016, 11, 13, 4, 0, 0));
console.log(new Intl.DateTimeFormat('ja-JP').format(date));
//  -> 2016/12/13
console.log(new Intl.DateTimeFormat('en-GB').format(date));
//  -> 13/12/2016
console.log(new Intl.DateTimeFormat('en-US').format(date));
//  -> 12/13/2016
console.log(new Intl.DateTimeFormat('ar-EG').format(date));
//  -> ١٣‏/١٢‏/٢٠١٦
```

しかし、スラッシュと数字だけの表示では味気ないかと思います。
その時は、オプションを渡せば数字だけではなく文字列での日付も返すことが可能です。

```JavaScript
var date = new Date(Date.UTC(2016, 11, 13, 4, 0, 0));
var options = { weekday: 'short', year: 'numeric', month: 'short', day: 'numeric' };
console.log(new Intl.DateTimeFormat('ja-JP', options).format(date));
//  -> 2016年12月13日(火)
console.log(new Intl.DateTimeFormat('en-GB', options).format(date));
//  -> Tue, 13 Dec 2016
console.log(new Intl.DateTimeFormat('en-US', options).format(date));
//  -> Tue, Dec 13, 2016
console.log(new Intl.DateTimeFormat('ar-EG', options).format(date));
// -> الثلاثاء، ١٣ ديسمبر، ٢٠١٦
```

もちろん時間も追加することが出来ます。

```JavaScript
var date = new Date(Date.UTC(2016, 11, 13, 4, 0, 0));
var options = { weekday: 'short', year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute: 'numeric', second: 'numeric' }
console.log(new Intl.DateTimeFormat('ja-JP', options).format(date));
//  -> 2016年12月13日(火) 13:00:00
console.log(new Intl.DateTimeFormat('en-GB', options).format(date));
//  -> Tue, 13 Dec 2016, 13:00:00
console.log(new Intl.DateTimeFormat('en-US', options).format(date));
//  -> Tue, Dec 13, 2016, 1:00:00 PM
console.log(new Intl.DateTimeFormat('ar-EG', options).format(date));
// -> الثلاثاء، ١٣ ديسمبر، ٢٠١٦ ١:٠٠:٠٠ م
```

国によって使われているのが24時間表記か12時間表記かもよしなに表示してくれます。素晴らしい


# Intl.NumberFormat

## Intl.NumberFormat.prototype.format

数字の表示では3桁区切りとかしたいと思いますが、今まではNumberを一度Stringにしてから3桁で区切っていたりしていました。
がこちらは勝手に3桁区切りをしてくれるというとても良いものです。

```JavaScript
var number = 12345678;
console.log(new Intl.NumberFormat().format(number));
//  -> 12,345,678
```

そして、通貨表示という最も難易度の高い表示をよしなにやってくれるというものになります。
何で難易度が高いかというと、通貨は国によって小数点があったりなかったり、あっても2桁だったり3桁だったりするのです。
そのような国特有のフォーマットをよしなに表示してくれます！！

```JavaScript
var number = 5000;
console.log(new Intl.NumberFormat('ja-JP', { style: 'currency', currency: 'JPY' }).format(number));
//  -> ￥5,000
console.log(new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(number));
//  -> $5,000.00
console.log(new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(number));
//  -> 5.000,00 €
console.log(new Intl.NumberFormat('en-GB', { style: 'currency', currency: 'GBP' }).format(number));
//  -> £5,000.00
```

そして、気になる利用できるブラウザはほぼすべてのモダンブラウザで利用可能となっています。

| Feature       | Chrome | Edge | Firefox (Gecko) | Internet Explorer | Safari | Chrome for Android | Safari Mobile |
|:--------------|:-------|:-----|:----------------|:------------------|:-------|:-------------------|:--------------|
| Basic support | 24     | 12   |29(29)           |11                 |10      |26                  |10             |

もし、対応していないブラウザでも利用したい場合は[polyfill.io](https://polyfill.io/)にてIntlが置いてありますので読み込んで使ってみてください。