• 動作環境
    • Python 3.6.1
    • pelican 3.7.1

状況

pelicanでタグ毎にページを表示するurlはtag/(タグ名).htmlであるが、日本語のタグを付けたときにはurlの(タグ名)の部分がよく分からない文字列に自動変換される。 正確にはアルファベットと数字以外の文字列を使った場合であり、これはカテゴリでも同様である。

例えば、日記というタグが付けられている記事一覧のurlはtag/ri-ji.htmlと変換される。

対処

これを直すためには、公式ドキュメントによると、SLUG_SUBSTITUTIONSAUTHOR_SUBSTITUTIONSCATEGORY_SUBSTITUTIONSTAG_SUBSTITUTIONSなどの設定をpelicanconf.pyに追加すればよく、以下の例のように置き換え元と置き換え先の文字列の組を記述すれば良い。

TAG_SUBSTITUTIONS = (('C++', 'cpp'))

この場合、C++というタグが付けられている記事一覧は、tag/cpp.htmlとなる。

しかし日本語タグの場合、同じように書いても上手く行かない。 例えば、

# 上手くいかない
TAG_SUBSTITUTIONS = (('日記', 'diary'))

と設定した場合、日記というタグが付けられている記事一覧のurlは、tag/diary.htmlとはならず、tag/ri-ji.htmlのままとなってしまう。

これをtag/diary.htmlにするには、

# 上手くいく
from unidecode import unidecode
TAG_SUBSTITUTIONS = ((unidecode('日記'), 'diary'))

とすれば直すことができる。

原因

ここからは上記のようになる理由である。

アルファベットと数字以外の文字列を使った場合の置き換え操作はslugify関数が用いられている。 これはvalue(置き換え対象のタグやカテゴリ)とsubstitutions(pelicanconf.pyで設定したTAG_SUBSTITUTIONSなど)を引数と取る関数であるが、この関数はvalueunidecode.unidecodeで変換した後に、substitutionsの置き換え元の文字列とvalueを比較して、一致するものがあれば置き換え先の文字列に変換するという動作をしている。

つまり上手くいかなかったの日記のタグの例では、日記という文字列をunidecode.unidecodeRi Jiに変換してから、substitutions内の日記という置き換え下の文字列と比較しているため、日本語タグはどう頑張っても変換されないということが起きていたと考えられる。

なので、TAG_SUBSTITUTIONSなどで設定を行う時点で、日本語をunidecode.unidecodeで変換しておけばよい。

おわりに

python2では検証していないので、もしかしたら違う動作になるかもしれません。 検証をお願いします。