WordPress の抜粋表示は日本語の場合めちゃくちゃになる。内部で単語数をカウントするため、半角スペースを使わない日本語の単語数を認識できない。デフォルトでは55ワードとなっているが、日本語が混ざると正常に動作しない。一方で、記事一覧では抜粋表示させたい。でも、記事を書く時に択一、<!--more-->
とか Excerpt フィールドに直接文字を入力して、となると、面倒この上ない。ということで、テーマで自動処理してしまおう。
抜粋がうまく機能していない
最初の何も手を加えていない状態だと、アーカイブの表示はこんな感じになっている。とても長い。<!--more-->
や Excerpt フィールドに入力していない場合、記事コンテンツがそのまま表示される。

ホームやアーカイブでは抜粋表示に
まず、テンプレートを編集して単一記事以外の場合は抜粋表示にするようにする。the_content
フィルターを使うかとも考えたけど、重複する無駄な処理が発生することになるので、サイト パフォーマンスの観点から 、少し複雑だけどテンプレートファイルを編集する方が良い。
Twenty Seventeen の場合
Twenty Seventeen の場合、次のラインが記事のタイトル、メタ、内容を表示する。index.php
も archive.php
も single.php
も search.php
にも全く同じラインが有る。
で、この関数の中身を追っていくと、/template-parts/post/content.php
の呼び出しに行き着く。つまり、content.php
を編集すれば良い。子テーマに同様のパスと名称のファイルを作成し、それを編集する。
変更内容
/template-parts/post/content.php
の次を
次のように変えてあげる。
これで、単一記事以外は抜粋表示の呼び出しになる。この状態で、アーカイブの表示がどのようになるか確認。次の画像のようになり、やはり長い。

文字数ではなく英単語数がカウントされる
WordPress のそのままの仕様だと、抜粋表示には内部で wp_trim_words()
という関数が呼び出され、そのコードを見ればわかるが、文字数ではなく英語の単語数をカウントしている。例えば、Word は4文字で1ワード。the_excerpt()
が呼ばれると、デフォルトでは55ワードで抜粋される仕様になっているが、日本語の中に混じった英語の中から55個目で切るとなると大変な長さになる。関数のコードを見てみよう。
WordPress コア関数: wp_trim_words()
$word_array
の中身を調べると、例えば次のような文章の場合、
このサイトは WordPress のデフォルトテーマの一つである、Twenty Seventeen を使っている。デフォルトテーマの問題点は、サンプルとして基本機能のショーケース的役割がある反面、味気無さがある。最近の記事のウィジェットもその一つだ。
デフォルトで搭載されている最近の記事のウィジェットは、最新記事幾つかをリストしてくれるが、アイキャッチ画像を表示してくれない。
これをサムネイルを表示してくれるプラグインがあった。
Recent Posts Widget With Thumbnails プラグイン
Recent Posts Widget With Thumbnails。 Dashboard -> Plugins -> Add New から Recent Posts Widget With Thumbnails と検索フォームに入力して、Install からの Activate。
使い方は簡単で、Dashboard -> Appearance -> Widgets から、Recent Posts Widget With Thumbnails を追加するだけだ。
すると、こんな感じになる。
各項目の上下ボーダーが気になるから取り除きたい。
カスタム CSS の追加
ブラウザの Inspector Element で要素を調べたら、.rpwwt-widget ul li クラスのようだ。ということで、Dashboard -> Appearance -> Customize -> Additional CSS で以下を追加。
すると、こんな感じになった。
なかなかいい感じだ。
以下の配列として扱われる。
これが55要素までで切られるため、日本語の場合はかなり長くなってしまう。
WP Multibyte Patch を使ってみるも
プラグインを有効にするだけではきちんと抜粋してくれない
WP Multibyte Patch (v2.8.3) というプラグインを導入し、次を functions.php
に入れてみたが、多少短くなったものの、長さにばらつきが出る。この状態ではまだ英単語数で切っている。

しかし、このプラグインの中身をみていくと、
wp-multibyte-patch.php
/ext/ja/class.php
とあり、mb_substr()
を使っているので、文字数で切っているはずなのだがうまく言っていない様子。
/wp-content/wpmp-config.php の配置
wpmp-config-sample-ja.php
を wpmp-config.php
にリネームし、/wp-content/
下に配置すると、

