Zola で日本語のインデックスと英語のインデックスを両方使う

結局インデックスを言語数分ビルドして読み込んだ

hata published on
3 min, 593 words

Categories: web

続き。 ← /posts/japanese-full-text-search-on-zola/

[languages.en] や [languages.fr] による複数言語インデックスの作成🔗

config.toml に [languages.fr] とかを default_language 以外で作ると、その分だけ search_index.<lang-code>.js ファイルが作られる。 それをうまく利用すればいいような気もするけど、自分の環境では default_language 以外のインデックスが実質中身がからになる( JS のガワだけは作られている)。 うーん、わからない。

結局対応したこと🔗

1) ビルド側🔗

config.toml を default_language = "en" で英語にして一度 zola build し、生成された public/search_index.en.js を退避しておく。
config.toml を default_language = "ja" で日本語にして再度 zola build し、退避しておいた search_index.en.js を移動して取り込む。

その際に search_index.en.js を少し書き換えた。 search_index.<lang-code>.js をエディタで開くと分かるが、作成した Javascript オブジェクトのインデックスを

window.searchIndex = {/*とても長いインデックスオブジェクトのコード....*/}

というふうにグローバルにインデックスオブジェクトを配置している。 複数言語のインデックスファイルを雑にそのまま読み込ませるとこれが衝突して上書きされるかたちになってしまうので、En(英語)のインデックスファイルだけ以下のように名前を変える。

window.searchIndexEn = {/*とても長いインデックスオブジェクトのコード....*/}

2) Theme の検索コード側🔗

使っている DeepThought の Theme の HTML 。 結局フォークした。

static/js/site.js

変更後の内容だけど、イメージは伝わると思う。 要はインデックスを両方読み込んで、それぞれの Search Engine を作って、それぞれ検索して、結果を concat しているだけ。

  var indexJa = elasticlunr.Index.load(window.searchIndex);
  var indexEn = elasticlunr.Index.load(window.searchIndexEn);

  $searchInput.addEventListener(
    "keyup",
    debounce(function () {
      var term = $searchInput.value.trim();
      if (term === currentTerm || !indexJa || !indexEn) {
        return;
      }
      $searchResults.style.display = term === "" ? "none" : "block";
      $searchResultsItems.innerHTML = "";
      if (term === "") {
        return;
      }

      var resultJa = indexJa.search(term, options);
      var resultEn = indexEn.search(term, options);
      var results = resultJa.concat(resultEn);
      if (results.length === 0) {
        $searchResults.style.display = "none";
        return;
      }

3) 検索関連の一連の Javascript の読み込みのところ🔗

templates/base.html

{% extends "deep-thought-fork/templates/base.html" %}
{% block other_lang_search_js %}
  <script src="\{{ get_url(path='js/search_index.en.js') \}}"></script>
  <script src="\{{ get_url(path='js/lunr.stemmer.support.js') \}}"></script>
  <script src="\{{ get_url(path='js/tinyseg.js') \}}"></script>
  <script src="\{{ get_url(path='js/lunr.' ~ lang ~ '.js') \}}"></script>
{% endblock %}

ちなみに上記の other_lang_search_js Tera Block の親側( Theme 側)

<!-- ...(省略)... -->
  <script src="\{{ get_url(path='elasticlunr.min.js') \}}"></script>
  <script src="\{{ get_url(path='search_index.' ~ lang ~ '.js') \}}"></script>
  {%- if lang != "en" -%}
  {%- block other_lang_search_js -%}
  {%- endblock -%}
  {%- endif -%}
  <script src="\{{ get_url(path='js/site.js') \}}"></script>
<!-- ...(省略)... -->
  • ※ 実際にはバッククオート「\」は不要。