2012/03/05

DECOLOGの絵文字変換処理

こんにちは tommy です。今回は絵文字シリーズ後半ということで、DECOLOG サイトでの絵文字処理方式について解説したいと思います。正直な話誰得な感じもしますけれども、滲み出るカオス感を楽しんでいただければ幸いです。なお絵文字そのものの仕様については、適宜前回の記事を参照ください。

1. 携帯時代

まずはスマートフォン登場以前の話です。
絵文字を DB に格納する
DECOLOG の携帯版のサイトでは、ブラウザの入出力の文字コードは Shift JIS、アプリケーション (PHP) およびデータベース (MySQL) の内部コードは UTF-8 としています。よってアプリケーション内で Shift JIS - UTF-8 間の変換を行っています。文字コード変換には CP932 のマッピング (PHP では "SJIS-win") を使います。ここいら辺は割と定番だと思います。
さて、これで 3 キャリアの絵文字のコードを入力するとどうなるかというと、絵文字コードの範囲は CP932 では「利用者定義領域(95区-114区)」または「IBM 拡張文字(115区-119区)」のいずれかに収まるため、一応 1:1 の関係で UTF-8 のコードに変換されます。これはキャリアが定義した Unicode マッピングとは別物 (但しDoCoMoに限っては一致します) であるためシステム外部との運用性はありませんが、内部コードとして使うことはできます。以下これを便宜上「DECOLOG絵文字コード」と呼ぶことにします。
とりあえずここまでは特に何もしなくても、同一キャリア間であれば絵文字を扱うことができることになります。
3キャリア間の絵文字変換
3キャリア間で絵文字をやり取りできるように、出力時に端末のキャリアに応じて文字の置き換えを行います。変換テーブルは
  • キャリア間で同じような絵文字があれば、それに置き換えて表示
  • 該当する絵文字がなければ、対応する言葉で置き換えて表示
といったルールで作成します。DoCoMo、au、SoftBank それぞれ相互に変換できるようにするので、変換テーブルは全部で 6 種類つくる必要があります。DECOLOG では自力で変換表を作りましたが、今はフリーのライブラリが充実しているので割と簡単に用意できると思います。処理の順番は、
  1. ユーザーが入力した文字列に対し、上記の変換テーブルを適用して変換
  2. 出力全体を UTF-8 から Shift JIS に変換する
  3. ブラウザへ送出
としています。
ここで問題となるのは、ユーザーが入力した文字列がどのキャリアの端末から入力されたのか知る必要があるということです。前回の記事の通り、Shift JIS 上の各キャリアの絵文字のコードポイントは一部重複しているため、ある一文字のコードポイントだけを見てそれがどのキャリアの文字かを判別することができません。
そんなわけで DECOLOG のデータベースでは、ユーザーが絵文字を入力できるテキストを含むテーブルそれぞれに、それがどのキャリアの端末で入力されたのかを保持するためのカラム (「text_mode」という名前です) を一つ用意するという割と力技でこの問題を解決しています。たまにカラムを作るのを忘れたために絵文字の変換がされない箇所が発生することがありますが、いつか直しますので許してください。
携帯時代の DECOLOG 絵文字対応まとめ
ここまでの内容をまとめると、以下のようになります。
  • ブラウザから入力された文字列は、そのまま UTF-8 に変換して DB に格納
  • DB 格納時に、キャリア情報を専用のカラム (text_mode) に保存
  • DB に格納された文字列を表示するときに、専用の変換テーブルを用いて表示しようとしている端末に応じた絵文字に変換

2. スマートフォン時代

DECOLOG では、2010年10月に (割とひっそりと) 携帯以外のアクセスを受け入れるようにしてから、少しずつスマートフォン対応を進めてきました。絵文字の扱いに関しても、やはり少しずつ改善しつつ今に至る、という感じです。現時点では、従来の携帯端末/iPhone/Android間でおおむね絵文字の相互変換ができるというところまで実現できています。
DECOLOG のスマートフォン対応について
DECOLOG のスマートフォン対応は大きく 2 段階で行われています。
  1. まずはスマートフォンからモバイルサイトにアクセスできるようにする(モバイルモード)
  2. 次にスマートフォンに表示最適化されたページを用意する(スマートフォンモード)
