🙄

【Shopify オリジナル構築③】 言語セレクターの設置

2023/03/31に公開

この記事では、Shopifyに言語セレクターを設置することに関してまとめます。

はじめに

言語セレクターですが、実はShopifyのデフォルトの機能で搭載されています。
しかし、設置個所はフッターのみとなっています。
今回は、この言語セレクターをヘッダーに設置してみようと思います。

言語の設定

多言語設定は、管理画面 > 設定 > 言語 にて設定可能です。
今回は、日本語(デフォルト)と英語の2つを使用言語とします。

ファイルの作成

今回は、snippets(スニペット)フォルダに新しいファイルを作成します。
名前をlang-switch.liquidとします。

デフォルトのコードについて

先述した通り、Shopifyにはデフォルトで言語セレクターがあります。
コードの場所ですが、footer.liquidの以下の箇所になります。

{%- if section.settings.enable_language_selector and localization.available_languages.size > 1 -%}
//間のコードは省略
{%- endif -%}

これをコピペしていきます。

コードの作成

作成したlang-switch.liquidに、デフォルトのコードを貼り付けていきます

HTML
<localization-form>
  {%- form 'localization', id: 'FooterLanguageForm', class: 'localization-form' -%}
    <div class="no-js-hidden">
      {% comment %}
      // 「言語」ワードを非表示
        <h2 class="caption-large text-body" id="FooterLanguageLabel">
          {{ 'localization.language_label' | t }}
        </h2>
      {% endcomment %}
      <div class="disclosure">
        <button
          type="button"
          class="disclosure__button localization-form__select localization-selector link link--text caption-large"
          aria-expanded="false"
          aria-controls="FooterLanguageList"
          aria-describedby="FooterLanguageLabel"
        >
          {{ localization.language.endonym_name | capitalize }}
          {% render 'icon-caret' %}
        </button>
        <div class="disclosure__list-wrapper" hidden>
          <ul id="FooterLanguageList" role="list" class="disclosure__list list-unstyled">
            {%- for language in localization.available_languages -%}
              <li class="disclosure__item" tabindex="-1">
                <a
                  class="link link--text disclosure__link caption-large{% if language.iso_code == localization.language.iso_code %} disclosure__link--active{% endif %} focus-inset"
                  href="#"
                  hreflang="{{ language.iso_code }}"
                  lang="{{ language.iso_code }}"
                  {% if language.iso_code == localization.language.iso_code %}
                    aria-current="true"
                  {% endif %}
                  data-value="{{ language.iso_code }}"
                >
                  {{ language.endonym_name | capitalize }}
                </a>
              </li>
            {%- endfor -%}
          </ul>
        </div>
      </div>
      <input type="hidden" name="locale_code" value="{{ localization.language.iso_code }}">
    </div>
  {%- endform -%}
</localization-form>
JS
class LocalizationForm extends HTMLElement {
  constructor() {
    super();
    this.elements = {
      input: this.querySelector('input[name="locale_code"], input[name="country_code"]'),
      button: this.querySelector('button'),
      panel: this.querySelector('.disclosure__list-wrapper'),
    };
    this.elements.button.addEventListener('click', this.openSelector.bind(this));
    this.elements.button.addEventListener('focusout', this.closeSelector.bind(this));
    this.addEventListener('keyup', this.onContainerKeyUp.bind(this));

    this.querySelectorAll('a').forEach((item) => item.addEventListener('click', this.onItemClick.bind(this)));
  }

  hidePanel() {
    this.elements.button.setAttribute('aria-expanded', 'false');
    this.elements.panel.setAttribute('hidden', true);
  }

  onContainerKeyUp(event) {
    if (event.code.toUpperCase() !== 'ESCAPE') return;

    this.hidePanel();
    this.elements.button.focus();
  }

  onItemClick(event) {
    event.preventDefault();
    const form = this.querySelector('form');
    this.elements.input.value = event.currentTarget.dataset.value;
    if (form) form.submit();
  }

  openSelector() {
    this.elements.button.focus();
    this.elements.panel.toggleAttribute('hidden');
    this.elements.button.setAttribute('aria-expanded', (this.elements.button.getAttribute('aria-expanded') === 'false').toString());
  }

  closeSelector(event) {
    const shouldClose = event.relatedTarget && event.relatedTarget.nodeName === 'BUTTON';
    if (event.relatedTarget === null || shouldClose) {
      this.hidePanel();
    }
  }
}

customElements.define('localization-form', LocalizationForm);

<localization-form>要素は、カスタム要素としてJSで登録されていますね!

ファイルの設置

まずは、header.liquidにschemaにて設定箇所を設けます。
header.liquidsettings内に次のコードを挿入します。

言語セレクター設定
{
  "type": "checkbox",
  "id": "lang-switch",
  "label": "言語セレクターを表示する",
  "default": true
}

そして、header.liquid内の<div class="header__icons">の最後の子要素に、以下のコードを追加します。

{% if section.settings.lang-switch %}
  <div class="lang-swich">{% render 'lang-switch' %}</div>
{% endif %}

これで言語セレクターの表示・非表示を設定できます。

liquidで設定言語を確認

Shopifyで設定されている言語は、

localization.language.iso_code

にて確認できます。

日本語に設定されているときは、

{{ localization.language.iso_code }} // 「ja」が出力される

これを用いて、ヘッダーメニューの言語をif文で条件分岐させ日本語と英語とで切り替えられる仕様にしてみましょう!

動作確認

https://www.youtube.com/watch?v=7hwd8EcyYkA&feature=youtu.be
きちんと言語が切り替えられていますね!

Shopifyの構築を承ります!

Shopifyで実装したいデザインなどがござましたら、お気軽にご相談、お問い合わせくださいませ!

Discussion