I18Nv2の基本
I18Nv2を使えば、コードからロケールに特有の書式を排除することができます。
まず、I18Nv2の基本的な使い方を確認します。次のコードによって、ブラウザの言語設定をPHP側で取得・設定することができます。
require_once 'I18Nv2/Negotiator.php'; require_once 'I18Nv2/Locale.php'; $i18n=new I18Nv2_Negotiator(); echo $i18n->getLocaleMatch();
ロケールが正しく設定されたことは、次のように確認できます。ブラウザの言語設定を英語/米国にして試してみましょう。
echo setlocale(LC_ALL,0); //English_United States.1252(日本語ならJapanese_Japan.932)
このような自動設定は便利なのですが、ユーザーによっては、自分のブラウザの設定とは違う言語でページを閲覧したいということもあるでしょう。Webアプリを作る際には、そのようなユーザーのためのインターフェイスは何かしら用意しておくべきです。そのようなインターフェイスがあったとして、それを通じて実際に手動でロケールを切り替えるには、次のようなコードを実行します。
$loc=new I18Nv2_Locale('en_US'); //英語/米国に $loc=new I18Nv2_Locale('ja'); //日本語に $loc=new I18Nv2_Locale('English_United States'); //英語/米国に
上のコードにI18Nv2を導入するメリットの一つが現れています。組み込みのsetlocaleを利用する際には、WindowsとWindows以外でその設定方法を変えなければなりませんでした。しかし、I18Nv2を用いると、この例のように、Windowsでも「en_US」のような表記が可能になるのです。
日付の表示
I18Nv2を使って日付を表示してみましょう。ブラウザの言語設定を英語/米国にして以下のコードを実行すると、日付が米国式に表示されます。
echo $loc->formatDate(mktime()); //18-Feb-2008
日本語を試す前に、formatDateの機能をもう少し紹介しましょう。日付の表示には、shortとmedium、long、fullという4つの形式が用意されています(指定しなければmediumになります)。
$loc->setDateFormat(I18Nv2_DATETIME_SHORT); echo $loc->formatDate(mktime()); //18/02/08 echo '<br />'; $loc->setDateFormat(I18Nv2_DATETIME_MEDIUM); echo $loc->formatDate(mktime()); //18-Feb-2008 echo '<br />'; $loc->setDateFormat(I18Nv2_DATETIME_LONG); echo $loc->formatDate(mktime()); //18 February 2008 echo '<br />'; $loc->setDateFormat(I18Nv2_DATETIME_FULL); echo $loc->formatDate(mktime()); //Monday, 18 February 2008
日本語への対応
ブラウザの言語設定を日本語にして上のコードを試してみましょう。もし、ほとんど何も表示されなくなってしまったとしたら、それは、日本語用の書式が用意されていないためです。
次のような内容のファイル「ja.php」を作って(UTF-8形式)、PHPがインストールされたディレクトリの下の「PEAR/I18Nv2/Locale」に置いてください(筆者の環境では「C:\xampp\php\PEAR\I18Nv2\Locale」)。
<?php $this->dateFormats=array( //日付の書式 I18Nv2_DATETIME_SHORT=>'%y/%m/%d', I18Nv2_DATETIME_DEFAULT=>'%Y/%m/%d', I18Nv2_DATETIME_MEDIUM=>'%Y/%m/%d', I18Nv2_DATETIME_LONG=>'%Y年%m月%d日', I18Nv2_DATETIME_FULL=>'%Y年%m月%d日' ); ?>
もう一度実行すれば、期待通りの結果が得られるはずです。
時刻の表示
時刻も日付と同様で、4つの書式を使い分けることができます。まずは、ブラウザの言語設定を英語/米国にして実行してみましょう。
$loc->setTimeFormat(I18Nv2_DATETIME_SHORT); echo $loc->formatTime(mktime()); //17:36 echo '<br />'; $loc->setTimeFormat(I18Nv2_DATETIME_MEDIUM); echo $loc->formatTime(mktime()); //17:36:04 echo '<br />'; $loc->setTimeFormat(I18Nv2_DATETIME_LONG); echo iconv('SJIS-WIN','UTF-8',$loc->formatTime(mktime())); //17:36:04 東京 (標準時) echo '<br />'; $loc->setTimeFormat(I18Nv2_DATETIME_FULL); echo iconv('SJIS-WIN','UTF-8',$loc->formatTime(mktime())); //17:36 o'clock 東京 (標準時)
formatTime
は内部的でstrftime
を呼んでいるのですが、タイムゾーン(%Z)が国際化されていないようです。しかもSJIS-WIN(Windows-31JあるいはCP932)で出力されるので、UTF-8に変換しています(注1)。
日本語への対応
日付の表示の際に初めて日本語に対応した(つまり、もともと日本語への対応がなされていなかった)場合には、ここでも日本語用の書式を用意しなければなりません。以下のコードを、先に作成した「ja.php」に追記してください。
$this->timeFormats=array( //時刻の書式 I18Nv2_DATETIME_SHORT=>'%H:%M', I18Nv2_DATETIME_DEFAULT=>'%H:%M:%S', I18Nv2_DATETIME_MEDIUM=>'%H:%M:%S', I18Nv2_DATETIME_LONG=>'%H時%M分%S秒', I18Nv2_DATETIME_FULL=>'%H時%M分%S秒 %Z' );
文字参照を使っています(「時」はU+6642、「分」はU+5206、「秒」はU+79D2です)。「%H時%M分%S秒」と書きたいところなのですが、さきほどタイムゾーンが国際化されていない問題を回避するために、SJIS-WIN(Windows-31JあるいはCP932)をUTF-8に変換するコードを書いてしまったので、ここでUTF-8の文字列を使うと文字化けが発生してしまいます。
タイムゾーンの問題に伴う文字コードの変換がなかったとしても、日付の「月」の時と同じ問題が発生するので、やはり文字参照を使うのが安全でしょう。
「ja.php」をShift_JIS(あるいはCP932)で書いて、スクリプト側ですべて変換することにしておけばよいと思うかもしれませんが、その方法で対応できるのは日本語と英語など、ごく一部の言語だけです。国際化のために使える文字コードはUnicodeしかありません。
日付と時刻をまとめて表示
日付(setDateFormat
で書式を設定しformatDate
で表示する)と時刻(setTimeFormat
で書式を設定しformatTime
で表示する)のほかに、日付と時刻をまとめて表示するメソッドも用意されています。setDateTimeFormat
で書式を設定し、formatDateTime
で表示します。書式の設定方法や使い方は日付や時刻と同じです。
日時を表現する際の注意
メソッドformatDate
やformatTime
、formatDateTime
には、引数としてint
型のタイムスタンプを与えます。そのため、『PHPにおける日付と時刻の混乱』で紹介した2038年問題がここでも発生します。1901-12-13T20:45:52+0000より前と2038-01-19T03:14:07+0000より後の日時を使う可能性のある状況では、I18Nv2を使うべきではありません。