Craft CMS で日本語タイトルをローマ字変換して slug にセットする(前編)

先日、X(旧 Twitter)でこんなポストを見かけました。

Craft CMS では、置換されたり除去される文字が一部あるものの、エレメントのタイトルとして入力された日本語テキストは、そのまま Slug にセットされてしまいます。

URI 文字列に日本語テキストが含まれるのを避けるには、slug の替わりに ID を利用したり、slug を半角英数で手入力する運用ルールを設けたりといった、対応が必要です。

そんな工夫をしなくても、自動的にローマ字変換できるのであれば確かに便利そうですね。

そこで、Craft CMS で日本語タイトルをローマ字変換して slug にセットする方法について、考えてみました。
これは Craft CMS Advent Calendar 2023 19日目の記事です。

どうやって、変換するか?

日本語テキストをローマ字に変換する方法を考えてみたところ、パッと思いついたのは次の3つでした。

  • JavaScript で入力されたキー情報を取得
  • 何らかのサービスを利用
  • 何らかのライブラリを利用

JavaScript で入力されたキー情報を取得

これは「お問い合わせフォームで氏名を漢字入力したら、ふりがなが自動入力される」ようなイメージです。

入力されたキー情報を取得して連結後、指定した要素にセットすれば良さそうですが、誤入力の打ち直しに対応するのが難しそうなので一旦保留。

何らかのサービスを利用

残念ながら「漢字混じりの日本語テキストを直接ローマ字に変換する」という、都合のいいサービスは見当たりませんでした。

ですが、形態素解析系の API サービスを利用することで、ひらがなへの変換は可能です。

日本語形態素解析(V2) - Yahoo!デベロッパーネットワーク
https://developer.yahoo.co.jp/webapi/jlp/ma/v2/parse.html

ひらがな化API |ソフト・アプリ開発のAPIなら【gooラボ】
https://labs.goo.ne.jp/api/jp/hiragana-translation/

ひらがなからローマ字に変換するライブラリであれば JavaScript や PHP でも存在するため、それらを組み合わせれば実現できそうですね。

ただし、「利用規約上、商用利用が可能か?」や「将来的に継続利用できるのか?」といった懸念があるため、これも一旦保留。

何らかのライブラリを利用

サービスと同様、形態素解析系のライブラリを導入すれば良さそう、ですね。
ということで、探してみた結果、次の3つに絞られました。

SamuraiT/mecab-python3: mecab-python.
https://github.com/SamuraiT/mecab-python3

miurahr/pykakasi: Lightweight converter from Japanese Kana-kanji sentences into Kana-Roman.
https://codeberg.org/miurahr/pykakasi

hexenq/kuroshiro: Japanese language library for converting Japanese sentence to Hiragana, Katakana or Romaji with furigana and okurigana modes supported.
https://github.com/hexenq/kuroshiro

きちんと作るなら MeCab などを利用した方が良いのだろうなと思いつつ、作者さん自ら「MeCab 他と比べて正確性には劣るけど、軽くてスピードを求めるなら使ってね(意訳)」 とリポジトリの issue コメントで言及されている pykakasi を採用することにします。

pykakasi を試してみる

はじめに、pykakasi をインストールします。

pip3 install pykakasi

ローカルの Docker 環境は Ubuntu なので、--break-system-packages オプションを付けてインストールしました。

参考:俺流!PEP668とうまくやっていく方法 | スクエニ ITエンジニア ブログ
https://blog.jp.square-enix.com/iteng-blog/posts/00043-play-with-the-pep668/

次に、Terminal で Python のインタラクティブシェルを起動します。

python3

>>> に続けてプロンプトが表示されていることを確認したら、次のコードを実行します。

import pykakasi
kks = pykakasi.kakasi()
text = "【Craft 4.5 の新機能】共有可能なエレメントフィルタで、管理画面をカスタマイズする(準備編)"
result = kks.convert(text)
for item in result:
     print("{}: kana '{}', hiragana '{}', hepburn: '{}'".format(item['orig'], item['kana'], item['hira'], item['hepburn']))

実行結果は次の通りです。

インタラクティブシェルの実行結果

ドットや半角スペースなど slug には不要な文字列があるものの、当初想定していたよりも簡単にひらがなやローマ字(ヘボン式)への変換ができました。

一旦、control + D でインタラクティブシェルを終了しておきましょう。

実行ファイルを準備する

今回の用途であれば pykakasi で問題なさそうなことがわかりましたので、convert2hepburn.py ファイルを作成し、次のコードを記述します。

