おそらく多くのJekyllテーマでは日本語表記に対応はしていても、1つの記事を読むのにかかる時間を計算するときに、日本語をできるだけ正確にカウントできる仕様になっていないと思う。かくいう私のブログで採用したフリーテーマも仕様になかったので、改善した。
Jekyllテーマ色々
テーマをピックアップ - Jekyll 日本語サイトに複数のギャラリーリンクが存在する。有料のものも存在する。
私のサイトで採用しているテーマはMinimal Mistakes。一応、検索したら他にも利用している日本人がいる(T-pot、k11i.biz、JekyllでMinimal Mistakesのテーマを使う - Qiita)。どうやら他テーマに比べて拡張しやすいらしい(他のテーマをまともに見ていないので知らない)。
本題:日本語文字数カウント
【Jekyll】日本語記事の「この記事は何分で読めます」を表示する | T-Potを参考にした。
元の状態
Jekyllテーマを管理しているディレクトリ上でnumber_of_words
を検索すると、該当ファイルが見つかるはず。Minimal mistakesの場合は、./_includes/page__meta.html
。以下、ファイル内のコード抜粋。
{% assign document = post | default: page %}
{% if document.read_time %}
{% assign words_per_minute = document.words_per_minute | default: site.words_per_minute | default: 200 %}
{% assign words = document.content | strip_html | number_of_words %}
<span class="page__meta-readtime">
<i class="far {% if include.type == 'grid' and document.read_time and document.show_date %}fa-fw {% endif %}fa-clock" aria-hidden="true"></i>
{% if words < words_per_minute %}
{{ site.data.ui-text[site.locale].less_than | default: "less than" }} 1 {{ site.data.ui-text[site.locale].minute_read | default: "minute read" }}
{% elsif words == words_per_minute %}
1 {{ site.data.ui-text[site.locale].minute_read | default: "minute read" }}
{% else %}
{{ words | divided_by: words_per_minute }} {{ site.data.ui-text[site.locale].minute_read | default: "minute read" }}
{% endif %}
</span>
{% endif %}
おおざっぱに説明すると、assign
で変数を定義しており、read_time = true
つまり読了予想時間を表示させる設定にしている場合は、別ファイルで定義したwords_per_minute
(つまり1分間に何単語読めるか)よりもドキュメントの単語数が少ないか、同じか、多いかでif分岐して数字 minute read
のように表示させている。
words_per_minute
は./_config.yml
で定義している。
words_per_minute: 200
200
は、英語話者の平均が200-300らしいので。あなたは1分間に英文を何語読めますか?WPMとは? | マスターイングリッシュ 富山市の英会話教室・英検・TOEIC講座
read_time: true
も./_config.yml
に記述しているがdefaults:
に含めてポストに共通のFront matterとして定義している。つまり、各ポスト(_posts/hogehoge.md
)の先頭に---
で囲って記述しているあれを、YAMLファイルで定義していちいち書く必要をなくしているだけ。
defaults:
# _posts
- scope:
path: ""
type: posts
values:
read_time: true
改善案
number_of_words
は英単語数をカウントするので、そのままでは日本語に合わない。
words_per_minute
とは別にcharacters_per_minute
を定義
words_per_minute: 200
characters_per_minute: 500
500
は、日本語話者の平均が400-600らしいので。人は1分間に何文字読めるの?スキマ時間で読まれる文字数を推測してみよう。 | WEBマスターの手帳
日本語用のカウント数を定義
元の状態にならって、assign
で変数を定義する。
{% assign words_per_minute = site.characters_per_minute | default: 500 %}
{% assign words = document.content | strip_html | strip_newlines | size %}
上はcharacters_per_minute
の設定内容をそのままwords_per_minute
に代入しているだけ、下はdocument.content
でポスト本文、あとはオプション
-
strip_html
:htmlに変換されて追加されるタグ(<p>
等)は除く -
strip_newlines
:行が空いていたらそれは除く -
size
:文字数をカウント
各オプションはLiquid template languageに詳しい。
ここで、size
とするか、number_of_words: "auto"
とするかは読者ターゲットにもよると考えられる。size
だと英単語もアルファベット1文字=1(wordなら4)としてカウントし、後者は、英単語は1単語=1(wordなら1)、漢字かなカナは1文字=1としてカウントする。広く一般向けならsize
で、技術記事が多くて英語をある程度嗜んでいる人向けならnumber_of_words: "auto"
で良いのでは。(Liquidフィルタ | Jekyll • シンプルで、ブログのような、静的サイトの"Number of Words"の項目参照)
if分岐で英単語、日本語の切り替えを可能にしておく
せっかく?なので、words_per_minute
、characters_per_minute
どちらを使うかで、元の状態つまり英語対応か、上の定義で日本語対応にするかをif分岐制御する。別にcharacters_per_minute
のみならif分岐は不要なので適宜削除してほしい。
{% assign document = post | default: page %}
{% if document.read_time %}
{% if site.words_per_minute %}
{% assign can_read_per_minute = site.words_per_minute | default: 200 %}
{% assign words = document.content | strip_html | number_of_words %}
{% elsif site.characters_per_minute %}
{% assign can_read_per_minute = site.characters_per_minute | default: 500 %}
{% assign words = document.content | strip_html | strip_newlines | size %}
{% endif %}
<span class="page__meta-readtime">
<i class="far {% if include.type == 'grid' and document.read_time and document.show_date %}fa-fw {% endif %}fa-clock" aria-hidden="true"></i>
{% if words < can_read_per_minute %}
{{ site.data.ui-text[site.locale].less_than | default: "less than" }} 1 {{ site.data.ui-text[site.locale].minute_read | default: "minute read" }}
{% elsif words == can_read_per_minute %}
1 {{ site.data.ui-text[site.locale].minute_read | default: "minute read" }}
{% else %}
{{ words | divided_by: can_read_per_minute }} {{ site.data.ui-text[site.locale].minute_read | default: "minute read" }}
{% endif %}
</span>
{% endif %}
ここで、両方に共通した意味合いを持たせるために、assign words_per_minute
をassign can_read_per_minute
に変数名を変更しているので、注意してもらうために元の状態をすべて書き直したものを載せている。
また、元の状態ではdocument.words_per_minute | default: site.words_per_minute
のように書かれていたのを、書き直したコードの5行目ではsite.words_per_minute
としている。もしポストごとに英語記事か日本語記事かを区別しているならいいが、サイト全体でしか今は考えないので、site
のみにしている(そのままでも問題はたぶんない)。
あと、サイト全体でしか今はwords(characters)_per_minute
変数を考えていないことから、付け加えたif分岐ではsite.words(characters)_per_minute
を条件に使う必要がある。
if分岐を使う場合
./_config.yml
では使わない方をコメントアウトする。
# words_per_minute: 200
characters_per_minute: 500
まとめ
今のところ日本語ばかりの記事しか書かないので、日本語話者が読了するのに必要な時間を出せるようにした。一応英語記事を書く段になった際スムーズに事が進むようにと、Jekyllファイルでif分岐に取り組んだことがなかったのでif分岐を使った。if分岐でsite
を使わなければいけないことに気付くまで時間がかかったことはナイショ。