絵文字の観点からモバイルモードとスマートフォンモードを比較したときに大きく違うのは文字コードです。モバイルモードは従来通り Shift JIS のページですが、スマートフォンモードでは UTF-8 のページとなっています。好みに応じて好きなモードを選べるようになっているため、どちらの文字コードの入出力にも対応する必要があります。
絵文字対応0: 携帯端末以外は絵文字変換しない
厳密には絵文字対応とは言いがたいのですが、PC のブラウザなどからのアクセスについては、絵文字変換を行わないという仕様になっています。絵文字が含まれているテキストを表示する際はそのまま表示し、入力されたテキストを DB に保存する際もキャリアは不明という扱いにしています。
絵文字対応1: スマートフォンからのアクセスでキャリアを判別する
前回の記事で触れたとおり、今のところどのスマートフォンも自社のキャリアの絵文字のみ入力できるという仕様になっています。なお、iOS5 の場合は au の iPhone でもパレットから入力できるのは SoftBank 由来の絵文字なので、正確には自社ではなく単一キャリアの文字ということになります。
このため、アクセスしてきたスマートフォン端末がどのキャリアのものか判別する必要が出てきます。従来の携帯端末に対してはアクセス元の IP 帯域やユーザーエージェントの文字列で簡単に判定できますが、スマートフォンでは簡単な判別手段は用意されていません。そのため、DECOLOG では次の手段で判別を行うことにしました。
iPhone
SoftBank絵文字が入力されたものとして扱う。
Android
ユーザーエージェントの文字列に含まれる機種名と出荷元のキャリアの対応表を用意して判別
ということで、またも力技です。なので Android の新機種が出ると都度対応表をアップデートしているという状況です。
絵文字対応2: スマートフォンへの出力で絵文字が表示できるようにする
端末のキャリアが分かると、まずは従来の携帯端末から入力された 3 キャリア別の DECOLOG 絵文字コードをスマートフォンで変換して表示できるようになります。変換ルールは前回の記事で説明したとおり、
種類 変換先
iPhone SoftBank UTF-8 絵文字コード
DoCoMo Android Google 絵文字コード (の DoCoMo 由来の範囲だけ)
au Android Google 絵文字コード (の au 由来の範囲だけ)
SoftBank Android Google 絵文字コード (の SoftBank 由来の範囲だけ)
となります。
これも変換テーブルを用意するわけですが、3 キャリアの絵文字コードをそれぞれ上の 4 パターンに変換するため計 12 種類のテーブルを作成しました。ただし、Andorid からモバイルモード(Shift JIS)のページにアクセスされた場合は、従来の携帯と同じ扱いとすれば良いので変換テーブルも従来の携帯向けのテーブルをそのまま適用します (それも含めると全 18 種類)。
といっても、これは手で作ったわけではなく、Unicode 6.0 の元になった emoji4unicode プロジェクトが作成した対応表の XML
http://emoji4unicode.googlecode.com/svn/trunk/data/emoji4unicode.xml
からほぼ機械的に作成できます。
例として、DoCoMo の DECOLOG 絵文字コードから au Android のコードに変換するテーブル(の一部)はこんな感じになっています。入力が UTF-8、出力が 16 進の数値参照形式です。

絵文字対応3: スマートフォンからのフォーム入力で絵文字を入力できるようにする
出力側が対応できたので次は入力側の対応です。DECOLOG ではそもそもメール投稿での絵文字利用をサポートしていないため、対応範囲は主にフォームから入力された絵文字ということになります (他に iPhone アプリからの記事投稿にも対応しています)。
スマートフォンから送出される絵文字を DB に格納するにあたって、そのコード体系は携帯時代の 3 キャリアの絵文字コードをそのまま踏襲することにしました。
最大の理由は、MySQL のテーブルが「utf8」で作成されていることです。iOS/Android 共に、送出される絵文字のコードは 4byte UTF-8 を含んでいます。これをそのまま「utf8」で作成されたテーブルに格納しようとすると、該当する文字以降がすべて切れて格納されてしまうという問題が発生します。MySQL で正しく 4byte UTF-8 を扱うためには、
  • MySQL のバージョンを 5.5.3 以降にアップグレードする
  • テーブルの文字コードを「utf8mb4」にする。既存のテーブルの場合、ALTER 文の実行が必要(!)

と、巨大なデータを扱っているサイトにとっては非常にハードルが高い対応が必要となります。これを避けるため、入力されたコードを、既存の DECOLOG 絵文字コードに変換して格納する、という方針をとることにしました。
で、これもやはり基本的には変換テーブルを用意して対応するわけです。コード体系の対応関係は以下のようになります。
種類 変換元 変換先
iPhone 〜iOS4: SoftBank UTF-8 絵文字コード
iOS5: Unicode 6.0 (の SoftBank 由来の範囲だけ)
DECOLOG 絵文字コード (SoftBank)
DoCoMo Android Google 絵文字コード (の DoCoMo 由来の範囲だけ) DECOLOG 絵文字コード (DoCoMo)
au Android Google 絵文字コード (の au 由来の範囲だけ) DECOLOG 絵文字コード (au)
SoftBank Android Google 絵文字コード (の SoftBank 由来の範囲だけ) DECOLOG 絵文字コード (SoftBank)
モバイルモード (Shift JIS) のページの場合扱いが異なります。iPhone の場合、上記のコードが HTML の数値参照で送られてくるため、変換前に数値参照を戻す処理が入ります。一方 Android の場合は、従来の携帯の Shift JIS 絵文字コードが送られてくるため、変換処理をスキップするようになっています。
注: 上記の表では変換元はいずれもどこかのキャリア由来の範囲のみとなっていますが、理屈上はどの端末においてもキャリア外の絵文字コードを送ることは不可能ではなありません。このため変換元と変換先の対応関係は 1:1 ではなく、変換先の定義が存在しない文字があります。今のところ端末のキャリア以外のコードが送られてくることはほぼないのですが、そのような文字に対しては出力時の変換と同様、対応する言葉で置き換えるようにテーブル定義を行っています。

3. 将来

歴史的な理由もあり、DECOLOG では以上のような複雑な変換ルールの束になっています。が、今新規にサイトを立ち上げる場合、このような方法を真似る必要は全くないと思います。おそらく
  • 4byte UTF-8 を正しく扱えるデータベースを用意する。MySQL なら 5.5.3 以降のバージョンで「utf8mb4」でテーブルを構築する
  • DB の内部コードは Unicode 6.0 の絵文字コード、または Google の絵文字コードのいずれかに統一する
とすることで、キャリア間の変換をやらなければならないにしてもその変換パターンは最小限に抑えることができるでしょう。また、PC のブラウザなどに対しては Unicode 6.0 の絵文字コードで入出力するようにしておけば、対応するフォントがインストールされている OS で絵文字の表示が可能になるはずです。
DECOLOG でもいずれ MySQL の問題をクリアして絵文字に限らず Unicode 6.0 の文字全部をダイレクトに扱えるようにしていければよいと思っています。いつになるかは分かりませんが……