Up 「ウェブページの文字化け」のロジック 作成: 2008-09-02
更新: 2008-09-02


「文字化け」のロジック

    文字化けに出会うと,ひとはたいていパニック行動を起こします。
    すなわち,理屈を考えずに,出口さがしでバタバタします。
    ネット検索して,「これで文字化けが解決される」の記事を見つけては,それの真似をします。
    そして,これによって却って,いままでまともであったシステムを損なっていきます。

    文字化けは,論理的帰結です。
    <文字化けして表示される>は,論理的帰結ということでは<文字化けしないで表示される>と同格です。 「文字化けしないで表示されるのが正常で,文字化けして表示されるのが異常」ということではありません。
    このことを先ず,しっかりアタマに入れておく必要があります。

    文字化けに際しては,くれぐれも「環境設定をやみくもにいじる」ということをしないように。
    また,サーバー運用者の場合には,「環境設定をやみくもにいじる」に加えて「サーバーソフトのインストールの際の configure オプションをいろいろいじる」があります。これも,やってはなりません。

    以下,文字化けのロジックを示しつつ,クライアントとサーバーそれぞれの「文字化けに対する処方」を示します。



    クライアントの場合

    あるウェブサイトにアクセスしたとき,ページが文字化けして表示された。 このとき,自分のブラウザの環境設定をいじることは,決してしないように。
    問題はサーバーの側にあり,クライアントの側にはありません。

    この文字化けはどうして起こったのか?

    クライアントのブラウザは,サーバーからの文字コードの指示を受け取ります。 ──例えば,「このページの文字コードは Shift-JIS である」とサーバーが言ってきたとしましょう。
    文字化けは,ページの実際の文字コードが Shift-JIS でないときに起きます。

    こんなことは,実際起こるのか?
    起こります。──これについては,「サーバーの場合」のところで述べます。


    ただ,文字化けの問題はサーバーの方にあるとしても,あなたは文字化けしたページを読んでみたいと思うでしょう。
    このときは,ブラウザのバーメニューにある「表示(View)」から文字コード指定へと進み,文字コードをいろいろ試す,というのが対処法です。

    当て推量でいろいろ試す前に,ソースファイルに文字コードの情報がのっていないかを調べるというのも,一つの手です。
    ソースファイルのヘッダ部に,つぎのような文字コード指定の METAタグが書かれているかも知れません:
      <META HTTP-EQUIV="Content-Type" CONTENT="text/html;charset=UTF-8">
    これにより,ページの文字コードは UTF-8 であるということがわかります。


    しかし,こう対処しても相変わらず文字化けしている場合も,論理としては,あり得ます。
    どんな場合か?
    つぎのような場合です:
      EUC の文字コードで書かれているページがある。
      クライアントがこれをリクエストしてきた。
      サーバは,「JIS から SJIS へ変換」の処置をしてから,クライアントに送る。
    EUC で書かれた文書が,JIS で書かれた文書として SJIS に変換されるわけですから,文字コードの意味がなくなります。
    この文字化けは,クライアント側ではどうしようもありません。


    文字化けに際してクライアントが行動することは,以上がすべてです。
    繰り返しますが,ブラウザの環境設定をいじるということは決してしないように。
    一部のウェブページでの文字化けに際してブラウザの環境設定をいじるということは,端的に間違いであり,無意味です。 これまでまともだったシステムを損なうことにしかなりません。



    サーバーの場合

    ここでは,つぎの場合を考えます:

    • Apache + PHP で HTTPサーバを構築・運用

    • Shift-JIS で書いているページと UTF-8 で書いているページがある。
      Shift-JIS を使っているのは,成り行き。すなわち,つぎのやり方でコンテンツづくりを始めたので,以降これを続けているということ:
      PC の上で,そしてシステムの文字コード Shift-JIS で,ソースの HTMLファイルを作成。そしてこれをそのままサーバにアップロード。
      UTF-8 を使うのは,Shift-JIS では文字が不足する場合。 文字不足の問題がない限りは,Shift-JIS を使っている。

    このとき,php.ini における文字コード処理に関する設定は,つぎのようになります:
      output_buffering = On
      output_handler = mb_output_handler
      default_charset = "Shift_JIS"
      mbstring.language = Japanese
      mbstring.internal_encoding = EUC-JP
      mbstring.http_input = auto
      mbstring.http_output = pass
      mbstring.encoding_translation = Off
      mbstring.substitute_character = none;
    ここで肝心なところは,つぎの2つです:

    1. 「default_charset = "Shift_JIS"」の設定。
    2. ソースファイルの文字コードをいじらないで,そのまま送信する。


    「default_charset = "Shift_JIS"」の設定により,HTTP プロトコルで,クライアントにつぎの指示が送られます:
      Content-Type: text/html; charset=Shift_JIS
    ここでもし
      default_charset = ""
    と書いて Default の文字コードを非設定にすると,
      Content-Type: text/html
    が送られることになり,このときのクライアントのブラウザの動作は,つぎのものになります:
      自分の環境設定の中で設定している Default の文字コードで,
      ページを展開する。
    ここの例では,サーバーの大部分のページは Shift-JIS で書かれています。 したがって,default_charset の非設定は,クライアントを混乱させる可能性の方が大きくなります。 よって,先ずは,default_charset に Shift_JIS を設定します。

    UTF-8 のコードで書かれているページがクライアントにおいて UTF-8 で展開されるようにするには,方法をこの後で述べますが,ページ個別に対応していくことになります。


    META タグで charset を指定する意味

    ページソースの HTML ファイルでは,ヘッダ部につぎのように書くことで文字コードを指示できるとされています。
      <META HTTP-EQUIV="Content-Type" CONTENT="text/html;charset=Shift_JIS">
    しかし,サーバから送信されてきたページの場合,ブラウザはこの文字コード指示に従うことはありません。 (言い換えると,従わないことになっています。)

    ブラウザは,あくまでも,HTTP プロトコルで受け取る「Content-Type: text/html; charset=[文字コード]」に従います。
    サーバー側で default_charset を指定していないときは,「Content-Type: text/html」が送られてきますが,このときは,ブラウザは自分の環境設定の中で設定している Default の文字コードでページを展開します。


    では,METAタグを使った文字コード指定は,まったく意味がないのか?
    ページのソースファイルに対しこれをブラウザで開くとき,ブラウザは文字コード指示を読みます。
    例えば,メールに添付されてきた HTMLファイルがブラウザで開かれる場合,METAタグを使った文字コード指定がその中に書かれていれば,ブラウザはそれを読んで指示に従います。

      メールに関わる文字化けは,関係する要素がウェブページの場合より増えるため,問題が複雑になります。 ( メールの文字化け)


    強調 : ブラウザは,HTTP プロトコルで受け取ったページに対しては,その中のMETAタグを使った文字コード指示には反応しない。


    ページ個別に文字コードを指定する方法

    ページ個別に文字コードを指定──例えば,UTF-8 を指定──するとは,HTTPプロトコルで
      Content-Type: text/html; charset=UTF-8
    が送信されるようにするということです。
    ソースファイルに
      <META HTTP-EQUIV="Content-Type" CONTENT="text/html;charset=UTF-8">
    を書いても,このことは起こりません。

    では,これを起こすには,どうしたらよいか?
    ソースファイルをつぎのように書き始める,というのがこれの答えです:
      <?
       header('Content-Type: text/html; charset=UTF-8');

    将来のことを考えると,作成したどのページにも,この方法で文字指定を必ずつけるようにするのがいいでしょう。