中文電脳/UTF-8で簡単多言語CGI

各種検索
サイト内検索

1.はじめに

掲示板やメールフォームなど、動的な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を多言語化

2.1 準備

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

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

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

2.2 CGIの改造

日本語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が配布している掲示板CGI、JawaNote?(v1.41)を、EmEditorを使って改造する。

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

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

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

CGIをUTF-8で保存する

em.png

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

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

UTF-8設定タグを追加する

次に、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の設定を無効にする

次に、「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> 

フォント指定の変更

改造に使っている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>

とするのが望ましい。

完了

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

改造したCGI:

CGIファイルのみです。CGI-StaTionさんからログファイルなどのセットをダウンロードして、CGIファイルを上書きして設置してください。設置方法もCGI-StaTionさん参照。なお、このCGIを利用することによって生じたあらゆる損害に対して、千田大介は責任をとりません。自己責任において、ご利用ください。転載等については、CGI-StaTionさんの規定に準じます。

改造版CGIに、言語タグ置換機能を追加しました。書式は以下の通り。

&lang(言語コード){文字列}
ex.
&lang(zh-cn){简体字}
&lang(zh-tw){繁體字}

文字列の中に改行が入っても大丈夫です。言語コードの一覧は、http://alis.isoc.org/langues/iso639.ja.htmあたりを参照して下さい。中国語は、大陸(簡体字):zh-cn、台湾(繁体字):zh-twです。BBS自体のページ言語が日本語に指定してあるため、日本語文字列については言語設定の必要はありません。

設置サンプル:ご自由におためしください。

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

おまけ:

YY-BOARDv.5.33をUTF-8したCGI。以下のCGIを、KTNT-WEBさんから落としたオリジナルファイルと入れ替ればOKのハズ。動作保証・質問などは一切受け付けません。自己責任でお使い下さい。

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

設置サンプル:ご自由におためしください。

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

3.問題点

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

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

3.1ブラウザの対応

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

3.2表示フォントの問題

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

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

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

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

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


*1 言語指定機能は、最新の改造配布版CGIに組み込み済み。

リロード   新規 編集 凍結 差分 添付 複製 改名   トップ 一覧 検索 最終更新 バックアップ   ヘルプ   最終更新のRSS
Last-modified: 2006-09-18 (月) 19:34:10 (3537d)