中文電脳/UTF-8で簡単多言語CGI のバックアップ差分(No.10)


  • 追加された行はこの色です。
  • 削除された行はこの色です。
*1.はじめに [#b128e2c5]

掲示板やメールフォームなど、動的なWebサイトの構築には、Perlを使ったCGIが一番手軽だ。しかし、こと多言語処理となると、問題が多いとされてきた。

Perlで日本語を処理する場合、jcode.pl などの日本語コード対応のモジュールを用意するのが一般的だ。これでJISコードに定義される文字は使えるようになるが、しかし、例えば中国語との多言語混在処理になると、お手上げだ。

日本語のCGIでも、ブラウザがJIS外の文字を「&#xnnnn;」に自動変換する機能を使って、多言語を混在させることはできるのだが、InternetExplorerとNetscapeでは機種依存文字の扱いが異なる、IE5.0では、日本語フォントにUnicode対応フォントを指定しないと一部の文字が「・」化けするという問題がどうしても発生する。

しかし、文字コードにUTF-8を使うと、jcode.pl に頼ることなく、Perl5.xで、多言語処理をすることができる。UTF-8とは、Unicodeの文字を処理するための文字コード番号の付け方の一つだ。といわれてもよくわからない人が多いと思うが、要するに、インターネットでUnicodeの文字を使うときに使われる文字コードだということだ。衆知のように、Unicodeは世界のあらゆる文字コードを一つの文字コード体系にまとめたもので、これを使えば、欧州諸語はもとより、日本語と中国語、ハングルなども混在処理することができる。

以下、日本語・中国語混在掲示板を例に、多言語処理可能なCGIの作成方法について解説する。

*2.UTF-8でCGIを多言語化 [#u3268045]

**2.1 準備 [#a0d2087f]

多言語CGIを作るのは、実はとても簡単だ。作業に必要なのは、

-カスタマイズしてもよいフリーCGIや自作CGI 
-Unicodeに対応したエディタ 

近頃は、EmEditorをはじめとする多くのエディタがUTF-8に対応しているので、それら最新版のオンラインエディタをダウンロードして使おう。ただし、エディタで中国語・日本語を混在表示するためには、Unicodeに対応したフォントが必要になる。SimSun、MS Song、PMingLiUなどのフォントを使えば良い。ただし、一部の環境やエディタでは、それらのフォントが上手く使えない場合もある。その場合は、Office2000/XP付属の「Arial Unicode MS」などのフォントを使おう。

**2.2 CGIの改造 [#b7886d07]

日本語CGIをUTF-8対応に改造するポイントは、以下の三点だ。

-CGIスクリプト、データファイルなどを全てUTF-8で保存する。 
-HTMLファイル生成部分で、生成されるページのヘッダにUTF-8指定メタタグ<meta http-equiv="Content-Type" content="text/html; charset=utf-8">を設定する。 
-jcode.plによる日本語処理部分を無効にする。 

CGIを設置するサーバがPerl5.8に対応していたら、スクリプトの冒頭の行頭に「#」のついている行の後に「use encode;」と書き加える。そうすれば、完全にUnicodeに対応するが、BBS程度であれば、これを記述しなくてもおおむね問題なく動作する。Perlのバージョンがそれ以前であったら、この行は書き加えない。

現在、Perl5.5以前のバージョンがあいかわらず使われているサーバも多い。そのため、以下では、Perl5.5以前を念頭に解説する。

それでは実際に、CGIをUTF-8によって多言語化してみよう。ここでは、[[CGI-StaTion>http://www7.big.or.jp/~jawa/]]が配布している掲示板CGI、JawaNote(v1.41)を、EmEditorを使って改造する。

ダウンロードしたファイルを解凍すると、次の5つのファイルが得られる。

-jawaback.gif 
-jawanote.cgi 
-jawanote.log 
-jcode.pl 
-readme.htm 

これらのうち、改造しなくてはならないのは、「jawanote.cgi」だけ、その他のファイルに手を加える必要はないし、jcode.plは必要ない。

***CGIをUTF-8で保存する [#b02b8421]

#ref(em.png,nolink);

まず、「jawanote.cgi」をEmEditorで開く。右クリックして「EmEditor」を選べばよい。文字化けしたら、「ファイル」→「読み直し」で文字コードを変更する。次に、「ファイル」→「名前をつけて保存」を選択し、文字コードを「UTF-8」、「Unicodeサイン(BOM)を付ける」をOFFに設定して、上書き保存する。

これで、CGIファイルがUTF-8で保存された。

***UTF-8設定タグを追加する [#s04b2a79]

次に、HTML生成部分に、UTF-8指定のメタタグを追加する。EmEditorで「<html>」を検索すると、123行目以下に、次のように記述されている。

 <HTML><HEAD>
 <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=$charset_code">
 <TITLE>$note_title</TITLE> 

124行目を書き換えて

 <HTML><HEAD>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 <TITLE>$note_title</TITLE> 

のように改造する。

また、

 if ($err) { print "Content-type: text/html\n\n<HTML><BODY>"; } 

の<HTML>と<BODY>の間にメタタグを入れる。""の中なので、タグの中の「"」を「\"」にするのを忘れずに。

 if ($err) {
 print "Content-type: text/html\n\n<HTML><meta http-equiv=\"Content-Type\"
 content=\"text/html; charset=utf-8\"><BODY>";
 } 

***jcodeの設定を無効にする [#m8a3b589]

次に、「jcode」を検索する。まず72行目

 $jcode = './jcode.pl'; # jcode.pl のある場所 

行頭に「#」を記入し、無効にする。つづけて、218行目

 &jcode'convert(*comment,'euc'); 

と222行目、703行目の

 &jcode'convert(*comment,$mojicode); 

も無効にする。たいていのCGIは、以上の設定だけで大丈夫だが、サンプルのCGIはちょっと凝っていて、文字コード判別処理を600行目以下でしている。

 # [ 文字コード関連 ]
 #
 
 sub check_code {
     if (!(-r $jcode)) { &error(1,"jcode.pl がみつかりません。"); }
     require $jcode;
     local($text) = ord(substr("中澤重人=じゃわ(^-^;;",0,1));
     if ($text == 0xc3) { $mojicode = "euc"; $charset_code = "x-euc-jp"; }
     elsif ($text == 0x92) { $mojicode = "sjis";$charset_code = "x-sjis"; }
     else { &error(1,"サポートしてない文字コードです"); }
 }
 sub change_code {
     local($text)=$_[0];
     &jcode'convert(*text,$mojicode);
     if ($mojicode eq 'sjis') { &jcode'h2z_sjis(*text); }
     if ($mojicode eq 'euc') { &jcode'h2z_euc(*text); }
     $text =~ s/</&lt;/g;
     $text =~ s/>/&gt;/g;
     return $text;
 } 

ここも、jcodeと文字コード関係の部分を全て無効にする。

 # [ 文字コード関連 ]
 #
 
 sub check_code {
 #     if (!(-r $jcode)) { &error(1,"jcode.pl がみつかりません。"); }
 #     require $jcode;
      local($text) = ord(substr("中澤重人=じゃわ(^-^;;",0,1));
 #     if ($text == 0xc3) { $mojicode = "euc"; $charset_code = "x-euc-jp"; }
 #     elsif ($text == 0x92) { $mojicode = "sjis";$charset_code = "x-sjis"; }
 #     else { &error(1,"サポートしてない文字コードです"); }
 }
 sub change_code {
      local($text)=$_[0];
 #     &jcode'convert(*text,$mojicode);
 #     if ($mojicode eq 'sjis') { &jcode'h2z_sjis(*text); }
 #     if ($mojicode eq 'euc') { &jcode'h2z_euc(*text); }
     $text =~ s/</&lt;/g;
     $text =~ s/>/&gt;/g;
     return $text;
 } 

このような文字コードチェック部分を備えているCGIは、むしろ少数派だ。もしも、Perlの知識が無くてよくわからなければ、以上のような複雑な文字コード処理部分の無いフリーCGIを選ぼう。

掲示板のフォームが日本語と中国語で表示されるようにするには、CGIファイルのフォームの説明部分を書き換える。フォームの表示部分は、270行目以下なので、そこを例えば下のように加筆修正すればよい。

 <B>タイトル(标题)</B>
 </TT></TD><TD>
 <INPUT TYPE=text NAME=title SIZE=42 MAXLENGTH=80 VALUE="$title_area">
 </TD></TR><TR><TD><TT>
 <B>ハンドル(笔名)</B>
 </TT></TD><TD>
 <INPUT TYPE=text NAME=name SIZE=42 MAXLENGTH=42 VALUE="$COOKIE{'name'}">
 </TD></TR><TR><TD><TT>
 <B>URL(家页)</B>
 </TT></TD><TD> 

***フォント指定の変更 [#m3c71a8c]

改造に使っているcgiでは、表示フォントを設定している部分がある。132行目

 <BASEFONT SIZE=3 FACE="MS ゴシック"><TT>

一般のHTML解説書では言及されていないが、日本語のフォント名を直接指定した場合、海外版OSからアクセスした際に
問題が生ずる。考えてみれば、英語版のOSで日本語のフォント名を解釈できないのは当然であろう。

この問題は、フォント名指定に日本語フォント名ではなく、日本語フォントの対応する英語名称(Post Script Name)
を使うことで解決できる。例えば「MS ゴシック」は「MS Gothic」、「MS 明朝」は「MS Mincho」と記述する。

 <BASEFONT SIZE=3 FACE="MS Gothic"><TT>

よりアクセシビリティーを高めるためには、スタイルシートでフォント名とともにフォントファミリーも設定する、さらにはフォントを一切指定せず、

 <BASEFONT SIZE=3><TT>

とするのが望ましい。

***完了 [#hb3922c3]

これで、CGIの改造は完了した。あとは、日本語CGIを設置するのと同じように各種設定をおこない、アップロード、パーミッションを変更すればよい。

改造したCGI:

#ref(jawanote.lzh);

>CGIファイルのみです。[[CGI-StaTion>http://www7.big.or.jp/~jawa/]]さんからログファイルなどのセットをダウンロードして、CGIファイルを上書きして設置してください。設置方法も[[CGI-StaTion>http://www7.big.or.jp/~jawa/]]さん参照。なお、このCGIを利用することによって生じたあらゆる損害に対して、千田大介は責任をとりません。自己責任において、ご利用ください。転載等については、[[CGI-StaTion>http://www7.big.or.jp/~jawa/]]さんの規定に準じます。
>>改造版CGIに、言語タグ置換機能を追加しました。書式は以下の通り。
 &lang(言語コード){文字列}
 ex.
 &lang(zh-cn){简体字}
 &lang(zh-tw){繁體字}
>>文字列の中に改行が入っても大丈夫です。言語コードの一覧は、http://alis.isoc.org/langues/iso639.ja.htmあたりを参照して下さい。中国語は、大陸(簡体字):zh-cn、台湾(繁体字):zh-twです。BBS自体のページ言語が日本語に指定してあるため、日本語文字列については言語設定の必要はありません。

[[設置サンプル>http://www.wagang.jp/bbss/utf8-bbs/jawanote.cgi]]:ご自由におためしください。

他のCGIでも改造のポイントは同様だが、メール送信機能を持ったCGIの場合は、メールヘッダ部分の文字コード指定を「Content-Type: text/plain; charset="UTF-8"」に変更しなくてはならない。

おまけ:

[[YY-BOARD>http://www.kent-web.com/bbs/yybbs.html]]v.5.33をUTF-8したCGI。以下のCGIを、[[KTNT-WEB>http://www.kent-web.com/]]さんから落としたオリジナルファイルと入れ替ればOKのハズ。動作保証・質問などは一切受け付けません。自己責任でお使い下さい。

>こちらも、言語タグ置換機能を追加しました。指定方法は上のJawa Noteと同じです。

#ref(yy.lzh);

[[設置サンプル>http://wagang.econ.hc.keio.ac.jp/yybbs/yybbs.cgi]]:ご自由におためしください。

>アイコンは、使用登録するのが面倒なので、置いていません(笑)。

*3.問題点 [#v8ce7042]

Perlは5.6で正式にUTF-8に対応し、5.8でマルチコード対応がほぼ完成した。
これは、文字列を文字単位で扱えるようにした、ということであり、
バイト単位で扱う場合にはPerl5.xでも問題が生じないようだ。
もちろん、文字の字数をカウントするようなUTF-8 CGIは、Perl5.6、
できれば5.8以上でなくては作れないが、掲示板程度であれば問題なく動作する。

しかし、UTF-8のCGIであるということで、幾つかの制限事項がある。

**3.1ブラウザの対応 [#he52daed]

Internet Explorerの場合は、バージョン4以降であれば、問題なくUTF-8のCGI
を使ったページを閲覧・投稿ができるが、Netscapeの場合はバージョ
ン6以降を使わなくてはならない。バージョン4.xもUTF-8には対応しているが、
しかし、Unicode内部処理化されていないため、書き込みができない。

**3.2表示フォントの問題 [#m5b959e5]

もう一つの問題が、表示フォントの問題だ。よく言われるように、「骨」の字は日本
と中国で字形が違う。しかし、前述の設定では、フォントの指定を全くしていないため、
日本語と中国語の「骨」を区別することができない。この問題は、ここ電脳瓦崗寨PukiWikiや[[UniWiki]]
などで実装している、spanタグで言語を指定
する機能を組み込めば解決できるが、最新版ブラウザでしか期待する効果が得
られない。((言語指定機能は、最新の改造配布版CGIに組み込み済み。))

もしも旧版ブラウザでも見られるようにしたければ、カスケード
スタイルシートを設定し、かつ書き込み部分に言語指定タグ・符号などを書き込むようにして、
言語によってフォント指定を切り替えるようにするしかないが、かなり面倒である。

多少の問題点はあるものの、上述の方法を使えば英語・日本語の豊富なCGIスクリプトを簡単に多言語化できるのであるから、その利点は大きいと言えよう。

なお、Perl5.6以前の環境でCGIをUTF-8化が出来るか否かは、実はかなり簡単に見分けられる。正規表現の置換先文字列にダブルバイトが入っていると、Perl5.6以前では動作不良が発生する、ということである。

※UTF-8ページであるため、半角「¥」は「\」で表示されています。日本語環境で作業する場合は、読み替えてください。

*フォローアップ [#pb036319]

-[[電脳瓦崗寨統合BBS>http://www.wagang.jp/bbs2/index.cgi]]