import re
import sys
import pykakasi

# 第一引数がなければ、エラーメッセージを出力して終了
if len(sys.argv) < 2:
  print("変換するテキストが指定されていません")
  sys.exit()

# 第一引数を text にセット
text = sys.argv[1]

# pykakasi を使って変換
kks    = pykakasi.kakasi()
result = kks.convert(text)

# ローマ字を格納する変数を初期化
list = []

for item in result:
  # item が ( または ) であればスキップ、それ以外なら処理を継続
  if item['hepburn'] == "(" or item['hepburn'] == ")":
    continue
  else:
    hepburn = item['hepburn']

    # 小文字に変換
    hepburn = hepburn.lower()

    # ( ) | , . / を削除
    hepburn = re.sub(r'[\(\)\|,\.\/]', '', hepburn)

    # 先頭と末尾のスペースとハイフンを削除
    hepburn = hepburn.strip()
    hepburn = hepburn.strip("-")

    # スペースと二重ハイフンをハイフンに置換
    hepburn = hepburn.replace(" ", "-")
    hepburn = hepburn.replace("--", "-")

    # リストに追加
    list.append(hepburn)

# リストをハイフンで連結して出力
output = '-'.join(list)
print(output)

ポイントを少し解説します。

import re
import sys
import pykakasi

はじめに、必要なモジュールをインポートします。
引数を取得するための sys と変換結果を正規表現で整形するために re をインポートしています。

# 第一引数がなければ、エラーメッセージを出力して終了
if len(sys.argv) < 2:
  print("変換するテキストが指定されていません")
  sys.exit()

# 第一引数を text にセット
text = sys.argv[1]

コマンド実行時に引数が指定されていなければ、エラーメッセージを出力して終了します。

# pykakasi を使って変換
kks    = pykakasi.kakasi()
result = kks.convert(text)

pykakasi を使って変換を行います。

for item in result:
  # item が ( または ) であればスキップ、それ以外なら処理を継続
  if item['hepburn'] == "(" or item['hepburn'] == ")":
    continue
  else:
    hepburn = item['hepburn']

    # (中略:テキストの整形)

    # リストに追加
    list.append(hepburn)

変換結果をループして、ローマ字(ヘボン式)をリストに追加します。
このとき、括弧のみであればスキップするようにしています。

    # 小文字に変換
    hepburn = hepburn.lower()

    # ( ) | , . / を削除
    hepburn = re.sub(r'[\(\)\|,\.\/]', '', hepburn)

    # 先頭と末尾のスペースとハイフンを削除
    hepburn = hepburn.strip()
    hepburn = hepburn.strip("-")

    # スペースと二重ハイフンをハイフンに置換
    hepburn = hepburn.replace(" ", "-")
    hepburn = hepburn.replace("--", "-")

ここでリストにセットする前に整形を行なっていますが、必要に応じて変更してください。

# リストをハイフンで連結して出力
output = '-'.join(list)
print(output)

最後にリストをハイフンで連結して出力します。

実行結果のサンプル

いくつかのブログ記事タイトルで実行してみた結果を載せておきます。

python3 ./pathTo/convert2hepburn.py "【Craft 4.5 の新機能】共有可能なエレメントフィルタで、管理画面をカスタマイズする(準備編)"
craft-4-5-no-shinkinou-kyouyuukanou-na-erementofiruta-de-kanri-gamen-wo-kasutamaizu-suru-junbi-hen
python3 ./pathTo/convert2hepburn.py "ColorfulBox / mixhost の CLI の PHP バージョンを変更する"
colorfulbox-mixhost-no-cli-no-php-baajon-wo-henkou-suru
python3 ./pathTo/convert2hepburn.py "MTAppjQuery の user.js で開発環境のみ固定メッセージを表示させる"
mtappjquery-no-user-js-de-kaihatsukankyou-nomi-kotei-messeeji-wo-hyoujisa-seru

「表示させる」が hyoujisa-seru になっているなど微調整が必要な箇所もありますが、導入の手軽さを考えると十分かなと考えています。

ここまでのまとめ

たまたま見かけたポストから興味を持って調べてみたのですが、思ったよりも簡単に実現できそうですね。

もちろん、最近流行りの固有名詞など辞書に登録されていない単語は期待通りの変換になりませんので、必要に応じた手入力による微調整は想定しておきましょう。(辞書ファイル自体の加筆・修正という手段もありますが...)

なお、次回の後編では、Craft CMS のモジュールとして実装する方法について、ご紹介したいと思っています。

comments powered by Disqus