• ホームページの文字化けはHTMLとHTTPヘッダーの文字コードをそろえて直す

ホームページの文字化けはHTMLとHTTPヘッダーの文字コードをそろえて直す

公開日: 執筆:佐藤

ホームページの文字化けは、画面に見える文字を直接直す前に、ブラウザーへ送られたHTMLの文字コードと宣言を照合します。確認するのは、実際の送信バイト列、HTTP応答ヘッダーのContent-Type、HTML内にcharset宣言があればその値です。

HTTPヘッダーのcharsetとHTML内の宣言が異なる場合、HTTPヘッダーが優先されます。HTML内の宣言は、HTTPヘッダーで文字コードを示せない場合の手掛かりにできます。宣言を追加しただけでは送信バイト列は変換されないため、実際の送信内容と有効な宣言を一致させます。

文字コードは文字とバイト列を対応させる決まりである

HTMLは、サーバーからブラウザーへバイト列として送られます。ブラウザーが日本語として表示するには、そのバイト列をどの文字コードで読み戻すかを知る必要があります。

HTML 4.01は、charsetを、バイト列を文字列へ変換する方法を示す値として説明しています。UTF-8、Shift_JIS、EUC-JPは、同じ日本語の文字を異なるバイト列で表す場合があります。同じバイト列でも、実際とは異なる文字コードで読み戻せば、別の文字や記号に見えます。文字コード名の大文字と小文字は区別されないため、Shift_JISとSHIFT_JISは同じ値です。

RFC 3629が定めるUTF-8では、U+0000からU+10FFFFまでの文字を、一つから四つのオクテットで表します。charset=UTF-8は、送られた内容がUTF-8で符号化されていることを示す表示です。内容を変換する命令ではありません。

HTTPヘッダーはHTML内の宣言より先に確認する

文字コードは、HTTP応答ヘッダーとHTML内の二か所で示せます。

HTTP応答ヘッダーでは、Content-Typeへ次のように指定します。

Content-Type: text/html; charset=UTF-8

HTTPヘッダーで文字コードを示せない場合、HTML 4.01の文書内では、head要素の早い位置へ次のように書けます。

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

HTML 4.01の文字コード判定順では、HTTPのContent-Typeにあるcharsetが、HTML内のmeta要素より優先されます。HTTP/1.1のRFC 2616も、Content-Typeが送信する内容のメディアタイプを示し、charsetを伴う例を示しています。

HTMLを開いてmeta要素だけを確認しても、サーバーが送ったHTTPヘッダーは分かりません。制作担当者は、ブラウザーの開発者向け機能などで実際のHTTP応答を確認します。サーバーがcharset=Shift_JISを送り、HTML内にcharset=UTF-8と書いているなら、ブラウザーはHTTPヘッダーのShift_JISを優先します。まず送信バイト列がどちらで符号化されているかを確かめ、誤っている宣言または出力を直します。

編集ソフトに表示される保存形式と、ブラウザーへ届くHTMLの文字コードは、常に同じとは限りません。HTML 4.01は、サーバーやプロキシが転送時に文字コードを変換する場合も示しています。静的なHTMLファイルを変換せずに配信していると確認できた場合だけ、そのファイルの保存形式を送信バイト列の文字コードとして扱えます。

すべてのページが崩れる場合と一部だけ崩れる場合を分ける

文字化けの範囲は、確認する出力元を絞る手掛かりになります。

文字化けする範囲 先に確認するもの 分けて考えること
サイトの多くのページ サーバーのContent-Typeと共通テンプレート 全ページに共通する宣言または出力設定
一つのHTMLだけ そのURLの送信バイト列、HTTPヘッダー、meta要素 URL固有の出力または宣言
見出しや共通部分だけ 該当部分を出力するテンプレート 本文とは異なるファイルからの出力
登録した本文だけ 保存されたデータと、HTMLへ出力するまでの変換 テンプレートと本文データの違い

表は原因を確定するものではありません。たとえば一ページだけ崩れていても、URLごとにサーバー設定が異なる場合があります。文字化けしたURLと箇所を記録し、正常なページとの違いを一つずつ確認します。

ブラウザーで文字コードを手動選択して正常に見えても、それは閲覧中の解釈を上書きしただけです。ほかの利用者へ正しい文字コードが通知されたとは限りません。手動選択は原因を探す手掛かりにとどめ、送信バイト列と有効な宣言を一致させます。

修正では送信バイト列と有効な宣言を一致させる

たとえば、実際の送信バイト列がShift_JISなのに、HTTPヘッダーとmeta要素がUTF-8を示しているとします。UTF-8へ統一するなら、宣言だけでなく、ブラウザーへ届くバイト列をUTF-8へ変換します。変換せずに配信する静的HTMLなら、ファイル自体をUTF-8として保存し直します。サーバーやプロキシが変換する構成なら、変換後のバイト列を確認します。反対に、送信バイト列をShift_JISのまま使うなら、HTTPヘッダーと、存在する場合はHTML内の宣言をShift_JISへ合わせます。

修正は、次の順で行います。

  1. 文字化けするURL、箇所、確認したブラウザーを記録する。
  2. 実際のHTTP応答にあるContent-Typeとcharsetを確認する。
  3. HTML内の文字コード宣言を確認する。
  4. ブラウザーへ届いたHTMLの送信バイト列と、出力までに行われる変換を確認する。
  5. 基準とする文字コードを一つ決め、送信バイト列とHTTPヘッダーを一致させ、HTML内に宣言があれば同じ値へそろえる。
  6. キャッシュだけを見ていないことを確かめ、文字化けしたURLと正常だったURLを再確認する。

UTF-8へ変更すること自体を目的にしません。HTML 4.01は、作成時に選んだ文字コードを正しく示すことを求めています。既存の文字コードを維持するかUTF-8へ変えるかは、テンプレート、保存済みデータ、更新方法、ほかのページへの影響を確認して決めます。

文字化けした状態で保存されたデータは表示設定と分けて戻す

正しい文字を誤った文字コードで読み、その崩れた文字列を上書き保存した場合、HTTPヘッダーを直すだけでは元の文字へ戻りません。表示の解釈を直す作業と、保存済みデータを戻す作業は別です。

上書き前のファイルやデータが残っているなら、先に退避し、元の文字を確認できる状態から復元します。元のデータがない場合は、推測した変換を全体へ一括適用しません。文字化けが起きた経路と変換回数を特定できなければ、別の文字まで壊すおそれがあるからです。

最初の一手は、文字化けしたページのmeta要素を書き換えることではありません。制作担当者へ、実際のHTTP応答のContent-Type、ブラウザーへ届いたHTMLの文字コード、HTML内に宣言があればそのcharsetという三点を確認してもらい、食い違う箇所を一つ特定してください。

戻る