うまくいった。プラグインサイトの説明では、次のように説明があり、
デフォルトで標準的な設定値が割り当てられるようになっています。これらの設定値を変更する必要がある場合は、
https://eastcoder.com/code/wp-multibyte-patch/wpmp-config-sample-ja.php
をwpmp-config.php
に変名し内容を編集してから下記のように配置してください。(WP_CONTENT_DIR
を変更している場合はその中に置いてください。)
「設定値を変更する必要が場合は」とあるものの、どうも、その必要がない場合でも置いたほうが良いみたい。 wp-multibyte-patch.php に次のようなラインがあり、設定ファイルの有無で作られるオブジェクトのクラスが違う。その為、設定ファイルが無い場合は文字数でカットする機能が働かない設計になっている模様。
WP Multibyte Patch の問題点
ただこれ、使ってみて、<!--more-->
や excerpt フィールドで指定している場合も強制的に文字列がカットされる。できれば、それらの設定を尊重したい。
もう少し詰める
ということで、一旦、 wpmp-config.php
は外して独自のコードで抜粋処理を施す。WP Multibyte Patch 自体は、他の検索語句だとか XML だとかでの補正機能を期待して有効にしておく。で、そうすると、excerpt_length
フィルターフックで返ってくる値が 110
となったままになる。プラグインを外すと、デフォルトの 55
。この状態だと次のような表示になる。

これはつまり、文字数ではなく英単語数、110単語目で切ってね、ということになるので、プラグインを入れる前よりも長い表示になってしまう。
しかし、コア関数 wp_trim_words()
の次の箇所を見ると文字数でも切れる機能が用意されていることがわかる。
これに関しては、gettext_with_context
と excerpt_length
フィルターで対応できる。 WP Multibyte Patch も使うフックで、excerpt_length
に関してはプライオリティを 100
などと低くしてやる必要がある。
で、それによって、まずまずの結果は得られるのだけど、問題があって、
- Excerpt フィールドに直接文字列を入れた場合は Continue reading リンクが表れない
- 抜粋適用文字数を大きく設定した時、
<!--more-->
の箇所がそれ以内だと Continue reading リンクが表れない - 抜粋適用文字数を小さく設定した時 、
<!--more-->
の箇所以前の箇所で切られ、設定位置が尊重されない
3つ目の問題をカバーしようとすると処理が重たくなるので、上の2つをカバーするところまでやる。
PHP コード
これを functions.php
に放り込む。
使い方
使い方は、最後のラインにあるように、クラスをインスタンス化するだけ。その時に次の引数を渡してあげる。
- ( integer ) 抜粋文字最大数。デフォルト:
110
- ( string ) 続きを読むのリンクのラベル デフォルト:
Continue reading
これで、記事中に <!--more-->
が入っていたり excerpt フィールドで直接文字列を指定している場合はそれらの内容が反映される。ただし、<!--more-->
の場合は、抜粋文字数が <!--more-->
以前に到達してしまうと、そこで切れてしまうという制限あり。
記事コンテンツ取得に、generate_postdata()
を使ったが Query Monitor で調べても DB クエリ数は増えなかったのでパフォーマンスに大した影響はないはず。
結果
うまくいくとこんな感じになる。

RSS フィードの抜粋表示
あと、RSS フィードにも抜粋を適用するには、Dashboard -> Settings -> Reading -> For each post in a feed, include を Summary にする必要がある。

Firefox の フィードのアドオンで開いたらきちんと抜粋表示されている。

ということで、めでたしめでたし!色んなケースできちんとテストしてるわけじゃないので、想定外の動作があるかも。
おまけ
ちなみに、Twenty Seventeen の CSS では “続きを読む” の文字が改行されちゃうので、以下の CSS を追加した。
余談
今回はかなり手こずった。コードのデザインがやはり英語圏の人のものなので、ホワイトスペースで単語を区切らない言語を想定して書かれていない。プログラミング全般にそうだけど、最初の設計で90%くらいその後の効率って決まってしまう。特にオープンソースでプロジェクトが大きくなってしまったものは簡単に変更できないので大変。最初の設計がいかに大事か再認識させられた。