[PHP-dev 250] PHP 5/Zend Engine 2の国際化について
Masaki Fujimoto
php-dev@php.gr.jp
Tue, 05 Mar 2002 22:15:27 +0900
皆様こんにちは。ふじもとです。
先日廣川さんよりメールを頂き、それによりますと
- Zeevが3月末に来日するそうです
- 廣川さんに多少の時間的余裕ができる予感が!(PHP-dev 249等から不躾なのを
承知で勝手にそう思ってしまいました。すみません...)
というで、そろそろ本格的にPHP5/ZE2の国際化作業に取り掛かる時期のような気
がしてきました(とりあえ、ずこのままずるずると国際化機能無しのZE2のままリ
リースされるのは避けたいなぁ、と思っています)。
廣川さんは、Zeevの来日に合わせて国際化作業に関するミーティングを開いては
どうか、そしてその前にある程度MLで議論を詰めておいたい、とおっしゃってい
て僕も大賛成させていただきました。で、その叩き台となればと考えて、他のス
クリプト言語の実装をのぞいてみたり個人的にちょっと考えてみたりしているこ
とを書かせて頂きます。
未熟者ですのでツッコみどころも多いかと思いますし、ちゃんと調べていない箇
所もあったりしますが、識者の皆様の御意見をお待ちしております。
--- PHP 5/Zend Engine 2 の国際化に関する考察 ---
(I) 手法
というと大げさですが、おおざっぱに言って「PHPの言語仕様として、あらか
じめ、もしくはコンパイル時に、はたまた実行時に決定された内部エンコーディ
ング」(以下、単純に内部エンコーディング)というものを取り入れるか、取り
入れないか、という問題があると思います。現在のところいわゆるスクリプト
言語で内部エンコーディングというものを明確に定義しているのは国際化版
PHP3くらいだと思います(他にもあるかもしれませんが、無知なもので^_^;)。
で、他の言語では全てスクリプトエンコーディング==内部エンコーディングに
なりますよね。
で、内部エンコーディングを採用するメリットは、色々有るとは思うのですが
真っ先に思いつくのは、エンコーディングとしてUCS-4等を採用することで、
シングルバイト/マルチバイトを意識する必要がなくなるということでしょう
か。
逆に、内部エンコーディングを採用する際に世間の人が一番心配するのは、エ
ンコーディング変換のパフォーマンスのようです。が、これに関してはコンパ
イラっぽいツール(APCやZend Encoder)を使用すればよいと思いますし、それ
が嫌なら内部エンコーディングで書けばよい話なので、それ程心配しなくても
よいかと考えています。
まぁ、内部エンコーディングを採用しない、となると話は一気に変わってくる
(そして単純になる)と思うので、ここでは内部エンコーディングがあることを
前提に話を進めます。
そして内部エンコーディングを何にするか(もしくはどの様に決定するか等)、
というのは、最後まで読んでいただければご理解いただけるかと思いますが、
結局国際化版PHP5の中心的問題となるのでここではちょっと結論できません。
# ひょっとして自分は大いなる勘違いをしているような気がしていて、なんだか
# 不安です。いえ、なんとなくそう思うだけなのですが。
(II) 個々の問題
(1) スクリプトのエンコーディング
スクリプトのエンコーディングに関して問題となる点は以下の2つかな、と
思っています。
- スクリプトエンコーディングの判別方法
これについては
(i) php.ini/.htaccessで指定
(ii) 自動判別
(iii) スクリプト中で指定
(iv) コマンドライン版PHPの場合はオプションで指定
が考えられると思います。(i)についてはとくに問題ないですが、言うま
でも無くサイト全体、もしくはディレクトリごとにしか指定できません。
(ii)に関してはあくまで補助機能的な位置付けになると思います。
(iii)は、よしかわさんや石井さんにヒントを頂き、現在の国際化版PHP4
ではencodingディレクティブとして実装されていますが、これには「卵が
先か、鶏が先か」問題が付きまといます。たとえば、php.iniで
script_encodingをEUC-JPに設定しているときに、UNICODEで書いたスクリ
プトにencodingディレクティブを記述しておいても、字句解析器が
encodingディレクティブにたどり着く前にparse errorになる、というよ
うなことです。これについては、根本的な解決策は思い浮かんでいません。
(iv)に関してはrubyやjavaでも採用されており、極々普通のアプローチか
と思います。ただ、これだとincludeされるファイルのエンコーディング
はどうするんだ、という問題は残りますが(includeにファイルのエンコー
ディングを指定するオプションをつけるとか?)。
- スクリプトエンコーディングと内部エンコーディングが共に字句解析器
(多分flex)の対応していないエンコーディングであった場合の処理
これは内部エンコーディングをどうするかに大きく依存する話ですので現
状では保留せざるを得ないかと思います(仮に、あくまで仮にですが内部
エンコーディングはutf-8に固定、となれば心配する必要は無いわけです
し)。
(2) 入力データのエンコーディング
(3) 出力データのエンコーディング
このうち(2)と(3)については、現在のところhttp_input, http_outputが実
装されていますが、その他の入出力(例えばI/O、データベースとの通信等)
については内部エンコーディング素通しです(言うまでも無く)。まぁ、現在
のinternal_encodingの意味はここ(DB連携等の都合)にあるのではないかと
勝手に思っているのですが、以前よしおかさんがおっしゃっていた通り、内
部エンコーディングは少なくともコンパイル時には決定すべきですよね(と、
これは廣川さんがおっしゃっていましたね)。
で、仮に内部エンコーディングをPHPとしてUCS-4等に固定するとデータベー
スとのやり取り、その他様々な箇所で問題が発生しそうです。pythonの様に
UNICODE変換モジュールをデフォルトでバンドルして、ユーザの責任におい
てASCII(その他) <-> UNICODE変換を適宜やってもらう、というアプローチ
も考えられますが、シングルバイト圏の方たちにはちょっと受け入れられそ
うもありませんよねぇ。
(4) 出力メッセージ
ちょっと疲れてきました-_-; ので簡単に済ませますが、これはzend_error
でメッセージカタログを使用して国際化、という方法で大丈夫かな、と考え
ています。もちろん、実装にあたってはもう少し決めなければいけないこと
が出てくるとは思いますが(localeの決め方等--環境変数? php.ini?)大筋と
してはよいかな、と(というか、他に思いつきません)。
(5) 結局どうなのか
結局現時点では、ほぼ全ての問題は「内部エンコーディング」ということに
集約されると思います。参考までに幾つか案を上げて見ますと(実装の実現
性云々は無視しています。実は最後にここを書いていて頭が飽和状態です:(
- 現状(PHP3国際化版)のまま
- UCS-4(もしくはUCS-2、はたまたUTF-16)を強行採用
- Mule Internal Encodingはどうでしょう?
- UTF-8に固定
- UTF-8に固定だとISO-8859-xな人々がアレなのでUTF-8もしくは素通し
- コンパイル時にユーザが指定(選択肢は?)
皆様、色々ご意見がおありかと思います。いかがでしょうか?
(II) (参考)他のスクリプト言語
(1) perl
スクリプトエンコーディング == 内部エンコーディングになっていて、御存
知の通り5.6以降でUTF-8をサポートしています。が、なんだか実装に混乱が
見られるように思えるのは僕だけでしょうか。最新バージョンではUTF-8で
スクリプトを書くと結構幸せみたいです。逆にUTF-8以外のエンコーディン
グではあまり幸せではないともいえます。
(2) ruby
作者が日本人の方ということで日本語の扱いの良さは周知のとおりですね
(rubyの正規表現には皆さんもお世話になっていることですし)。しかし、
意外(?)にも「国際化」という意味ではそんなに進んでないように思えます。
昔のメールですが
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/2587
の最後をみると日本語以外への対応はそれほど重視していらっしゃらないよ
うで、最新バージョンでもそれほど状況は代わっていません(多分)。
先ほど泥縄的にrubyのソースを見てみたのですが非常に面白いですね。Zend
Engineとは結構アプローチが異なるのであまり参考にはなりませんが字句解
析にlex/flexを使用せず、ruby自身の正規表現エンジンを用いて自前で行っ
ているようです(構文解析にはbisonを使用しています)。これにより、スク
リプトのエンコーディングがShift_JISでも問題なくparse出来るようになっ
ています。引数でエンコーディングが指定できるのも「正しい」感じですよ
ね。
(3) python
スクリプトのエンコーディング関しては素のPHPと似たような状況のようで
す(Shift_JISパッチが出ていますが、残念ながら「国際化」という観点から
はあまり参考になりません)。ただ、UNICODEに関しては結構意識しているよ
うで str = u"文字列" とすることでUNICODEに変換できたりします。でも今
のところそれだけと言えばそれだけのような。
# 長文失礼しました
--
藤本 真樹
アストラザスタジオ
fujimoto@studio.co.jp
fujimoto@php.net