このエントリはMagento Advent Calendar 2017の3日目です。

Magentoは1つのアプリケーション上で多言語・多通貨・マルチサイトができるように設計されています。
マルチサイトにおいてはFQDNが異なっていても運用ができますが、Magento1とMagento2では特に多言語運用時のストアビュー切り替えの仕組みに違いがあります。

Magento1でのストアビュー切り替え

Magento1の設計では、ストアビュー切り替えは下記の形式のURLを用いて実現していました。

<ドメイン名>/?___store=en&___from_store=default

切り替え元のストアビューコードと切り替え先のストアビューコードをURLに含めることで、非常にわかりやすく、かつ簡単にストアビューを切り替えることができました。
この仕組をうまく使ってこれまでカスタマイズをしてきた方も多いのではないでしょうか。

Magento2でのストアビュー切り替え

Magento2ではこの仕組みは一応残されてはいますが、基本的な動作が大きく変わりました。

GETではなくPOSTを使う

Magento1ではURLに切り替え元と切り替え先のストアビューコードを含めていたので、必然的にGETを使っていました。
Magento2では原則POSTを使い、以下のURLに一旦移動した上でストアビュー切り替えを行っています。

<ドメイン名>/stores/store/switch/

この時、2つのパラメータがサーバーには送られます。

  • ___store
  • uenc

___storeは切り替え先のストアビューコード。
uencはbase64エンコードされた文字列で、デコードするとドメイン名が入っています。

この2つのパラメータを渡し、ストアビューを切り替えたあとでuencで指定したURLに戻ってくるという作りになっています。

なぜこんな作りになったのか

Magento2がこの仕組を採用したのは、Varnishを全面的に採用したということが大きな理由でしょう。
Magento用のVarnish設定ファイルを読むと、次のようなことが書いてあります。

sub vcl_recv {
~中略~

# We only deal with GET and HEAD by default
if (req.method != "GET" && req.method != "HEAD") {
    return (pass);
}

~中略~

}

この定義は、GETまたはHEAD以外の場合はアプリケーションサーバーに処理をそのまま流すということを意味しています。
つまり、GETやHEADを使ってしまうと、場合によってはVarnishが予期しないキャッシュ結果を返してしまう恐れがあるということです。
そのため、Magento2ではストアビュー切り替えにPOSTを使うようになったと考えられます。

Magento2でやってはいけないストアビューの切り替え方

もし、構築予定のサイトでVarnishを使うのであれば、ストアビュー切り替えなどでGETを使った切替方法は全くおすすめできません。
GETを使って切り替えてしまうと、異なるストアビューのキャッシュがVarnishから戻される可能性があり、予想しないコンテンツが表示される恐れがあります。
安易にストアビュー切り替えをいじると大地雷を踏む恐れがあるので、よくよく注意したほうがよいでしょう。

標準の切り替えの仕組みは、以下のようなマークアップで実現しています。

<div class="switcher language switcher-language" data-ui-id="language-switcher" id="switcher-language">
    <strong class="label switcher-label"><span>言語</span></strong>
    <div class="actions dropdown options switcher-options">
        <div class="action toggle switcher-trigger" id="switcher-language-trigger">
            <strong class="view-jp">
                <span>日本語</span>
            </strong>
        </div>
        <ul class="dropdown switcher-dropdown"
            data-mage-init='{"dropdownDialog":{
                "appendTo":"#switcher-language > .options",
                "triggerTarget":"#switcher-language-trigger",
                "closeOnMouseLeave": false,
                "triggerClass":"active",
                "parentClass":"active",
                "buttons":null}}'>
                                                <li class="view-en switcher-option">
                        <a href="#" data-post='{"action":"<ドメイン名>\/stores\/store\/switch\/","data":{"___store":"en","uenc":"<base64エンコードされた文字列>"}}'>
                            英語</a>
                    </li>
                                                                                            <li class="view-de switcher-option">
                        <a href="#" data-post='{"action":"<><ドメイン名>\/stores\/store\/switch\/","data":{"___store":"de","uenc":"<base64エンコードされた文字列>"}}'>
                            ドイツ語</a>
                    </li>
                                    </ul>
    </div>
</div>

ulタグやliタグの周りの構造を少しカスタマイズし、国旗やリンク形式にするのであればおそらく問題ないでしょう。
ですが大幅に書き換えてしまうと、多分色々と問題が起きると思います。

推奨設定はなんだろう

Magento公式のDevdocsにはこういったマルチサイト運用時の設定サンプルが公開されています。

Multiple websites or stores

ただ、どの例を見てもストアビュー別にホスト名を分ける設定を推奨しています。
おそらくはGoogleのクローラーにhreflangを伝えるにはそのほうが効率的だからでしょう。
最近はSSL証明書が格安で手に入るようになったので、他システムとの連携で支障がなければ言語別にFQDNを変えてしまっても良いかもしれません。

終わりに

Magento2になってJavaScriptの多用化やVarnishの全面採用といった大きな変更がたくさん入っています。
Magento1や他のアプリケーションで通用した方法も、Magento2ではうまくいかないことが多々あります。
自己流で弄る前に、Devdocsなどを読んでから挑戦することをおすすめします。

さて、明日は4日目。Magento1の末期にEnterprise Edition1.13から導入された「インデックスの動作モード」について解説します。