b2evolution 2.4.1 の日本語周りの改造
b2evolution 2.4.1 "Nevada" の日本語対応に関する改造の改訂版です。
私の改造の考慮不足により発生していたトラックバック受信関連のバグを修正しました。送られてきたトラックバックに文字セット指定が付いていない際に文字コード自動判定が行われない問題と、不要な警告メッセージが出る場合がある問題を修正したつもりです。
2008年4月9日追記: 三点、改造のミスを修正しました。(1)経由検索エンジンのキーワードを文字コード自動判定する部分が機能しないミスをしてしまっていたので修正しました。(2)トラックバック受信関連の改造で、不必要なロケールの切り替えを行ってしまっていた部分があり、実害はありませんが無駄な処理なので修正しました。(3)メール送信のメールヘッダ・エンコード時に変数未設定の警告が出ることがあったのを修正しました。
配布アーカイブファイルを差し替えましたので、すでにダウンロードした方は新しいものをダウンロードしなおしてください。
2008年4月10日追記: トラックバック受信関連をさらに修正しました。(1)送られてきたトラックバックのurl
パラメータも文字コード変換するようにしました。(2)まだ変数未設定の警告が出ることがあったのを修正しました。(3)この改造版では文字セットをUTF-8に統一しているので問題は発生しないのですが、b2evoオリジナルのままロケールごとに文字セットが異なる設定になっていると、送られてきたトラックバックの文字セット指定と無関係に、param()
の処理で勝手に文字コード変換が行われてしまう場合があるのを回避するようにしました(改造版ではまったく影響は無いので、単にオリジナルの内容に少しでも沿ったものにしたいという気休めみたいなものです)。
また、トラックバック送信関連で、charset
パラメータのエンコードに他のパラメータと同じ rawurlencode()
を使うようにしました。
配布アーカイブファイルを変更しましたので、すでにダウンロードした方は新しいものをダウンロードしなおしてください。
以下、説明(ほぼ以前の使い回し)と、改造差し替えファイルのダウンロードリンクを記述します。
単に使ってみたいだけという方は、「前置き」以降の説明文は読まず、「はじめに」と「改造差し替えファイル」だけ読んで利用していただいて構いません。ただ、どこに変更を加えていて、どの機能は手付かずなのか知りたくなった時など、それ以外も参照してみてください。
(例えば、多くの方が興味があるのに、私の改造で手を付けていない部分の最たるものは、「メールによる記事投稿」機能の日本語文字化けです。修正のための動作検証に手間もかかりますし、たとえ文字化けを直しても、主に需要のある、添付ファイル付きメール投稿、いわゆる写メール投稿には元々b2evolutionが対応していませんから、あまり必要性は無いと思っています)
はじめに: 改造差し替えファイルを使用する際の注意
私が言うまでも無いことかもしれませんが、適用する前にバックアップはちゃんと取っておいてください。ファイルとデータベースの両方を忘れずにバックアップしましょう。
インストールの際に、インストールページで最初に「Japanese (JP)」(日本語 (JP))のリンクを使って言語を日本語に指定しておくと、ブログやユーザのデフォルトの言語が日本語になり、後の設定が楽になりますので、「Japanese (JP)」(日本語 (JP))の選択を行ってください。
また、過去に管理(Admin)画面の「全体設定 › 地域」(Global settings › Regional)で設定を変更していた場合、「全体設定 › 地域」ページの下のほうに「デフォルトにリセット (データベース テーブルを削除)」(Reset to defaults (delete database table))リンクが表示されています。
この状態では blogs/conf/_locales.php
の更新が反映されませんので、「デフォルトにリセット (データベース テーブルを削除)」でリセットを行ってください。
なお、通常の使い方では「全体設定 › 地域」(Global settings › Regional)の設定を変更する必要はありませんので、リセット後はデフォルトそのままにしておいてください。
改造差し替えファイル
以下が、改造部分の差し替えファイルをまとめたアーカイブ・ファイルです。差し替えファイルで既存のファイルを置き換えてください(バックアップを取るのを忘れずに)。
2.4.1用の日本語メッセージファイルは作成していませんのでご注意ください。後に示す古い1.8.x用が一応使えます。
b2evolution-2.4.1-japanese-mod2008-04-10.zip
ファイル・サイズ: 199,151 bytes,
MD5: 2bda92fe0c320e062bb8d6b125acfe8f ,
SHA1: b87233a2710fabe632b3ad7ee33c34b5c29f4837
(ここXREA.COM無料サーバからのファイルのダウンロードは、混み合う時間帯には特に、途中で中断してしまう場合がありますので、ダウンロード後にファイル・サイズを確認して、もしサイズが小さい場合はダウンロードしなおしてみてください)
日本語メッセージファイル(1.8.x用)
以下は、1.8.x用の日本語メッセージファイルのアーカイブ・ファイルです。バージョンが古いので、部分的にしか日本語にならず、英語のままの部分も多く残りますが、無いよりはマシかと思います。
使用する際は、b2evolution公式サイトのlanguage packと同様に b2evolution/blogs/locales
内に展開してください。
ファイル・サイズ: 140,918 bytes,
MD5: 9d6d29577c6d096360a1d661476d7e75 ,
SHA1: 0fadb28c4a6a8d70afb8b8244e24c0e67eb0610f
前置き: 文字化けの原因
この前置きは長くてややこしい話ですし、実のところ私は完全には調査・理解できていない状態なので間違いもあるかと思います。あまり興味のない方は読まなくて構いません。
b2evolutionの文字化けにはいくつかの原因がありますが、根本的なものは、使用する文字セット(charset)の決定方法に問題があるという点です。
なお、「うちはb2evoを一切変更していないけど日本語も文字化けしないよ」という方は、ウェブブラウザの言語設定(HTTPリクエストの Accept-Language: ヘッダの指定内容)を英語(en や en-US など)のみにして、ログインしていない状態でご自分のブログにアクセスしてみてください。おそらく、文字化けするのが確認できるはずです。
(言語設定の変更は、IE6では「ツール」-「インターネット オプション」-「全般」タブ -「言語」、Firefox 2では「ツール」-「オプション」-「詳細 > 一般」タブ -「言語設定」で行います)
b2evoでは大雑把に言って、「ウェブブラウザの言語設定」→「ログインしている場合はユーザのロケール(言語・地域)設定」→「ブログのロケール設定」、の順番でロケールを判別します。最初の「ウェブブラウザの言語設定」のロケールから $evo_charset
(内部の文字セット設定)が決定され、これは特殊な場合を除き、出力処理が終わるまで基本的に変更されません。
この仕様により、英語設定のウェブブラウザでアクセスがあると、$evo_charset
(内部の文字セット設定)が ISO-8859-1 に設定されてしまいます。しかし、b2evoの日本語設定ユーザの書いた記事は、実際には UTF-8 で書かれていますので、UTF-8 の文字列を誤って ISO-8859-1 と見なしてしまう(MySQLデータベースからISO-8859-1 (Latin1)に無理な変換をして取り出す)現象が発生します。
そして、UTF-8 で書かれた記事の ISO-8859-1 と見なされた文字列は ISO-8859-1 しか考慮されていないエスケープ処理が施されます。
さらに、「ブログのロケール設定」はすでに決定された $evo_charset
(内部の文字セット設定)は変更できませんが、$io_charset
(出力時の変換文字セット設定。入力の文字セットも同一と見なされる)は「ブログのロケール設定」に合わせて変更が行われます。日本語ブログなら $io_charset
は UTF-8 になります。そして、出力時に $evo_charset
(ISO-8859-1)から $io_charset
(UTF-8)への文字コード変換が行われます。
このため、最初からの流れで言うと、実際には UTF-8 であるのに ISO-8859-1 と見なされた(MySQLからISO-8859-1 (Latin1)に無理に変換して取り出された)文字列は、ISO-8859-1 しか考慮されていないエスケープ処理が施された後、さらに ISO-8859-1 から UTF-8 に変換する処理が行われて出力されます。本当は、元々 UTF-8 なので UTF-8 出力するなら変換処理する必要も無いのですが。
こうして多重に誤った変換が施されるせいで、文字列が原形を留めず、単なる文字セット指定ミスとは違う、ウェブブラウザ側では修復不能な文字化けが発生することになります。
(一応 blogs/conf/_locales.php
であらかじめ $evo_charset
, $force_io_charset_if_accepted
などを強制指定することにより文字化けを発生しにくくすることができるようになっていますが、完全ではありません。わかっている問題では、$force_io_charset_if_accepted
の指定は、Accept-Charset: ヘッダの内容と食い違った時など、条件によって無視される場合があります)
改造の説明
ここからが説明の本題です。
変更部分のコードを書き写すのは、記事がやたら長くなってしまいますし面倒なので行いません。ご自身でオリジナルと私の改造版のファイルの差分を取るなどして、見比べてみてください。
ロケール(言語・地域)設定の変更
対象ファイル: blogs/conf/_locales.php
私の改造版では、blogs/conf/_locales.php
での各ロケール設定の文字セット指定をすべて UTF-8 に統一しています。
これによって、前述「前置き: 文字化けの原因」で書いた $evo_charset
(内部の文字セット設定)や $io_charset
(出力時の変換文字セット設定。入力の文字セットも同一と見なされる)の食い違いを無くし、不必要な文字コード変換や ISO-8859-1 しか考慮されていないエスケープ処理も行われないようになります。
根本的な解決ではありませんが、確実に問題を回避できるはずです。
(少なくとも、b2evolutionの日本語ユーザの間で良く行われているらしい、blogs/conf/_locales.php
ファイルで $evo_charset
, $force_io_charset_if_accepted
, $db_config['connection_charset']
を utf-8 / utf8 に強制指定しておく方法よりは、(条件によって $force_io_charset_if_accepted
が無視されるなどして)ロケール設定からUTF-8以外の文字セット設定が混じり込む可能性が無いので、同じUTF-8統一指定でもこちらの方法のほうが信頼性が高くなります)
また、b2evolution の配布ファイルに付属してくる言語ファイル blogs/locales/de_DE/_global.php
と blogs/locales/fr_FR/_global.php
の2つは、どちらも ISO-8859-1 で書かれていますが、改造版ではロケールの文字セット設定をUTF-8に変更していますので、これらの言語ファイルの内容も UTF-8 に変換してあります。
サブドメインが1文字のホスト名を不正とみなす問題の対策
対象ファイル: blogs/inc/_core/_url.funcs.php
はてなダイアリー(d.hatena.ne.jp)など、サブドメインが1文字のホスト名へのリンクを記事に書き込むなどした場合に、「Invalid URL format」エラーになってしまいます。
ざっと調べた範囲では、サブドメインが1文字でも、RFC2181の「11. Name syntax」あたりを見る限り問題は無いようですので、b2evolutionのバグの可能性が高いと思われます。
記事以外にもコメント、トラックバックの他、サブドメインが1文字のサイトからリンクをたどってきた場合のリファラ(Referer:)判定でも引っかかる(リファラspamと見なされる)ようです。
blogs/inc/_core/_url.funcs.php
の94~105行目で、ホスト名の最初の .
(ドット)まで2文字以上必要としている判定部分を、1文字でもエラーにならないようにしました。
UTF-8のメッセージファイル使用時に管理画面の一部で発生するエラー対策
対象ファイル: blogs/inc/_core/ui/results/_results.class.php
(_results.class.php
を編集する際は、特殊な文字が含まれているため、できれば西ヨーロッパ言語 (ISO-8859-1, Windows-1252 (CP1252)) を編集可能なエディタを使用することをお勧めします)
管理画面で機能アイコン画像等を表示するために(「全体設定 › ファイルタイプ」ページなど)、特殊な文字列置き換えとPHPコード実行処理が行われる際に、UTF-8のメッセージファイル(日本語等)で定義される文字列の一部が誤って置き換え対象となり、evalエラーを引き起こす問題の簡易的な回避策を施しています。
(これは完全な対処とは言えませんので、まだ条件が合うとエラーが発生する可能性も残っています。またUTF-8以外でも該当するものがあるかもしれません)
blogs/inc/_core/ui/results/_results.class.php
の1560行目で、¤ (0xA4)に囲まれた部分をPHPコードとして処理をするために置き換えていますが、例えば「除」のUTF-8コードは十六進表記で E9 99 A4 となり A4 が含まれているため、文字の並び方によっては誤判定が起こります。他にも 0xA4 が含まれる文字は「イ, 複, 検」など、いくつかあります。
簡易的な回避策として、¤ (0xA4)で囲まれた部分の始まりと終わりの文字がASCII文字であるかどうか判定するようにしました。置き換えるのはPHPコードであるはずなので、非ASCII文字が最初と最後に付くことはありえませんので。あくまで簡易処置ですが、これでも効果はあるようです。
また、日本語メッセージファイルのほうでも、該当部分で使われることが明らかな文字列は該当する文字を実体参照に置き換えています。例えば「除」→「除」など。
(もし根本的な修正を考えるなら、「¤」1文字だけで範囲指定するやり方を変えてしまったほうがいいのではないかと思います。例えば同じ文字でも3文字以上並べれば偶然の一致は起こりにくいでしょう)
トラックバック送信
対象ファイル: blogs/inc/comments/_trackback.funcs.php
b2evolutionのトラックバック機能は、相手が同じ文字セットを使用していることを前提に作られていますので、文字セットの違うブログとのトラックバックのやり取りで文字化けを起こす可能性があります。文字セットUTF-8、EUC-JP、Shift_JISが混在する日本語のブログ間では起こりやすい問題ですので、それを防ぐための対策を施します。
一点目は、トラックバックの仕様 TrackBack Technical Specification Version 1.2 で導入された、POSTリクエスト・Content-Type:ヘッダへの charset 記載を行うようにします。加えて、過去に日本の一部で独自に使用されていたパラメータ charset
も念のため使用します。
これにより、仕様に沿って作られたブログでは、受け取ったトラックバックの文字セットを認識して、適切な文字コード変換をしてくれるはずです。
二点目は、トラックバック送信にはHTTP GETリクエストは使用せず、HTTP POSTリクエストのみを使用するように変更しました。(よほど古いままバージョンアップされていないブログ相手でない限り、問題は起きないと思います)
TrackBack Technical Specification のVersion 1.1以降ではトラックバックの送信にHTTP POSTリクエストを使わなければいけないことになっています。現在ではPOSTリクエストのみ受け付け、HTTP GETリクエストでのトラックバックは拒否するブログも、多くはありませんが存在するようになっています。
しかし、b2evolutionは5年以上昔の仕様との互換性を考慮して、相手のトラックバックURLに「?」が含まれるとHTTP GETリクエストを使うように作られています。ただし「?」を含むトラックバックURLは多く存在しており、結果として、かなり多くの場合に必要も無いのにGETリクエストでトラックバックを送っていましたので、これを止めるように変更しました。
三点目に、マルチバイト文字列関数を使用して(使用可能な場合)、マルチバイト文字の途中で文字を切ってしまって文字化けを起こすことの無いようにしました。
トラックバック受信
対象ファイル: blogs/htsrv/trackback.php
一点目は、トラックバックの仕様に則ってPOSTリクエスト・Content-Type:ヘッダへの charset 記載を認識して、マルチバイト文字列関数が使用可能ならば、文字コード変換を行うようにしました。念のため、過去に日本の一部で独自に使用されていたパラメータ charset
も認識します。
charset 指定が無い場合でも、ブログのロケール(言語・地域設定)がja-JP(日本語)で、マルチバイト文字列関数が使用可能であれば、文字コード自動判別を行います。
二点目に、マルチバイト文字列関数を使用して(使用可能な場合)、マルチバイト文字の途中で文字を切ってしまって文字化けを起こすことの無いようにしました。
三点目に、Movable Typeなどからb2evolutionにトラックバックを送信した場合、成功したにもかかわらず、失敗したとMovable Type側で表示される問題の対処をしました。
トラックバックの仕様では、トラックバック受信時の相手へのレスポンスは、成功した場合はエラーコード 0 でメッセージ無しを返すことになっていますが、b2evolutionはエラーコード 0 とメッセージ「ok」を返していました。Movable Typeはメッセージがあるので失敗であるかのような表示をしてしまっているようです。
これを、成功した場合にはメッセージ無しになるように変更しました。ついでに、失敗した時に仕様には無いエラーコード 2 を返す場合があったのを、失敗のエラーコードは 1 に統一しました。
メール送信
対象ファイル: blogs/inc/_core/_misc.funcs.php
マルチバイト文字列関数が使用可能ならば、
- メール送信時のロケール(言語・地域設定)が日本語(ja-JP)で、かつメールの内容が完全にISO-2022-JP文字セットに変換可能な場合、ISO-2022-JPでメールを送信するようにしました。(その他の場合は、ロケールの文字セットで送信します)
- メールのFrom:とTo:ヘッダに非ASCII文字が含まれている場合、MIME Base64エンコード/ punycodeエンコードするようにしました。
メールのSubject:ヘッダは元々MIME Base64エンコードされるようになっていますが、MIMEヘッダエンコード関数 mb_encode_mimeheader()
を使用する際に設定が必要な、mb_internal_encoding()
が適切に設定されていない場合がありましたので、適切な設定を行うようにしています。
なお、どんな条件でもISO-2022-JPでは送信したくない場合は、改造版 blogs/inc/_core/_misc.funcs.php
の1567行目の、$want_to_use_iso2022jp = 1;
を $want_to_use_iso2022jp = 0;
に書き換えてください(1 を 0 に)。
ウェブブラウザの言語設定からのロケール判別
対象ファイル: blogs/inc/locales/_locale.funcs.php
ログイン画面やインストール・データベースアップデート画面で、ウェブブラウザの言語設定を元にロケール(言語・地域設定)を自動決定するようになっていますが、誤判定が多いです。
ウェブブラウザの言語設定が、例えば良くある設定で「ja(日本語), en-US(英語・アメリカ), en(英語)」という順番になっていると、本来は「ja」が採用されなければならないところ、b2evolutionは2文字より5文字のロケールを優先してしまい「en-US」を採用してしまっていました。
これを、順序に従って「ja」が採用されて、ロケール設定「ja-JP」になるようにしました。
なお、ウェブブラウザの言語設定が「en(英語), en-NZ(英語・ニュージーランド)」とか、同じ言語で2文字より5文字(地域付き)のほうが後に来てしまっている、あまり適切とは言えない設定になっていても、元々のb2evoの動作通り、うまく「en-NZ」を採用するはずです。
さらに、b2evolution側のロケール設定で「pl-PL-utf-8」や「zh-CN-utf-8」など5文字を超えるものが、ウェブブラウザ側の言語設定「pl-PL」や「zh-CN」を完全一致と認識しない問題にも対処したつもりです。
経由検索エンジンのキーワード文字化け
対象ファイル: blogs/inc/sessions/model/_hitlog.funcs.php
統計の検索エンジン経由アクセスの使用キーワード表示がISO-8859-1にしか対応していませんので、その文字化け対策です。htmlentities()
に文字セット指定を行って、ISO-8859-1決め打ちにならないようにしました。ただし、検索エンジン側とb2evo側で使用している文字セットが違う場合の文字化けはこれでは直りません。
ロケール(言語・地域設定)が日本語になっていて、マルチバイト文字列関数が使える場合は、文字コードの自動判別も行います。日本語に関しては検索キーワード表示の文字化けが軽減されます。
年月日表示
対象ファイル:
blogs/inc/items/model/_itemlistlight.class.php
blogs/plugins/_archives.plugin.php
blogs/plugins/_calendar.plugin.php
日毎表示のタイトル部分、アーカイブ一覧の年月表示、カレンダーの年月表示では、日本語で一般的な語順でなく、「4月 2008, 8」や「4月 2008」のような表示になってしまいます。ロケール(言語・地域設定)が「ja-JP(日本語)」の時は、これを日本語らしい形式「2008年4月8日」や「2008年4月」にするよう変更しました。
なお、スキンで独自に設定が行われている場合もあるので、この改造ですべてが変更できるわけではありません。
ブックマークレット使用時の文字化け
対象ファイル: blogs/plugins/_bookmarklet.plugin.php
ブックマークレットでの文字化けは、ブックマークレットのJavaScriptで escape()
が用いられていることが原因です。encodeURIComponent()
を使用するように変更しました。
欧文のみの環境ですと、escape()
のほうが問題が少ないようです。しかし、UTF-8を使用する場合では encodeURIComponent()
のほうが無難です。