SWELLのブログカード(関連記事ブロック)が特定の外部サイトだけ文字化けするようになりました。
今までは文字化けしていなかったのですが、先方サイトのリニューアルの影響があった模様です。
フォーラムに同じ内容の投稿があったので、この記事でまとめてみます。
今回の問題は、SWELL ver2.7.8.3で改善されました。
SWELL最新版にアップデートすることでこの記事の不具合は起きません。

ブログカードが文字化けしたサイト
↓関連記事がこんな感じで文字化けします。

SWELLのブログカードが文字化けする理由
SWELLのブログカードはで外部サイトのデータをget_ogp_inwp.php
のparse()
でHTMLとして取得しています。
public static function parse( $response_body, $targets ) {
// Data to be finally returned
$ogp_data = [];
// Avoid getting a loadHTML () parsing error
$old_libxml_error = libxml_use_internal_errors( true );
// Load HTML
$doc = new DOMDocument();
$doc->loadHTML( $response_body );
libxml_use_internal_errors( $old_libxml_error );
https://stackoverflow.com/questions/8218230/php-domdocument-loadhtml-not-encoding-utf-8-correctly
DOMDocument::loadHTML
特に指定しない限り、文字列は ISO-8859-1 (HTTP/1.1 のデフォルト文字セット) であるものとして扱われます。これにより、UTF-8 文字列が正しく解釈されなくなります。
元サイトのHTMLに以下の記述がないことが原因のようです。
<?xml encoding="utf-8" ?>
読み込んだHTMLを処理してブログカードの情報として利用しているのですが、HTMLの文字コードが明示的にUTF-8に指定されていない場合、ブログカードが文字化けします。
つまり、SWELLが利用しているコードは、PHPでnative DOMをスクレーピングする処理では定番の文字化け処理が抜けています。
SWELLのブログカードが文字化けを回避するコード
親テーマのアップデートで消えてしまうので、あまりやりたくない方法ですが、SWELLが使っているライブラリを直接書き換えるしか方法がありません。
$doc->loadHTML( $response_body );
を$doc->loadHTML( mb_convert_encoding($response_body, 'HTML-ENTITIES', 'UTF-8') );
に置き換えます。
public static function parse( $response_body, $targets ) {
// Data to be finally returned
$ogp_data = [];
// Avoid getting a loadHTML () parsing error
$old_libxml_error = libxml_use_internal_errors( true );
// Load HTML
$doc = new DOMDocument();
//$doc->loadHTML( $response_body );
$doc->loadHTML( mb_convert_encoding($response_body, 'HTML-ENTITIES', 'UTF-8') );
libxml_use_internal_errors( $old_libxml_error );
まとめ
世の中に、SWELLのブログカードが文字化けするようなサイトがどれぐらいあるのか?というとそれほど多くはないでしょう。
通常のWordpressサイトであれば、以下の記述は間違いなくあるからです。
<?xml encoding="utf-8" ?>
今回のように、Vue.jsやNuxt.jsで作られたようなサイトの場合は、headに必要な情報が無いこともあり、今後は文字化けするサイトが増えていく可能性があります。
コメント